Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
23e53286bd | ||
![]() |
47acff05e2 | ||
![]() |
5572928619 | ||
![]() |
85b4cd6339 | ||
![]() |
f0d38ab260 | ||
![]() |
1276af43ef | ||
![]() |
66d42fc2bc | ||
![]() |
1f058f954d | ||
![]() |
8259fb515c | ||
![]() |
6c2a4c3256 | ||
![]() |
51532657d7 | ||
![]() |
fd56fac353 | ||
![]() |
260f533b41 | ||
![]() |
c09ca3b810 | ||
![]() |
f07fb50eff | ||
![]() |
ea62a20c80 | ||
![]() |
2bb0ded20e | ||
![]() |
fec43f55f2 | ||
![]() |
271e901398 | ||
![]() |
c6f01ce839 | ||
![]() |
2dd404c02c | ||
![]() |
2f29bbcee4 | ||
![]() |
63a8c82535 |
@@ -1,2 +1,3 @@
|
||||
DATABASE_URL=data.db
|
||||
DATABASE_TYPE=sqlite
|
||||
DATABASE_TYPE=sqlite
|
||||
CUSTOM_ACCESS_TOKEN_SCRIPT="function(user,tokenPayload){var data = tokenPayload;data.extra = {'x-extra-id': user.id};return data;}"
|
12
.github/CONTRIBUTING.md
vendored
12
.github/CONTRIBUTING.md
vendored
@@ -43,12 +43,14 @@ Please ask as many questions as you need, either directly in the issue or on [Di
|
||||
### Project Setup for Authorizer core
|
||||
|
||||
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
|
||||
2. `git clone https://github.com/authorizerdev/authorizer.git`
|
||||
3. `cd authorizer`
|
||||
4. `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
||||
5. Build the code `make clean && make`
|
||||
2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
|
||||
3. Change directory to authorizer: `cd authorizer`
|
||||
5. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
||||
6. Build Dashboard `make build-dashboard`
|
||||
7. Build App `make build-app`
|
||||
8. Build Server `make clean && make`
|
||||
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command
|
||||
6. Run binary `./build/server`
|
||||
9. Run binary `./build/server`
|
||||
|
||||
### Testing
|
||||
|
||||
|
3
Makefile
3
Makefile
@@ -11,3 +11,6 @@ clean:
|
||||
rm -rf build
|
||||
test:
|
||||
cd server && go clean --testcache && go test -v ./test
|
||||
generate:
|
||||
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate
|
||||
|
12
README.md
12
README.md
@@ -78,12 +78,14 @@ This guide helps you practice using Authorizer to evaluate it before you use it
|
||||
### Project Setup
|
||||
|
||||
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
|
||||
2. `git clone https://github.com/authorizerdev/authorizer.git`
|
||||
3. `cd authorizer`
|
||||
4. `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
||||
5. Build the code `make clean && make`
|
||||
2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
|
||||
3. Change directory to authorizer: `cd authorizer`
|
||||
5. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
||||
6. Build Dashboard `make build-dashboard`
|
||||
7. Build App `make build-app`
|
||||
8. Build Server `make clean && make`
|
||||
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command
|
||||
6. Run binary `./build/server`
|
||||
9. Run binary `./build/server`
|
||||
|
||||
## Install using binaries
|
||||
|
||||
|
826
app/package-lock.json
generated
826
app/package-lock.json
generated
@@ -1,8 +1,832 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@authorizerdev/authorizer-react": "latest",
|
||||
"@types/react": "^17.0.15",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"esbuild": "^0.12.17",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-is": "^17.0.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react-router-dom": "^5.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@authorizerdev/authorizer-js": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.2.1.tgz",
|
||||
"integrity": "sha512-5lQlh+nc5xTsPongfTyCSX24A1WESu/BjhmZwUNuScEOGady0qPoDHE3RBf46dpi5v05wbHCDN1IFEalX5zssQ==",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@authorizerdev/authorizer-react": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.4.3.tgz",
|
||||
"integrity": "sha512-o/wWe9zZ3ARYdjbDfhGfvOxe1YQrE1YQ+UN9pcq85YSDkbfBkOfcnJ4YxlxWdL0Obd/ErDIeQ3vskyrfvRf3sA==",
|
||||
"dependencies": {
|
||||
"@authorizerdev/authorizer-js": "^0.2.1",
|
||||
"final-form": "^4.20.2",
|
||||
"react-final-form": "^6.5.3",
|
||||
"styled-components": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
|
||||
"integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
|
||||
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.8",
|
||||
"jsesc": "^2.5.1",
|
||||
"source-map": "^0.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-annotate-as-pure": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
|
||||
"integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-environment-visitor": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
|
||||
"integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-function-name": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
|
||||
"integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
|
||||
"dependencies": {
|
||||
"@babel/helper-get-function-arity": "^7.16.7",
|
||||
"@babel/template": "^7.16.7",
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-get-function-arity": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
|
||||
"integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-hoist-variables": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
|
||||
"integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-imports": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
|
||||
"integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-split-export-declaration": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
|
||||
"integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
|
||||
"integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.16.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
|
||||
"integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.16.7",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.16.12",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz",
|
||||
"integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz",
|
||||
"integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
|
||||
"integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.16.7",
|
||||
"@babel/parser": "^7.16.7",
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.16.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz",
|
||||
"integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.16.7",
|
||||
"@babel/generator": "^7.16.8",
|
||||
"@babel/helper-environment-visitor": "^7.16.7",
|
||||
"@babel/helper-function-name": "^7.16.7",
|
||||
"@babel/helper-hoist-variables": "^7.16.7",
|
||||
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||
"@babel/parser": "^7.16.10",
|
||||
"@babel/types": "^7.16.8",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
|
||||
"integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.16.7",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "0.7.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/memoize": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
|
||||
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
|
||||
},
|
||||
"node_modules/@emotion/stylis": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
|
||||
"integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
|
||||
},
|
||||
"node_modules/@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
},
|
||||
"node_modules/@types/history": {
|
||||
"version": "4.7.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz",
|
||||
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
|
||||
"integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "17.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz",
|
||||
"integrity": "sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "17.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
||||
"integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-router": {
|
||||
"version": "5.1.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.16.tgz",
|
||||
"integrity": "sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/history": "*",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-router-dom": {
|
||||
"version": "5.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz",
|
||||
"integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/history": "*",
|
||||
"@types/react": "*",
|
||||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-styled-components": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz",
|
||||
"integrity": "sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-annotate-as-pure": "^7.16.0",
|
||||
"@babel/helper-module-imports": "^7.16.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"styled-components": ">= 2"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-syntax-jsx": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
|
||||
},
|
||||
"node_modules/camelize": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
|
||||
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"node_modules/css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/css-to-react-native": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
|
||||
"integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==",
|
||||
"dependencies": {
|
||||
"camelize": "^1.0.0",
|
||||
"css-color-keywords": "^1.0.0",
|
||||
"postcss-value-parser": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.12.17",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.17.tgz",
|
||||
"integrity": "sha512-GshKJyVYUnlSXIZj/NheC2O0Kblh42CS7P1wJyTbbIHevTG4jYMS9NNw8EOd8dDWD0dzydYHS01MpZoUcQXB4g==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/final-form": {
|
||||
"version": "4.20.6",
|
||||
"resolved": "https://registry.npmjs.org/final-form/-/final-form-4.20.6.tgz",
|
||||
"integrity": "sha512-fCdwIj49KOaFfDRlXB57Eo+GghIMZQWrA9TakQI3C9uQxHwaFHXqZSNRlUdfnQmNNeySwGOaGPZCvjy58hyv4w==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/final-form"
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/history": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
|
||||
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"loose-envify": "^1.2.0",
|
||||
"resolve-pathname": "^3.0.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0",
|
||||
"value-equal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"dependencies": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
|
||||
"bin": {
|
||||
"jsesc": "bin/jsesc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mini-create-react-context": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
|
||||
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"tiny-warning": "^1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prop-types": "^15.0.0",
|
||||
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
|
||||
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
|
||||
"dependencies": {
|
||||
"isarray": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-value-parser": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"scheduler": "^0.20.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-final-form": {
|
||||
"version": "6.5.7",
|
||||
"resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-6.5.7.tgz",
|
||||
"integrity": "sha512-o7tvJXB+McGiXOILqIC8lnOcX4aLhIBiF/Xi9Qet35b7XOS8R7KL8HLRKTfnZWQJm6MCE15v1U0SFive0NcxyA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/final-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"final-form": "4.20.4",
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-final-form/node_modules/@babel/runtime": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
|
||||
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
|
||||
"integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"history": "^4.9.0",
|
||||
"hoist-non-react-statics": "^3.1.0",
|
||||
"loose-envify": "^1.3.1",
|
||||
"mini-create-react-context": "^0.4.0",
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-is": "^16.6.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
|
||||
"integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"history": "^4.9.0",
|
||||
"loose-envify": "^1.3.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-router": "5.2.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"node_modules/resolve-pathname": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
|
||||
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/shallowequal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-components": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz",
|
||||
"integrity": "sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@babel/traverse": "^7.4.5",
|
||||
"@emotion/is-prop-valid": "^0.8.8",
|
||||
"@emotion/stylis": "^0.8.4",
|
||||
"@emotion/unitless": "^0.7.4",
|
||||
"babel-plugin-styled-components": ">= 1.12.0",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"shallowequal": "^1.1.0",
|
||||
"supports-color": "^5.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/styled-components"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0",
|
||||
"react-dom": ">= 16.8.0",
|
||||
"react-is": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
|
||||
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
|
||||
},
|
||||
"node_modules/tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
|
||||
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/value-equal": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
|
||||
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@authorizerdev/authorizer-js": {
|
||||
"version": "0.2.1",
|
||||
|
@@ -259,17 +259,6 @@ const InputField = ({
|
||||
);
|
||||
}
|
||||
if (Object.values(SelectInputType).includes(inputType)) {
|
||||
if (inputType === SelectInputType.JWT_TYPE) {
|
||||
return (
|
||||
<Select size="sm" {...props}>
|
||||
{[variables[inputType]].map((value: string) => (
|
||||
<option value="value" key={value}>
|
||||
{value}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
const { options, ...rest } = props;
|
||||
return (
|
||||
<Select
|
||||
@@ -293,10 +282,18 @@ const InputField = ({
|
||||
<Textarea
|
||||
{...props}
|
||||
size="lg"
|
||||
value={inputData[inputType]}
|
||||
onChange={(e: any) => {
|
||||
setInputData({ ...inputData, [inputType]: e.target.value });
|
||||
}}
|
||||
fontSize={14}
|
||||
value={variables[inputType] ? variables[inputType] : ''}
|
||||
onChange={(
|
||||
event: Event & {
|
||||
target: HTMLInputElement;
|
||||
}
|
||||
) =>
|
||||
setVariables({
|
||||
...variables,
|
||||
[inputType]: event.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -40,9 +40,9 @@ interface LinkItemProps {
|
||||
route: string;
|
||||
}
|
||||
const LinkItems: Array<LinkItemProps> = [
|
||||
{ name: 'Home', icon: FiHome, route: '/' },
|
||||
// { name: 'Home', icon: FiHome, route: '/' },
|
||||
{ name: 'Environment Variables', icon: FiSettings, route: '/' },
|
||||
{ name: 'Users', icon: FiUsers, route: '/users' },
|
||||
{ name: 'Environment Variables', icon: FiSettings, route: '/environment' },
|
||||
];
|
||||
|
||||
interface SidebarProps extends BoxProps {
|
||||
|
@@ -49,6 +49,8 @@ export const SelectInputType = {
|
||||
|
||||
export const TextAreaInputType = {
|
||||
CUSTOM_ACCESS_TOKEN_SCRIPT: 'CUSTOM_ACCESS_TOKEN_SCRIPT',
|
||||
JWT_PRIVATE_KEY: 'JWT_PRIVATE_KEY',
|
||||
JWT_PUBLIC_KEY: 'JWT_PUBLIC_KEY',
|
||||
};
|
||||
|
||||
export const SwitchInputType = {
|
||||
@@ -66,3 +68,21 @@ export const ArrayInputOperations = {
|
||||
APPEND: 'APPEND',
|
||||
REMOVE: 'REMOVE',
|
||||
};
|
||||
|
||||
export const HMACEncryptionType = {
|
||||
HS256: 'HS256',
|
||||
HS384: 'HS384',
|
||||
HS512: 'HS512',
|
||||
};
|
||||
|
||||
export const RSAEncryptionType = {
|
||||
RS256: 'RS256',
|
||||
RS384: 'RS384',
|
||||
RS512: 'RS512',
|
||||
};
|
||||
|
||||
export const ECDSAEncryptionType = {
|
||||
ES256: 'ES256',
|
||||
ES384: 'ES384',
|
||||
ES512: 'ES512',
|
||||
};
|
||||
|
@@ -21,6 +21,8 @@ export const EnvVariablesQuery = `
|
||||
JWT_TYPE,
|
||||
JWT_SECRET,
|
||||
JWT_ROLE_CLAIM,
|
||||
JWT_PRIVATE_KEY,
|
||||
JWT_PUBLIC_KEY,
|
||||
REDIS_URL,
|
||||
SMTP_HOST,
|
||||
SMTP_PORT,
|
||||
|
@@ -73,17 +73,25 @@ export default function Auth() {
|
||||
fontWeight="bold"
|
||||
mb="2"
|
||||
>
|
||||
Hi there 👋 <br />
|
||||
Hello Admin 👋 <br />
|
||||
</Text>
|
||||
<Text fontSize="large" textAlign="center" color="gray.500" mb="8">
|
||||
Welcome to Authorizer Administrative Dashboard
|
||||
Welcome to Admin Dashboard
|
||||
</Text>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<VStack spacing="5" justify="space-between">
|
||||
<FormControl isRequired>
|
||||
{/* <FormLabel htmlFor="admin-secret">
|
||||
{isLogin ? 'Enter' : 'Configure'} Admin Secret
|
||||
</FormLabel> */}
|
||||
<FormLabel htmlFor="admin-username">Username</FormLabel>
|
||||
<Input
|
||||
size="lg"
|
||||
id="admin-username"
|
||||
placeholder="Username"
|
||||
disabled
|
||||
value="admin"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl isRequired>
|
||||
<FormLabel htmlFor="admin-secret">Password</FormLabel>
|
||||
<Input
|
||||
size="lg"
|
||||
id="admin-secret"
|
||||
@@ -111,10 +119,7 @@ export default function Auth() {
|
||||
</Text>
|
||||
) : (
|
||||
<Text color="gray.600" fontSize="sm">
|
||||
<b>Note:</b> You can also configure admin secret by setting{' '}
|
||||
<code>ADMIN_SECRET</code> environment variable. For more
|
||||
information, please refer to the{' '}
|
||||
<a href="https://docs.authorizer.dev/core/env/">documentation</a>.
|
||||
<b>Note:</b> Configure the password to start using your dashboard.
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
|
@@ -31,6 +31,9 @@ import {
|
||||
TextInputType,
|
||||
TextAreaInputType,
|
||||
SwitchInputType,
|
||||
HMACEncryptionType,
|
||||
RSAEncryptionType,
|
||||
ECDSAEncryptionType,
|
||||
} from '../constants';
|
||||
import { UpdateEnvVariables } from '../graphql/mutation';
|
||||
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
||||
@@ -48,6 +51,8 @@ interface envVarTypes {
|
||||
JWT_TYPE: string;
|
||||
JWT_SECRET: string;
|
||||
JWT_ROLE_CLAIM: string;
|
||||
JWT_PRIVATE_KEY: string;
|
||||
JWT_PUBLIC_KEY: string;
|
||||
REDIS_URL: string;
|
||||
SMTP_HOST: string;
|
||||
SMTP_PORT: string;
|
||||
@@ -92,6 +97,8 @@ export default function Environment() {
|
||||
JWT_TYPE: '',
|
||||
JWT_SECRET: '',
|
||||
JWT_ROLE_CLAIM: '',
|
||||
JWT_PRIVATE_KEY: '',
|
||||
JWT_PUBLIC_KEY: '',
|
||||
REDIS_URL: '',
|
||||
SMTP_HOST: '',
|
||||
SMTP_PORT: '',
|
||||
@@ -177,7 +184,6 @@ export default function Environment() {
|
||||
const {
|
||||
data: { _env: envData },
|
||||
} = await client.query(EnvVariablesQuery).toPromise();
|
||||
|
||||
const diff = getObjectDiff(envVariables, envData);
|
||||
const updatedEnvVariables = diff.reduce(
|
||||
(acc: any, property: string) => ({
|
||||
@@ -374,39 +380,67 @@ export default function Environment() {
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Type:</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<Flex w="100%" justifyContent="space-between">
|
||||
<Flex flex="2">
|
||||
<InputField
|
||||
variables={envVariables}
|
||||
setVariables={setEnvVariables}
|
||||
inputType={SelectInputType.JWT_TYPE}
|
||||
isDisabled={true}
|
||||
defaultValue={SelectInputType.JWT_TYPE}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex flex="3" justifyContent="center" alignItems="center">
|
||||
<Text fontSize="sm">
|
||||
More JWT types will be enabled in upcoming releases.
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Center>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Secret</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<Flex w="70%">
|
||||
<InputField
|
||||
variables={envVariables}
|
||||
setVariables={setEnvVariables}
|
||||
fieldVisibility={fieldVisibility}
|
||||
setFieldVisibility={setFieldVisibility}
|
||||
inputType={HiddenInputType.JWT_SECRET}
|
||||
inputType={SelectInputType.JWT_TYPE}
|
||||
value={SelectInputType.JWT_TYPE}
|
||||
options={{
|
||||
...HMACEncryptionType,
|
||||
...RSAEncryptionType,
|
||||
...ECDSAEncryptionType,
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
</Flex>
|
||||
</Flex>
|
||||
{Object.values(HMACEncryptionType).includes(envVariables.JWT_TYPE) ? (
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Secret</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
variables={envVariables}
|
||||
setVariables={setEnvVariables}
|
||||
fieldVisibility={fieldVisibility}
|
||||
setFieldVisibility={setFieldVisibility}
|
||||
inputType={HiddenInputType.JWT_SECRET}
|
||||
/>
|
||||
</Center>
|
||||
</Flex>
|
||||
) : (
|
||||
<>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Public Key</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
variables={envVariables}
|
||||
setVariables={setEnvVariables}
|
||||
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
||||
placeholder="Add public key here"
|
||||
minH="25vh"
|
||||
/>
|
||||
</Center>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Private Key</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
variables={envVariables}
|
||||
setVariables={setEnvVariables}
|
||||
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
||||
placeholder="Add private key here"
|
||||
minH="25vh"
|
||||
/>
|
||||
</Center>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Role Claim:</Text>
|
||||
@@ -457,7 +491,7 @@ export default function Environment() {
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Port:</Text>
|
||||
<Text fontSize="sm">SMTP Port:</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
@@ -469,7 +503,7 @@ export default function Environment() {
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Username:</Text>
|
||||
<Text fontSize="sm">SMTP Username:</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
@@ -481,7 +515,7 @@ export default function Environment() {
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Password:</Text>
|
||||
<Text fontSize="sm">SMTP Password:</Text>
|
||||
</Flex>
|
||||
<Center w="70%">
|
||||
<InputField
|
||||
@@ -556,7 +590,7 @@ export default function Environment() {
|
||||
</Stack>
|
||||
<Divider marginTop="2%" marginBottom="2%" />
|
||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||
Custom Scripts
|
||||
Custom Access Token Scripts
|
||||
</Text>
|
||||
<Stack spacing={6} padding="2% 0%">
|
||||
<Flex>
|
||||
|
@@ -23,7 +23,7 @@ export const AppRoutes = () => {
|
||||
</DashboardLayout>
|
||||
}
|
||||
>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/" element={<Environment />} />
|
||||
<Route path="users" element={<Users />} />
|
||||
<Route path="environment" element={<Environment />} />
|
||||
<Route path="*" element={<Home />} />
|
||||
|
@@ -13,4 +13,8 @@ const (
|
||||
DbTypeArangodb = "arangodb"
|
||||
// DbTypeMongodb is the mongodb database type
|
||||
DbTypeMongodb = "mongodb"
|
||||
// DbTypeYugabyte is the yugabyte database type
|
||||
DbTypeYugabyte = "yugabyte"
|
||||
// DbTypeMariaDB is the mariadb database type
|
||||
DbTypeMariaDB = "mariadb"
|
||||
)
|
||||
|
@@ -43,6 +43,10 @@ const (
|
||||
EnvKeyJwtType = "JWT_TYPE"
|
||||
// EnvKeyJwtSecret key for env variable JWT_SECRET
|
||||
EnvKeyJwtSecret = "JWT_SECRET"
|
||||
// EnvKeyJwtPrivateKey key for env variable JWT_PRIVATE_KEY
|
||||
EnvKeyJwtPrivateKey = "JWT_PRIVATE_KEY"
|
||||
// EnvKeyJwtPublicKey key for env variable JWT_PUBLIC_KEY
|
||||
EnvKeyJwtPublicKey = "JWT_PUBLIC_KEY"
|
||||
// EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS
|
||||
EnvKeyAllowedOrigins = "ALLOWED_ORIGINS"
|
||||
// EnvKeyAppURL key for env variable APP_URL
|
||||
|
@@ -1,6 +1,10 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
@@ -9,6 +13,7 @@ import (
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/driver/sqlserver"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
@@ -20,26 +25,31 @@ type provider struct {
|
||||
func NewProvider() (*provider, error) {
|
||||
var sqlDB *gorm.DB
|
||||
var err error
|
||||
customLogger := logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // Slow SQL threshold
|
||||
LogLevel: logger.Silent, // Log level
|
||||
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
|
||||
Colorful: false, // Disable color
|
||||
},
|
||||
)
|
||||
|
||||
ormConfig := &gorm.Config{
|
||||
Logger: customLogger,
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
TablePrefix: models.Prefix,
|
||||
},
|
||||
}
|
||||
|
||||
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
||||
case constants.DbTypePostgres:
|
||||
case constants.DbTypePostgres, constants.DbTypeYugabyte:
|
||||
sqlDB, err = gorm.Open(postgres.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||
break
|
||||
case constants.DbTypeSqlite:
|
||||
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||
break
|
||||
case constants.DbTypeMysql:
|
||||
case constants.DbTypeMysql, constants.DbTypeMariaDB:
|
||||
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||
break
|
||||
case constants.DbTypeSqlserver:
|
||||
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
83
server/env/env.go
vendored
83
server/env/env.go
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
@@ -18,14 +19,14 @@ func InitEnv() {
|
||||
envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
||||
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv("ENV")
|
||||
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
|
||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
||||
envData.StringEnv[constants.EnvKeyEnv] = "production"
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyEnv] == "production" {
|
||||
envData.BoolEnv[constants.EnvKeyIsProd] = true
|
||||
os.Setenv("GIN_MODE", "release")
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
} else {
|
||||
envData.BoolEnv[constants.EnvKeyIsProd] = false
|
||||
}
|
||||
@@ -45,22 +46,22 @@ func InitEnv() {
|
||||
|
||||
err := godotenv.Load(envData.StringEnv[constants.EnvKeyEnvPath])
|
||||
if err != nil {
|
||||
log.Printf("error loading %s file", envData.StringEnv[constants.EnvKeyEnvPath])
|
||||
log.Printf("using OS env instead of %s file", envData.StringEnv[constants.EnvKeyEnvPath])
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
||||
envData.StringEnv[constants.EnvKeyPort] = os.Getenv("PORT")
|
||||
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
|
||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
||||
envData.StringEnv[constants.EnvKeyPort] = "8080"
|
||||
}
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyAdminSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv("ADMIN_SECRET")
|
||||
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv(constants.EnvKeyAdminSecret)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyDatabaseType] == "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv("DATABASE_TYPE")
|
||||
envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv(constants.EnvKeyDatabaseType)
|
||||
|
||||
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseType] = *envstore.ARG_DB_TYPE
|
||||
@@ -72,7 +73,7 @@ func InitEnv() {
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv("DATABASE_URL")
|
||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv(constants.EnvKeyDatabaseURL)
|
||||
|
||||
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = *envstore.ARG_DB_URL
|
||||
@@ -84,48 +85,56 @@ func InitEnv() {
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv("DATABASE_NAME")
|
||||
envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv(constants.EnvKeyDatabaseName)
|
||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
||||
envData.StringEnv[constants.EnvKeyDatabaseName] = "authorizer"
|
||||
}
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeySmtpHost] == "" {
|
||||
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv("SMTP_HOST")
|
||||
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv(constants.EnvKeySmtpHost)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeySmtpPort] == "" {
|
||||
envData.StringEnv[constants.EnvKeySmtpPort] = os.Getenv("SMTP_PORT")
|
||||
envData.StringEnv[constants.EnvKeySmtpPort] = os.Getenv(constants.EnvKeySmtpPort)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeySmtpUsername] == "" {
|
||||
envData.StringEnv[constants.EnvKeySmtpUsername] = os.Getenv("SMTP_USERNAME")
|
||||
envData.StringEnv[constants.EnvKeySmtpUsername] = os.Getenv(constants.EnvKeySmtpUsername)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeySmtpPassword] == "" {
|
||||
envData.StringEnv[constants.EnvKeySmtpPassword] = os.Getenv("SMTP_PASSWORD")
|
||||
envData.StringEnv[constants.EnvKeySmtpPassword] = os.Getenv(constants.EnvKeySmtpPassword)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeySenderEmail] == "" {
|
||||
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv("SENDER_EMAIL")
|
||||
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv("JWT_SECRET")
|
||||
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
|
||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtSecret] = uuid.New().String()
|
||||
}
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = os.Getenv(constants.EnvKeyJwtPrivateKey)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtPublicKey] = os.Getenv(constants.EnvKeyJwtPublicKey)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv("JWT_TYPE")
|
||||
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
|
||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtType] = "HS256"
|
||||
}
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv("JWT_ROLE_CLAIM")
|
||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv(constants.EnvKeyJwtRoleClaim)
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = "role"
|
||||
@@ -133,48 +142,48 @@ func InitEnv() {
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyRedisURL] == "" {
|
||||
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv("REDIS_URL")
|
||||
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv(constants.EnvKeyRedisURL)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyCookieName] == "" {
|
||||
envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv("COOKIE_NAME")
|
||||
envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv(constants.EnvKeyCookieName)
|
||||
if envData.StringEnv[constants.EnvKeyCookieName] == "" {
|
||||
envData.StringEnv[constants.EnvKeyCookieName] = "authorizer"
|
||||
}
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyGoogleClientID] == "" {
|
||||
envData.StringEnv[constants.EnvKeyGoogleClientID] = os.Getenv("GOOGLE_CLIENT_ID")
|
||||
envData.StringEnv[constants.EnvKeyGoogleClientID] = os.Getenv(constants.EnvKeyGoogleClientID)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyGoogleClientSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyGoogleClientSecret] = os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||
envData.StringEnv[constants.EnvKeyGoogleClientSecret] = os.Getenv(constants.EnvKeyGoogleClientSecret)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyGithubClientID] == "" {
|
||||
envData.StringEnv[constants.EnvKeyGithubClientID] = os.Getenv("GITHUB_CLIENT_ID")
|
||||
envData.StringEnv[constants.EnvKeyGithubClientID] = os.Getenv(constants.EnvKeyGithubClientID)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyGithubClientSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyGithubClientSecret] = os.Getenv("GITHUB_CLIENT_SECRET")
|
||||
envData.StringEnv[constants.EnvKeyGithubClientSecret] = os.Getenv(constants.EnvKeyGithubClientSecret)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyFacebookClientID] == "" {
|
||||
envData.StringEnv[constants.EnvKeyFacebookClientID] = os.Getenv("FACEBOOK_CLIENT_ID")
|
||||
envData.StringEnv[constants.EnvKeyFacebookClientID] = os.Getenv(constants.EnvKeyFacebookClientID)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyFacebookClientSecret] == "" {
|
||||
envData.StringEnv[constants.EnvKeyFacebookClientSecret] = os.Getenv("FACEBOOK_CLIENT_SECRET")
|
||||
envData.StringEnv[constants.EnvKeyFacebookClientSecret] = os.Getenv(constants.EnvKeyFacebookClientSecret)
|
||||
}
|
||||
|
||||
if envData.StringEnv[constants.EnvKeyResetPasswordURL] == "" {
|
||||
envData.StringEnv[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/")
|
||||
envData.StringEnv[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv(constants.EnvKeyResetPasswordURL), "/")
|
||||
}
|
||||
|
||||
envData.BoolEnv[constants.EnvKeyDisableBasicAuthentication] = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableLoginPage] = os.Getenv("DISABLE_LOGIN_PAGE") == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableBasicAuthentication] = os.Getenv(constants.EnvKeyDisableBasicAuthentication) == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = os.Getenv(constants.EnvKeyDisableEmailVerification) == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv(constants.EnvKeyDisableMagicLinkLogin) == "true"
|
||||
envData.BoolEnv[constants.EnvKeyDisableLoginPage] = os.Getenv(constants.EnvKeyDisableLoginPage) == "true"
|
||||
|
||||
// no need to add nil check as its already done above
|
||||
if envData.StringEnv[constants.EnvKeySmtpHost] == "" || envData.StringEnv[constants.EnvKeySmtpUsername] == "" || envData.StringEnv[constants.EnvKeySmtpPassword] == "" || envData.StringEnv[constants.EnvKeySenderEmail] == "" && envData.StringEnv[constants.EnvKeySmtpPort] == "" {
|
||||
@@ -186,7 +195,7 @@ func InitEnv() {
|
||||
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||
}
|
||||
|
||||
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
|
||||
allowedOriginsSplit := strings.Split(os.Getenv(constants.EnvKeyAllowedOrigins), ",")
|
||||
allowedOrigins := []string{}
|
||||
hasWildCard := false
|
||||
|
||||
@@ -214,14 +223,14 @@ func InitEnv() {
|
||||
|
||||
envData.SliceEnv[constants.EnvKeyAllowedOrigins] = allowedOrigins
|
||||
|
||||
rolesEnv := strings.TrimSpace(os.Getenv("ROLES"))
|
||||
rolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyRoles))
|
||||
rolesSplit := strings.Split(rolesEnv, ",")
|
||||
roles := []string{}
|
||||
if len(rolesEnv) == 0 {
|
||||
roles = []string{"user"}
|
||||
}
|
||||
|
||||
defaultRolesEnv := strings.TrimSpace(os.Getenv("DEFAULT_ROLES"))
|
||||
defaultRolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyDefaultRoles))
|
||||
defaultRoleSplit := strings.Split(defaultRolesEnv, ",")
|
||||
defaultRoles := []string{}
|
||||
|
||||
@@ -229,7 +238,7 @@ func InitEnv() {
|
||||
defaultRoles = []string{"user"}
|
||||
}
|
||||
|
||||
protectedRolesEnv := strings.TrimSpace(os.Getenv("PROTECTED_ROLES"))
|
||||
protectedRolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyProtectedRoles))
|
||||
protectedRolesSplit := strings.Split(protectedRolesEnv, ",")
|
||||
protectedRoles := []string{}
|
||||
|
||||
@@ -258,12 +267,12 @@ func InitEnv() {
|
||||
envData.SliceEnv[constants.EnvKeyDefaultRoles] = defaultRoles
|
||||
envData.SliceEnv[constants.EnvKeyProtectedRoles] = protectedRoles
|
||||
|
||||
if os.Getenv("ORGANIZATION_NAME") != "" {
|
||||
envData.StringEnv[constants.EnvKeyOrganizationName] = os.Getenv("ORGANIZATION_NAME")
|
||||
if os.Getenv(constants.EnvKeyOrganizationName) != "" {
|
||||
envData.StringEnv[constants.EnvKeyOrganizationName] = os.Getenv(constants.EnvKeyOrganizationName)
|
||||
}
|
||||
|
||||
if os.Getenv("ORGANIZATION_LOGO") != "" {
|
||||
envData.StringEnv[constants.EnvKeyOrganizationLogo] = os.Getenv("ORGANIZATION_LOGO")
|
||||
if os.Getenv(constants.EnvKeyOrganizationLogo) != "" {
|
||||
envData.StringEnv[constants.EnvKeyOrganizationLogo] = os.Getenv(constants.EnvKeyOrganizationLogo)
|
||||
}
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(envData)
|
||||
|
@@ -70,6 +70,8 @@ type ComplexityRoot struct {
|
||||
GithubClientSecret func(childComplexity int) int
|
||||
GoogleClientID func(childComplexity int) int
|
||||
GoogleClientSecret func(childComplexity int) int
|
||||
JwtPrivateKey func(childComplexity int) int
|
||||
JwtPublicKey func(childComplexity int) int
|
||||
JwtRoleClaim func(childComplexity int) int
|
||||
JwtSecret func(childComplexity int) int
|
||||
JwtType func(childComplexity int) int
|
||||
@@ -391,6 +393,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Env.GoogleClientSecret(childComplexity), true
|
||||
|
||||
case "Env.JWT_PRIVATE_KEY":
|
||||
if e.complexity.Env.JwtPrivateKey == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Env.JwtPrivateKey(childComplexity), true
|
||||
|
||||
case "Env.JWT_PUBLIC_KEY":
|
||||
if e.complexity.Env.JwtPublicKey == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Env.JwtPublicKey(childComplexity), true
|
||||
|
||||
case "Env.JWT_ROLE_CLAIM":
|
||||
if e.complexity.Env.JwtRoleClaim == nil {
|
||||
break
|
||||
@@ -1206,6 +1222,8 @@ type Env {
|
||||
SENDER_EMAIL: String
|
||||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
JWT_PRIVATE_KEY: String
|
||||
JWT_PUBLIC_KEY: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
@@ -1240,6 +1258,8 @@ input UpdateEnvInput {
|
||||
SENDER_EMAIL: String
|
||||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
JWT_PRIVATE_KEY: String
|
||||
JWT_PUBLIC_KEY: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
@@ -2229,6 +2249,70 @@ func (ec *executionContext) _Env_JWT_SECRET(ctx context.Context, field graphql.C
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_JWT_PRIVATE_KEY(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Env",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.JwtPrivateKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_JWT_PUBLIC_KEY(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Env",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.JwtPublicKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_ALLOWED_ORIGINS(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -7044,6 +7128,22 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "JWT_PRIVATE_KEY":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("JWT_PRIVATE_KEY"))
|
||||
it.JwtPrivateKey, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "JWT_PUBLIC_KEY":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("JWT_PUBLIC_KEY"))
|
||||
it.JwtPublicKey, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "ALLOWED_ORIGINS":
|
||||
var err error
|
||||
|
||||
@@ -7539,6 +7639,10 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
|
||||
out.Values[i] = ec._Env_JWT_TYPE(ctx, field, obj)
|
||||
case "JWT_SECRET":
|
||||
out.Values[i] = ec._Env_JWT_SECRET(ctx, field, obj)
|
||||
case "JWT_PRIVATE_KEY":
|
||||
out.Values[i] = ec._Env_JWT_PRIVATE_KEY(ctx, field, obj)
|
||||
case "JWT_PUBLIC_KEY":
|
||||
out.Values[i] = ec._Env_JWT_PUBLIC_KEY(ctx, field, obj)
|
||||
case "ALLOWED_ORIGINS":
|
||||
out.Values[i] = ec._Env_ALLOWED_ORIGINS(ctx, field, obj)
|
||||
case "APP_URL":
|
||||
|
@@ -34,6 +34,8 @@ type Env struct {
|
||||
SenderEmail *string `json:"SENDER_EMAIL"`
|
||||
JwtType *string `json:"JWT_TYPE"`
|
||||
JwtSecret *string `json:"JWT_SECRET"`
|
||||
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
||||
JwtPublicKey *string `json:"JWT_PUBLIC_KEY"`
|
||||
AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
|
||||
AppURL *string `json:"APP_URL"`
|
||||
RedisURL *string `json:"REDIS_URL"`
|
||||
@@ -153,6 +155,8 @@ type UpdateEnvInput struct {
|
||||
SenderEmail *string `json:"SENDER_EMAIL"`
|
||||
JwtType *string `json:"JWT_TYPE"`
|
||||
JwtSecret *string `json:"JWT_SECRET"`
|
||||
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
||||
JwtPublicKey *string `json:"JWT_PUBLIC_KEY"`
|
||||
AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
|
||||
AppURL *string `json:"APP_URL"`
|
||||
RedisURL *string `json:"REDIS_URL"`
|
||||
|
@@ -97,6 +97,8 @@ type Env {
|
||||
SENDER_EMAIL: String
|
||||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
JWT_PRIVATE_KEY: String
|
||||
JWT_PUBLIC_KEY: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
@@ -131,6 +133,8 @@ input UpdateEnvInput {
|
||||
SENDER_EMAIL: String
|
||||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
JWT_PRIVATE_KEY: String
|
||||
JWT_PUBLIC_KEY: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
|
15
server/handlers/health.go
Normal file
15
server/handlers/health.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// HealthHandler is the handler for /health route.
|
||||
// It states if server is in healthy state or not
|
||||
func HealthHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "OK")
|
||||
}
|
||||
}
|
@@ -96,8 +96,8 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
if !strings.Contains(signupMethod, provider) {
|
||||
signupMethod = signupMethod + "," + provider
|
||||
}
|
||||
user = existingUser
|
||||
user.SignupMethods = signupMethod
|
||||
user.Password = existingUser.Password
|
||||
|
||||
if user.EmailVerifiedAt == nil {
|
||||
now := time.Now().Unix()
|
||||
@@ -136,12 +136,13 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
} else {
|
||||
user.Roles = existingUser.Roles
|
||||
}
|
||||
user.Key = existingUser.Key
|
||||
user.ID = existingUser.ID
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
}
|
||||
|
||||
user, _ = db.Provider.GetUserByEmail(user.Email)
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
authToken, _ := token.CreateAuthToken(user, inputRoles)
|
||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
|
@@ -33,13 +33,13 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
||||
}
|
||||
|
||||
// verify if token exists in db
|
||||
claim, err := token.VerifyVerificationToken(tokenInQuery)
|
||||
claim, err := token.ParseJWTToken(tokenInQuery)
|
||||
if err != nil {
|
||||
c.JSON(400, errorRes)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(claim.Email)
|
||||
user, err := db.Provider.GetUserByEmail(claim["email"].(string))
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"message": err.Error(),
|
||||
@@ -68,6 +68,6 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
||||
cookie.SetCookie(c, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
||||
utils.SaveSessionInDB(user.ID, c)
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
||||
c.Redirect(http.StatusTemporaryRedirect, claim["redirect_url"].(string))
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,8 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
||||
jwtType := store.StringEnv[constants.EnvKeyJwtType]
|
||||
jwtSecret := store.StringEnv[constants.EnvKeyJwtSecret]
|
||||
jwtRoleClaim := store.StringEnv[constants.EnvKeyJwtRoleClaim]
|
||||
jwtPublicKey := store.StringEnv[constants.EnvKeyJwtPublicKey]
|
||||
jwtPrivateKey := store.StringEnv[constants.EnvKeyJwtPrivateKey]
|
||||
allowedOrigins := store.SliceEnv[constants.EnvKeyAllowedOrigins]
|
||||
appURL := store.StringEnv[constants.EnvKeyAppURL]
|
||||
redisURL := store.StringEnv[constants.EnvKeyRedisURL]
|
||||
@@ -74,6 +76,8 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
||||
SenderEmail: &senderEmail,
|
||||
JwtType: &jwtType,
|
||||
JwtSecret: &jwtSecret,
|
||||
JwtPrivateKey: &jwtPrivateKey,
|
||||
JwtPublicKey: &jwtPublicKey,
|
||||
JwtRoleClaim: &jwtRoleClaim,
|
||||
AllowedOrigins: allowedOrigins,
|
||||
AppURL: &appURL,
|
||||
|
@@ -26,7 +26,7 @@ func IsValidJwtResolver(ctx context.Context, params *model.IsValidJWTQueryInput)
|
||||
}
|
||||
}
|
||||
|
||||
claims, err := tokenHelper.VerifyJWTToken(token)
|
||||
claims, err := tokenHelper.ParseJWTToken(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ func LogoutResolver(ctx context.Context) (*model.Response, error) {
|
||||
fingerPrint := string(decryptedFingerPrint)
|
||||
|
||||
// verify refresh token and fingerprint
|
||||
claims, err := token.VerifyJWTToken(refreshToken)
|
||||
claims, err := token.ParseJWTToken(refreshToken)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@@ -31,12 +31,12 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
||||
}
|
||||
|
||||
// verify if token exists in db
|
||||
claim, err := token.VerifyVerificationToken(params.Token)
|
||||
claim, err := token.ParseJWTToken(params.Token)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf(`invalid token`)
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(claim.Email)
|
||||
user, err := db.Provider.GetUserByEmail(claim["email"].(string))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
||||
fingerPrint := string(decryptedFingerPrint)
|
||||
|
||||
// verify refresh token and fingerprint
|
||||
claims, err := token.VerifyJWTToken(refreshToken)
|
||||
claims, err := token.ParseJWTToken(refreshToken)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@@ -28,12 +28,12 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
||||
}
|
||||
|
||||
// verify if token exists in db
|
||||
claim, err := token.VerifyVerificationToken(params.Token)
|
||||
claim, err := token.ParseJWTToken(params.Token)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf(`invalid token`)
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(claim.Email)
|
||||
user, err := db.Provider.GetUserByEmail(claim["email"].(string))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ func InitRouter() *gin.Engine {
|
||||
router.Use(middlewares.CORSMiddleware())
|
||||
|
||||
router.GET("/", handlers.RootHandler())
|
||||
router.GET("/health", handlers.HealthHandler())
|
||||
router.POST("/graphql", handlers.GraphqlHandler())
|
||||
router.GET("/playground", handlers.PlaygroundHandler())
|
||||
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||
|
@@ -138,7 +138,6 @@ func InitSession() {
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Println("using in memory store to save sessions")
|
||||
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
|
||||
store: map[string]map[string]string{},
|
||||
socialLoginState: map[string]string{},
|
||||
|
143
server/test/jwt_test.go
Normal file
143
server/test/jwt_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJwt(t *testing.T) {
|
||||
claims := jwt.MapClaims{
|
||||
"exp": time.Now().Add(time.Minute * 30).Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
"email": "test@yopmail.com",
|
||||
}
|
||||
|
||||
// persist older data till test is done and then reset it
|
||||
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||
jwtSecret := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
|
||||
|
||||
t.Run("invalid jwt type", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "invalid")
|
||||
token, err := token.SignJWTToken(claims)
|
||||
assert.Error(t, err, "unsupported signing method")
|
||||
assert.Empty(t, token)
|
||||
})
|
||||
t.Run("expired jwt token", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
|
||||
expiredClaims := jwt.MapClaims{
|
||||
"exp": time.Now().Add(-time.Minute * 30).Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
"email": "test@yopmail.com",
|
||||
}
|
||||
jwtToken, err := token.SignJWTToken(expiredClaims)
|
||||
assert.NoError(t, err)
|
||||
_, err = token.ParseJWTToken(jwtToken)
|
||||
assert.Error(t, err, err.Error(), "Token is expired")
|
||||
})
|
||||
t.Run("HMAC algorithms", func(t *testing.T) {
|
||||
t.Run("HS256", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("HS384", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS384")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("HS512", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS512")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("RSA algorithms", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN RSA PRIVATE KEY-----\nMIICWgIBAAKBgHUQac/v0f3c8m4L9BMWfxBiEzkdV5CoaqfxhO5IwAX/1cs0WceN\njM7g/qzC7YmEOSiYqupiRtsyn6riz0xT/VUg4uv1uZ/muC6EVfOjR5Ack3Brquql\nD+oMxN4CeA0Wzp2dEV4N3Gv7wWHdhg9ZSc4g6+ZUdlkhIPfeO9RNK9pPAgMBAAEC\ngYBqLrIbp0dNQn0vbm48ZhppDNys4L2NfAYKQZs23Aw5JN6Si/CnffBrsk+u+ryl\nEKcb+KaHJQ9qQdfsFAC+FizhMQy0Dq9yw6shnqHX+paB6E6z2/vX8ToPzJRwxBY3\nyuaetCEpSXR7pQEd5YWDTUH7qYnb9FObD+umhVvmlsTHCQJBALagPmexu0DvMXKZ\nWdplik6eXg9lptiuj5MYqitEUyzU9E9HNeHKlZM7szGeWG3jNduoKcyo4M0Flvt9\ncP+soVUCQQCkGOQ5Y3/GoZmclKWMVwqGdmL6wEjhNfg4PRfgUalHBif9Q1KnM8FP\nAvIqIH8bttRfyT185WmaM2gml0ApwF0TAkBVil9QoK4t7xvBKtUsd809n+481gc9\njR4Q70edtoYjBKhejeNOHF7NNPRtNFcFOZybg3v4sc2CGrEqoQoRp+F1AkBeLmMe\nhPrbF/jAI5h4WaSS0/OvExlBGOaj8Hx5pKTRPLlK5I7VpCC4pmoyv3/0ehSd/TQr\nMMhRVlvaeki7Lcq9AkBravJUadVCAIsB6oh03mo8gUFFFqXDyEl6BiJYqrjCQ5wd\nAQYJGbqQvgjPxN9+PTPldDNi6KVXntSg5gF/dA+Z\n-----END RSA PRIVATE KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHUQac/v0f3c8m4L9BMWfxBiEzkd\nV5CoaqfxhO5IwAX/1cs0WceNjM7g/qzC7YmEOSiYqupiRtsyn6riz0xT/VUg4uv1\nuZ/muC6EVfOjR5Ack3BrquqlD+oMxN4CeA0Wzp2dEV4N3Gv7wWHdhg9ZSc4g6+ZU\ndlkhIPfeO9RNK9pPAgMBAAE=\n-----END PUBLIC KEY-----")
|
||||
t.Run("RS256", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS256")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("RS384", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS384")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("RS512", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS512")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ECDSA algorithms", func(t *testing.T) {
|
||||
t.Run("ES256", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2\nOF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r\n1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G\n-----END PRIVATE KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9\nq9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==\n-----END PUBLIC KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES256")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("ES384", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCAHpFQ62QnGCEvYh/p\nE9QmR1C9aLcDItRbslbmhen/h1tt8AyMhskeenT+rAyyPhGhZANiAAQLW5ZJePZz\nMIPAxMtZXkEWbDF0zo9f2n4+T1h/2sh/fviblc/VTyrv10GEtIi5qiOy85Pf1RRw\n8lE5IPUWpgu553SteKigiKLUPeNpbqmYZUkWGh3MLfVzLmx85ii2vMU=\n-----END PRIVATE KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+\nPk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii\n1D3jaW6pmGVJFhodzC31cy5sfOYotrzF\n-----END PUBLIC KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES384")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
t.Run("ES512", func(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBiyAa7aRHFDCh2qga\n9sTUGINE5jHAFnmM8xWeT/uni5I4tNqhV5Xx0pDrmCV9mbroFtfEa0XVfKuMAxxf\nZ6LM/yKhgYkDgYYABAGBzgdnP798FsLuWYTDDQA7c0r3BVk8NnRUSexpQUsRilPN\nv3SchO0lRw9Ru86x1khnVDx+duq4BiDFcvlSAcyjLACJvjvoyTLJiA+TQFdmrear\njMiZNE25pT2yWP1NUndJxPcvVtfBW48kPOmvkY4WlqP5bAwCXwbsKrCgk6xbsp12\new==\n-----END PRIVATE KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\nPDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\n6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\nAl8G7CqwoJOsW7Kddns=\n-----END PUBLIC KEY-----")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES512")
|
||||
jwtToken, err := token.SignJWTToken(claims)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, jwtToken)
|
||||
c, err := token.ParseJWTToken(jwtToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c["email"].(string), claims["email"])
|
||||
})
|
||||
})
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, jwtType)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtSecret, jwtSecret)
|
||||
}
|
@@ -62,7 +62,6 @@ func CreateAuthToken(user models.User, roles []string) (*Token, error) {
|
||||
|
||||
// CreateRefreshToken util to create JWT token
|
||||
func CreateRefreshToken(user models.User, roles []string) (string, int64, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
|
||||
// expires in 1 year
|
||||
expiryBound := time.Hour * 8760
|
||||
expiresAt := time.Now().Add(expiryBound).Unix()
|
||||
@@ -75,8 +74,7 @@ func CreateRefreshToken(user models.User, roles []string) (string, int64, error)
|
||||
"id": user.ID,
|
||||
}
|
||||
|
||||
t.Claims = customClaims
|
||||
token, err := t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||
token, err := SignJWTToken(customClaims)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
@@ -86,9 +84,7 @@ func CreateRefreshToken(user models.User, roles []string) (string, int64, error)
|
||||
// CreateAccessToken util to create JWT token, based on
|
||||
// user information, roles config and CUSTOM_ACCESS_TOKEN_SCRIPT
|
||||
func CreateAccessToken(user models.User, roles []string) (string, int64, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
|
||||
expiryBound := time.Minute * 30
|
||||
|
||||
expiresAt := time.Now().Add(expiryBound).Unix()
|
||||
|
||||
resUser := user.AsAPIUser()
|
||||
@@ -141,9 +137,7 @@ func CreateAccessToken(user models.User, roles []string) (string, int64, error)
|
||||
}
|
||||
}
|
||||
|
||||
t.Claims = customClaims
|
||||
|
||||
token, err := t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||
token, err := SignJWTToken(customClaims)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
@@ -187,43 +181,13 @@ func GetFingerPrint(gc *gin.Context) (string, error) {
|
||||
return fingerPrint, nil
|
||||
}
|
||||
|
||||
// VerifyJWTToken helps in verifying the JWT token
|
||||
func VerifyJWTToken(token string) (map[string]interface{}, error) {
|
||||
var res map[string]interface{}
|
||||
claims := jwt.MapClaims{}
|
||||
|
||||
t, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
|
||||
})
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if !t.Valid {
|
||||
return res, fmt.Errorf(`invalid token`)
|
||||
}
|
||||
|
||||
// claim parses exp & iat into float 64 with e^10,
|
||||
// but we expect it to be int64
|
||||
// hence we need to assert interface and convert to int64
|
||||
intExp := int64(claims["exp"].(float64))
|
||||
intIat := int64(claims["iat"].(float64))
|
||||
|
||||
data, _ := json.Marshal(claims)
|
||||
json.Unmarshal(data, &res)
|
||||
res["exp"] = intExp
|
||||
res["iat"] = intIat
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func ValidateAccessToken(gc *gin.Context) (map[string]interface{}, error) {
|
||||
token, err := GetAccessToken(gc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims, err := VerifyJWTToken(token)
|
||||
claims, err := ParseJWTToken(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
89
server/token/jwt.go
Normal file
89
server/token/jwt.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
// SignJWTToken common util to sing jwt token
|
||||
func SignJWTToken(claims jwt.MapClaims) (string, error) {
|
||||
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||
signingMethod := jwt.GetSigningMethod(jwtType)
|
||||
if signingMethod == nil {
|
||||
return "", errors.New("unsupported signing method")
|
||||
}
|
||||
t := jwt.New(signingMethod)
|
||||
if t == nil {
|
||||
return "", errors.New("unsupported signing method")
|
||||
}
|
||||
t.Claims = claims
|
||||
|
||||
switch signingMethod {
|
||||
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
|
||||
return t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return t.SignedString(key)
|
||||
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
|
||||
key, err := jwt.ParseECPrivateKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return t.SignedString(key)
|
||||
default:
|
||||
return "", errors.New("unsupported signing method")
|
||||
}
|
||||
}
|
||||
|
||||
// ParseJWTToken common util to parse jwt token
|
||||
func ParseJWTToken(token string) (jwt.MapClaims, error) {
|
||||
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||
signingMethod := jwt.GetSigningMethod(jwtType)
|
||||
|
||||
var err error
|
||||
var claims jwt.MapClaims
|
||||
|
||||
switch signingMethod {
|
||||
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
|
||||
})
|
||||
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
key, err := jwt.ParseRSAPublicKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
key, err := jwt.ParseECPublicKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
default:
|
||||
err = errors.New("unsupported signing method")
|
||||
}
|
||||
if err != nil {
|
||||
return claims, err
|
||||
}
|
||||
|
||||
// claim parses exp & iat into float 64 with e^10,
|
||||
// but we expect it to be int64
|
||||
// hence we need to assert interface and convert to int64
|
||||
intExp := int64(claims["exp"].(float64))
|
||||
intIat := int64(claims["iat"].(float64))
|
||||
claims["exp"] = intExp
|
||||
claims["iat"] = intIat
|
||||
|
||||
return claims, nil
|
||||
}
|
@@ -8,44 +8,16 @@ import (
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
// VerificationRequestToken is the user info that is stored in the JWT of verification request
|
||||
type VerificationRequestToken struct {
|
||||
Email string `json:"email"`
|
||||
Host string `json:"host"`
|
||||
RedirectURL string `json:"redirect_url"`
|
||||
}
|
||||
|
||||
// CustomClaim is the custom claim that is stored in the JWT of verification request
|
||||
type CustomClaim struct {
|
||||
*jwt.StandardClaims
|
||||
TokenType string `json:"token_type"`
|
||||
VerificationRequestToken
|
||||
}
|
||||
|
||||
// CreateVerificationToken creates a verification JWT token
|
||||
func CreateVerificationToken(email, tokenType, hostname string) (string, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
|
||||
|
||||
t.Claims = &CustomClaim{
|
||||
&jwt.StandardClaims{
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
},
|
||||
tokenType,
|
||||
VerificationRequestToken{Email: email, Host: hostname, RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)},
|
||||
claims := jwt.MapClaims{
|
||||
"exp": time.Now().Add(time.Minute * 30).Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
"token_type": tokenType,
|
||||
"email": email,
|
||||
"host": hostname,
|
||||
"redirect_url": envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL),
|
||||
}
|
||||
|
||||
return t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||
}
|
||||
|
||||
// VerifyVerificationToken verifies the verification JWT token
|
||||
func VerifyVerificationToken(token string) (*CustomClaim, error) {
|
||||
claims := &CustomClaim{}
|
||||
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
|
||||
})
|
||||
if err != nil {
|
||||
return claims, err
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
return SignJWTToken(claims)
|
||||
}
|
||||
|
Reference in New Issue
Block a user