Compare commits
112 Commits
0.22.2
...
fix/passwo
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2de0ea57d0 | ||
![]() |
f2886e6da8 | ||
![]() |
6b57bce6d9 | ||
![]() |
bfbeb6add2 | ||
![]() |
1fe0d65874 | ||
![]() |
bfaa0f9d89 | ||
![]() |
4f5a6c77f8 | ||
![]() |
018a13ab3c | ||
![]() |
334041d0e4 | ||
![]() |
6a8309a231 | ||
![]() |
6347b60753 | ||
![]() |
bbb064b939 | ||
![]() |
e91a819067 | ||
![]() |
09c3eafe6b | ||
![]() |
bb51775d34 | ||
![]() |
6d586b16e4 | ||
![]() |
e8eb62769e | ||
![]() |
0ffb3f67f1 | ||
![]() |
ec62686fbc | ||
![]() |
a8064e79a1 | ||
![]() |
265331801f | ||
![]() |
6a74a50493 | ||
![]() |
8c27f20534 | ||
![]() |
29c6003ea3 | ||
![]() |
ae34fc7c2b | ||
![]() |
2a5d5d43b0 | ||
![]() |
e6a4670ba9 | ||
![]() |
64d64b4099 | ||
![]() |
88f9a10f21 | ||
![]() |
4e08d4f8fd | ||
![]() |
1c4dda9299 | ||
![]() |
ab18fa5832 | ||
![]() |
484d0c0882 | ||
![]() |
be59c3615f | ||
![]() |
db351f7771 | ||
![]() |
91c29c4092 | ||
![]() |
415b97535e | ||
![]() |
7d1272d815 | ||
![]() |
c9ba0b13f8 | ||
![]() |
fadd9f6168 | ||
![]() |
395e2e2a85 | ||
![]() |
6335084835 | ||
![]() |
eab336cd3d | ||
![]() |
f4691fca1f | ||
![]() |
341d4fbae5 | ||
![]() |
e467b45ab1 | ||
![]() |
7edfad3486 | ||
![]() |
80578b88ac | ||
![]() |
5646e7a0e7 | ||
![]() |
53a592ef63 | ||
![]() |
3337dbd0a4 | ||
![]() |
82a2a42f84 | ||
![]() |
ac49b5bb70 | ||
![]() |
926ab07c07 | ||
![]() |
7a2dbea019 | ||
![]() |
dff50097e8 | ||
![]() |
aff9d3af20 | ||
![]() |
02eb1d6677 | ||
![]() |
78a673e4ad | ||
![]() |
e0d8644264 | ||
![]() |
d8c662eaad | ||
![]() |
6d1d259f71 | ||
![]() |
2841853d37 | ||
![]() |
360dd3c3bd | ||
![]() |
c6add0cca6 | ||
![]() |
7ac6252aac | ||
![]() |
5d2d1c342b | ||
![]() |
6da0a85936 | ||
![]() |
116972d725 | ||
![]() |
d1e1e287db | ||
![]() |
a7f04f8754 | ||
![]() |
69b56c9912 | ||
![]() |
98015708a2 | ||
![]() |
1b5a7b8fb0 | ||
![]() |
8b9bcdfdbe | ||
![]() |
ba429da05f | ||
![]() |
7c7bb42003 | ||
![]() |
eeff88c853 | ||
![]() |
cf8762b7a0 | ||
![]() |
c61c3024ec | ||
![]() |
7e3bd6a721 | ||
![]() |
1146468a03 | ||
![]() |
268b22ffb2 | ||
![]() |
43359f1dba | ||
![]() |
1941cf4299 | ||
![]() |
7b13034081 | ||
![]() |
7c16900618 | ||
![]() |
d722fe258d | ||
![]() |
99dc5ee572 | ||
![]() |
8bee421d0a | ||
![]() |
714b79e4ab | ||
![]() |
d886d780b4 | ||
![]() |
d7bb10fd21 | ||
![]() |
f5515bec28 | ||
![]() |
b35d86fd40 | ||
![]() |
a638f02014 | ||
![]() |
2c4bc9adb6 | ||
![]() |
ed855a274a | ||
![]() |
2bc4c74930 | ||
![]() |
da0fcb109b | ||
![]() |
3e51a7bd01 | ||
![]() |
28bed69b2e | ||
![]() |
0433d64737 | ||
![]() |
de44c40de5 | ||
![]() |
a7fa988bf0 | ||
![]() |
538a2d0b59 | ||
![]() |
f519f0eb0e | ||
![]() |
d5ad4a6e55 | ||
![]() |
d9b49ca932 | ||
![]() |
7c5aab7bf3 | ||
![]() |
c783e101d5 | ||
![]() |
ebccfb18cd |
@@ -1,3 +1,4 @@
|
|||||||
|
ENV=production
|
||||||
DATABASE_URL=data.db
|
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;}"
|
CUSTOM_ACCESS_TOKEN_SCRIPT="function(user,tokenPayload){var data = tokenPayload;data.extra = {'x-extra-id': user.id};return data;}"
|
9
.env.test
Normal file
9
.env.test
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
ENV=test
|
||||||
|
DATABASE_URL=test.db
|
||||||
|
DATABASE_TYPE=sqlite
|
||||||
|
CUSTOM_ACCESS_TOKEN_SCRIPT="function(user,tokenPayload){var data = tokenPayload;data.extra = {'x-extra-id': user.id};return data;}"
|
||||||
|
SMTP_HOST=smtp.mailtrap.io
|
||||||
|
SMTP_PORT=2525
|
||||||
|
SMTP_USERNAME=test
|
||||||
|
SMTP_PASSWORD=test
|
||||||
|
SENDER_EMAIL="info@authorizer.dev"
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,6 +8,7 @@ dashboard/build
|
|||||||
build
|
build
|
||||||
.env
|
.env
|
||||||
data.db
|
data.db
|
||||||
|
test.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env.local
|
.env.local
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ build-dashboard:
|
|||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
test:
|
test:
|
||||||
cd server && go clean --testcache && go test -v ./test
|
rm -rf server/test/test.db && rm -rf test.db && cd server && go clean --testcache && go test -p 1 -v ./test
|
||||||
generate:
|
generate:
|
||||||
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate
|
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate
|
||||||
|
|
88
app/package-lock.json
generated
88
app/package-lock.json
generated
@@ -9,7 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-react": "^0.17.0",
|
"@authorizerdev/authorizer-react": "^0.25.0",
|
||||||
"@types/react": "^17.0.15",
|
"@types/react": "^17.0.15",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"esbuild": "^0.12.17",
|
"esbuild": "^0.12.17",
|
||||||
@@ -17,16 +17,18 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-is": "^17.0.2",
|
"react-is": "^17.0.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
|
"styled-components": "^5.3.0",
|
||||||
"typescript": "^4.3.5"
|
"typescript": "^4.3.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react-router-dom": "^5.1.8"
|
"@types/react-router-dom": "^5.1.8",
|
||||||
|
"@types/styled-components": "^5.1.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-js": {
|
"node_modules/@authorizerdev/authorizer-js": {
|
||||||
"version": "0.10.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.14.0.tgz",
|
||||||
"integrity": "sha512-REM8FLD/Ej9gzA2zDGDAke6QFss33ubePlTDmLDmIYUuQmpHFlO5mCCS6nVsKkN7F/Bcwkmp+eUNQjkdGCaKLg==",
|
"integrity": "sha512-cpeeFrmG623QPLn+nf+ACHayZYqW8xokIidGikeboBDJtuAAQB50a54/7HwLHriG2FB7WvPuHQ/9LFFX//N1lg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "^2.6.1"
|
"node-fetch": "^2.6.1"
|
||||||
},
|
},
|
||||||
@@ -35,11 +37,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-react": {
|
"node_modules/@authorizerdev/authorizer-react": {
|
||||||
"version": "0.17.0",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.25.0.tgz",
|
||||||
"integrity": "sha512-7WcNCU7hDFkVfFb8LcJXFwWiLYd8aY78z1AbNPxCa2Cw5G85PaRkzjKybP6h01ITVOHO6M03lLwPj8p6Sr6fEg==",
|
"integrity": "sha512-Dt2rZf+cGCVb8dqcJ/9l8Trx+QeXnTdfhER6r/cq0iOnFC9MqWzQPB3RgrlUoMLHtZvKNDXIk1HvfD5hSX9lhw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": "^0.10.0",
|
"@authorizerdev/authorizer-js": "^0.14.0",
|
||||||
"final-form": "^4.20.2",
|
"final-form": "^4.20.2",
|
||||||
"react-final-form": "^6.5.3",
|
"react-final-form": "^6.5.3",
|
||||||
"styled-components": "^5.3.0"
|
"styled-components": "^5.3.0"
|
||||||
@@ -271,6 +273,16 @@
|
|||||||
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.4",
|
"version": "15.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
|
||||||
@@ -320,6 +332,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/styled-components": {
|
||||||
|
"version": "5.1.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.25.tgz",
|
||||||
|
"integrity": "sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hoist-non-react-statics": "*",
|
||||||
|
"@types/react": "*",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-styles": {
|
"node_modules/ansi-styles": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
@@ -793,7 +816,7 @@
|
|||||||
"node_modules/tr46": {
|
"node_modules/tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.3.5",
|
"version": "4.3.5",
|
||||||
@@ -815,12 +838,12 @@
|
|||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
},
|
},
|
||||||
"node_modules/whatwg-url": {
|
"node_modules/whatwg-url": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tr46": "~0.0.3",
|
"tr46": "~0.0.3",
|
||||||
"webidl-conversions": "^3.0.0"
|
"webidl-conversions": "^3.0.0"
|
||||||
@@ -829,19 +852,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": {
|
"@authorizerdev/authorizer-js": {
|
||||||
"version": "0.10.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.14.0.tgz",
|
||||||
"integrity": "sha512-REM8FLD/Ej9gzA2zDGDAke6QFss33ubePlTDmLDmIYUuQmpHFlO5mCCS6nVsKkN7F/Bcwkmp+eUNQjkdGCaKLg==",
|
"integrity": "sha512-cpeeFrmG623QPLn+nf+ACHayZYqW8xokIidGikeboBDJtuAAQB50a54/7HwLHriG2FB7WvPuHQ/9LFFX//N1lg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-fetch": "^2.6.1"
|
"node-fetch": "^2.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@authorizerdev/authorizer-react": {
|
"@authorizerdev/authorizer-react": {
|
||||||
"version": "0.17.0",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.25.0.tgz",
|
||||||
"integrity": "sha512-7WcNCU7hDFkVfFb8LcJXFwWiLYd8aY78z1AbNPxCa2Cw5G85PaRkzjKybP6h01ITVOHO6M03lLwPj8p6Sr6fEg==",
|
"integrity": "sha512-Dt2rZf+cGCVb8dqcJ/9l8Trx+QeXnTdfhER6r/cq0iOnFC9MqWzQPB3RgrlUoMLHtZvKNDXIk1HvfD5hSX9lhw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@authorizerdev/authorizer-js": "^0.10.0",
|
"@authorizerdev/authorizer-js": "^0.14.0",
|
||||||
"final-form": "^4.20.2",
|
"final-form": "^4.20.2",
|
||||||
"react-final-form": "^6.5.3",
|
"react-final-form": "^6.5.3",
|
||||||
"styled-components": "^5.3.0"
|
"styled-components": "^5.3.0"
|
||||||
@@ -1016,6 +1039,16 @@
|
|||||||
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/prop-types": {
|
"@types/prop-types": {
|
||||||
"version": "15.7.4",
|
"version": "15.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
|
||||||
@@ -1065,6 +1098,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
||||||
},
|
},
|
||||||
|
"@types/styled-components": {
|
||||||
|
"version": "5.1.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.25.tgz",
|
||||||
|
"integrity": "sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/hoist-non-react-statics": "*",
|
||||||
|
"@types/react": "*",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
@@ -1438,7 +1482,7 @@
|
|||||||
"tr46": {
|
"tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.3.5",
|
"version": "4.3.5",
|
||||||
@@ -1453,12 +1497,12 @@
|
|||||||
"webidl-conversions": {
|
"webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
},
|
},
|
||||||
"whatwg-url": {
|
"whatwg-url": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tr46": "~0.0.3",
|
"tr46": "~0.0.3",
|
||||||
"webidl-conversions": "^3.0.0"
|
"webidl-conversions": "^3.0.0"
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
"author": "Lakhan Samani",
|
"author": "Lakhan Samani",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-react": "^0.17.0",
|
"@authorizerdev/authorizer-react": "^0.25.0",
|
||||||
"@types/react": "^17.0.15",
|
"@types/react": "^17.0.15",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"esbuild": "^0.12.17",
|
"esbuild": "^0.12.17",
|
||||||
@@ -19,9 +19,11 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-is": "^17.0.2",
|
"react-is": "^17.0.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"typescript": "^4.3.5"
|
"typescript": "^4.3.5",
|
||||||
|
"styled-components": "^5.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react-router-dom": "^5.1.8"
|
"@types/react-router-dom": "^5.1.8",
|
||||||
|
"@types/styled-components": "^5.1.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,28 @@
|
|||||||
import React, { useEffect, lazy, Suspense } from 'react';
|
import React, { useEffect, lazy, Suspense } from 'react';
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route } from 'react-router-dom';
|
||||||
import { useAuthorizer } from '@authorizerdev/authorizer-react';
|
import { useAuthorizer } from '@authorizerdev/authorizer-react';
|
||||||
|
import styled, { ThemeProvider } from 'styled-components';
|
||||||
import SetupPassword from './pages/setup-password';
|
import SetupPassword from './pages/setup-password';
|
||||||
|
import { hasWindow, createRandomString } from './utils/common';
|
||||||
|
import { theme } from './theme';
|
||||||
|
|
||||||
const ResetPassword = lazy(() => import('./pages/rest-password'));
|
const ResetPassword = lazy(() => import('./pages/rest-password'));
|
||||||
const Login = lazy(() => import('./pages/login'));
|
const Login = lazy(() => import('./pages/login'));
|
||||||
const Dashboard = lazy(() => import('./pages/dashboard'));
|
const Dashboard = lazy(() => import('./pages/dashboard'));
|
||||||
|
const SignUp = lazy(() => import('./pages/signup'));
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
font-family: ${(props) => props.theme.fonts.fontStack};
|
||||||
|
color: ${(props) => props.theme.colors.textColor};
|
||||||
|
font-size: ${(props) => props.theme.fonts.mediumText};
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export default function Root({
|
export default function Root({
|
||||||
globalState,
|
globalState,
|
||||||
@@ -14,6 +31,29 @@ export default function Root({
|
|||||||
}) {
|
}) {
|
||||||
const { token, loading, config } = useAuthorizer();
|
const { token, loading, config } = useAuthorizer();
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(
|
||||||
|
hasWindow() ? window.location.search : ``
|
||||||
|
);
|
||||||
|
const state = searchParams.get('state') || createRandomString();
|
||||||
|
const scope = searchParams.get('scope')
|
||||||
|
? searchParams.get('scope')?.toString().split(' ')
|
||||||
|
: ['openid', 'profile', 'email'];
|
||||||
|
|
||||||
|
const urlProps: Record<string, any> = {
|
||||||
|
state,
|
||||||
|
scope,
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectURL =
|
||||||
|
searchParams.get('redirect_uri') || searchParams.get('redirectURL');
|
||||||
|
if (redirectURL) {
|
||||||
|
urlProps.redirectURL = redirectURL;
|
||||||
|
} else {
|
||||||
|
urlProps.redirectURL = hasWindow() ? window.location.origin : redirectURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
urlProps.redirect_uri = urlProps.redirectURL;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (token) {
|
if (token) {
|
||||||
let redirectURL = config.redirectURL || '/app';
|
let redirectURL = config.redirectURL || '/app';
|
||||||
@@ -54,9 +94,14 @@ export default function Root({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<></>}>
|
<Suspense fallback={<></>}>
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
<Wrapper>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/app" exact>
|
<Route path="/app" exact>
|
||||||
<Login />
|
<Login urlProps={urlProps} />
|
||||||
|
</Route>
|
||||||
|
<Route path="/app/signup" exact>
|
||||||
|
<SignUp urlProps={urlProps} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/app/reset-password">
|
<Route path="/app/reset-password">
|
||||||
<ResetPassword />
|
<ResetPassword />
|
||||||
@@ -65,6 +110,8 @@ export default function Root({
|
|||||||
<SetupPassword />
|
<SetupPassword />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
</Wrapper>
|
||||||
|
</ThemeProvider>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,84 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment, useState } from 'react';
|
||||||
import { Authorizer } from '@authorizerdev/authorizer-react';
|
import {
|
||||||
|
AuthorizerBasicAuthLogin,
|
||||||
|
AuthorizerForgotPassword,
|
||||||
|
AuthorizerMagicLinkLogin,
|
||||||
|
AuthorizerSocialLogin,
|
||||||
|
useAuthorizer,
|
||||||
|
} from '@authorizerdev/authorizer-react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
export default function Login() {
|
const enum VIEW_TYPES {
|
||||||
|
LOGIN = 'login',
|
||||||
|
FORGOT_PASSWORD = 'forgot-password',
|
||||||
|
}
|
||||||
|
|
||||||
|
const Footer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const FooterContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function Login({ urlProps }: { urlProps: Record<string, any> }) {
|
||||||
|
const { config } = useAuthorizer();
|
||||||
|
const [view, setView] = useState<VIEW_TYPES>(VIEW_TYPES.LOGIN);
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Authorizer />
|
{view === VIEW_TYPES.LOGIN && (
|
||||||
|
<Fragment>
|
||||||
|
<h1 style={{ textAlign: 'center' }}>Login</h1>
|
||||||
|
<br />
|
||||||
|
<AuthorizerSocialLogin urlProps={urlProps} />
|
||||||
|
{config.is_basic_authentication_enabled &&
|
||||||
|
!config.is_magic_link_login_enabled && (
|
||||||
|
<AuthorizerBasicAuthLogin urlProps={urlProps} />
|
||||||
|
)}
|
||||||
|
{config.is_magic_link_login_enabled && (
|
||||||
|
<AuthorizerMagicLinkLogin urlProps={urlProps} />
|
||||||
|
)}
|
||||||
|
<Footer>
|
||||||
|
<Link
|
||||||
|
to="#"
|
||||||
|
onClick={() => setView(VIEW_TYPES.FORGOT_PASSWORD)}
|
||||||
|
style={{ marginBottom: 10 }}
|
||||||
|
>
|
||||||
|
Forgot Password?
|
||||||
|
</Link>
|
||||||
|
</Footer>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
{view === VIEW_TYPES.FORGOT_PASSWORD && (
|
||||||
|
<Fragment>
|
||||||
|
<h1 style={{ textAlign: 'center' }}>Forgot Password</h1>
|
||||||
|
<AuthorizerForgotPassword urlProps={urlProps} />
|
||||||
|
<Footer>
|
||||||
|
<Link
|
||||||
|
to="#"
|
||||||
|
onClick={() => setView(VIEW_TYPES.LOGIN)}
|
||||||
|
style={{ marginBottom: 10 }}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</Link>
|
||||||
|
</Footer>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
{config.is_basic_authentication_enabled &&
|
||||||
|
!config.is_magic_link_login_enabled &&
|
||||||
|
config.is_sign_up_enabled && (
|
||||||
|
<FooterContent>
|
||||||
|
Don't have an account? <Link to="/app/signup"> Sign Up</Link>
|
||||||
|
</FooterContent>
|
||||||
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
28
app/src/pages/signup.tsx
Normal file
28
app/src/pages/signup.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import { AuthorizerSignup } from '@authorizerdev/authorizer-react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const FooterContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function SignUp({
|
||||||
|
urlProps,
|
||||||
|
}: {
|
||||||
|
urlProps: Record<string, any>;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<h1 style={{ textAlign: 'center' }}>Sign Up</h1>
|
||||||
|
<br />
|
||||||
|
<AuthorizerSignup urlProps={urlProps} />
|
||||||
|
<FooterContent>
|
||||||
|
Already have an account? <Link to="/app"> Login</Link>
|
||||||
|
</FooterContent>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
28
app/src/theme.ts
Normal file
28
app/src/theme.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// colors: https://tailwindcss.com/docs/customizing-colors
|
||||||
|
|
||||||
|
export const theme = {
|
||||||
|
colors: {
|
||||||
|
primary: '#3B82F6',
|
||||||
|
primaryDisabled: '#60A5FA',
|
||||||
|
gray: '#D1D5DB',
|
||||||
|
danger: '#DC2626',
|
||||||
|
success: '#10B981',
|
||||||
|
textColor: '#374151',
|
||||||
|
},
|
||||||
|
fonts: {
|
||||||
|
// typography
|
||||||
|
fontStack: '-apple-system, system-ui, sans-serif',
|
||||||
|
|
||||||
|
// font sizes
|
||||||
|
largeText: '18px',
|
||||||
|
mediumText: '14px',
|
||||||
|
smallText: '12px',
|
||||||
|
tinyText: '10px',
|
||||||
|
},
|
||||||
|
|
||||||
|
radius: {
|
||||||
|
card: '5px',
|
||||||
|
button: '5px',
|
||||||
|
input: '5px',
|
||||||
|
},
|
||||||
|
};
|
@@ -20,3 +20,5 @@ export const createQueryParams = (params: any) => {
|
|||||||
.map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
|
.map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
|
||||||
.join('&');
|
.join('&');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const hasWindow = (): boolean => typeof window !== 'undefined';
|
||||||
|
22
dashboard/package-lock.json
generated
22
dashboard/package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^1.7.3",
|
"@chakra-ui/react": "^1.7.3",
|
||||||
|
"@emotion/core": "^11.0.0",
|
||||||
"@emotion/react": "^11.7.1",
|
"@emotion/react": "^11.7.1",
|
||||||
"@emotion/styled": "^11.6.0",
|
"@emotion/styled": "^11.6.0",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"esbuild": "^0.14.9",
|
"esbuild": "^0.14.9",
|
||||||
|
"focus-visible": "^5.2.0",
|
||||||
"framer-motion": "^5.5.5",
|
"framer-motion": "^5.5.5",
|
||||||
"graphql": "^16.2.0",
|
"graphql": "^16.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -978,6 +980,11 @@
|
|||||||
"stylis": "4.0.13"
|
"stylis": "4.0.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@emotion/core": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
|
||||||
|
},
|
||||||
"node_modules/@emotion/hash": {
|
"node_modules/@emotion/hash": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
@@ -1667,6 +1674,11 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/focus-visible": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
|
||||||
|
},
|
||||||
"node_modules/framer-motion": {
|
"node_modules/framer-motion": {
|
||||||
"version": "5.5.5",
|
"version": "5.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
||||||
@@ -3038,6 +3050,11 @@
|
|||||||
"stylis": "4.0.13"
|
"stylis": "4.0.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@emotion/core": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
|
||||||
|
},
|
||||||
"@emotion/hash": {
|
"@emotion/hash": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
@@ -3540,6 +3557,11 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"focus-visible": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
|
||||||
|
},
|
||||||
"framer-motion": {
|
"framer-motion": {
|
||||||
"version": "5.5.5",
|
"version": "5.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^1.7.3",
|
"@chakra-ui/react": "^1.7.3",
|
||||||
|
"@emotion/core": "^11.0.0",
|
||||||
"@emotion/react": "^11.7.1",
|
"@emotion/react": "^11.7.1",
|
||||||
"@emotion/styled": "^11.6.0",
|
"@emotion/styled": "^11.6.0",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"esbuild": "^0.14.9",
|
"esbuild": "^0.14.9",
|
||||||
|
"focus-visible": "^5.2.0",
|
||||||
"framer-motion": "^5.5.5",
|
"framer-motion": "^5.5.5",
|
||||||
"graphql": "^16.2.0",
|
"graphql": "^16.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Fragment } from 'react';
|
||||||
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
|
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
import { createClient, Provider } from 'urql';
|
import { createClient, Provider } from 'urql';
|
||||||
@@ -22,8 +23,8 @@ const theme = extendTheme({
|
|||||||
styles: {
|
styles: {
|
||||||
global: {
|
global: {
|
||||||
'html, body, #root': {
|
'html, body, #root': {
|
||||||
fontFamily: 'Avenir, Helvetica, Arial, sans-serif',
|
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
outline: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -36,6 +37,7 @@ const theme = extendTheme({
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
|
<Fragment>
|
||||||
<ChakraProvider theme={theme}>
|
<ChakraProvider theme={theme}>
|
||||||
<Provider value={queryClient}>
|
<Provider value={queryClient}>
|
||||||
<BrowserRouter basename="/dashboard">
|
<BrowserRouter basename="/dashboard">
|
||||||
@@ -45,5 +47,6 @@ export default function App() {
|
|||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
</ChakraProvider>
|
</ChakraProvider>
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
65
dashboard/src/components/EnvComponents/AccessToken.tsx
Normal file
65
dashboard/src/components/EnvComponents/AccessToken.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { TextInputType, TextAreaInputType } from "../../constants";
|
||||||
|
|
||||||
|
const AccessToken = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Access Token
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "50%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Access Token Expiry Time:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ACCESS_TOKEN_EXPIRY_TIME}
|
||||||
|
placeholder="0h15m0s"
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "60%"}
|
||||||
|
justifyContent="start"
|
||||||
|
direction="column"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Custom Scripts:</Text>
|
||||||
|
<Text fontSize="xs" color="blackAlpha.500">
|
||||||
|
(Used to add custom fields in ID token)
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.CUSTOM_ACCESS_TOKEN_SCRIPT}
|
||||||
|
placeholder="Add script here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccessToken;
|
@@ -0,0 +1,89 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import InputField from '../../components/InputField';
|
||||||
|
import { TextInputType } from '../../constants';
|
||||||
|
|
||||||
|
const DatabaseCredentials = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{' '}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
|
Database Credentials
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="3% 0">
|
||||||
|
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
||||||
|
Note: Database related environment variables cannot be updated from
|
||||||
|
dashboard. Please use .env file or OS environment variables to update
|
||||||
|
it.
|
||||||
|
</Text>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase Name:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_NAME}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase Type:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_TYPE}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase URL:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_URL}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DatabaseCredentials;
|
@@ -0,0 +1,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { ArrayInputType} from "../../constants";
|
||||||
|
|
||||||
|
const DomainWhiteListing = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Domain White Listing
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Allowed Origins:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.ALLOWED_ORIGINS}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DomainWhiteListing;
|
114
dashboard/src/components/EnvComponents/EmailConfiguration.tsx
Normal file
114
dashboard/src/components/EnvComponents/EmailConfiguration.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { TextInputType, HiddenInputType} from "../../constants";
|
||||||
|
const EmailConfigurations = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Email Configurations
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">SMTP Host:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_HOST}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">SMTP Port:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_PORT}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">SMTP Username:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_USERNAME}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">SMTP Password:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.SMTP_PASSWORD}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">From Email:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SENDER_EMAIL}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EmailConfigurations;
|
91
dashboard/src/components/EnvComponents/Features.tsx
Normal file
91
dashboard/src/components/EnvComponents/Features.tsx
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Flex, Stack, Text } from '@chakra-ui/react';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
import { SwitchInputType } from '../../constants';
|
||||||
|
|
||||||
|
const Features = ({ variables, setVariables }: any) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{' '}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Disable Features
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Login Page:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Email Verification:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Magic Login Link:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Basic Authentication:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Sign Up:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start" mb={3}>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Strong Password:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start" mb={3}>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_STRONG_PASSWORD}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Features;
|
154
dashboard/src/components/EnvComponents/JWTConfiguration.tsx
Normal file
154
dashboard/src/components/EnvComponents/JWTConfiguration.tsx
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import {
|
||||||
|
HiddenInputType,
|
||||||
|
TextInputType,
|
||||||
|
TextAreaInputType,
|
||||||
|
} from "../../constants";
|
||||||
|
import GenerateKeysModal from "../GenerateKeysModal";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
|
||||||
|
const JSTConfigurations = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
SelectInputType,
|
||||||
|
getData,
|
||||||
|
HMACEncryptionType,
|
||||||
|
RSAEncryptionType,
|
||||||
|
ECDSAEncryptionType,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Flex
|
||||||
|
borderRadius={5}
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
paddingTop="2%"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontSize={isNotSmallerScreen ? "md" : "sm"}
|
||||||
|
fontWeight="bold"
|
||||||
|
mb={5}
|
||||||
|
>
|
||||||
|
JWT (JSON Web Tokens) Configurations
|
||||||
|
</Text>
|
||||||
|
<Flex mb={7}>
|
||||||
|
<GenerateKeysModal jwtType={variables.JWT_TYPE} getData={getData} />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">JWT Type:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SelectInputType}
|
||||||
|
value={SelectInputType}
|
||||||
|
options={{
|
||||||
|
...HMACEncryptionType,
|
||||||
|
...RSAEncryptionType,
|
||||||
|
...ECDSAEncryptionType,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
{Object.values(HMACEncryptionType).includes(variables.JWT_TYPE) ? (
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">JWT Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.JWT_SECRET}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Public Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
||||||
|
placeholder="Add public key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Private Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
||||||
|
placeholder="Add private key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm" orientation="vertical">
|
||||||
|
JWT Role Claim:
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.JWT_ROLE_CLAIM}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default JSTConfigurations;
|
273
dashboard/src/components/EnvComponents/OAuthConfig.tsx
Normal file
273
dashboard/src/components/EnvComponents/OAuthConfig.tsx
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
import {
|
||||||
|
Flex,
|
||||||
|
Stack,
|
||||||
|
Center,
|
||||||
|
Text,
|
||||||
|
Box,
|
||||||
|
Divider,
|
||||||
|
useMediaQuery,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import {
|
||||||
|
FaGoogle,
|
||||||
|
FaGithub,
|
||||||
|
FaFacebookF,
|
||||||
|
FaLinkedin,
|
||||||
|
FaApple,
|
||||||
|
} from 'react-icons/fa';
|
||||||
|
import { TextInputType, HiddenInputType } from '../../constants';
|
||||||
|
|
||||||
|
const OAuthConfig = ({
|
||||||
|
envVariables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:667px)');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Box>
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={6}>
|
||||||
|
Authorizer Config
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client ID</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={() => {}}
|
||||||
|
inputType={TextInputType.CLIENT_ID}
|
||||||
|
placeholder="Client ID"
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.CLIENT_SECRET}
|
||||||
|
placeholder="Client Secret"
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
<Divider mt={5} mb={2} color="blackAlpha.700" />
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={4}>
|
||||||
|
Social Media Logins
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #ff3e30"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaGoogle style={{ color: '#ff3e30' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.GOOGLE_CLIENT_ID}
|
||||||
|
placeholder="Google Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.GOOGLE_CLIENT_SECRET}
|
||||||
|
placeholder="Google Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #171515"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaGithub style={{ color: '#171515' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.GITHUB_CLIENT_ID}
|
||||||
|
placeholder="Github Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.GITHUB_CLIENT_SECRET}
|
||||||
|
placeholder="Github Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #3b5998"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaFacebookF style={{ color: '#3b5998' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.FACEBOOK_CLIENT_ID}
|
||||||
|
placeholder="Facebook Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.FACEBOOK_CLIENT_SECRET}
|
||||||
|
placeholder="Facebook Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #3b5998"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaLinkedin style={{ color: '#3b5998' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.LINKEDIN_CLIENT_ID}
|
||||||
|
placeholder="LinkedIn Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.LINKEDIN_CLIENT_SECRET}
|
||||||
|
placeholder="LinkedIn Client Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #3b5998"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaApple style={{ color: '#3b5998' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.APPLE_CLIENT_ID}
|
||||||
|
placeholder="Apple Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.APPLE_CLIENT_SECRET}
|
||||||
|
placeholder="Apple CLient Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OAuthConfig;
|
60
dashboard/src/components/EnvComponents/OrganizationInfo.tsx
Normal file
60
dashboard/src/components/EnvComponents/OrganizationInfo.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
import { TextInputType } from "../../constants";
|
||||||
|
|
||||||
|
const OrganizationInfo = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Organization Information
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Organization Name:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ORGANIZATION_NAME}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Organization Logo:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ORGANIZATION_LOGO}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrganizationInfo;
|
68
dashboard/src/components/EnvComponents/Roles.tsx
Normal file
68
dashboard/src/components/EnvComponents/Roles.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
|
import { ArrayInputType } from '../../constants';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
|
||||||
|
const Roles = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{' '}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Roles
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
|
overflow="hidden"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={7}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Default Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.DEFAULT_ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Protected Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.PROTECTED_ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Roles;
|
138
dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
Normal file
138
dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Flex,
|
||||||
|
Stack,
|
||||||
|
Center,
|
||||||
|
Text,
|
||||||
|
Input,
|
||||||
|
InputGroup,
|
||||||
|
InputRightElement,
|
||||||
|
useMediaQuery,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { FaRegEyeSlash, FaRegEye } from "react-icons/fa";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
import { HiddenInputType } from "../../constants";
|
||||||
|
const SecurityAdminSecret = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
validateAdminSecretHandler,
|
||||||
|
adminSecret,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
|
Security (Admin Secret)
|
||||||
|
</Text>
|
||||||
|
<Stack
|
||||||
|
spacing={6}
|
||||||
|
padding="0 5%"
|
||||||
|
marginTop="3%"
|
||||||
|
border="1px solid #ff7875"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
marginTop={isNotSmallerScreen ? "3%" : "5%"}
|
||||||
|
direction={isNotSmallerScreen ? "row" : "column"}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
mt={3}
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Old Admin Secret:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputGroup size="sm">
|
||||||
|
<Input
|
||||||
|
borderRadius={5}
|
||||||
|
size="sm"
|
||||||
|
placeholder="Enter Old Admin Secret"
|
||||||
|
value={adminSecret.value as string}
|
||||||
|
onChange={(event: any) => validateAdminSecretHandler(event)}
|
||||||
|
type={
|
||||||
|
!fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
|
||||||
|
? "password"
|
||||||
|
: "text"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<InputRightElement
|
||||||
|
right="5px"
|
||||||
|
children={
|
||||||
|
<Flex>
|
||||||
|
{fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
|
||||||
|
<Center
|
||||||
|
w="25px"
|
||||||
|
margin="0 1.5%"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setFieldVisibility({
|
||||||
|
...fieldVisibility,
|
||||||
|
[HiddenInputType.OLD_ADMIN_SECRET]: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegEyeSlash color="#bfbfbf" />
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
<Center
|
||||||
|
w="25px"
|
||||||
|
margin="0 1.5%"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setFieldVisibility({
|
||||||
|
...fieldVisibility,
|
||||||
|
[HiddenInputType.OLD_ADMIN_SECRET]: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegEye color="#bfbfbf" />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
paddingBottom="3%"
|
||||||
|
direction={isNotSmallerScreen ? "row" : "column"}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "50%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">New Admin Secret:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
mb={3}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={HiddenInputType.ADMIN_SECRET}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
isDisabled={adminSecret.disableInputField}
|
||||||
|
placeholder="Enter New Admin Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecurityAdminSecret;
|
42
dashboard/src/components/EnvComponents/SessionStorage.tsx
Normal file
42
dashboard/src/components/EnvComponents/SessionStorage.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
|
||||||
|
const SessionStorage = ({ variables, setVariables, RedisURL }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{' '}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Session Storage
|
||||||
|
</Text>
|
||||||
|
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
||||||
|
Note: Redis related environment variables cannot be updated from
|
||||||
|
dashboard. Please use .env file or OS environment variables to update
|
||||||
|
it.
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Redis URL:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
disabled
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={RedisURL}
|
||||||
|
placeholder="Redis URL"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SessionStorage;
|
@@ -13,6 +13,7 @@ import {
|
|||||||
Textarea,
|
Textarea,
|
||||||
Switch,
|
Switch,
|
||||||
Code,
|
Code,
|
||||||
|
Text,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
FaRegClone,
|
FaRegClone,
|
||||||
@@ -116,7 +117,7 @@ const InputField = ({
|
|||||||
<InputGroup size="sm">
|
<InputGroup size="sm">
|
||||||
<Input
|
<Input
|
||||||
{...props}
|
{...props}
|
||||||
value={variables[inputType]}
|
value={variables[inputType] ?? ''}
|
||||||
onChange={(
|
onChange={(
|
||||||
event: Event & {
|
event: Event & {
|
||||||
target: HTMLInputElement;
|
target: HTMLInputElement;
|
||||||
@@ -181,8 +182,9 @@ const InputField = ({
|
|||||||
<Flex
|
<Flex
|
||||||
border="1px solid #e2e8f0"
|
border="1px solid #e2e8f0"
|
||||||
w="100%"
|
w="100%"
|
||||||
|
borderRadius={5}
|
||||||
paddingTop="0.5%"
|
paddingTop="0.5%"
|
||||||
overflowX="scroll"
|
overflowX={variables[inputType].length > 3 ? 'scroll' : 'hidden'}
|
||||||
overflowY="hidden"
|
overflowY="hidden"
|
||||||
justifyContent="start"
|
justifyContent="start"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
@@ -220,7 +222,7 @@ const InputField = ({
|
|||||||
size="xs"
|
size="xs"
|
||||||
minW="150px"
|
minW="150px"
|
||||||
placeholder="add a new value"
|
placeholder="add a new value"
|
||||||
value={inputData[inputType]}
|
value={inputData[inputType] ?? ''}
|
||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
setInputData({ ...inputData, [inputType]: e.target.value });
|
setInputData({ ...inputData, [inputType]: e.target.value });
|
||||||
}}
|
}}
|
||||||
@@ -300,7 +302,9 @@ const InputField = ({
|
|||||||
if (Object.values(SwitchInputType).includes(inputType)) {
|
if (Object.values(SwitchInputType).includes(inputType)) {
|
||||||
return (
|
return (
|
||||||
<Flex w="25%" justifyContent="space-between">
|
<Flex w="25%" justifyContent="space-between">
|
||||||
<Code h="75%">Off</Code>
|
<Text h="75%" fontWeight="bold" marginRight="2">
|
||||||
|
Off
|
||||||
|
</Text>
|
||||||
<Switch
|
<Switch
|
||||||
size="md"
|
size="md"
|
||||||
isChecked={variables[inputType]}
|
isChecked={variables[inputType]}
|
||||||
@@ -311,7 +315,9 @@ const InputField = ({
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Code h="75%">On</Code>
|
<Text h="75%" fontWeight="bold" marginLeft="2">
|
||||||
|
On
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ import {
|
|||||||
InputRightElement,
|
InputRightElement,
|
||||||
Text,
|
Text,
|
||||||
Link,
|
Link,
|
||||||
|
Tooltip,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useClient } from 'urql';
|
import { useClient } from 'urql';
|
||||||
import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa';
|
import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa';
|
||||||
@@ -186,7 +187,22 @@ const InviteMembersModal = ({
|
|||||||
isDisabled={disabled}
|
isDisabled={disabled}
|
||||||
size="sm"
|
size="sm"
|
||||||
>
|
>
|
||||||
<Center h="100%">Invite Members</Center>
|
<Center h="100%">
|
||||||
|
{disabled ? (
|
||||||
|
<Tooltip
|
||||||
|
mr={8}
|
||||||
|
mt={1}
|
||||||
|
hasArrow
|
||||||
|
bg="gray.300"
|
||||||
|
color="black"
|
||||||
|
label="Email verification is disabled, refer to 'Features' tab within 'Environment' to enable it."
|
||||||
|
>
|
||||||
|
Invite Members
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
'Invite Members'
|
||||||
|
)}
|
||||||
|
</Center>{' '}
|
||||||
</Button>
|
</Button>
|
||||||
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { Fragment, ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
IconButton,
|
IconButton,
|
||||||
Box,
|
Box,
|
||||||
@@ -17,16 +17,27 @@ import {
|
|||||||
MenuButton,
|
MenuButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
|
Accordion,
|
||||||
|
AccordionButton,
|
||||||
|
AccordionPanel,
|
||||||
|
AccordionItem,
|
||||||
|
useMediaQuery,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
FiHome,
|
FiUser,
|
||||||
FiCode,
|
FiCode,
|
||||||
FiSettings,
|
FiSettings,
|
||||||
FiMenu,
|
FiMenu,
|
||||||
FiUser,
|
|
||||||
FiUsers,
|
FiUsers,
|
||||||
FiChevronDown,
|
FiChevronDown,
|
||||||
} from 'react-icons/fi';
|
} from 'react-icons/fi';
|
||||||
|
import { BiCustomize } from 'react-icons/bi';
|
||||||
|
import { AiOutlineKey } from 'react-icons/ai';
|
||||||
|
import { SiOpenaccess, SiJsonwebtokens } from 'react-icons/si';
|
||||||
|
import { MdSecurity } from 'react-icons/md';
|
||||||
|
import { RiDatabase2Line } from 'react-icons/ri';
|
||||||
|
import { BsCheck2Circle } from 'react-icons/bs';
|
||||||
|
import { HiOutlineMail, HiOutlineOfficeBuilding } from 'react-icons/hi';
|
||||||
import { IconType } from 'react-icons';
|
import { IconType } from 'react-icons';
|
||||||
import { ReactText } from 'react';
|
import { ReactText } from 'react';
|
||||||
import { useMutation, useQuery } from 'urql';
|
import { useMutation, useQuery } from 'urql';
|
||||||
@@ -35,14 +46,70 @@ import { useAuthContext } from '../contexts/AuthContext';
|
|||||||
import { AdminLogout } from '../graphql/mutation';
|
import { AdminLogout } from '../graphql/mutation';
|
||||||
import { MetaQuery } from '../graphql/queries';
|
import { MetaQuery } from '../graphql/queries';
|
||||||
|
|
||||||
interface LinkItemProps {
|
interface SubRoutes {
|
||||||
name: string;
|
name: string;
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
route: string;
|
route: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LinkItemProps {
|
||||||
|
name: string;
|
||||||
|
icon: IconType;
|
||||||
|
route: string;
|
||||||
|
subRoutes?: SubRoutes[];
|
||||||
|
}
|
||||||
const LinkItems: Array<LinkItemProps> = [
|
const LinkItems: Array<LinkItemProps> = [
|
||||||
// { name: 'Home', icon: FiHome, route: '/' },
|
{
|
||||||
{ name: 'Environment Variables', icon: FiSettings, route: '/' },
|
name: 'Environment ',
|
||||||
|
icon: FiSettings,
|
||||||
|
route: '/',
|
||||||
|
subRoutes: [
|
||||||
|
{
|
||||||
|
name: 'OAuth Config',
|
||||||
|
icon: AiOutlineKey,
|
||||||
|
route: '/oauth-setting',
|
||||||
|
},
|
||||||
|
|
||||||
|
{ name: 'Roles', icon: FiUser, route: '/roles' },
|
||||||
|
{
|
||||||
|
name: 'JWT Secrets',
|
||||||
|
icon: SiJsonwebtokens,
|
||||||
|
route: '/jwt-config',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Session Storage',
|
||||||
|
icon: RiDatabase2Line,
|
||||||
|
route: '/session-storage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Email Configurations',
|
||||||
|
icon: HiOutlineMail,
|
||||||
|
route: '/email-config',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Domain White Listing',
|
||||||
|
icon: BsCheck2Circle,
|
||||||
|
route: '/whitelist-variables',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Organization Info',
|
||||||
|
icon: HiOutlineOfficeBuilding,
|
||||||
|
route: '/organization-info',
|
||||||
|
},
|
||||||
|
{ name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
|
||||||
|
{
|
||||||
|
name: 'Features',
|
||||||
|
icon: BiCustomize,
|
||||||
|
route: '/features',
|
||||||
|
},
|
||||||
|
{ name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
|
||||||
|
{
|
||||||
|
name: ' Security',
|
||||||
|
icon: MdSecurity,
|
||||||
|
route: '/admin-secret',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{ name: 'Users', icon: FiUsers, route: '/users' },
|
{ name: 'Users', icon: FiUsers, route: '/users' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -52,21 +119,28 @@ interface SidebarProps extends BoxProps {
|
|||||||
|
|
||||||
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
const [{ data }] = useQuery({ query: MetaQuery });
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
transition="3s ease"
|
transition="3s ease"
|
||||||
bg={useColorModeValue('white', 'gray.900')}
|
bg={useColorModeValue('white', 'gray.900')}
|
||||||
borderRight="1px"
|
borderRight="1px"
|
||||||
borderRightColor={useColorModeValue('gray.200', 'gray.700')}
|
borderRightColor={useColorModeValue('gray.200', 'gray.700')}
|
||||||
w={{ base: 'full', md: 60 }}
|
w={{ base: 'full', md: '64' }}
|
||||||
pos="fixed"
|
pos="fixed"
|
||||||
h="full"
|
h="full"
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Flex h="20" alignItems="center" mx="8" justifyContent="space-between">
|
<Flex
|
||||||
|
h="20"
|
||||||
|
alignItems="center"
|
||||||
|
mx="18"
|
||||||
|
justifyContent="space-between"
|
||||||
|
flexDirection="row"
|
||||||
|
>
|
||||||
<NavLink to="/">
|
<NavLink to="/">
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center" mt="6">
|
||||||
<Image
|
<Image
|
||||||
src="https://authorizer.dev/images/logo.png"
|
src="https://authorizer.dev/images/logo.png"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
@@ -79,17 +153,69 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
<CloseButton display={{ base: 'flex', md: 'none' }} onClick={onClose} />
|
<CloseButton display={{ base: 'flex', md: 'none' }} onClick={onClose} />
|
||||||
</Flex>
|
</Flex>
|
||||||
{LinkItems.map((link) => (
|
|
||||||
<NavLink key={link.name} to={link.route}>
|
<Accordion defaultIndex={[0]} allowMultiple>
|
||||||
|
<AccordionItem textAlign="center" border="none" w="100%">
|
||||||
|
{LinkItems.map((link) =>
|
||||||
|
link?.subRoutes ? (
|
||||||
|
<div key={link.name}>
|
||||||
|
<AccordionButton _focus={{ boxShadow: 'none' }}>
|
||||||
|
<Text as="div" fontSize="md">
|
||||||
<NavItem
|
<NavItem
|
||||||
icon={link.icon}
|
icon={link.icon}
|
||||||
color={pathname === link.route ? 'blue.500' : ''}
|
color={pathname === link.route ? 'blue.500' : ''}
|
||||||
|
style={{ outline: 'unset' }}
|
||||||
|
height={12}
|
||||||
|
ml={-1}
|
||||||
|
mb={isNotSmallerScreen ? -1 : -4}
|
||||||
|
w={isNotSmallerScreen ? '100%' : '310%'}
|
||||||
>
|
>
|
||||||
|
<Fragment>
|
||||||
{link.name}
|
{link.name}
|
||||||
|
<Box display={{ base: 'none', md: 'flex' }} ml={12}>
|
||||||
|
<FiChevronDown />
|
||||||
|
</Box>
|
||||||
|
</Fragment>
|
||||||
</NavItem>
|
</NavItem>
|
||||||
|
</Text>
|
||||||
|
</AccordionButton>
|
||||||
|
<AccordionPanel>
|
||||||
|
{link.subRoutes?.map((sublink) => (
|
||||||
|
<NavLink
|
||||||
|
key={sublink.name}
|
||||||
|
to={sublink.route}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
<Text as="div" fontSize="xs" ml={2}>
|
||||||
|
<NavItem
|
||||||
|
icon={sublink.icon}
|
||||||
|
color={pathname === sublink.route ? 'blue.500' : ''}
|
||||||
|
height={8}
|
||||||
|
>
|
||||||
|
{sublink.name}
|
||||||
|
</NavItem>{' '}
|
||||||
|
</Text>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
|
</AccordionPanel>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<NavLink key={link.name} to={link.route}>
|
||||||
|
{' '}
|
||||||
|
<Text as="div" fontSize="md" w="100%" mt={-2}>
|
||||||
|
<NavItem
|
||||||
|
icon={link.icon}
|
||||||
|
color={pathname === link.route ? 'blue.500' : ''}
|
||||||
|
height={12}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
{link.name}
|
||||||
|
</NavItem>{' '}
|
||||||
|
</Text>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
)}
|
||||||
<Link
|
<Link
|
||||||
href="/playground"
|
href="/playground"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -100,10 +226,14 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
>
|
>
|
||||||
<NavItem icon={FiCode}>API Playground</NavItem>
|
<NavItem icon={FiCode}>API Playground</NavItem>
|
||||||
</Link>
|
</Link>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
{data?.meta?.version && (
|
{data?.meta?.version && (
|
||||||
|
<Flex alignContent="center">
|
||||||
|
{' '}
|
||||||
<Text
|
<Text
|
||||||
color="gray.600"
|
color="gray.400"
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
@@ -112,6 +242,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
>
|
>
|
||||||
Current Version: {data.meta.version}
|
Current Version: {data.meta.version}
|
||||||
</Text>
|
</Text>
|
||||||
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -119,7 +250,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
|
|
||||||
interface NavItemProps extends FlexProps {
|
interface NavItemProps extends FlexProps {
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
children: ReactText;
|
children: ReactText | JSX.Element | JSX.Element[];
|
||||||
}
|
}
|
||||||
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
|
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
|
||||||
return (
|
return (
|
||||||
@@ -167,7 +298,7 @@ export const MobileNav = ({ onOpen, ...rest }: MobileProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
ml={{ base: 0, md: 60 }}
|
ml={{ base: 0, md: 64 }}
|
||||||
px={{ base: 4, md: 4 }}
|
px={{ base: 4, md: 4 }}
|
||||||
height="20"
|
height="20"
|
||||||
position="fixed"
|
position="fixed"
|
||||||
@@ -204,7 +335,7 @@ export const MobileNav = ({ onOpen, ...rest }: MobileProps) => {
|
|||||||
transition="all 0.3s"
|
transition="all 0.3s"
|
||||||
_focus={{ boxShadow: 'none' }}
|
_focus={{ boxShadow: 'none' }}
|
||||||
>
|
>
|
||||||
<HStack>
|
<HStack mr={5}>
|
||||||
<FiUser />
|
<FiUser />
|
||||||
<VStack
|
<VStack
|
||||||
display={{ base: 'none', md: 'flex' }}
|
display={{ base: 'none', md: 'flex' }}
|
||||||
|
@@ -7,6 +7,8 @@ export const TextInputType = {
|
|||||||
GOOGLE_CLIENT_ID: 'GOOGLE_CLIENT_ID',
|
GOOGLE_CLIENT_ID: 'GOOGLE_CLIENT_ID',
|
||||||
GITHUB_CLIENT_ID: 'GITHUB_CLIENT_ID',
|
GITHUB_CLIENT_ID: 'GITHUB_CLIENT_ID',
|
||||||
FACEBOOK_CLIENT_ID: 'FACEBOOK_CLIENT_ID',
|
FACEBOOK_CLIENT_ID: 'FACEBOOK_CLIENT_ID',
|
||||||
|
LINKEDIN_CLIENT_ID: 'LINKEDIN_CLIENT_ID',
|
||||||
|
APPLE_CLIENT_ID: 'APPLE_CLIENT_ID',
|
||||||
JWT_ROLE_CLAIM: 'JWT_ROLE_CLAIM',
|
JWT_ROLE_CLAIM: 'JWT_ROLE_CLAIM',
|
||||||
REDIS_URL: 'REDIS_URL',
|
REDIS_URL: 'REDIS_URL',
|
||||||
SMTP_HOST: 'SMTP_HOST',
|
SMTP_HOST: 'SMTP_HOST',
|
||||||
@@ -31,6 +33,8 @@ export const HiddenInputType = {
|
|||||||
GOOGLE_CLIENT_SECRET: 'GOOGLE_CLIENT_SECRET',
|
GOOGLE_CLIENT_SECRET: 'GOOGLE_CLIENT_SECRET',
|
||||||
GITHUB_CLIENT_SECRET: 'GITHUB_CLIENT_SECRET',
|
GITHUB_CLIENT_SECRET: 'GITHUB_CLIENT_SECRET',
|
||||||
FACEBOOK_CLIENT_SECRET: 'FACEBOOK_CLIENT_SECRET',
|
FACEBOOK_CLIENT_SECRET: 'FACEBOOK_CLIENT_SECRET',
|
||||||
|
LINKEDIN_CLIENT_SECRET: 'LINKEDIN_CLIENT_SECRET',
|
||||||
|
APPLE_CLIENT_SECRET: 'APPLE_CLIENT_SECRET',
|
||||||
JWT_SECRET: 'JWT_SECRET',
|
JWT_SECRET: 'JWT_SECRET',
|
||||||
SMTP_PASSWORD: 'SMTP_PASSWORD',
|
SMTP_PASSWORD: 'SMTP_PASSWORD',
|
||||||
ADMIN_SECRET: 'ADMIN_SECRET',
|
ADMIN_SECRET: 'ADMIN_SECRET',
|
||||||
@@ -62,6 +66,8 @@ export const SwitchInputType = {
|
|||||||
DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION',
|
DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION',
|
||||||
DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION',
|
DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION',
|
||||||
DISABLE_SIGN_UP: 'DISABLE_SIGN_UP',
|
DISABLE_SIGN_UP: 'DISABLE_SIGN_UP',
|
||||||
|
DISABLE_REDIS_FOR_ENV: 'DISABLE_REDIS_FOR_ENV',
|
||||||
|
DISABLE_STRONG_PASSWORD: 'DISABLE_STRONG_PASSWORD',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DateInputType = {
|
export const DateInputType = {
|
||||||
@@ -98,6 +104,10 @@ export interface envVarTypes {
|
|||||||
GITHUB_CLIENT_SECRET: string;
|
GITHUB_CLIENT_SECRET: string;
|
||||||
FACEBOOK_CLIENT_ID: string;
|
FACEBOOK_CLIENT_ID: string;
|
||||||
FACEBOOK_CLIENT_SECRET: string;
|
FACEBOOK_CLIENT_SECRET: string;
|
||||||
|
LINKEDIN_CLIENT_ID: string;
|
||||||
|
LINKEDIN_CLIENT_SECRET: string;
|
||||||
|
APPLE_CLIENT_ID: string;
|
||||||
|
APPLE_CLIENT_SECRET: string;
|
||||||
ROLES: [string] | [];
|
ROLES: [string] | [];
|
||||||
DEFAULT_ROLES: [string] | [];
|
DEFAULT_ROLES: [string] | [];
|
||||||
PROTECTED_ROLES: [string] | [];
|
PROTECTED_ROLES: [string] | [];
|
||||||
@@ -122,9 +132,24 @@ export interface envVarTypes {
|
|||||||
DISABLE_EMAIL_VERIFICATION: boolean;
|
DISABLE_EMAIL_VERIFICATION: boolean;
|
||||||
DISABLE_BASIC_AUTHENTICATION: boolean;
|
DISABLE_BASIC_AUTHENTICATION: boolean;
|
||||||
DISABLE_SIGN_UP: boolean;
|
DISABLE_SIGN_UP: boolean;
|
||||||
|
DISABLE_STRONG_PASSWORD: boolean;
|
||||||
OLD_ADMIN_SECRET: string;
|
OLD_ADMIN_SECRET: string;
|
||||||
DATABASE_NAME: string;
|
DATABASE_NAME: string;
|
||||||
DATABASE_TYPE: string;
|
DATABASE_TYPE: string;
|
||||||
DATABASE_URL: string;
|
DATABASE_URL: string;
|
||||||
ACCESS_TOKEN_EXPIRY_TIME: string;
|
ACCESS_TOKEN_EXPIRY_TIME: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const envSubViews = {
|
||||||
|
INSTANCE_INFO: 'instance-info',
|
||||||
|
ROLES: 'roles',
|
||||||
|
JWT_CONFIG: 'jwt-config',
|
||||||
|
SESSION_STORAGE: 'session-storage',
|
||||||
|
EMAIL_CONFIG: 'email-config',
|
||||||
|
WHITELIST_VARIABLES: 'whitelist-variables',
|
||||||
|
ORGANIZATION_INFO: 'organization-info',
|
||||||
|
ACCESS_TOKEN: 'access-token',
|
||||||
|
FEATURES: 'features',
|
||||||
|
ADMIN_SECRET: 'admin-secret',
|
||||||
|
DB_CRED: 'db-cred',
|
||||||
|
};
|
||||||
|
@@ -26,9 +26,13 @@ export const EnvVariablesQuery = `
|
|||||||
GITHUB_CLIENT_SECRET,
|
GITHUB_CLIENT_SECRET,
|
||||||
FACEBOOK_CLIENT_ID,
|
FACEBOOK_CLIENT_ID,
|
||||||
FACEBOOK_CLIENT_SECRET,
|
FACEBOOK_CLIENT_SECRET,
|
||||||
ROLES,
|
LINKEDIN_CLIENT_ID,
|
||||||
|
LINKEDIN_CLIENT_SECRET,
|
||||||
|
APPLE_CLIENT_ID,
|
||||||
|
APPLE_CLIENT_SECRET,
|
||||||
DEFAULT_ROLES,
|
DEFAULT_ROLES,
|
||||||
PROTECTED_ROLES,
|
PROTECTED_ROLES,
|
||||||
|
ROLES,
|
||||||
JWT_TYPE,
|
JWT_TYPE,
|
||||||
JWT_SECRET,
|
JWT_SECRET,
|
||||||
JWT_ROLE_CLAIM,
|
JWT_ROLE_CLAIM,
|
||||||
@@ -49,6 +53,8 @@ export const EnvVariablesQuery = `
|
|||||||
DISABLE_EMAIL_VERIFICATION,
|
DISABLE_EMAIL_VERIFICATION,
|
||||||
DISABLE_BASIC_AUTHENTICATION,
|
DISABLE_BASIC_AUTHENTICATION,
|
||||||
DISABLE_SIGN_UP,
|
DISABLE_SIGN_UP,
|
||||||
|
DISABLE_STRONG_PASSWORD,
|
||||||
|
DISABLE_REDIS_FOR_ENV,
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT,
|
CUSTOM_ACCESS_TOKEN_SCRIPT,
|
||||||
DATABASE_NAME,
|
DATABASE_NAME,
|
||||||
DATABASE_TYPE,
|
DATABASE_TYPE,
|
||||||
|
@@ -2,4 +2,9 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
ReactDOM.render(<App />, document.getElementById('root'));
|
ReactDOM.render(
|
||||||
|
<div>
|
||||||
|
<App />
|
||||||
|
</div>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
@@ -1,20 +1,28 @@
|
|||||||
import { Box, Flex, Image, Text, Spinner } from '@chakra-ui/react';
|
import {
|
||||||
|
Box,
|
||||||
|
Flex,
|
||||||
|
Image,
|
||||||
|
Text,
|
||||||
|
Spinner,
|
||||||
|
useMediaQuery,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useQuery } from 'urql';
|
import { useQuery } from 'urql';
|
||||||
import { MetaQuery } from '../graphql/queries';
|
import { MetaQuery } from '../graphql/queries';
|
||||||
|
|
||||||
export function AuthLayout({ children }: { children: React.ReactNode }) {
|
export function AuthLayout({ children }: { children: React.ReactNode }) {
|
||||||
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
flexWrap="wrap"
|
h="100vh"
|
||||||
h="100%"
|
|
||||||
bg="gray.100"
|
bg="gray.100"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
flexDirection="column"
|
direction={['column', 'column']}
|
||||||
|
padding={['2%', '2%', '2%', '2%']}
|
||||||
>
|
>
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center" maxW="100%">
|
||||||
<Image
|
<Image
|
||||||
src="https://authorizer.dev/images/logo.png"
|
src="https://authorizer.dev/images/logo.png"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
@@ -29,7 +37,15 @@ export function AuthLayout({ children }: { children: React.ReactNode }) {
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Box p="6" m="5" rounded="5" bg="white" w="500px" shadow="xl">
|
<Box
|
||||||
|
p="6"
|
||||||
|
m="5"
|
||||||
|
rounded="5"
|
||||||
|
bg="white"
|
||||||
|
w={isNotSmallerScreen ? '500px' : '450px'}
|
||||||
|
shadow="xl"
|
||||||
|
maxW="100%"
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
<Text color="gray.600" fontSize="sm">
|
<Text color="gray.600" fontSize="sm">
|
||||||
|
@@ -31,7 +31,7 @@ export function DashboardLayout({ children }: { children: ReactNode }) {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
{/* mobilenav */}
|
{/* mobilenav */}
|
||||||
<MobileNav onOpen={onOpen} />
|
<MobileNav onOpen={onOpen} />
|
||||||
<Box ml={{ base: 0, md: 60 }} p="4" pt="24">
|
<Box ml={{ base: 0, md: '64' }} p="4" pt="24">
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -101,10 +101,10 @@ export default function Auth() {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
isLoading={signUpResult.fetching || loginResult.fetching}
|
isLoading={signUpResult.fetching || loginResult.fetching}
|
||||||
|
loadingText="Submitting"
|
||||||
colorScheme="blue"
|
colorScheme="blue"
|
||||||
size="lg"
|
size="lg"
|
||||||
w="100%"
|
w="100%"
|
||||||
d="block"
|
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{isLogin ? 'Login' : 'Sign up'}
|
{isLogin ? 'Login' : 'Sign up'}
|
||||||
|
@@ -1,46 +1,35 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import {
|
import { useParams } from 'react-router-dom';
|
||||||
Box,
|
import { Box, Flex, Stack, Button, useToast } from '@chakra-ui/react';
|
||||||
Divider,
|
|
||||||
Flex,
|
|
||||||
Stack,
|
|
||||||
Center,
|
|
||||||
Text,
|
|
||||||
Button,
|
|
||||||
Input,
|
|
||||||
InputGroup,
|
|
||||||
InputRightElement,
|
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { useClient } from 'urql';
|
import { useClient } from 'urql';
|
||||||
import {
|
import { FaSave } from 'react-icons/fa';
|
||||||
FaGoogle,
|
|
||||||
FaGithub,
|
|
||||||
FaFacebookF,
|
|
||||||
FaSave,
|
|
||||||
FaRegEyeSlash,
|
|
||||||
FaRegEye,
|
|
||||||
} from 'react-icons/fa';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import InputField from '../components/InputField';
|
|
||||||
import { EnvVariablesQuery } from '../graphql/queries';
|
import { EnvVariablesQuery } from '../graphql/queries';
|
||||||
import {
|
import {
|
||||||
ArrayInputType,
|
|
||||||
SelectInputType,
|
SelectInputType,
|
||||||
HiddenInputType,
|
HiddenInputType,
|
||||||
TextInputType,
|
TextInputType,
|
||||||
TextAreaInputType,
|
|
||||||
SwitchInputType,
|
|
||||||
HMACEncryptionType,
|
HMACEncryptionType,
|
||||||
RSAEncryptionType,
|
RSAEncryptionType,
|
||||||
ECDSAEncryptionType,
|
ECDSAEncryptionType,
|
||||||
envVarTypes,
|
envVarTypes,
|
||||||
|
envSubViews,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { UpdateEnvVariables } from '../graphql/mutation';
|
import { UpdateEnvVariables } from '../graphql/mutation';
|
||||||
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
||||||
import GenerateKeysModal from '../components/GenerateKeysModal';
|
import OAuthConfig from '../components/EnvComponents/OAuthConfig';
|
||||||
|
import Roles from '../components/EnvComponents/Roles';
|
||||||
|
import JWTConfigurations from '../components/EnvComponents/JWTConfiguration';
|
||||||
|
import SessionStorage from '../components/EnvComponents/SessionStorage';
|
||||||
|
import EmailConfigurations from '../components/EnvComponents/EmailConfiguration';
|
||||||
|
import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting';
|
||||||
|
import OrganizationInfo from '../components/EnvComponents/OrganizationInfo';
|
||||||
|
import AccessToken from '../components/EnvComponents/AccessToken';
|
||||||
|
import Features from '../components/EnvComponents/Features';
|
||||||
|
import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret';
|
||||||
|
import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials';
|
||||||
|
|
||||||
export default function Environment() {
|
const Environment = () => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const [adminSecret, setAdminSecret] = React.useState<
|
const [adminSecret, setAdminSecret] = React.useState<
|
||||||
@@ -57,6 +46,10 @@ export default function Environment() {
|
|||||||
GITHUB_CLIENT_SECRET: '',
|
GITHUB_CLIENT_SECRET: '',
|
||||||
FACEBOOK_CLIENT_ID: '',
|
FACEBOOK_CLIENT_ID: '',
|
||||||
FACEBOOK_CLIENT_SECRET: '',
|
FACEBOOK_CLIENT_SECRET: '',
|
||||||
|
LINKEDIN_CLIENT_ID: '',
|
||||||
|
LINKEDIN_CLIENT_SECRET: '',
|
||||||
|
APPLE_CLIENT_ID: '',
|
||||||
|
APPLE_CLIENT_SECRET: '',
|
||||||
ROLES: [],
|
ROLES: [],
|
||||||
DEFAULT_ROLES: [],
|
DEFAULT_ROLES: [],
|
||||||
PROTECTED_ROLES: [],
|
PROTECTED_ROLES: [],
|
||||||
@@ -81,6 +74,7 @@ export default function Environment() {
|
|||||||
DISABLE_EMAIL_VERIFICATION: false,
|
DISABLE_EMAIL_VERIFICATION: false,
|
||||||
DISABLE_BASIC_AUTHENTICATION: false,
|
DISABLE_BASIC_AUTHENTICATION: false,
|
||||||
DISABLE_SIGN_UP: false,
|
DISABLE_SIGN_UP: false,
|
||||||
|
DISABLE_STRONG_PASSWORD: false,
|
||||||
OLD_ADMIN_SECRET: '',
|
OLD_ADMIN_SECRET: '',
|
||||||
DATABASE_NAME: '',
|
DATABASE_NAME: '',
|
||||||
DATABASE_TYPE: '',
|
DATABASE_TYPE: '',
|
||||||
@@ -94,17 +88,22 @@ export default function Environment() {
|
|||||||
GOOGLE_CLIENT_SECRET: false,
|
GOOGLE_CLIENT_SECRET: false,
|
||||||
GITHUB_CLIENT_SECRET: false,
|
GITHUB_CLIENT_SECRET: false,
|
||||||
FACEBOOK_CLIENT_SECRET: false,
|
FACEBOOK_CLIENT_SECRET: false,
|
||||||
|
LINKEDIN_CLIENT_SECRET: false,
|
||||||
|
APPLE_CLIENT_SECRET: false,
|
||||||
JWT_SECRET: false,
|
JWT_SECRET: false,
|
||||||
SMTP_PASSWORD: false,
|
SMTP_PASSWORD: false,
|
||||||
ADMIN_SECRET: false,
|
ADMIN_SECRET: false,
|
||||||
OLD_ADMIN_SECRET: false,
|
OLD_ADMIN_SECRET: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { sec } = useParams();
|
||||||
|
|
||||||
async function getData() {
|
async function getData() {
|
||||||
const {
|
const {
|
||||||
data: { _env: envData },
|
data: { _env: envData },
|
||||||
} = await client.query(EnvVariablesQuery).toPromise();
|
} = await client.query(EnvVariablesQuery).toPromise();
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
setEnvVariables({
|
setEnvVariables({
|
||||||
...envData,
|
...envData,
|
||||||
OLD_ADMIN_SECRET: envData.ADMIN_SECRET,
|
OLD_ADMIN_SECRET: envData.ADMIN_SECRET,
|
||||||
@@ -118,7 +117,7 @@ export default function Environment() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getData();
|
getData();
|
||||||
}, []);
|
}, [sec]);
|
||||||
|
|
||||||
const validateAdminSecretHandler = (event: any) => {
|
const validateAdminSecretHandler = (event: any) => {
|
||||||
if (envVariables.OLD_ADMIN_SECRET === event.target.value) {
|
if (envVariables.OLD_ADMIN_SECRET === event.target.value) {
|
||||||
@@ -200,636 +199,110 @@ export default function Environment() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderComponent = (tab: any) => {
|
||||||
|
switch (tab) {
|
||||||
|
case envSubViews.INSTANCE_INFO:
|
||||||
return (
|
return (
|
||||||
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
<OAuthConfig
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
envVariables={envVariables}
|
||||||
Your instance information
|
setVariables={setEnvVariables}
|
||||||
</Text>
|
fieldVisibility={fieldVisibility}
|
||||||
<Stack spacing={6} padding="2% 0%">
|
setFieldVisibility={setFieldVisibility}
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Client ID</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={() => {}}
|
|
||||||
inputType={TextInputType.CLIENT_ID}
|
|
||||||
placeholder="Client ID"
|
|
||||||
readOnly={true}
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.ROLES:
|
||||||
<Flex>
|
return (
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Roles variables={envVariables} setVariables={setEnvVariables} />
|
||||||
<Text fontSize="sm">Client Secret</Text>
|
);
|
||||||
</Flex>
|
case envSubViews.JWT_CONFIG:
|
||||||
<Center w="70%">
|
return (
|
||||||
<InputField
|
<JWTConfigurations
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
fieldVisibility={fieldVisibility}
|
fieldVisibility={fieldVisibility}
|
||||||
setFieldVisibility={setFieldVisibility}
|
setFieldVisibility={setFieldVisibility}
|
||||||
inputType={HiddenInputType.CLIENT_SECRET}
|
SelectInputType={SelectInputType.JWT_TYPE}
|
||||||
placeholder="Client Secret"
|
HMACEncryptionType={HMACEncryptionType}
|
||||||
readOnly={true}
|
RSAEncryptionType={RSAEncryptionType}
|
||||||
/>
|
ECDSAEncryptionType={ECDSAEncryptionType}
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Social Media Logins
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaGoogle style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.GOOGLE_CLIENT_ID}
|
|
||||||
placeholder="Google Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.GOOGLE_CLIENT_SECRET}
|
|
||||||
placeholder="Google Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaGithub style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.GITHUB_CLIENT_ID}
|
|
||||||
placeholder="Github Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.GITHUB_CLIENT_SECRET}
|
|
||||||
placeholder="Github Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaFacebookF style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.FACEBOOK_CLIENT_ID}
|
|
||||||
placeholder="Facebook Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.FACEBOOK_CLIENT_SECRET}
|
|
||||||
placeholder="Facebook Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Roles
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Default Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.DEFAULT_ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Protected Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.PROTECTED_ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Flex
|
|
||||||
width="100%"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
paddingTop="2%"
|
|
||||||
>
|
|
||||||
<Text fontSize="md" fontWeight="bold">
|
|
||||||
JWT (JSON Web Tokens) Configurations
|
|
||||||
</Text>
|
|
||||||
<Flex>
|
|
||||||
<GenerateKeysModal
|
|
||||||
jwtType={envVariables.JWT_TYPE}
|
|
||||||
getData={getData}
|
getData={getData}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
);
|
||||||
</Flex>
|
case envSubViews.SESSION_STORAGE:
|
||||||
<Stack spacing={6} padding="2% 0%">
|
return (
|
||||||
<Flex>
|
<SessionStorage
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">JWT Type:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={SelectInputType.JWT_TYPE}
|
RedisURL={TextInputType.REDIS_URL}
|
||||||
value={SelectInputType.JWT_TYPE}
|
|
||||||
options={{
|
|
||||||
...HMACEncryptionType,
|
|
||||||
...RSAEncryptionType,
|
|
||||||
...ECDSAEncryptionType,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Flex>
|
);
|
||||||
</Flex>
|
case envSubViews.EMAIL_CONFIG:
|
||||||
{Object.values(HMACEncryptionType).includes(envVariables.JWT_TYPE) ? (
|
return (
|
||||||
<Flex>
|
<EmailConfigurations
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">JWT Secret</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
fieldVisibility={fieldVisibility}
|
fieldVisibility={fieldVisibility}
|
||||||
setFieldVisibility={setFieldVisibility}
|
setFieldVisibility={setFieldVisibility}
|
||||||
inputType={HiddenInputType.JWT_SECRET}
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.WHITELIST_VARIABLES:
|
||||||
) : (
|
return (
|
||||||
<>
|
<DomainWhiteListing
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Public Key</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
|
||||||
placeholder="Add public key here"
|
|
||||||
minH="25vh"
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.ORGANIZATION_INFO:
|
||||||
<Flex>
|
return (
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<OrganizationInfo
|
||||||
<Text fontSize="sm">Private Key</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
|
||||||
placeholder="Add private key here"
|
|
||||||
minH="25vh"
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.ACCESS_TOKEN:
|
||||||
</>
|
return (
|
||||||
)}
|
<AccessToken
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">JWT Role Claim:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={TextInputType.JWT_ROLE_CLAIM}
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.FEATURES:
|
||||||
</Stack>
|
return (
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
<Features variables={envVariables} setVariables={setEnvVariables} />
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
);
|
||||||
Session Storage
|
case envSubViews.ADMIN_SECRET:
|
||||||
</Text>
|
return (
|
||||||
<Stack spacing={6} padding="2% 0%">
|
<SecurityAdminSecret
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Redis URL:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.REDIS_URL}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Email Configurations
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Host:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_HOST}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Port:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_PORT}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Username:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_USERNAME}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Password:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
fieldVisibility={fieldVisibility}
|
fieldVisibility={fieldVisibility}
|
||||||
setFieldVisibility={setFieldVisibility}
|
setFieldVisibility={setFieldVisibility}
|
||||||
inputType={HiddenInputType.SMTP_PASSWORD}
|
validateAdminSecretHandler={validateAdminSecretHandler}
|
||||||
|
adminSecret={adminSecret}
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
case envSubViews.DB_CRED:
|
||||||
<Flex>
|
return (
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<DatabaseCredentials
|
||||||
<Text fontSize="sm">From Email:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={TextInputType.SENDER_EMAIL}
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
default:
|
||||||
</Stack>
|
return (
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
<OAuthConfig
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
envVariables={envVariables}
|
||||||
White Listing
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Allowed Origins:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
inputType={ArrayInputType.ALLOWED_ORIGINS}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Organization Information
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Organization Name:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ORGANIZATION_NAME}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Organization Logo:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ORGANIZATION_LOGO}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Access Token
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Access Token Expiry Time:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ACCESS_TOKEN_EXPIRY_TIME}
|
|
||||||
placeholder="0h15m0s"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" direction="column">
|
|
||||||
<Text fontSize="sm">Custom Scripts:</Text>
|
|
||||||
<Text fontSize="sm">Used to add custom fields in ID token</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextAreaInputType.CUSTOM_ACCESS_TOKEN_SCRIPT}
|
|
||||||
placeholder="Add script here"
|
|
||||||
minH="25vh"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Disable Features
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Login Page:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Email Verification:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Magic Login Link:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Basic Authentication:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Sign Up:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Danger
|
|
||||||
</Text>
|
|
||||||
<Stack
|
|
||||||
spacing={6}
|
|
||||||
padding="0 5%"
|
|
||||||
marginTop="3%"
|
|
||||||
border="1px solid #ff7875"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<Stack spacing={6} padding="3% 0">
|
|
||||||
<Text fontStyle="italic" fontSize="sm" color="gray.600">
|
|
||||||
Note: Database related environment variables cannot be updated from
|
|
||||||
dashboard :(
|
|
||||||
</Text>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase Name:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_NAME}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase Type:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_TYPE}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase URL:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_URL}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Flex marginTop="3%">
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Old Admin Secret:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputGroup size="sm">
|
|
||||||
<Input
|
|
||||||
size="sm"
|
|
||||||
placeholder="Enter Old Admin Secret"
|
|
||||||
value={adminSecret.value as string}
|
|
||||||
onChange={(event: any) => validateAdminSecretHandler(event)}
|
|
||||||
type={
|
|
||||||
!fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
|
|
||||||
? 'password'
|
|
||||||
: 'text'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<InputRightElement
|
|
||||||
right="5px"
|
|
||||||
children={
|
|
||||||
<Flex>
|
|
||||||
{fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
|
|
||||||
<Center
|
|
||||||
w="25px"
|
|
||||||
margin="0 1.5%"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setFieldVisibility({
|
|
||||||
...fieldVisibility,
|
|
||||||
[HiddenInputType.OLD_ADMIN_SECRET]: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaRegEyeSlash color="#bfbfbf" />
|
|
||||||
</Center>
|
|
||||||
) : (
|
|
||||||
<Center
|
|
||||||
w="25px"
|
|
||||||
margin="0 1.5%"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setFieldVisibility({
|
|
||||||
...fieldVisibility,
|
|
||||||
[HiddenInputType.OLD_ADMIN_SECRET]: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaRegEye color="#bfbfbf" />
|
|
||||||
</Center>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex paddingBottom="3%">
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">New Admin Secret:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={HiddenInputType.ADMIN_SECRET}
|
|
||||||
fieldVisibility={fieldVisibility}
|
fieldVisibility={fieldVisibility}
|
||||||
setFieldVisibility={setFieldVisibility}
|
setFieldVisibility={setFieldVisibility}
|
||||||
isDisabled={adminSecret.disableInputField}
|
|
||||||
placeholder="Enter New Admin Secret"
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
);
|
||||||
</Flex>
|
}
|
||||||
</Stack>
|
};
|
||||||
<Divider marginTop="5%" marginBottom="2%" />
|
return (
|
||||||
<Stack spacing={6} padding="1% 0">
|
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
||||||
|
{renderComponent(sec)}
|
||||||
|
<Stack spacing={6} padding="1% 0" mt={4}>
|
||||||
<Flex justifyContent="end" alignItems="center">
|
<Flex justifyContent="end" alignItems="center">
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<FaSave />}
|
leftIcon={<FaSave />}
|
||||||
@@ -844,4 +317,6 @@ export default function Environment() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Environment;
|
||||||
|
@@ -14,6 +14,7 @@ export const AppRoutes = () => {
|
|||||||
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
<Suspense fallback={<></>}>
|
<Suspense fallback={<></>}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
@@ -23,13 +24,16 @@ export const AppRoutes = () => {
|
|||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Route path="/" element={<Environment />} />
|
<Route path="/" element={<Outlet />}>
|
||||||
|
<Route index element={<Environment />} />
|
||||||
|
<Route path="/:sec" element={<Environment />} />
|
||||||
|
</Route>
|
||||||
<Route path="users" element={<Users />} />
|
<Route path="users" element={<Users />} />
|
||||||
<Route path="environment" element={<Environment />} />
|
|
||||||
<Route path="*" element={<Home />} />
|
<Route path="*" element={<Home />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "authorizer",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
14
server/cli/cli.go
Normal file
14
server/cli/cli.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ARG_DB_URL is the cli arg variable for the database url
|
||||||
|
ARG_DB_URL *string
|
||||||
|
// ARG_DB_TYPE is the cli arg variable for the database type
|
||||||
|
ARG_DB_TYPE *string
|
||||||
|
// ARG_ENV_FILE is the cli arg variable for the env file
|
||||||
|
ARG_ENV_FILE *string
|
||||||
|
// ARG_LOG_LEVEL is the cli arg variable for the log level
|
||||||
|
ARG_LOG_LEVEL *string
|
||||||
|
// ARG_REDIS_URL is the cli arg variable for the redis url
|
||||||
|
ARG_REDIS_URL *string
|
||||||
|
)
|
18
server/constants/auth_methods.go
Normal file
18
server/constants/auth_methods.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AuthRecipeMethodBasicAuth is the basic_auth auth method
|
||||||
|
AuthRecipeMethodBasicAuth = "basic_auth"
|
||||||
|
// AuthRecipeMethodMagicLinkLogin is the magic_link_login auth method
|
||||||
|
AuthRecipeMethodMagicLinkLogin = "magic_link_login"
|
||||||
|
// AuthRecipeMethodGoogle is the google auth method
|
||||||
|
AuthRecipeMethodGoogle = "google"
|
||||||
|
// AuthRecipeMethodGithub is the github auth method
|
||||||
|
AuthRecipeMethodGithub = "github"
|
||||||
|
// AuthRecipeMethodFacebook is the facebook auth method
|
||||||
|
AuthRecipeMethodFacebook = "facebook"
|
||||||
|
// AuthRecipeMethodLinkedin is the linkedin auth method
|
||||||
|
AuthRecipeMethodLinkedIn = "linkedin"
|
||||||
|
// AuthRecipeMethodApple is the apple auth method
|
||||||
|
AuthRecipeMethodApple = "apple"
|
||||||
|
)
|
8
server/constants/cookie.go
Normal file
8
server/constants/cookie.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AppCookieName is the name of the cookie that is used to store the application token
|
||||||
|
AppCookieName = "cookie"
|
||||||
|
// AdminCookieName is the name of the cookie that is used to store the admin token
|
||||||
|
AdminCookieName = "authorizer-admin"
|
||||||
|
)
|
@@ -19,4 +19,10 @@ const (
|
|||||||
DbTypeMariaDB = "mariadb"
|
DbTypeMariaDB = "mariadb"
|
||||||
// DbTypeCassandra is the cassandra database type
|
// DbTypeCassandra is the cassandra database type
|
||||||
DbTypeCassandraDB = "cassandradb"
|
DbTypeCassandraDB = "cassandradb"
|
||||||
|
// DbTypeScyllaDB is the scylla database type
|
||||||
|
DbTypeScyllaDB = "scylladb"
|
||||||
|
// DbTypeCockroachDB is the cockroach database type
|
||||||
|
DbTypeCockroachDB = "cockroachdb"
|
||||||
|
// DbTypePlanetScaleDB is the planetscale database type
|
||||||
|
DbTypePlanetScaleDB = "planetscale"
|
||||||
)
|
)
|
||||||
|
@@ -3,14 +3,8 @@ package constants
|
|||||||
var VERSION = "0.0.1"
|
var VERSION = "0.0.1"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Envstore identifier
|
// TestEnv is used for testing
|
||||||
// StringStore string store identifier
|
TestEnv = "test"
|
||||||
StringStoreIdentifier = "stringStore"
|
|
||||||
// BoolStore bool store identifier
|
|
||||||
BoolStoreIdentifier = "boolStore"
|
|
||||||
// SliceStore slice store identifier
|
|
||||||
SliceStoreIdentifier = "sliceStore"
|
|
||||||
|
|
||||||
// EnvKeyEnv key for env variable ENV
|
// EnvKeyEnv key for env variable ENV
|
||||||
EnvKeyEnv = "ENV"
|
EnvKeyEnv = "ENV"
|
||||||
// EnvKeyEnvPath key for cli arg variable ENV_PATH
|
// EnvKeyEnvPath key for cli arg variable ENV_PATH
|
||||||
@@ -19,7 +13,6 @@ const (
|
|||||||
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
||||||
// EnvKeyPort key for env variable PORT
|
// EnvKeyPort key for env variable PORT
|
||||||
EnvKeyPort = "PORT"
|
EnvKeyPort = "PORT"
|
||||||
|
|
||||||
// EnvKeyAccessTokenExpiryTime key for env variable ACCESS_TOKEN_EXPIRY_TIME
|
// EnvKeyAccessTokenExpiryTime key for env variable ACCESS_TOKEN_EXPIRY_TIME
|
||||||
EnvKeyAccessTokenExpiryTime = "ACCESS_TOKEN_EXPIRY_TIME"
|
EnvKeyAccessTokenExpiryTime = "ACCESS_TOKEN_EXPIRY_TIME"
|
||||||
// EnvKeyAdminSecret key for env variable ADMIN_SECRET
|
// EnvKeyAdminSecret key for env variable ADMIN_SECRET
|
||||||
@@ -62,34 +55,12 @@ const (
|
|||||||
EnvKeyJwtPrivateKey = "JWT_PRIVATE_KEY"
|
EnvKeyJwtPrivateKey = "JWT_PRIVATE_KEY"
|
||||||
// EnvKeyJwtPublicKey key for env variable JWT_PUBLIC_KEY
|
// EnvKeyJwtPublicKey key for env variable JWT_PUBLIC_KEY
|
||||||
EnvKeyJwtPublicKey = "JWT_PUBLIC_KEY"
|
EnvKeyJwtPublicKey = "JWT_PUBLIC_KEY"
|
||||||
// EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS
|
|
||||||
EnvKeyAllowedOrigins = "ALLOWED_ORIGINS"
|
|
||||||
// EnvKeyAppURL key for env variable APP_URL
|
// EnvKeyAppURL key for env variable APP_URL
|
||||||
EnvKeyAppURL = "APP_URL"
|
EnvKeyAppURL = "APP_URL"
|
||||||
// EnvKeyRedisURL key for env variable REDIS_URL
|
// EnvKeyRedisURL key for env variable REDIS_URL
|
||||||
EnvKeyRedisURL = "REDIS_URL"
|
EnvKeyRedisURL = "REDIS_URL"
|
||||||
// EnvKeyCookieName key for env variable COOKIE_NAME
|
|
||||||
EnvKeyCookieName = "COOKIE_NAME"
|
|
||||||
// EnvKeyAdminCookieName key for env variable ADMIN_COOKIE_NAME
|
|
||||||
EnvKeyAdminCookieName = "ADMIN_COOKIE_NAME"
|
|
||||||
// EnvKeyResetPasswordURL key for env variable RESET_PASSWORD_URL
|
// EnvKeyResetPasswordURL key for env variable RESET_PASSWORD_URL
|
||||||
EnvKeyResetPasswordURL = "RESET_PASSWORD_URL"
|
EnvKeyResetPasswordURL = "RESET_PASSWORD_URL"
|
||||||
// EnvKeyDisableEmailVerification key for env variable DISABLE_EMAIL_VERIFICATION
|
|
||||||
EnvKeyDisableEmailVerification = "DISABLE_EMAIL_VERIFICATION"
|
|
||||||
// EnvKeyDisableBasicAuthentication key for env variable DISABLE_BASIC_AUTH
|
|
||||||
EnvKeyDisableBasicAuthentication = "DISABLE_BASIC_AUTHENTICATION"
|
|
||||||
// EnvKeyDisableMagicLinkLogin key for env variable DISABLE_MAGIC_LINK_LOGIN
|
|
||||||
EnvKeyDisableMagicLinkLogin = "DISABLE_MAGIC_LINK_LOGIN"
|
|
||||||
// EnvKeyDisableLoginPage key for env variable DISABLE_LOGIN_PAGE
|
|
||||||
EnvKeyDisableLoginPage = "DISABLE_LOGIN_PAGE"
|
|
||||||
// EnvKeyDisableSignUp key for env variable DISABLE_SIGN_UP
|
|
||||||
EnvKeyDisableSignUp = "DISABLE_SIGN_UP"
|
|
||||||
// EnvKeyRoles key for env variable ROLES
|
|
||||||
EnvKeyRoles = "ROLES"
|
|
||||||
// EnvKeyProtectedRoles key for env variable PROTECTED_ROLES
|
|
||||||
EnvKeyProtectedRoles = "PROTECTED_ROLES"
|
|
||||||
// EnvKeyDefaultRoles key for env variable DEFAULT_ROLES
|
|
||||||
EnvKeyDefaultRoles = "DEFAULT_ROLES"
|
|
||||||
// EnvKeyJwtRoleClaim key for env variable JWT_ROLE_CLAIM
|
// EnvKeyJwtRoleClaim key for env variable JWT_ROLE_CLAIM
|
||||||
EnvKeyJwtRoleClaim = "JWT_ROLE_CLAIM"
|
EnvKeyJwtRoleClaim = "JWT_ROLE_CLAIM"
|
||||||
// EnvKeyGoogleClientID key for env variable GOOGLE_CLIENT_ID
|
// EnvKeyGoogleClientID key for env variable GOOGLE_CLIENT_ID
|
||||||
@@ -104,6 +75,14 @@ const (
|
|||||||
EnvKeyFacebookClientID = "FACEBOOK_CLIENT_ID"
|
EnvKeyFacebookClientID = "FACEBOOK_CLIENT_ID"
|
||||||
// EnvKeyFacebookClientSecret key for env variable FACEBOOK_CLIENT_SECRET
|
// EnvKeyFacebookClientSecret key for env variable FACEBOOK_CLIENT_SECRET
|
||||||
EnvKeyFacebookClientSecret = "FACEBOOK_CLIENT_SECRET"
|
EnvKeyFacebookClientSecret = "FACEBOOK_CLIENT_SECRET"
|
||||||
|
// EnvKeyLinkedinClientID key for env variable LINKEDIN_CLIENT_ID
|
||||||
|
EnvKeyLinkedInClientID = "LINKEDIN_CLIENT_ID"
|
||||||
|
// EnvKeyLinkedinClientSecret key for env variable LINKEDIN_CLIENT_SECRET
|
||||||
|
EnvKeyLinkedInClientSecret = "LINKEDIN_CLIENT_SECRET"
|
||||||
|
// EnvKeyAppleClientID key for env variable APPLE_CLIENT_ID
|
||||||
|
EnvKeyAppleClientID = "APPLE_CLIENT_ID"
|
||||||
|
// EnvKeyAppleClientSecret key for env variable APPLE_CLIENT_SECRET
|
||||||
|
EnvKeyAppleClientSecret = "APPLE_CLIENT_SECRET"
|
||||||
// EnvKeyOrganizationName key for env variable ORGANIZATION_NAME
|
// EnvKeyOrganizationName key for env variable ORGANIZATION_NAME
|
||||||
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
||||||
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
||||||
@@ -120,6 +99,32 @@ const (
|
|||||||
EnvKeyEncryptionKey = "ENCRYPTION_KEY"
|
EnvKeyEncryptionKey = "ENCRYPTION_KEY"
|
||||||
// EnvKeyJWK key for env variable JWK
|
// EnvKeyJWK key for env variable JWK
|
||||||
EnvKeyJWK = "JWK"
|
EnvKeyJWK = "JWK"
|
||||||
|
|
||||||
|
// Boolean variables
|
||||||
// EnvKeyIsProd key for env variable IS_PROD
|
// EnvKeyIsProd key for env variable IS_PROD
|
||||||
EnvKeyIsProd = "IS_PROD"
|
EnvKeyIsProd = "IS_PROD"
|
||||||
|
// EnvKeyDisableEmailVerification key for env variable DISABLE_EMAIL_VERIFICATION
|
||||||
|
EnvKeyDisableEmailVerification = "DISABLE_EMAIL_VERIFICATION"
|
||||||
|
// EnvKeyDisableBasicAuthentication key for env variable DISABLE_BASIC_AUTH
|
||||||
|
EnvKeyDisableBasicAuthentication = "DISABLE_BASIC_AUTHENTICATION"
|
||||||
|
// EnvKeyDisableMagicLinkLogin key for env variable DISABLE_MAGIC_LINK_LOGIN
|
||||||
|
EnvKeyDisableMagicLinkLogin = "DISABLE_MAGIC_LINK_LOGIN"
|
||||||
|
// EnvKeyDisableLoginPage key for env variable DISABLE_LOGIN_PAGE
|
||||||
|
EnvKeyDisableLoginPage = "DISABLE_LOGIN_PAGE"
|
||||||
|
// EnvKeyDisableSignUp key for env variable DISABLE_SIGN_UP
|
||||||
|
EnvKeyDisableSignUp = "DISABLE_SIGN_UP"
|
||||||
|
// EnvKeyDisableRedisForEnv key for env variable DISABLE_REDIS_FOR_ENV
|
||||||
|
EnvKeyDisableRedisForEnv = "DISABLE_REDIS_FOR_ENV"
|
||||||
|
// EnvKeyDisableStrongPassword key for env variable DISABLE_STRONG_PASSWORD
|
||||||
|
EnvKeyDisableStrongPassword = "DISABLE_STRONG_PASSWORD"
|
||||||
|
|
||||||
|
// Slice variables
|
||||||
|
// EnvKeyRoles key for env variable ROLES
|
||||||
|
EnvKeyRoles = "ROLES"
|
||||||
|
// EnvKeyProtectedRoles key for env variable PROTECTED_ROLES
|
||||||
|
EnvKeyProtectedRoles = "PROTECTED_ROLES"
|
||||||
|
// EnvKeyDefaultRoles key for env variable DEFAULT_ROLES
|
||||||
|
EnvKeyDefaultRoles = "DEFAULT_ROLES"
|
||||||
|
// EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS
|
||||||
|
EnvKeyAllowedOrigins = "ALLOWED_ORIGINS"
|
||||||
)
|
)
|
||||||
|
@@ -8,4 +8,7 @@ const (
|
|||||||
FacebookUserInfoURL = "https://graph.facebook.com/me?fields=id,first_name,last_name,name,email,picture&access_token="
|
FacebookUserInfoURL = "https://graph.facebook.com/me?fields=id,first_name,last_name,name,email,picture&access_token="
|
||||||
// Ref: https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#3-your-github-app-accesses-the-api-with-the-users-access-token
|
// Ref: https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#3-your-github-app-accesses-the-api-with-the-users-access-token
|
||||||
GithubUserInfoURL = "https://api.github.com/user"
|
GithubUserInfoURL = "https://api.github.com/user"
|
||||||
|
// Ref: https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api
|
||||||
|
LinkedInUserInfoURL = "https://api.linkedin.com/v2/me?projection=(id,localizedFirstName,localizedLastName,emailAddress,profilePicture(displayImage~:playableStreams))"
|
||||||
|
LinkedInEmailURL = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))"
|
||||||
)
|
)
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
package constants
|
|
||||||
|
|
||||||
const (
|
|
||||||
// SignupMethodBasicAuth is the basic_auth signup method
|
|
||||||
SignupMethodBasicAuth = "basic_auth"
|
|
||||||
// SignupMethodMagicLinkLogin is the magic_link_login signup method
|
|
||||||
SignupMethodMagicLinkLogin = "magic_link_login"
|
|
||||||
// SignupMethodGoogle is the google signup method
|
|
||||||
SignupMethodGoogle = "google"
|
|
||||||
// SignupMethodGithub is the github signup method
|
|
||||||
SignupMethodGithub = "github"
|
|
||||||
// SignupMethodFacebook is the facebook signup method
|
|
||||||
SignupMethodFacebook = "facebook"
|
|
||||||
)
|
|
@@ -7,4 +7,6 @@ const (
|
|||||||
TokenTypeAccessToken = "access_token"
|
TokenTypeAccessToken = "access_token"
|
||||||
// TokenTypeIdentityToken is the identity_token token type
|
// TokenTypeIdentityToken is the identity_token token type
|
||||||
TokenTypeIdentityToken = "id_token"
|
TokenTypeIdentityToken = "id_token"
|
||||||
|
// TokenTypeSessionToken is the session_token type used for browser session
|
||||||
|
TokenTypeSessionToken = "session_token"
|
||||||
)
|
)
|
||||||
|
18
server/constants/webhook_event.go
Normal file
18
server/constants/webhook_event.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// UserLoginWebhookEvent name for login event
|
||||||
|
UserLoginWebhookEvent = `user.login`
|
||||||
|
// UserCreatedWebhookEvent name for user creation event
|
||||||
|
// This is triggered when user entry is created but still not verified
|
||||||
|
UserCreatedWebhookEvent = `user.created`
|
||||||
|
// UserSignUpWebhookEvent name for signup event
|
||||||
|
UserSignUpWebhookEvent = `user.signup`
|
||||||
|
// UserAccessRevokedWebhookEvent name for user access revoke event
|
||||||
|
UserAccessRevokedWebhookEvent = `user.access_revoked`
|
||||||
|
// UserAccessEnabledWebhookEvent name for user access enable event
|
||||||
|
UserAccessEnabledWebhookEvent = `user.access_enabled`
|
||||||
|
// UserDeletedWebhookEvent name for user deleted event
|
||||||
|
UserDeletedWebhookEvent = `user.deleted`
|
||||||
|
)
|
@@ -4,8 +4,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/parsers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,15 +12,14 @@ import (
|
|||||||
func SetAdminCookie(gc *gin.Context, token string) {
|
func SetAdminCookie(gc *gin.Context, token string) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
hostname := utils.GetHost(gc)
|
hostname := parsers.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := parsers.GetHostParts(hostname)
|
||||||
|
gc.SetCookie(constants.AdminCookieName, token, 3600, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), token, 3600, "/", host, secure, httpOnly)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAdminCookie gets the admin cookie from the request
|
// GetAdminCookie gets the admin cookie from the request
|
||||||
func GetAdminCookie(gc *gin.Context) (string, error) {
|
func GetAdminCookie(gc *gin.Context) (string, error) {
|
||||||
cookie, err := gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName))
|
cookie, err := gc.Request.Cookie(constants.AdminCookieName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -39,8 +37,7 @@ func GetAdminCookie(gc *gin.Context) (string, error) {
|
|||||||
func DeleteAdminCookie(gc *gin.Context) {
|
func DeleteAdminCookie(gc *gin.Context) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
hostname := utils.GetHost(gc)
|
hostname := parsers.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := parsers.GetHostParts(hostname)
|
||||||
|
gc.SetCookie(constants.AdminCookieName, "", -1, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), "", -1, "/", host, secure, httpOnly)
|
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/parsers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,9 +13,9 @@ import (
|
|||||||
func SetSession(gc *gin.Context, sessionID string) {
|
func SetSession(gc *gin.Context, sessionID string) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
hostname := utils.GetHost(gc)
|
hostname := parsers.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := parsers.GetHostParts(hostname)
|
||||||
domain := utils.GetDomainName(hostname)
|
domain := parsers.GetDomainName(hostname)
|
||||||
if domain != "localhost" {
|
if domain != "localhost" {
|
||||||
domain = "." + domain
|
domain = "." + domain
|
||||||
}
|
}
|
||||||
@@ -25,33 +24,33 @@ func SetSession(gc *gin.Context, sessionID string) {
|
|||||||
year := 60 * 60 * 24 * 365
|
year := 60 * 60 * 24 * 365
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", sessionID, year, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.AppCookieName+"_session", sessionID, year, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session_domain", sessionID, year, "/", domain, secure, httpOnly)
|
gc.SetCookie(constants.AppCookieName+"_session_domain", sessionID, year, "/", domain, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession sets session cookies to expire
|
// DeleteSession sets session cookies to expire
|
||||||
func DeleteSession(gc *gin.Context) {
|
func DeleteSession(gc *gin.Context) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
hostname := utils.GetHost(gc)
|
hostname := parsers.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := parsers.GetHostParts(hostname)
|
||||||
domain := utils.GetDomainName(hostname)
|
domain := parsers.GetDomainName(hostname)
|
||||||
if domain != "localhost" {
|
if domain != "localhost" {
|
||||||
domain = "." + domain
|
domain = "." + domain
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", "", -1, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.AppCookieName+"_session", "", -1, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session_domain", "", -1, "/", domain, secure, httpOnly)
|
gc.SetCookie(constants.AppCookieName+"_session_domain", "", -1, "/", domain, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSession gets the session cookie from context
|
// GetSession gets the session cookie from context
|
||||||
func GetSession(gc *gin.Context) (string, error) {
|
func GetSession(gc *gin.Context) (string, error) {
|
||||||
var cookie *http.Cookie
|
var cookie *http.Cookie
|
||||||
var err error
|
var err error
|
||||||
cookie, err = gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + "_session")
|
cookie, err = gc.Request.Cookie(constants.AppCookieName + "_session")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cookie, err = gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + "_session_domain")
|
cookie, err = gc.Request.Cookie(constants.AppCookieName + "_session_domain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@@ -7,14 +7,18 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
var bytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 0o5}
|
var bytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 0o5}
|
||||||
|
|
||||||
// EncryptAES method is to encrypt or hide any classified text
|
// EncryptAES method is to encrypt or hide any classified text
|
||||||
func EncryptAES(text string) (string, error) {
|
func EncryptAES(text string) (string, error) {
|
||||||
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
k, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
key := []byte(k)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -28,7 +32,11 @@ func EncryptAES(text string) (string, error) {
|
|||||||
|
|
||||||
// DecryptAES method is to extract back the encrypted text
|
// DecryptAES method is to extract back the encrypted text
|
||||||
func DecryptAES(text string) (string, error) {
|
func DecryptAES(text string) (string, error) {
|
||||||
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
k, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
key := []byte(k)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -46,9 +54,13 @@ func DecryptAES(text string) (string, error) {
|
|||||||
// EncryptAESEnv encrypts data using AES algorithm
|
// EncryptAESEnv encrypts data using AES algorithm
|
||||||
// kept for the backward compatibility of env data encryption
|
// kept for the backward compatibility of env data encryption
|
||||||
func EncryptAESEnv(text []byte) ([]byte, error) {
|
func EncryptAESEnv(text []byte) ([]byte, error) {
|
||||||
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
|
||||||
c, err := aes.NewCipher(key)
|
|
||||||
var res []byte
|
var res []byte
|
||||||
|
k, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
key := []byte(k)
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -81,9 +93,13 @@ func EncryptAESEnv(text []byte) ([]byte, error) {
|
|||||||
// DecryptAES decrypts data using AES algorithm
|
// DecryptAES decrypts data using AES algorithm
|
||||||
// Kept for the backward compatibility of env data decryption
|
// Kept for the backward compatibility of env data decryption
|
||||||
func DecryptAESEnv(ciphertext []byte) ([]byte, error) {
|
func DecryptAESEnv(ciphertext []byte) ([]byte, error) {
|
||||||
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
|
||||||
c, err := aes.NewCipher(key)
|
|
||||||
var res []byte
|
var res []byte
|
||||||
|
k, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
key := []byte(k)
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
@@ -37,20 +37,35 @@ func GetPubJWK(algo, keyID string, publicKey interface{}) (string, error) {
|
|||||||
// this is called while initializing app / when env is updated
|
// this is called while initializing app / when env is updated
|
||||||
func GenerateJWKBasedOnEnv() (string, error) {
|
func GenerateJWKBasedOnEnv() (string, error) {
|
||||||
jwk := ""
|
jwk := ""
|
||||||
algo := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
algo, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||||
clientID := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
if err != nil {
|
||||||
|
return jwk, err
|
||||||
|
}
|
||||||
|
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
||||||
|
if err != nil {
|
||||||
|
return jwk, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
|
||||||
|
if err != nil {
|
||||||
|
return jwk, err
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
// check if jwt secret is provided
|
// check if jwt secret is provided
|
||||||
if IsHMACA(algo) {
|
if IsHMACA(algo) {
|
||||||
jwk, err = GetPubJWK(algo, clientID, []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
jwk, err = GetPubJWK(algo, clientID, []byte(jwtSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return jwk, err
|
||||||
|
}
|
||||||
|
|
||||||
if IsRSA(algo) {
|
if IsRSA(algo) {
|
||||||
publicKeyInstance, err := ParseRsaPublicKeyFromPemStr(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey))
|
publicKeyInstance, err := ParseRsaPublicKeyFromPemStr(jwtPublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -62,7 +77,11 @@ func GenerateJWKBasedOnEnv() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if IsECDSA(algo) {
|
if IsECDSA(algo) {
|
||||||
publicKeyInstance, err := ParseEcdsaPublicKeyFromPemStr(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey))
|
jwtPublicKey, err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return jwk, err
|
||||||
|
}
|
||||||
|
publicKeyInstance, err := ParseEcdsaPublicKeyFromPemStr(jwtPublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -77,13 +96,16 @@ func GenerateJWKBasedOnEnv() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EncryptEnvData is used to encrypt the env data
|
// EncryptEnvData is used to encrypt the env data
|
||||||
func EncryptEnvData(data envstore.Store) (string, error) {
|
func EncryptEnvData(data map[string]interface{}) (string, error) {
|
||||||
jsonBytes, err := json.Marshal(data)
|
jsonBytes, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
storeData := envstore.EnvStoreObj.GetEnvStoreClone()
|
storeData, err := memorystore.Provider.GetEnvStore()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(jsonBytes, &storeData)
|
err = json.Unmarshal(jsonBytes, &storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers"
|
"github.com/authorizerdev/authorizer/server/db/providers"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/cassandradb"
|
"github.com/authorizerdev/authorizer/server/db/providers/cassandradb"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
|
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/sql"
|
"github.com/authorizerdev/authorizer/server/db/providers/sql"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provider returns the current database provider
|
// Provider returns the current database provider
|
||||||
@@ -16,35 +18,45 @@ var Provider providers.Provider
|
|||||||
func InitDB() error {
|
func InitDB() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeCassandraDB
|
envs := memorystore.RequiredEnvStoreObj.GetRequiredEnv()
|
||||||
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
|
|
||||||
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
|
isSQL := envs.DatabaseType != constants.DbTypeArangodb && envs.DatabaseType != constants.DbTypeMongodb && envs.DatabaseType != constants.DbTypeCassandraDB && envs.DatabaseType != constants.DbTypeScyllaDB
|
||||||
isCassandra := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeCassandraDB
|
isArangoDB := envs.DatabaseType == constants.DbTypeArangodb
|
||||||
|
isMongoDB := envs.DatabaseType == constants.DbTypeMongodb
|
||||||
|
isCassandra := envs.DatabaseType == constants.DbTypeCassandraDB || envs.DatabaseType == constants.DbTypeScyllaDB
|
||||||
|
|
||||||
if isSQL {
|
if isSQL {
|
||||||
|
log.Info("Initializing SQL Driver for: ", envs.DatabaseType)
|
||||||
Provider, err = sql.NewProvider()
|
Provider, err = sql.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize SQL driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isArangoDB {
|
if isArangoDB {
|
||||||
|
log.Info("Initializing ArangoDB Driver")
|
||||||
Provider, err = arangodb.NewProvider()
|
Provider, err = arangodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize ArangoDB driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isMongoDB {
|
if isMongoDB {
|
||||||
|
log.Info("Initializing MongoDB Driver")
|
||||||
Provider, err = mongodb.NewProvider()
|
Provider, err = mongodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize MongoDB driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isCassandra {
|
if isCassandra {
|
||||||
|
log.Info("Initializing CassandraDB Driver")
|
||||||
Provider, err = cassandradb.NewProvider()
|
Provider, err = cassandradb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize CassandraDB driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,8 @@ type CollectionList struct {
|
|||||||
VerificationRequest string
|
VerificationRequest string
|
||||||
Session string
|
Session string
|
||||||
Env string
|
Env string
|
||||||
|
Webhook string
|
||||||
|
WebhookLog string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -17,5 +19,7 @@ var (
|
|||||||
VerificationRequest: Prefix + "verification_requests",
|
VerificationRequest: Prefix + "verification_requests",
|
||||||
Session: Prefix + "sessions",
|
Session: Prefix + "sessions",
|
||||||
Env: Prefix + "env",
|
Env: Prefix + "env",
|
||||||
|
Webhook: Prefix + "webhook",
|
||||||
|
WebhookLog: Prefix + "webhook_log",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -6,8 +6,7 @@ package models
|
|||||||
type Session struct {
|
type Session struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id" cql:"user_id"`
|
UserID string `gorm:"type:char(36)" json:"user_id" bson:"user_id" cql:"user_id"`
|
||||||
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"`
|
|
||||||
UserAgent string `json:"user_agent" bson:"user_agent" cql:"user_agent"`
|
UserAgent string `json:"user_agent" bson:"user_agent" cql:"user_agent"`
|
||||||
IP string `json:"ip" bson:"ip" cql:"ip"`
|
IP string `json:"ip" bson:"ip" cql:"ip"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
|
@@ -38,9 +38,13 @@ func (user *User) AsAPIUser() *model.User {
|
|||||||
email := user.Email
|
email := user.Email
|
||||||
createdAt := user.CreatedAt
|
createdAt := user.CreatedAt
|
||||||
updatedAt := user.UpdatedAt
|
updatedAt := user.UpdatedAt
|
||||||
revokedTimestamp := user.RevokedTimestamp
|
|
||||||
|
id := user.ID
|
||||||
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.WebhookLog+"/")
|
||||||
|
}
|
||||||
return &model.User{
|
return &model.User{
|
||||||
ID: user.ID,
|
ID: id,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
EmailVerified: isEmailVerified,
|
EmailVerified: isEmailVerified,
|
||||||
SignupMethods: user.SignupMethods,
|
SignupMethods: user.SignupMethods,
|
||||||
@@ -55,7 +59,7 @@ func (user *User) AsAPIUser() *model.User {
|
|||||||
PhoneNumberVerified: &isPhoneVerified,
|
PhoneNumberVerified: &isPhoneVerified,
|
||||||
Picture: user.Picture,
|
Picture: user.Picture,
|
||||||
Roles: strings.Split(user.Roles, ","),
|
Roles: strings.Split(user.Roles, ","),
|
||||||
RevokedTimestamp: revokedTimestamp,
|
RevokedTimestamp: user.RevokedTimestamp,
|
||||||
CreatedAt: &createdAt,
|
CreatedAt: &createdAt,
|
||||||
UpdatedAt: &updatedAt,
|
UpdatedAt: &updatedAt,
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/authorizerdev/authorizer/server/graph/model"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
)
|
||||||
|
|
||||||
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
@@ -27,8 +31,13 @@ func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequ
|
|||||||
redirectURI := v.RedirectURI
|
redirectURI := v.RedirectURI
|
||||||
expires := v.ExpiresAt
|
expires := v.ExpiresAt
|
||||||
identifier := v.Identifier
|
identifier := v.Identifier
|
||||||
|
|
||||||
|
id := v.ID
|
||||||
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.WebhookLog+"/")
|
||||||
|
}
|
||||||
return &model.VerificationRequest{
|
return &model.VerificationRequest{
|
||||||
ID: v.ID,
|
ID: id,
|
||||||
Token: &token,
|
Token: &token,
|
||||||
Identifier: &identifier,
|
Identifier: &identifier,
|
||||||
Expires: &expires,
|
Expires: &expires,
|
||||||
|
41
server/db/models/webhook.go
Normal file
41
server/db/models/webhook.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
|
// Webhook model for db
|
||||||
|
type Webhook struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
|
EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"`
|
||||||
|
EndPoint string `gorm:"type:text" json:"endpoint" bson:"endpoint" cql:"endpoint"`
|
||||||
|
Headers string `gorm:"type:text" json:"headers" bson:"headers" cql:"headers"`
|
||||||
|
Enabled bool `json:"enabled" bson:"enabled" cql:"enabled"`
|
||||||
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Webhook) AsAPIWebhook() *model.Webhook {
|
||||||
|
headersMap := make(map[string]interface{})
|
||||||
|
json.Unmarshal([]byte(w.Headers), &headersMap)
|
||||||
|
|
||||||
|
id := w.ID
|
||||||
|
if strings.Contains(id, Collections.Webhook+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.Webhook+"/")
|
||||||
|
}
|
||||||
|
return &model.Webhook{
|
||||||
|
ID: id,
|
||||||
|
EventName: &w.EventName,
|
||||||
|
Endpoint: &w.EndPoint,
|
||||||
|
Headers: headersMap,
|
||||||
|
Enabled: &w.Enabled,
|
||||||
|
CreatedAt: &w.CreatedAt,
|
||||||
|
UpdatedAt: &w.UpdatedAt,
|
||||||
|
}
|
||||||
|
}
|
37
server/db/models/webhook_log.go
Normal file
37
server/db/models/webhook_log.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
|
// WebhookLog model for db
|
||||||
|
type WebhookLog struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
|
HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"`
|
||||||
|
Response string `gorm:"type:text" json:"response" bson:"response" cql:"response"`
|
||||||
|
Request string `gorm:"type:text" json:"request" bson:"request" cql:"request"`
|
||||||
|
WebhookID string `gorm:"type:char(36)" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"`
|
||||||
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog {
|
||||||
|
id := w.ID
|
||||||
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.WebhookLog+"/")
|
||||||
|
}
|
||||||
|
return &model.WebhookLog{
|
||||||
|
ID: id,
|
||||||
|
HTTPStatus: &w.HttpStatus,
|
||||||
|
Response: &w.Response,
|
||||||
|
Request: &w.Request,
|
||||||
|
WebhookID: &w.WebhookID,
|
||||||
|
CreatedAt: &w.CreatedAt,
|
||||||
|
UpdatedAt: &w.UpdatedAt,
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
package arangodb
|
package arangodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
@@ -12,17 +12,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
if env.ID == "" {
|
if env.ID == "" {
|
||||||
env.ID = uuid.New().String()
|
env.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
env.CreatedAt = time.Now().Unix()
|
env.CreatedAt = time.Now().Unix()
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
configCollection, _ := p.db.Collection(nil, models.Collections.Env)
|
configCollection, _ := p.db.Collection(ctx, models.Collections.Env)
|
||||||
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env)
|
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
env.Key = meta.Key
|
env.Key = meta.Key
|
||||||
@@ -31,12 +30,11 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
collection, _ := p.db.Collection(nil, models.Collections.Env)
|
collection, _ := p.db.Collection(ctx, models.Collections.Env)
|
||||||
meta, err := collection.UpdateDocument(nil, env.Key, env)
|
meta, err := collection.UpdateDocument(ctx, env.Key, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,11 +44,11 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
func (p *provider) GetEnv() (models.Env, error) {
|
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||||
var env models.Env
|
var env models.Env
|
||||||
query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env)
|
query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env)
|
||||||
|
|
||||||
cursor, err := p.db.Query(nil, query, nil)
|
cursor, err := p.db.Query(ctx, query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
@@ -63,7 +61,7 @@ func (p *provider) GetEnv() (models.Env, error) {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err := cursor.ReadDocument(nil, &env)
|
_, err := cursor.ReadDocument(ctx, &env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
|
@@ -2,14 +2,12 @@ package arangodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
"github.com/arangodb/go-driver/http"
|
"github.com/arangodb/go-driver/http"
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
@@ -23,8 +21,9 @@ type provider struct {
|
|||||||
// NewProvider to initialize arangodb connection
|
// NewProvider to initialize arangodb connection
|
||||||
func NewProvider() (*provider, error) {
|
func NewProvider() (*provider, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
dbURL := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseURL
|
||||||
conn, err := http.NewConnection(http.ConnectionConfig{
|
conn, err := http.NewConnection(http.ConnectionConfig{
|
||||||
Endpoints: []string{envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)},
|
Endpoints: []string{dbURL},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -38,29 +37,26 @@ func NewProvider() (*provider, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var arangodb driver.Database
|
var arangodb driver.Database
|
||||||
|
dbName := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseName
|
||||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb_exists, err := arangoClient.DatabaseExists(nil, dbName)
|
||||||
|
|
||||||
if arangodb_exists {
|
if arangodb_exists {
|
||||||
log.Println(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName) + " db exists already")
|
arangodb, err = arangoClient.Database(nil, dbName)
|
||||||
arangodb, err = arangoClient.Database(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arangodb, err = arangoClient.CreateDatabase(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), nil)
|
arangodb, err = arangoClient.CreateDatabase(nil, dbName, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.User)
|
userCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.User)
|
||||||
if userCollectionExists {
|
if !userCollectionExists {
|
||||||
log.Println(models.Collections.User + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.User, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.User, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.User+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userCollection, _ := arangodb.Collection(nil, models.Collections.User)
|
userCollection, _ := arangodb.Collection(nil, models.Collections.User)
|
||||||
@@ -74,12 +70,10 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
verificationRequestCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.VerificationRequest)
|
verificationRequestCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.VerificationRequest)
|
||||||
if verificationRequestCollectionExists {
|
if !verificationRequestCollectionExists {
|
||||||
log.Println(models.Collections.VerificationRequest + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.VerificationRequest, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.VerificationRequest, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.VerificationRequest+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +87,10 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sessionCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Session)
|
sessionCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Session)
|
||||||
if sessionCollectionExists {
|
if !sessionCollectionExists {
|
||||||
log.Println(models.Collections.Session + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.Session, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Session, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.Session+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,15 +100,40 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
configCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Env)
|
configCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Env)
|
||||||
if configCollectionExists {
|
if !configCollectionExists {
|
||||||
log.Println(models.Collections.Env + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.Env, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Env, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.Env+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webhookCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Webhook)
|
||||||
|
if !webhookCollectionExists {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Webhook, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookCollection, _ := arangodb.Collection(nil, models.Collections.Webhook)
|
||||||
|
webhookCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
webhookLogCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.WebhookLog)
|
||||||
|
if !webhookLogCollectionExists {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.WebhookLog, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLogCollection, _ := arangodb.Collection(nil, models.Collections.WebhookLog)
|
||||||
|
webhookLogCollection.EnsureHashIndex(ctx, []string{"webhook_id"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: arangodb,
|
db: arangodb,
|
||||||
}, err
|
}, err
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
package arangodb
|
package arangodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -10,32 +9,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
func (p *provider) AddSession(session models.Session) error {
|
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||||
if session.ID == "" {
|
if session.ID == "" {
|
||||||
session.ID = uuid.New().String()
|
session.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
session.CreatedAt = time.Now().Unix()
|
session.CreatedAt = time.Now().Unix()
|
||||||
session.UpdatedAt = time.Now().Unix()
|
session.UpdatedAt = time.Now().Unix()
|
||||||
sessionCollection, _ := p.db.Collection(nil, models.Collections.Session)
|
sessionCollection, _ := p.db.Collection(ctx, models.Collections.Session)
|
||||||
_, err := sessionCollection.CreateDocument(nil, session)
|
_, err := sessionCollection.CreateDocument(ctx, session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error saving session`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession to delete session information from database
|
|
||||||
func (p *provider) DeleteSession(userId string) error {
|
|
||||||
query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @userId REMOVE { _key: d._key } IN %s`, models.Collections.Session, models.Collections.Session)
|
|
||||||
bindVars := map[string]interface{}{
|
|
||||||
"userId": userId,
|
|
||||||
}
|
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cursor.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -3,35 +3,36 @@ package arangodb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
user.Roles = defaultRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
userCollection, _ := p.db.Collection(nil, models.Collections.User)
|
userCollection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||||
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user)
|
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
user.Key = meta.Key
|
user.Key = meta.Key
|
||||||
@@ -41,12 +42,11 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
collection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||||
meta, err := collection.UpdateDocument(nil, user.Key, user)
|
meta, err := collection.UpdateDocument(ctx, user.Key, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,25 +56,34 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
func (p *provider) DeleteUser(user models.User) error {
|
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
collection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||||
_, err := collection.RemoveDocument(nil, user.Key)
|
_, err := collection.RemoveDocument(ctx, user.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error deleting user:`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @user_id REMOVE { _key: d._key } IN %s`, models.Collections.Session, models.Collections.Session)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"user_id": user.ID,
|
||||||
|
}
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||||
var users []*model.User
|
var users []*model.User
|
||||||
ctx := driver.WithQueryFullCount(context.Background())
|
sctx := driver.WithQueryFullCount(ctx)
|
||||||
|
|
||||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit)
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit)
|
||||||
|
|
||||||
cursor, err := p.db.Query(ctx, query, nil)
|
cursor, err := p.db.Query(sctx, query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -85,7 +94,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
var user models.User
|
var user models.User
|
||||||
meta, err := cursor.ReadDocument(nil, &user)
|
meta, err := cursor.ReadDocument(ctx, &user)
|
||||||
|
|
||||||
if arangoDriver.IsNoMoreDocuments(err) {
|
if arangoDriver.IsNoMoreDocuments(err) {
|
||||||
break
|
break
|
||||||
@@ -105,7 +114,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email RETURN d", models.Collections.User)
|
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email RETURN d", models.Collections.User)
|
||||||
@@ -113,7 +122,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
"email": email,
|
"email": email,
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -126,7 +135,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err := cursor.ReadDocument(nil, &user)
|
_, err := cursor.ReadDocument(ctx, &user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -136,7 +145,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", models.Collections.User)
|
query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", models.Collections.User)
|
||||||
@@ -144,7 +153,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) {
|
|||||||
"id": id,
|
"id": id,
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -157,7 +166,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err := cursor.ReadDocument(nil, &user)
|
_, err := cursor.ReadDocument(ctx, &user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ package arangodb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
@@ -13,17 +12,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
if verificationRequest.ID == "" {
|
if verificationRequest.ID == "" {
|
||||||
verificationRequest.ID = uuid.New().String()
|
verificationRequest.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest.CreatedAt = time.Now().Unix()
|
verificationRequest.CreatedAt = time.Now().Unix()
|
||||||
verificationRequest.UpdatedAt = time.Now().Unix()
|
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||||
verificationRequestRequestCollection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
verificationRequestRequestCollection, _ := p.db.Collection(ctx, models.Collections.VerificationRequest)
|
||||||
meta, err := verificationRequestRequestCollection.CreateDocument(nil, verificationRequest)
|
meta, err := verificationRequestRequestCollection.CreateDocument(ctx, verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error saving verificationRequest record:", err)
|
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
verificationRequest.Key = meta.Key
|
verificationRequest.Key = meta.Key
|
||||||
@@ -33,14 +31,14 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d.token == @token LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
query := fmt.Sprintf("FOR d in %s FILTER d.token == @token LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
||||||
bindVars := map[string]interface{}{
|
bindVars := map[string]interface{}{
|
||||||
"token": token,
|
"token": token,
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -53,7 +51,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err := cursor.ReadDocument(nil, &verificationRequest)
|
_, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -63,7 +61,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email FILTER d.identifier == @identifier LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email FILTER d.identifier == @identifier LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
||||||
@@ -72,7 +70,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
"identifier": identifier,
|
"identifier": identifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -85,7 +83,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err := cursor.ReadDocument(nil, &verificationRequest)
|
_, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -95,12 +93,12 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
var verificationRequests []*model.VerificationRequest
|
var verificationRequests []*model.VerificationRequest
|
||||||
ctx := driver.WithQueryFullCount(context.Background())
|
sctx := driver.WithQueryFullCount(ctx)
|
||||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.VerificationRequest, pagination.Offset, pagination.Limit)
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.VerificationRequest, pagination.Offset, pagination.Limit)
|
||||||
|
|
||||||
cursor, err := p.db.Query(ctx, query, nil)
|
cursor, err := p.db.Query(sctx, query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -111,7 +109,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
meta, err := cursor.ReadDocument(nil, &verificationRequest)
|
meta, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||||
|
|
||||||
if driver.IsNoMoreDocuments(err) {
|
if driver.IsNoMoreDocuments(err) {
|
||||||
break
|
break
|
||||||
@@ -132,11 +130,10 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||||
collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
||||||
_, err := collection.RemoveDocument(nil, verificationRequest.Key)
|
_, err := collection.RemoveDocument(nil, verificationRequest.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error deleting verification request:`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
161
server/db/providers/arangodb/webhook.go
Normal file
161
server/db/providers/arangodb/webhook.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package arangodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
if webhook.ID == "" {
|
||||||
|
webhook.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = webhook.ID
|
||||||
|
webhook.CreatedAt = time.Now().Unix()
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||||
|
_, err := webhookCollection.CreateDocument(ctx, webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||||
|
meta, err := webhookCollection.UpdateDocument(ctx, webhook.Key, webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = meta.Key
|
||||||
|
webhook.ID = meta.ID.String()
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||||
|
webhooks := []*model.Webhook{}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.Webhook, pagination.Offset, pagination.Limit)
|
||||||
|
|
||||||
|
sctx := driver.WithQueryFullCount(ctx)
|
||||||
|
cursor, err := p.db.Query(sctx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = cursor.Statistics().FullCount()
|
||||||
|
|
||||||
|
for {
|
||||||
|
var webhook models.Webhook
|
||||||
|
meta, err := cursor.ReadDocument(ctx, &webhook)
|
||||||
|
|
||||||
|
if arangoDriver.IsNoMoreDocuments(err) {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.Key != "" {
|
||||||
|
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Webhooks{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
Webhooks: webhooks,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d._key == @webhook_id RETURN d", models.Collections.Webhook)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"webhook_id": webhookID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if webhook.Key == "" {
|
||||||
|
return nil, fmt.Errorf("webhook not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.Webhook)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"event_name": eventName,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if webhook.Key == "" {
|
||||||
|
return nil, fmt.Errorf("webhook not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||||
|
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||||
|
_, err := webhookCollection.RemoveDocument(ctx, webhook.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("FOR d IN %s FILTER d.webhook_id == @webhook_id REMOVE { _key: d._key } IN %s", models.Collections.WebhookLog, models.Collections.WebhookLog)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"webhook_id": webhook.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
75
server/db/providers/arangodb/webhook_log.go
Normal file
75
server/db/providers/arangodb/webhook_log.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package arangodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||||
|
if webhookLog.ID == "" {
|
||||||
|
webhookLog.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLog.Key = webhookLog.ID
|
||||||
|
webhookLog.CreatedAt = time.Now().Unix()
|
||||||
|
webhookLog.UpdatedAt = time.Now().Unix()
|
||||||
|
webhookLogCollection, _ := p.db.Collection(ctx, models.Collections.WebhookLog)
|
||||||
|
_, err := webhookLogCollection.CreateDocument(ctx, webhookLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhookLog.AsAPIWebhookLog(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||||
|
webhookLogs := []*model.WebhookLog{}
|
||||||
|
bindVariables := map[string]interface{}{}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit)
|
||||||
|
|
||||||
|
if webhookID != "" {
|
||||||
|
query = fmt.Sprintf("FOR d in %s FILTER d.webhook_id == @webhook_id SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit)
|
||||||
|
bindVariables = map[string]interface{}{
|
||||||
|
"webhook_id": webhookID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sctx := driver.WithQueryFullCount(ctx)
|
||||||
|
cursor, err := p.db.Query(sctx, query, bindVariables)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = cursor.Statistics().FullCount()
|
||||||
|
|
||||||
|
for {
|
||||||
|
var webhookLog models.WebhookLog
|
||||||
|
meta, err := cursor.ReadDocument(ctx, &webhookLog)
|
||||||
|
|
||||||
|
if arangoDriver.IsNoMoreDocuments(err) {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.Key != "" {
|
||||||
|
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.WebhookLogs{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
WebhookLogs: webhookLogs,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package cassandradb
|
package cassandradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
if env.ID == "" {
|
if env.ID == "" {
|
||||||
env.ID = uuid.New().String()
|
env.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -27,7 +28,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID)
|
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID)
|
||||||
@@ -39,7 +40,7 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
func (p *provider) GetEnv() (models.Env, error) {
|
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||||
var env models.Env
|
var env models.Env
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env)
|
query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env)
|
||||||
|
@@ -4,13 +4,13 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/gocql/gocql"
|
"github.com/gocql/gocql"
|
||||||
cansandraDriver "github.com/gocql/gocql"
|
cansandraDriver "github.com/gocql/gocql"
|
||||||
)
|
)
|
||||||
@@ -24,15 +24,21 @@ var KeySpace string
|
|||||||
|
|
||||||
// NewProvider to initialize arangodb connection
|
// NewProvider to initialize arangodb connection
|
||||||
func NewProvider() (*provider, error) {
|
func NewProvider() (*provider, error) {
|
||||||
dbURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)
|
dbURL := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseURL
|
||||||
if dbURL == "" {
|
if dbURL == "" {
|
||||||
dbURL = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseHost)
|
dbHost := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseHost
|
||||||
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort) != "" {
|
dbPort := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabasePort
|
||||||
dbURL = fmt.Sprintf("%s:%s", dbURL, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort))
|
if dbPort != "" && dbHost != "" {
|
||||||
|
dbURL = fmt.Sprintf("%s:%s", dbHost, dbPort)
|
||||||
|
} else if dbHost != "" {
|
||||||
|
dbURL = dbHost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySpace = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName)
|
KeySpace = memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseName
|
||||||
|
if KeySpace == "" {
|
||||||
|
KeySpace = constants.EnvKeyDatabaseName
|
||||||
|
}
|
||||||
clusterURL := []string{}
|
clusterURL := []string{}
|
||||||
if strings.Contains(dbURL, ",") {
|
if strings.Contains(dbURL, ",") {
|
||||||
clusterURL = strings.Split(dbURL, ",")
|
clusterURL = strings.Split(dbURL, ",")
|
||||||
@@ -40,25 +46,31 @@ func NewProvider() (*provider, error) {
|
|||||||
clusterURL = append(clusterURL, dbURL)
|
clusterURL = append(clusterURL, dbURL)
|
||||||
}
|
}
|
||||||
cassandraClient := cansandraDriver.NewCluster(clusterURL...)
|
cassandraClient := cansandraDriver.NewCluster(clusterURL...)
|
||||||
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword) != "" {
|
dbUsername := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseUsername
|
||||||
|
dbPassword := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabasePassword
|
||||||
|
|
||||||
|
if dbUsername != "" && dbPassword != "" {
|
||||||
cassandraClient.Authenticator = &cansandraDriver.PasswordAuthenticator{
|
cassandraClient.Authenticator = &cansandraDriver.PasswordAuthenticator{
|
||||||
Username: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername),
|
Username: dbUsername,
|
||||||
Password: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword),
|
Password: dbPassword,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey) != "" {
|
dbCert := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseCert
|
||||||
certString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert))
|
dbCACert := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseCACert
|
||||||
|
dbCertKey := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseCertKey
|
||||||
|
if dbCert != "" && dbCACert != "" && dbCertKey != "" {
|
||||||
|
certString, err := crypto.DecryptB64(dbCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
keyString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey))
|
keyString, err := crypto.DecryptB64(dbCertKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
caString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert))
|
caString, err := crypto.DecryptB64(dbCACert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -85,10 +97,11 @@ func NewProvider() (*provider, error) {
|
|||||||
NumRetries: 3,
|
NumRetries: 3,
|
||||||
}
|
}
|
||||||
cassandraClient.Consistency = gocql.LocalQuorum
|
cassandraClient.Consistency = gocql.LocalQuorum
|
||||||
|
cassandraClient.ConnectTimeout = 10 * time.Second
|
||||||
|
cassandraClient.ProtoVersion = 4
|
||||||
|
|
||||||
session, err := cassandraClient.CreateSession()
|
session, err := cassandraClient.CreateSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while creating connection to cassandra db", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +114,6 @@ func NewProvider() (*provider, error) {
|
|||||||
var keySpace string
|
var keySpace string
|
||||||
err := scanner.Scan(&keySpace)
|
err := scanner.Scan(&keySpace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while getting keyspace information", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if keySpace == KeySpace {
|
if keySpace == KeySpace {
|
||||||
@@ -114,7 +126,6 @@ func NewProvider() (*provider, error) {
|
|||||||
createKeySpaceQuery := fmt.Sprintf("CREATE KEYSPACE %s WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};", KeySpace)
|
createKeySpaceQuery := fmt.Sprintf("CREATE KEYSPACE %s WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};", KeySpace)
|
||||||
err = session.Query(createKeySpaceQuery).Exec()
|
err = session.Query(createKeySpaceQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while creating keyspace", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,27 +135,28 @@ func NewProvider() (*provider, error) {
|
|||||||
KeySpace, models.Collections.Env)
|
KeySpace, models.Collections.Env)
|
||||||
err = session.Query(envCollectionQuery).Exec()
|
err = session.Query(envCollectionQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create env collection:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, user_id text, user_agent text, ip text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Session)
|
sessionCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, user_id text, user_agent text, ip text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Session)
|
||||||
err = session.Query(sessionCollectionQuery).Exec()
|
err = session.Query(sessionCollectionQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create session collection:", err)
|
return nil, err
|
||||||
|
}
|
||||||
|
sessionIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_session_user_id ON %s.%s (user_id)", KeySpace, models.Collections.Session)
|
||||||
|
err = session.Query(sessionIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, email text, email_verified_at bigint, password text, signup_methods text, given_name text, family_name text, middle_name text, nickname text, gender text, birthdate text, phone_number text, phone_number_verified_at bigint, picture text, roles text, updated_at bigint, created_at bigint, revoked_timestamp bigint, PRIMARY KEY (id))", KeySpace, models.Collections.User)
|
userCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, email text, email_verified_at bigint, password text, signup_methods text, given_name text, family_name text, middle_name text, nickname text, gender text, birthdate text, phone_number text, phone_number_verified_at bigint, picture text, roles text, updated_at bigint, created_at bigint, revoked_timestamp bigint, PRIMARY KEY (id))", KeySpace, models.Collections.User)
|
||||||
err = session.Query(userCollectionQuery).Exec()
|
err = session.Query(userCollectionQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create user collection:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
userIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_user_email ON %s.%s (email)", KeySpace, models.Collections.User)
|
userIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_user_email ON %s.%s (email)", KeySpace, models.Collections.User)
|
||||||
err = session.Query(userIndexQuery).Exec()
|
err = session.Query(userIndexQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create user index:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,25 +164,43 @@ func NewProvider() (*provider, error) {
|
|||||||
verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest)
|
verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest)
|
||||||
err = session.Query(verificationRequestCollectionQuery).Exec()
|
err = session.Query(verificationRequestCollectionQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create verification request collection:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
verificationRequestIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_email ON %s.%s (email)", KeySpace, models.Collections.VerificationRequest)
|
verificationRequestIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_email ON %s.%s (email)", KeySpace, models.Collections.VerificationRequest)
|
||||||
err = session.Query(verificationRequestIndexQuery).Exec()
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create verification_requests index:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_identifier ON %s.%s (identifier)", KeySpace, models.Collections.VerificationRequest)
|
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_identifier ON %s.%s (identifier)", KeySpace, models.Collections.VerificationRequest)
|
||||||
err = session.Query(verificationRequestIndexQuery).Exec()
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create verification_requests index:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_jwt_token ON %s.%s (jwt_token)", KeySpace, models.Collections.VerificationRequest)
|
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_jwt_token ON %s.%s (jwt_token)", KeySpace, models.Collections.VerificationRequest)
|
||||||
err = session.Query(verificationRequestIndexQuery).Exec()
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to create verification_requests index:", err)
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, event_name text, endpoint text, enabled boolean, headers text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Webhook)
|
||||||
|
err = session.Query(webhookCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhookIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_event_name ON %s.%s (event_name)", KeySpace, models.Collections.Webhook)
|
||||||
|
err = session.Query(webhookIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLogCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, http_status bigint, response text, request text, webhook_id text,updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.WebhookLog)
|
||||||
|
err = session.Query(webhookLogCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhookLogIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_log_webhook_id ON %s.%s (webhook_id)", KeySpace, models.Collections.WebhookLog)
|
||||||
|
err = session.Query(webhookLogIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package cassandradb
|
package cassandradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
func (p *provider) AddSession(session models.Session) error {
|
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||||
if session.ID == "" {
|
if session.ID == "" {
|
||||||
session.ID = uuid.New().String()
|
session.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -24,13 +25,3 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession to delete session information from database
|
|
||||||
func (p *provider) DeleteSession(userId string) error {
|
|
||||||
deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE user_id = '%s'", KeySpace+"."+models.Collections.Session, userId)
|
|
||||||
err := p.db.Query(deleteSessionQuery).Exec()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package cassandradb
|
package cassandradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -9,20 +10,24 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/gocql/gocql"
|
"github.com/gocql/gocql"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
user.Roles = defaultRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
@@ -75,7 +80,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
bytes, err := json.Marshal(user)
|
bytes, err := json.Marshal(user)
|
||||||
@@ -93,10 +98,11 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
|
|
||||||
updateFields := ""
|
updateFields := ""
|
||||||
for key, value := range userMap {
|
for key, value := range userMap {
|
||||||
if value != nil && key != "_id" {
|
if key == "_id" {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == "_id" {
|
if key == "_key" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,14 +132,36 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
func (p *provider) DeleteUser(user models.User) error {
|
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||||
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID)
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID)
|
||||||
err := p.db.Query(query).Exec()
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSessionsQuery := fmt.Sprintf("SELECT id FROM %s WHERE user_id = '%s' ALLOW FILTERING", KeySpace+"."+models.Collections.Session, user.ID)
|
||||||
|
scanner := p.db.Query(getSessionsQuery).Iter().Scanner()
|
||||||
|
sessionIDs := ""
|
||||||
|
for scanner.Next() {
|
||||||
|
var wlID string
|
||||||
|
err = scanner.Scan(&wlID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sessionIDs += fmt.Sprintf("'%s',", wlID)
|
||||||
|
}
|
||||||
|
sessionIDs = strings.TrimSuffix(sessionIDs, ",")
|
||||||
|
deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE id IN (%s)", KeySpace+"."+models.Collections.Session, sessionIDs)
|
||||||
|
err = p.db.Query(deleteSessionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||||
responseUsers := []*model.User{}
|
responseUsers := []*model.User{}
|
||||||
paginationClone := pagination
|
paginationClone := pagination
|
||||||
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User)
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User)
|
||||||
@@ -167,9 +195,9 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, email)
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1 ALLOW FILTERING", KeySpace+"."+models.Collections.User, email)
|
||||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
@@ -178,7 +206,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
||||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
package cassandradb
|
package cassandradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
if verificationRequest.ID == "" {
|
if verificationRequest.ID == "" {
|
||||||
verificationRequest.ID = uuid.New().String()
|
verificationRequest.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token)
|
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token)
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier)
|
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier)
|
||||||
|
|
||||||
@@ -54,14 +54,13 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
var verificationRequests []*model.VerificationRequest
|
var verificationRequests []*model.VerificationRequest
|
||||||
|
|
||||||
paginationClone := pagination
|
paginationClone := pagination
|
||||||
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.VerificationRequest)
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.VerificationRequest)
|
||||||
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while quering verification request", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,6 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
err := scanner.Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
|
err := scanner.Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while parsing verification request", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest())
|
verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest())
|
||||||
@@ -92,7 +90,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||||
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID)
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID)
|
||||||
err := p.db.Query(query).Exec()
|
err := p.db.Query(query).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
172
server/db/providers/cassandradb/webhook.go
Normal file
172
server/db/providers/cassandradb/webhook.go
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
if webhook.ID == "" {
|
||||||
|
webhook.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = webhook.ID
|
||||||
|
webhook.CreatedAt = time.Now().Unix()
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
existingHook, _ := p.GetWebhookByEventName(ctx, webhook.EventName)
|
||||||
|
if existingHook != nil {
|
||||||
|
return nil, fmt.Errorf("Webhook with %s event_name already exists", webhook.EventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, endpoint, headers, enabled, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %t, %d, %d)", KeySpace+"."+models.Collections.Webhook, webhook.ID, webhook.EventName, webhook.EndPoint, webhook.Headers, webhook.Enabled, webhook.CreatedAt, webhook.UpdatedAt)
|
||||||
|
err := p.db.Query(insertQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
|
||||||
|
decoder.UseNumber()
|
||||||
|
webhookMap := map[string]interface{}{}
|
||||||
|
err = decoder.Decode(&webhookMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields := ""
|
||||||
|
for key, value := range webhookMap {
|
||||||
|
if key == "_id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "_key" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == nil {
|
||||||
|
updateFields += fmt.Sprintf("%s = null,", key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
valueType := reflect.TypeOf(value)
|
||||||
|
if valueType.Name() == "string" {
|
||||||
|
updateFields += fmt.Sprintf("%s = '%s', ", key, value.(string))
|
||||||
|
} else {
|
||||||
|
updateFields += fmt.Sprintf("%s = %v, ", key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateFields = strings.Trim(updateFields, " ")
|
||||||
|
updateFields = strings.TrimSuffix(updateFields, ",")
|
||||||
|
|
||||||
|
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, updateFields, webhook.ID)
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||||
|
webhooks := []*model.Webhook{}
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.Webhook)
|
||||||
|
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is no offset in cassandra
|
||||||
|
// so we fetch till limit + offset
|
||||||
|
// and return the results from offset to limit
|
||||||
|
query := fmt.Sprintf("SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.Webhook, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var webhook models.Webhook
|
||||||
|
err := scanner.Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Webhooks{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
Webhooks: webhooks,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, webhookID)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.Webhook, eventName)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, webhook.ID)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
getWebhookLogQuery := fmt.Sprintf("SELECT id FROM %s WHERE webhook_id = '%s' ALLOW FILTERING", KeySpace+"."+models.Collections.WebhookLog, webhook.ID)
|
||||||
|
scanner := p.db.Query(getWebhookLogQuery).Iter().Scanner()
|
||||||
|
webhookLogIDs := ""
|
||||||
|
for scanner.Next() {
|
||||||
|
var wlID string
|
||||||
|
err = scanner.Scan(&wlID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
webhookLogIDs += fmt.Sprintf("'%s',", wlID)
|
||||||
|
}
|
||||||
|
webhookLogIDs = strings.TrimSuffix(webhookLogIDs, ",")
|
||||||
|
query = fmt.Sprintf("DELETE FROM %s WHERE id IN (%s)", KeySpace+"."+models.Collections.WebhookLog, webhookLogIDs)
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
return err
|
||||||
|
}
|
70
server/db/providers/cassandradb/webhook_log.go
Normal file
70
server/db/providers/cassandradb/webhook_log.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||||
|
if webhookLog.ID == "" {
|
||||||
|
webhookLog.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLog.Key = webhookLog.ID
|
||||||
|
webhookLog.CreatedAt = time.Now().Unix()
|
||||||
|
webhookLog.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
insertQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt)
|
||||||
|
err := p.db.Query(insertQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhookLog.AsAPIWebhookLog(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||||
|
webhookLogs := []*model.WebhookLog{}
|
||||||
|
paginationClone := pagination
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.WebhookLog)
|
||||||
|
// there is no offset in cassandra
|
||||||
|
// so we fetch till limit + offset
|
||||||
|
// and return the results from offset to limit
|
||||||
|
query := fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.WebhookLog, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
if webhookID != "" {
|
||||||
|
totalCountQuery = fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE webhook_id='%s' ALLOW FILTERING`, KeySpace+"."+models.Collections.WebhookLog, webhookID)
|
||||||
|
query = fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s WHERE webhook_id = '%s' LIMIT %d ALLOW FILTERING", KeySpace+"."+models.Collections.WebhookLog, webhookID, pagination.Limit+pagination.Offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var webhookLog models.WebhookLog
|
||||||
|
err := scanner.Scan(&webhookLog.ID, &webhookLog.HttpStatus, &webhookLog.Response, &webhookLog.Request, &webhookLog.WebhookID, &webhookLog.CreatedAt, &webhookLog.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.WebhookLogs{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
WebhookLogs: webhookLogs,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
if env.ID == "" {
|
if env.ID == "" {
|
||||||
env.ID = uuid.New().String()
|
env.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -21,35 +21,33 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
env.Key = env.ID
|
env.Key = env.ID
|
||||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
_, err := configCollection.InsertOne(nil, env)
|
_, err := configCollection.InsertOne(ctx, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
_, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
_, err := configCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
func (p *provider) GetEnv() (models.Env, error) {
|
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||||
var env models.Env
|
var env models.Env
|
||||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
cursor, err := configCollection.Find(nil, bson.M{}, options.Find())
|
cursor, err := configCollection.Find(ctx, bson.M{}, options.Find())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(nil)
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
for cursor.Next(nil) {
|
for cursor.Next(nil) {
|
||||||
err := cursor.Decode(&env)
|
err := cursor.Decode(&env)
|
||||||
|
@@ -4,9 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
@@ -19,7 +18,8 @@ type provider struct {
|
|||||||
|
|
||||||
// NewProvider to initialize mongodb connection
|
// NewProvider to initialize mongodb connection
|
||||||
func NewProvider() (*provider, error) {
|
func NewProvider() (*provider, error) {
|
||||||
mongodbOptions := options.Client().ApplyURI(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL))
|
dbURL := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseURL
|
||||||
|
mongodbOptions := options.Client().ApplyURI(dbURL)
|
||||||
maxWait := time.Duration(5 * time.Second)
|
maxWait := time.Duration(5 * time.Second)
|
||||||
mongodbOptions.ConnectTimeout = &maxWait
|
mongodbOptions.ConnectTimeout = &maxWait
|
||||||
mongoClient, err := mongo.NewClient(mongodbOptions)
|
mongoClient, err := mongo.NewClient(mongodbOptions)
|
||||||
@@ -37,18 +37,19 @@ func NewProvider() (*provider, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mongodb := mongoClient.Database(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), options.Database())
|
dbName := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseName
|
||||||
|
mongodb := mongoClient.Database(dbName, options.Database())
|
||||||
|
|
||||||
mongodb.CreateCollection(ctx, models.Collections.User, options.CreateCollection())
|
mongodb.CreateCollection(ctx, models.Collections.User, options.CreateCollection())
|
||||||
userCollection := mongodb.Collection(models.Collections.User, options.Collection())
|
userCollection := mongodb.Collection(models.Collections.User, options.Collection())
|
||||||
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
mongo.IndexModel{
|
{
|
||||||
Keys: bson.M{"email": 1},
|
Keys: bson.M{"email": 1},
|
||||||
Options: options.Index().SetUnique(true).SetSparse(true),
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
},
|
},
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
mongo.IndexModel{
|
{
|
||||||
Keys: bson.M{"phone_number": 1},
|
Keys: bson.M{"phone_number": 1},
|
||||||
Options: options.Index().SetUnique(true).SetSparse(true).SetPartialFilterExpression(map[string]interface{}{
|
Options: options.Index().SetUnique(true).SetSparse(true).SetPartialFilterExpression(map[string]interface{}{
|
||||||
"phone_number": map[string]string{"$type": "string"},
|
"phone_number": map[string]string{"$type": "string"},
|
||||||
@@ -59,13 +60,13 @@ func NewProvider() (*provider, error) {
|
|||||||
mongodb.CreateCollection(ctx, models.Collections.VerificationRequest, options.CreateCollection())
|
mongodb.CreateCollection(ctx, models.Collections.VerificationRequest, options.CreateCollection())
|
||||||
verificationRequestCollection := mongodb.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := mongodb.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
mongo.IndexModel{
|
{
|
||||||
Keys: bson.M{"email": 1, "identifier": 1},
|
Keys: bson.M{"email": 1, "identifier": 1},
|
||||||
Options: options.Index().SetUnique(true).SetSparse(true),
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
},
|
},
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
mongo.IndexModel{
|
{
|
||||||
Keys: bson.M{"token": 1},
|
Keys: bson.M{"token": 1},
|
||||||
Options: options.Index().SetSparse(true),
|
Options: options.Index().SetSparse(true),
|
||||||
},
|
},
|
||||||
@@ -74,7 +75,7 @@ func NewProvider() (*provider, error) {
|
|||||||
mongodb.CreateCollection(ctx, models.Collections.Session, options.CreateCollection())
|
mongodb.CreateCollection(ctx, models.Collections.Session, options.CreateCollection())
|
||||||
sessionCollection := mongodb.Collection(models.Collections.Session, options.Collection())
|
sessionCollection := mongodb.Collection(models.Collections.Session, options.Collection())
|
||||||
sessionCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
sessionCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
mongo.IndexModel{
|
{
|
||||||
Keys: bson.M{"user_id": 1},
|
Keys: bson.M{"user_id": 1},
|
||||||
Options: options.Index().SetSparse(true),
|
Options: options.Index().SetSparse(true),
|
||||||
},
|
},
|
||||||
@@ -82,6 +83,24 @@ func NewProvider() (*provider, error) {
|
|||||||
|
|
||||||
mongodb.CreateCollection(ctx, models.Collections.Env, options.CreateCollection())
|
mongodb.CreateCollection(ctx, models.Collections.Env, options.CreateCollection())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.Webhook, options.CreateCollection())
|
||||||
|
webhookCollection := mongodb.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
webhookCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.M{"event_name": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.WebhookLog, options.CreateCollection())
|
||||||
|
webhookLogCollection := mongodb.Collection(models.Collections.WebhookLog, options.Collection())
|
||||||
|
webhookLogCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.M{"webhook_id": 1},
|
||||||
|
Options: options.Index().SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: mongodb,
|
db: mongodb,
|
||||||
}, nil
|
}, nil
|
||||||
|
@@ -1,17 +1,16 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
func (p *provider) AddSession(session models.Session) error {
|
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||||
if session.ID == "" {
|
if session.ID == "" {
|
||||||
session.ID = uuid.New().String()
|
session.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -20,20 +19,8 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
session.CreatedAt = time.Now().Unix()
|
session.CreatedAt = time.Now().Unix()
|
||||||
session.UpdatedAt = time.Now().Unix()
|
session.UpdatedAt = time.Now().Unix()
|
||||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
_, err := sessionCollection.InsertOne(nil, session)
|
_, err := sessionCollection.InsertOne(ctx, session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error saving session`, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSession to delete session information from database
|
|
||||||
func (p *provider) DeleteSession(userId string) error {
|
|
||||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
|
||||||
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
|
||||||
if err != nil {
|
|
||||||
log.Println("error deleting session:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -1,35 +1,37 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
user.Roles = defaultRoles
|
||||||
}
|
}
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
user.Key = user.ID
|
user.Key = user.ID
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.InsertOne(nil, user)
|
_, err := userCollection.InsertOne(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,23 +39,27 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
_, err := userCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
func (p *provider) DeleteUser(user models.User) error {
|
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete())
|
_, err := userCollection.DeleteOne(ctx, bson.M{"_id": user.ID}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
|
_, err = sessionCollection.DeleteMany(ctx, bson.M{"user_id": user.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting user:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +67,7 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||||
var users []*model.User
|
var users []*model.User
|
||||||
opts := options.Find()
|
opts := options.Find()
|
||||||
opts.SetLimit(pagination.Limit)
|
opts.SetLimit(pagination.Limit)
|
||||||
@@ -69,25 +75,22 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
opts.SetSort(bson.M{"created_at": -1})
|
opts.SetSort(bson.M{"created_at": -1})
|
||||||
|
|
||||||
paginationClone := pagination
|
paginationClone := pagination
|
||||||
// TODO add pagination total
|
|
||||||
|
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count())
|
count, err := userCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting total users:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
paginationClone.Total = count
|
paginationClone.Total = count
|
||||||
|
|
||||||
cursor, err := userCollection.Find(nil, bson.M{}, opts)
|
cursor, err := userCollection.Find(ctx, bson.M{}, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting users:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(nil)
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
for cursor.Next(nil) {
|
for cursor.Next(ctx) {
|
||||||
var user models.User
|
var user models.User
|
||||||
err := cursor.Decode(&user)
|
err := cursor.Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,10 +106,10 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
err := userCollection.FindOne(nil, bson.M{"email": email}).Decode(&user)
|
err := userCollection.FindOne(ctx, bson.M{"email": email}).Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -115,11 +118,11 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
err := userCollection.FindOne(nil, bson.M{"_id": id}).Decode(&user)
|
err := userCollection.FindOne(ctx, bson.M{"_id": id}).Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
if verificationRequest.ID == "" {
|
if verificationRequest.ID == "" {
|
||||||
verificationRequest.ID = uuid.New().String()
|
verificationRequest.ID = uuid.New().String()
|
||||||
|
|
||||||
@@ -20,9 +20,8 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
verificationRequest.UpdatedAt = time.Now().Unix()
|
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||||
verificationRequest.Key = verificationRequest.ID
|
verificationRequest.Key = verificationRequest.ID
|
||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
_, err := verificationRequestCollection.InsertOne(nil, verificationRequest)
|
_, err := verificationRequestCollection.InsertOne(ctx, verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error saving verification record:", err)
|
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,11 +30,11 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
err := verificationRequestCollection.FindOne(nil, bson.M{"token": token}).Decode(&verificationRequest)
|
err := verificationRequestCollection.FindOne(ctx, bson.M{"token": token}).Decode(&verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -44,11 +43,11 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
err := verificationRequestCollection.FindOne(nil, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest)
|
err := verificationRequestCollection.FindOne(ctx, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -57,7 +56,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
var verificationRequests []*model.VerificationRequest
|
var verificationRequests []*model.VerificationRequest
|
||||||
|
|
||||||
opts := options.Find()
|
opts := options.Find()
|
||||||
@@ -67,18 +66,17 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
|
|
||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
|
|
||||||
verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(nil, bson.M{})
|
verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(ctx, bson.M{})
|
||||||
paginationClone := pagination
|
paginationClone := pagination
|
||||||
paginationClone.Total = verificationRequestCollectionCount
|
paginationClone.Total = verificationRequestCollectionCount
|
||||||
|
|
||||||
cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts)
|
cursor, err := verificationRequestCollection.Find(ctx, bson.M{}, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting verification requests:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(nil)
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
for cursor.Next(nil) {
|
for cursor.Next(ctx) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
err := cursor.Decode(&verificationRequest)
|
err := cursor.Decode(&verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -94,11 +92,10 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
_, err := verificationRequestCollection.DeleteOne(ctx, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting verification request::", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
120
server/db/providers/mongodb/webhook.go
Normal file
120
server/db/providers/mongodb/webhook.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
if webhook.ID == "" {
|
||||||
|
webhook.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = webhook.ID
|
||||||
|
webhook.CreatedAt = time.Now().Unix()
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
_, err := webhookCollection.InsertOne(ctx, webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
_, err := webhookCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": webhook.ID}}, bson.M{"$set": webhook}, options.MergeUpdateOptions())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||||
|
var webhooks []*model.Webhook
|
||||||
|
opts := options.Find()
|
||||||
|
opts.SetLimit(pagination.Limit)
|
||||||
|
opts.SetSkip(pagination.Offset)
|
||||||
|
opts.SetSort(bson.M{"created_at": -1})
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
count, err := webhookCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone.Total = count
|
||||||
|
|
||||||
|
cursor, err := webhookCollection.Find(ctx, bson.M{}, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
|
for cursor.Next(ctx) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
err := cursor.Decode(&webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Webhooks{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
Webhooks: webhooks,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
err := webhookCollection.FindOne(ctx, bson.M{"_id": webhookID}).Decode(&webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
err := webhookCollection.FindOne(ctx, bson.M{"event_name": eventName}).Decode(&webhook)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||||
|
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||||
|
_, err := webhookCollection.DeleteOne(nil, bson.M{"_id": webhook.ID}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||||
|
_, err = webhookLogCollection.DeleteMany(nil, bson.M{"webhook_id": webhook.ID}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
74
server/db/providers/mongodb/webhook_log.go
Normal file
74
server/db/providers/mongodb/webhook_log.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||||
|
if webhookLog.ID == "" {
|
||||||
|
webhookLog.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLog.Key = webhookLog.ID
|
||||||
|
webhookLog.CreatedAt = time.Now().Unix()
|
||||||
|
webhookLog.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||||
|
_, err := webhookLogCollection.InsertOne(ctx, webhookLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webhookLog.AsAPIWebhookLog(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||||
|
webhookLogs := []*model.WebhookLog{}
|
||||||
|
opts := options.Find()
|
||||||
|
opts.SetLimit(pagination.Limit)
|
||||||
|
opts.SetSkip(pagination.Offset)
|
||||||
|
opts.SetSort(bson.M{"created_at": -1})
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
query := bson.M{}
|
||||||
|
|
||||||
|
if webhookID != "" {
|
||||||
|
query = bson.M{"webhook_id": webhookID}
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||||
|
count, err := webhookLogCollection.CountDocuments(ctx, query, options.Count())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone.Total = count
|
||||||
|
|
||||||
|
cursor, err := webhookLogCollection.Find(ctx, query, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
|
for cursor.Next(ctx) {
|
||||||
|
var webhookLog models.WebhookLog
|
||||||
|
err := cursor.Decode(&webhookLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.WebhookLogs{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
WebhookLogs: webhookLogs,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package provider_template
|
package provider_template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -8,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
if env.ID == "" {
|
if env.ID == "" {
|
||||||
env.ID = uuid.New().String()
|
env.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -19,13 +20,13 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
func (p *provider) GetEnv() (models.Env, error) {
|
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||||
var env models.Env
|
var env models.Env
|
||||||
|
|
||||||
return env, nil
|
return env, nil
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package provider_template
|
package provider_template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -8,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
func (p *provider) AddSession(session models.Session) error {
|
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||||
if session.ID == "" {
|
if session.ID == "" {
|
||||||
session.ID = uuid.New().String()
|
session.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -19,6 +20,6 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession to delete session information from database
|
// DeleteSession to delete session information from database
|
||||||
func (p *provider) DeleteSession(userId string) error {
|
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,28 @@
|
|||||||
package provider_template
|
package provider_template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
user.Roles = defaultRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
@@ -28,30 +32,30 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
func (p *provider) DeleteUser(user models.User) error {
|
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package provider_template
|
package provider_template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -9,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
if verificationRequest.ID == "" {
|
if verificationRequest.ID == "" {
|
||||||
verificationRequest.ID = uuid.New().String()
|
verificationRequest.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -21,25 +22,25 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
return verificationRequest, nil
|
return verificationRequest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
return verificationRequest, nil
|
return verificationRequest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
49
server/db/providers/provider_template/webhook.go
Normal file
49
server/db/providers/provider_template/webhook.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
if webhook.ID == "" {
|
||||||
|
webhook.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = webhook.ID
|
||||||
|
webhook.CreatedAt = time.Now().Unix()
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||||
|
// Also delete webhook logs for given webhook id
|
||||||
|
return nil
|
||||||
|
}
|
27
server/db/providers/provider_template/webhook_log.go
Normal file
27
server/db/providers/provider_template/webhook_log.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||||
|
if webhookLog.ID == "" {
|
||||||
|
webhookLog.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLog.Key = webhookLog.ID
|
||||||
|
webhookLog.CreatedAt = time.Now().Unix()
|
||||||
|
webhookLog.UpdatedAt = time.Now().Unix()
|
||||||
|
return webhookLog.AsAPIWebhookLog(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
@@ -1,44 +1,62 @@
|
|||||||
package providers
|
package providers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
AddUser(user models.User) (models.User, error)
|
AddUser(ctx context.Context, user models.User) (models.User, error)
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
UpdateUser(user models.User) (models.User, error)
|
UpdateUser(ctx context.Context, user models.User) (models.User, error)
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
DeleteUser(user models.User) error
|
DeleteUser(ctx context.Context, user models.User) error
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
ListUsers(pagination model.Pagination) (*model.Users, error)
|
ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error)
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
GetUserByEmail(email string) (models.User, error)
|
GetUserByEmail(ctx context.Context, email string) (models.User, error)
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
GetUserByID(id string) (models.User, error)
|
GetUserByID(ctx context.Context, id string) (models.User, error)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error)
|
AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error)
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
GetVerificationRequestByToken(token string) (models.VerificationRequest, error)
|
GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error)
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error)
|
GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error)
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error)
|
ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error)
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
DeleteVerificationRequest(verificationRequest models.VerificationRequest) error
|
DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
AddSession(session models.Session) error
|
AddSession(ctx context.Context, session models.Session) error
|
||||||
// DeleteSession to delete session information from database
|
|
||||||
DeleteSession(userId string) error
|
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
AddEnv(env models.Env) (models.Env, error)
|
AddEnv(ctx context.Context, env models.Env) (models.Env, error)
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
UpdateEnv(env models.Env) (models.Env, error)
|
UpdateEnv(ctx context.Context, env models.Env) (models.Env, error)
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
GetEnv() (models.Env, error)
|
GetEnv(ctx context.Context) (models.Env, error)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error)
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error)
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error)
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error)
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error)
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
DeleteWebhook(ctx context.Context, webhook *model.Webhook) error
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error)
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error)
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEnv to save environment information in database
|
// AddEnv to save environment information in database
|
||||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
if env.ID == "" {
|
if env.ID == "" {
|
||||||
env.ID = uuid.New().String()
|
env.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -20,26 +20,24 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
|
|
||||||
result := p.db.Create(&env)
|
result := p.db.Create(&env)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error adding config:", result.Error)
|
|
||||||
return env, result.Error
|
return env, result.Error
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnv to update environment information in database
|
// UpdateEnv to update environment information in database
|
||||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||||
env.UpdatedAt = time.Now().Unix()
|
env.UpdatedAt = time.Now().Unix()
|
||||||
result := p.db.Save(&env)
|
result := p.db.Save(&env)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error updating config:", result.Error)
|
|
||||||
return env, result.Error
|
return env, result.Error
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEnv to get environment information from database
|
// GetEnv to get environment information from database
|
||||||
func (p *provider) GetEnv() (models.Env, error) {
|
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||||
var env models.Env
|
var env models.Env
|
||||||
result := p.db.First(&env)
|
result := p.db.First(&env)
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
@@ -41,22 +41,26 @@ func NewProvider() (*provider, error) {
|
|||||||
TablePrefix: models.Prefix,
|
TablePrefix: models.Prefix,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
switch envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
|
||||||
case constants.DbTypePostgres, constants.DbTypeYugabyte:
|
dbType := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseType
|
||||||
sqlDB, err = gorm.Open(postgres.Open(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
dbURL := memorystore.RequiredEnvStoreObj.GetRequiredEnv().DatabaseURL
|
||||||
|
|
||||||
|
switch dbType {
|
||||||
|
case constants.DbTypePostgres, constants.DbTypeYugabyte, constants.DbTypeCockroachDB:
|
||||||
|
sqlDB, err = gorm.Open(postgres.Open(dbURL), ormConfig)
|
||||||
case constants.DbTypeSqlite:
|
case constants.DbTypeSqlite:
|
||||||
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(sqlite.Open(dbURL), ormConfig)
|
||||||
case constants.DbTypeMysql, constants.DbTypeMariaDB:
|
case constants.DbTypeMysql, constants.DbTypeMariaDB, constants.DbTypePlanetScaleDB:
|
||||||
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(mysql.Open(dbURL), ormConfig)
|
||||||
case constants.DbTypeSqlserver:
|
case constants.DbTypeSqlserver:
|
||||||
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(sqlserver.Open(dbURL), ormConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{})
|
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}, &models.Webhook{}, models.WebhookLog{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddSession to save session information in database
|
// AddSession to save session information in database
|
||||||
func (p *provider) AddSession(session models.Session) error {
|
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||||
if session.ID == "" {
|
if session.ID == "" {
|
||||||
session.ID = uuid.New().String()
|
session.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -23,19 +23,7 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
DoNothing: true,
|
DoNothing: true,
|
||||||
}).Create(&session)
|
}).Create(&session)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
log.Println(`error saving session`, res.Error)
|
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession to delete session information from database
|
|
||||||
func (p *provider) DeleteSession(userId string) error {
|
|
||||||
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
|
||||||
|
|
||||||
if result.Error != nil {
|
|
||||||
log.Println(`error deleting session:`, result.Error)
|
|
||||||
return result.Error
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -1,26 +1,29 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser to save user information in database
|
// AddUser to save user information in database
|
||||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
user.Roles = defaultRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
@@ -33,7 +36,6 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}).Create(&user)
|
}).Create(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error adding user:", result.Error)
|
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,13 +43,12 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser to update user information in database
|
// UpdateUser to update user information in database
|
||||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
result := p.db.Save(&user)
|
result := p.db.Save(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error updating user:", result.Error)
|
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,11 +56,15 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser to delete user information from database
|
// DeleteUser to delete user information from database
|
||||||
func (p *provider) DeleteUser(user models.User) error {
|
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||||
result := p.db.Delete(&user)
|
result := p.db.Delete(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error deleting user:`, result.Error)
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = p.db.Where("user_id = ?", user.ID).Delete(&models.Session{})
|
||||||
|
if result.Error != nil {
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,11 +72,10 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListUsers to get list of users from database
|
// ListUsers to get list of users from database
|
||||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||||
var users []models.User
|
var users []models.User
|
||||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users)
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error getting users:", result.Error)
|
|
||||||
return nil, result.Error
|
return nil, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,10 +100,9 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
result := p.db.Where("email = ?", email).First(&user)
|
result := p.db.Where("email = ?", email).First(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
@@ -108,11 +111,10 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
result := p.db.Where("id = ?", id).First(&user)
|
result := p.db.Where("id = ?", id).First(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddVerification to save verification request in database
|
// AddVerification to save verification request in database
|
||||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
if verificationRequest.ID == "" {
|
if verificationRequest.ID == "" {
|
||||||
verificationRequest.ID = uuid.New().String()
|
verificationRequest.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,6 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}).Create(&verificationRequest)
|
}).Create(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error saving verification request record`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,12 +32,11 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByToken to get verification request from database using token
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error getting verification request:`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,13 +44,12 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetVerificationRequestByEmail to get verification request by email from database
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||||
var verificationRequest models.VerificationRequest
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error getting verification token:`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,12 +57,11 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListVerificationRequests to get list of verification requests from database
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
var verificationRequests []models.VerificationRequest
|
var verificationRequests []models.VerificationRequest
|
||||||
|
|
||||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests)
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error getting verification requests:", result.Error)
|
|
||||||
return nil, result.Error
|
return nil, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,11 +86,10 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteVerificationRequest to delete verification request from database
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||||
result := p.db.Delete(&verificationRequest)
|
result := p.db.Delete(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error deleting verification request:`, result.Error)
|
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
104
server/db/providers/sql/webhook.go
Normal file
104
server/db/providers/sql/webhook.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhook to add webhook
|
||||||
|
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
if webhook.ID == "" {
|
||||||
|
webhook.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Key = webhook.ID
|
||||||
|
webhook.CreatedAt = time.Now().Unix()
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
res := p.db.Create(&webhook)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook to update webhook
|
||||||
|
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||||
|
webhook.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
result := p.db.Save(&webhook)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooks to list webhook
|
||||||
|
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||||
|
var webhooks []models.Webhook
|
||||||
|
|
||||||
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhooks)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
totalRes := p.db.Model(&models.Webhook{}).Count(&total)
|
||||||
|
if totalRes.Error != nil {
|
||||||
|
return nil, totalRes.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = total
|
||||||
|
|
||||||
|
responseWebhooks := []*model.Webhook{}
|
||||||
|
for _, w := range webhooks {
|
||||||
|
responseWebhooks = append(responseWebhooks, w.AsAPIWebhook())
|
||||||
|
}
|
||||||
|
return &model.Webhooks{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
Webhooks: responseWebhooks,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByID to get webhook by id
|
||||||
|
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
|
||||||
|
result := p.db.Where("id = ?", webhookID).First(&webhook)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookByEventName to get webhook by event_name
|
||||||
|
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||||
|
var webhook models.Webhook
|
||||||
|
|
||||||
|
result := p.db.Where("event_name = ?", eventName).First(&webhook)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return webhook.AsAPIWebhook(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook to delete webhook
|
||||||
|
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||||
|
result := p.db.Delete(&models.Webhook{
|
||||||
|
ID: webhook.ID,
|
||||||
|
})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = p.db.Where("webhook_id = ?", webhook.ID).Delete(&models.WebhookLog{})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
68
server/db/providers/sql/webhook_log.go
Normal file
68
server/db/providers/sql/webhook_log.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWebhookLog to add webhook log
|
||||||
|
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||||
|
if webhookLog.ID == "" {
|
||||||
|
webhookLog.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookLog.Key = webhookLog.ID
|
||||||
|
webhookLog.CreatedAt = time.Now().Unix()
|
||||||
|
webhookLog.UpdatedAt = time.Now().Unix()
|
||||||
|
res := p.db.Clauses(
|
||||||
|
clause.OnConflict{
|
||||||
|
DoNothing: true,
|
||||||
|
}).Create(&webhookLog)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhookLog.AsAPIWebhookLog(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookLogs to list webhook logs
|
||||||
|
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||||
|
var webhookLogs []models.WebhookLog
|
||||||
|
var result *gorm.DB
|
||||||
|
var totalRes *gorm.DB
|
||||||
|
var total int64
|
||||||
|
|
||||||
|
if webhookID != "" {
|
||||||
|
result = p.db.Where("webhook_id = ?", webhookID).Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs)
|
||||||
|
totalRes = p.db.Where("webhook_id = ?", webhookID).Model(&models.WebhookLog{}).Count(&total)
|
||||||
|
} else {
|
||||||
|
result = p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs)
|
||||||
|
totalRes = p.db.Model(&models.WebhookLog{}).Count(&total)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalRes.Error != nil {
|
||||||
|
return nil, totalRes.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = total
|
||||||
|
|
||||||
|
responseWebhookLogs := []*model.WebhookLog{}
|
||||||
|
for _, w := range webhookLogs {
|
||||||
|
responseWebhookLogs = append(responseWebhookLogs, w.AsAPIWebhookLog())
|
||||||
|
}
|
||||||
|
return &model.WebhookLogs{
|
||||||
|
WebhookLogs: responseWebhookLogs,
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -4,13 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
gomail "gopkg.in/mail.v2"
|
gomail "gopkg.in/mail.v2"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// addEmailTemplate is used to add html template in email body
|
// addEmailTemplate is used to add html template in email body
|
||||||
@@ -32,21 +33,61 @@ func addEmailTemplate(a string, b map[string]interface{}, templateName string) s
|
|||||||
// SendMail function to send mail
|
// SendMail function to send mail
|
||||||
func SendMail(to []string, Subject, bodyMessage string) error {
|
func SendMail(to []string, Subject, bodyMessage string) error {
|
||||||
// dont trigger email sending in case of test
|
// dont trigger email sending in case of test
|
||||||
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnv) == "test" {
|
envKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEnv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if envKey == constants.TestEnv {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
m := gomail.NewMessage()
|
m := gomail.NewMessage()
|
||||||
m.SetHeader("From", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySenderEmail))
|
senderEmail, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySenderEmail)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting sender email from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
smtpPort, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting smtp port from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
smtpHost, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpHost)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting smtp host from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
smtpUsername, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpUsername)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting smtp username from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
smtpPassword, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpPassword)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting smtp password from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isProd, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsProd)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SetHeader("From", senderEmail)
|
||||||
m.SetHeader("To", to...)
|
m.SetHeader("To", to...)
|
||||||
m.SetHeader("Subject", Subject)
|
m.SetHeader("Subject", Subject)
|
||||||
m.SetBody("text/html", bodyMessage)
|
m.SetBody("text/html", bodyMessage)
|
||||||
port, _ := strconv.Atoi(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPort))
|
port, _ := strconv.Atoi(smtpPort)
|
||||||
d := gomail.NewDialer(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpHost), port, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpUsername), envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPassword))
|
d := gomail.NewDialer(smtpHost, port, smtpUsername, smtpPassword)
|
||||||
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnv) == "development" {
|
if !isProd {
|
||||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
}
|
}
|
||||||
if err := d.DialAndSend(m); err != nil {
|
if err := d.DialAndSend(m); err != nil {
|
||||||
log.Printf("smtp error: %s", err)
|
log.Debug("SMTP Failed: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -2,14 +2,19 @@ package email
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SendForgotPasswordMail to send forgot password email
|
// SendForgotPasswordMail to send forgot password email
|
||||||
func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
||||||
resetPasswordUrl := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
|
resetPasswordUrl, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if resetPasswordUrl == "" {
|
if resetPasswordUrl == "" {
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password")
|
if err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||||
@@ -103,8 +108,14 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
|||||||
`
|
`
|
||||||
|
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["org_logo"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||||
data["org_name"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
data["verification_url"] = resetPasswordUrl + "?token=" + token
|
data["verification_url"] = resetPasswordUrl + "?token=" + token
|
||||||
message = addEmailTemplate(message, data, "reset_password_email.tmpl")
|
message = addEmailTemplate(message, data, "reset_password_email.tmpl")
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
package email
|
package email
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InviteEmail to send invite email
|
// InviteEmail to send invite email
|
||||||
@@ -99,15 +99,22 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["org_logo"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
var err error
|
||||||
data["org_name"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
data["verification_url"] = verificationURL + "?token=" + token + "&redirect_uri=" + redirectURI
|
data["verification_url"] = verificationURL + "?token=" + token + "&redirect_uri=" + redirectURI
|
||||||
message = addEmailTemplate(message, data, "invite_email.tmpl")
|
message = addEmailTemplate(message, data, "invite_email.tmpl")
|
||||||
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
|
||||||
err := SendMail(Receiver, Subject, message)
|
err = SendMail(Receiver, Subject, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error sending email:", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
package email
|
package email
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SendVerificationMail to send verification email
|
// SendVerificationMail to send verification email
|
||||||
@@ -99,15 +99,22 @@ func SendVerificationMail(toEmail, token, hostname string) error {
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["org_logo"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
var err error
|
||||||
data["org_name"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
data["verification_url"] = hostname + "/verify_email?token=" + token
|
data["verification_url"] = hostname + "/verify_email?token=" + token
|
||||||
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
||||||
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
|
||||||
err := SendMail(Receiver, Subject, message)
|
err = SendMail(Receiver, Subject, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error sending email:", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
693
server/env/env.go
vendored
693
server/env/env.go
vendored
@@ -2,209 +2,247 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/joho/godotenv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitRequiredEnv to initialize EnvData and through error if required env are not present
|
|
||||||
func InitRequiredEnv() error {
|
|
||||||
envPath := os.Getenv(constants.EnvKeyEnvPath)
|
|
||||||
|
|
||||||
if envPath == "" {
|
|
||||||
envPath = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnvPath)
|
|
||||||
if envPath == "" {
|
|
||||||
envPath = `.env`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
|
||||||
envPath = *envstore.ARG_ENV_FILE
|
|
||||||
}
|
|
||||||
|
|
||||||
err := godotenv.Load(envPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("using OS env instead of %s file", envPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
|
|
||||||
dbType := os.Getenv(constants.EnvKeyDatabaseType)
|
|
||||||
dbName := os.Getenv(constants.EnvKeyDatabaseName)
|
|
||||||
dbPort := os.Getenv(constants.EnvKeyDatabasePort)
|
|
||||||
dbHost := os.Getenv(constants.EnvKeyDatabaseHost)
|
|
||||||
dbUsername := os.Getenv(constants.EnvKeyDatabaseUsername)
|
|
||||||
dbPassword := os.Getenv(constants.EnvKeyDatabasePassword)
|
|
||||||
dbCert := os.Getenv(constants.EnvKeyDatabaseCert)
|
|
||||||
dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey)
|
|
||||||
dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert)
|
|
||||||
|
|
||||||
if strings.TrimSpace(dbType) == "" {
|
|
||||||
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
|
||||||
dbType = strings.TrimSpace(*envstore.ARG_DB_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dbType == "" {
|
|
||||||
return errors.New("invalid database type. DATABASE_TYPE is empty")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.TrimSpace(dbURL) == "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL) == "" {
|
|
||||||
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
|
||||||
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {
|
|
||||||
return errors.New("invalid database url. DATABASE_URL is required")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if dbName == "" {
|
|
||||||
if dbName == "" {
|
|
||||||
dbName = "authorizer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, envPath)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseHost, dbHost)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePort, dbPort)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseUsername, dbUsername)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePassword, dbPassword)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCert, dbCert)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCertKey, dbCertKey)
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCACert, dbCACert)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitEnv to initialize EnvData and through error if required env are not present
|
// InitEnv to initialize EnvData and through error if required env are not present
|
||||||
func InitAllEnv() error {
|
func InitAllEnv() error {
|
||||||
envData, err := GetEnvData()
|
envData, err := GetEnvData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("No env data found in db, using local clone of env data")
|
log.Info("No env data found in db, using local clone of env data")
|
||||||
// get clone of current store
|
// get clone of current store
|
||||||
envData = envstore.EnvStoreObj.GetEnvStoreClone()
|
envData, err = memorystore.Provider.GetEnvStore()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while getting env data from memorystore: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clientID := envData.StringEnv[constants.EnvKeyClientID]
|
|
||||||
// unique client id for each instance
|
// unique client id for each instance
|
||||||
if clientID == "" {
|
cid, ok := envData[constants.EnvKeyClientID]
|
||||||
|
clientID := ""
|
||||||
|
if !ok || cid == "" {
|
||||||
clientID = uuid.New().String()
|
clientID = uuid.New().String()
|
||||||
envData.StringEnv[constants.EnvKeyClientID] = clientID
|
envData[constants.EnvKeyClientID] = clientID
|
||||||
}
|
|
||||||
|
|
||||||
clientSecret := envData.StringEnv[constants.EnvKeyClientSecret]
|
|
||||||
// unique client id for each instance
|
|
||||||
if clientSecret == "" {
|
|
||||||
clientSecret = uuid.New().String()
|
|
||||||
envData.StringEnv[constants.EnvKeyClientSecret] = clientSecret
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
|
||||||
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
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
|
||||||
} else {
|
} else {
|
||||||
envData.BoolEnv[constants.EnvKeyIsProd] = false
|
clientID = cid.(string)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyAppURL] == "" {
|
// unique client secret for each instance
|
||||||
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
if val, ok := envData[constants.EnvKeyClientSecret]; !ok || val != "" {
|
||||||
|
envData[constants.EnvKeyClientSecret] = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyAuthorizerURL] == "" {
|
// os string envs
|
||||||
envData.StringEnv[constants.EnvKeyAuthorizerURL] = os.Getenv(constants.EnvKeyAuthorizerURL)
|
osEnv := os.Getenv(constants.EnvKeyEnv)
|
||||||
|
osAppURL := os.Getenv(constants.EnvKeyAppURL)
|
||||||
|
osAuthorizerURL := os.Getenv(constants.EnvKeyAuthorizerURL)
|
||||||
|
osPort := os.Getenv(constants.EnvKeyPort)
|
||||||
|
osAccessTokenExpiryTime := os.Getenv(constants.EnvKeyAccessTokenExpiryTime)
|
||||||
|
osAdminSecret := os.Getenv(constants.EnvKeyAdminSecret)
|
||||||
|
osSmtpHost := os.Getenv(constants.EnvKeySmtpHost)
|
||||||
|
osSmtpPort := os.Getenv(constants.EnvKeySmtpPort)
|
||||||
|
osSmtpUsername := os.Getenv(constants.EnvKeySmtpUsername)
|
||||||
|
osSmtpPassword := os.Getenv(constants.EnvKeySmtpPassword)
|
||||||
|
osSenderEmail := os.Getenv(constants.EnvKeySenderEmail)
|
||||||
|
osJwtType := os.Getenv(constants.EnvKeyJwtType)
|
||||||
|
osJwtSecret := os.Getenv(constants.EnvKeyJwtSecret)
|
||||||
|
osJwtPrivateKey := os.Getenv(constants.EnvKeyJwtPrivateKey)
|
||||||
|
osJwtPublicKey := os.Getenv(constants.EnvKeyJwtPublicKey)
|
||||||
|
osJwtRoleClaim := os.Getenv(constants.EnvKeyJwtRoleClaim)
|
||||||
|
osCustomAccessTokenScript := os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
||||||
|
osGoogleClientID := os.Getenv(constants.EnvKeyGoogleClientID)
|
||||||
|
osGoogleClientSecret := os.Getenv(constants.EnvKeyGoogleClientSecret)
|
||||||
|
osGithubClientID := os.Getenv(constants.EnvKeyGithubClientID)
|
||||||
|
osGithubClientSecret := os.Getenv(constants.EnvKeyGithubClientSecret)
|
||||||
|
osFacebookClientID := os.Getenv(constants.EnvKeyFacebookClientID)
|
||||||
|
osFacebookClientSecret := os.Getenv(constants.EnvKeyFacebookClientSecret)
|
||||||
|
osLinkedInClientID := os.Getenv(constants.EnvKeyLinkedInClientID)
|
||||||
|
osLinkedInClientSecret := os.Getenv(constants.EnvKeyLinkedInClientSecret)
|
||||||
|
osAppleClientID := os.Getenv(constants.EnvKeyAppleClientID)
|
||||||
|
osAppleClientSecret := os.Getenv(constants.EnvKeyAppleClientSecret)
|
||||||
|
osResetPasswordURL := os.Getenv(constants.EnvKeyResetPasswordURL)
|
||||||
|
osOrganizationName := os.Getenv(constants.EnvKeyOrganizationName)
|
||||||
|
osOrganizationLogo := os.Getenv(constants.EnvKeyOrganizationLogo)
|
||||||
|
|
||||||
|
// os bool vars
|
||||||
|
osDisableBasicAuthentication := os.Getenv(constants.EnvKeyDisableBasicAuthentication)
|
||||||
|
osDisableEmailVerification := os.Getenv(constants.EnvKeyDisableEmailVerification)
|
||||||
|
osDisableMagicLinkLogin := os.Getenv(constants.EnvKeyDisableMagicLinkLogin)
|
||||||
|
osDisableLoginPage := os.Getenv(constants.EnvKeyDisableLoginPage)
|
||||||
|
osDisableSignUp := os.Getenv(constants.EnvKeyDisableSignUp)
|
||||||
|
osDisableRedisForEnv := os.Getenv(constants.EnvKeyDisableRedisForEnv)
|
||||||
|
osDisableStrongPassword := os.Getenv(constants.EnvKeyDisableStrongPassword)
|
||||||
|
|
||||||
|
// os slice vars
|
||||||
|
osAllowedOrigins := os.Getenv(constants.EnvKeyAllowedOrigins)
|
||||||
|
osRoles := os.Getenv(constants.EnvKeyRoles)
|
||||||
|
osDefaultRoles := os.Getenv(constants.EnvKeyDefaultRoles)
|
||||||
|
osProtectedRoles := os.Getenv(constants.EnvKeyProtectedRoles)
|
||||||
|
|
||||||
|
ienv, ok := envData[constants.EnvKeyEnv]
|
||||||
|
if !ok || ienv == "" {
|
||||||
|
envData[constants.EnvKeyEnv] = osEnv
|
||||||
|
if envData[constants.EnvKeyEnv] == "" {
|
||||||
|
envData[constants.EnvKeyEnv] = "production"
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
if envData[constants.EnvKeyEnv] == "production" {
|
||||||
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
|
envData[constants.EnvKeyIsProd] = true
|
||||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyPort] = "8080"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyAccessTokenExpiryTime] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyAccessTokenExpiryTime] = os.Getenv(constants.EnvKeyAccessTokenExpiryTime)
|
|
||||||
if envData.StringEnv[constants.EnvKeyAccessTokenExpiryTime] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyAccessTokenExpiryTime] = "30m"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyAdminSecret] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv(constants.EnvKeyAdminSecret)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySmtpHost] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv(constants.EnvKeySmtpHost)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySmtpPort] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeySmtpPort] = os.Getenv(constants.EnvKeySmtpPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySmtpUsername] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeySmtpUsername] = os.Getenv(constants.EnvKeySmtpUsername)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySmtpPassword] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeySmtpPassword] = os.Getenv(constants.EnvKeySmtpPassword)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySenderEmail] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
|
|
||||||
}
|
|
||||||
|
|
||||||
algo := envData.StringEnv[constants.EnvKeyJwtType]
|
|
||||||
if algo == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = "RS256"
|
|
||||||
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
|
||||||
} else {
|
} else {
|
||||||
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
envData[constants.EnvKeyIsProd] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osEnv != "" && osEnv != envData[constants.EnvKeyEnv] {
|
||||||
|
envData[constants.EnvKeyEnv] = osEnv
|
||||||
|
if envData[constants.EnvKeyEnv] == "production" {
|
||||||
|
envData[constants.EnvKeyIsProd] = true
|
||||||
|
} else {
|
||||||
|
envData[constants.EnvKeyIsProd] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAppURL]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAppURL] = osAppURL
|
||||||
|
}
|
||||||
|
if osAppURL != "" && envData[constants.EnvKeyAppURL] != osAppURL {
|
||||||
|
envData[constants.EnvKeyAppURL] = osAppURL
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAuthorizerURL]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAuthorizerURL] = osAuthorizerURL
|
||||||
|
}
|
||||||
|
if osAuthorizerURL != "" && envData[constants.EnvKeyAuthorizerURL] != osAuthorizerURL {
|
||||||
|
envData[constants.EnvKeyAuthorizerURL] = osAuthorizerURL
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyPort]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyPort] = osPort
|
||||||
|
if envData[constants.EnvKeyPort] == "" {
|
||||||
|
envData[constants.EnvKeyPort] = "8080"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osPort != "" && envData[constants.EnvKeyPort] != osPort {
|
||||||
|
envData[constants.EnvKeyPort] = osPort
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAccessTokenExpiryTime]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAccessTokenExpiryTime] = osAccessTokenExpiryTime
|
||||||
|
if envData[constants.EnvKeyAccessTokenExpiryTime] == "" {
|
||||||
|
envData[constants.EnvKeyAccessTokenExpiryTime] = "30m"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osAccessTokenExpiryTime != "" && envData[constants.EnvKeyAccessTokenExpiryTime] != osAccessTokenExpiryTime {
|
||||||
|
envData[constants.EnvKeyAccessTokenExpiryTime] = osAccessTokenExpiryTime
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAdminSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAdminSecret] = osAdminSecret
|
||||||
|
}
|
||||||
|
if osAdminSecret != "" && envData[constants.EnvKeyAdminSecret] != osAdminSecret {
|
||||||
|
envData[constants.EnvKeyAdminSecret] = osAdminSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySmtpHost]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySmtpHost] = osSmtpHost
|
||||||
|
}
|
||||||
|
if osSmtpHost != "" && envData[constants.EnvKeySmtpHost] != osSmtpHost {
|
||||||
|
envData[constants.EnvKeySmtpHost] = osSmtpHost
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySmtpPort]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySmtpPort] = osSmtpPort
|
||||||
|
}
|
||||||
|
if osSmtpPort != "" && envData[constants.EnvKeySmtpPort] != osSmtpPort {
|
||||||
|
envData[constants.EnvKeySmtpPort] = osSmtpPort
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySmtpUsername]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySmtpUsername] = osSmtpUsername
|
||||||
|
}
|
||||||
|
if osSmtpUsername != "" && envData[constants.EnvKeySmtpUsername] != osSmtpUsername {
|
||||||
|
envData[constants.EnvKeySmtpUsername] = osSmtpUsername
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySmtpPassword]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySmtpPassword] = osSmtpPassword
|
||||||
|
}
|
||||||
|
if osSmtpPassword != "" && envData[constants.EnvKeySmtpPassword] != osSmtpPassword {
|
||||||
|
envData[constants.EnvKeySmtpPassword] = osSmtpPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySenderEmail]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySenderEmail] = osSenderEmail
|
||||||
|
}
|
||||||
|
if osSenderEmail != "" && envData[constants.EnvKeySenderEmail] != osSenderEmail {
|
||||||
|
envData[constants.EnvKeySenderEmail] = osSenderEmail
|
||||||
|
}
|
||||||
|
|
||||||
|
algoVal, ok := envData[constants.EnvKeyJwtType]
|
||||||
|
algo := ""
|
||||||
|
if !ok || algoVal == "" {
|
||||||
|
envData[constants.EnvKeyJwtType] = osJwtType
|
||||||
|
if envData[constants.EnvKeyJwtType] == "" {
|
||||||
|
envData[constants.EnvKeyJwtType] = "RS256"
|
||||||
|
algo = envData[constants.EnvKeyJwtType].(string)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
algo = algoVal.(string)
|
||||||
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
||||||
|
log.Debug("Invalid JWT Algorithm")
|
||||||
return errors.New("invalid JWT_TYPE")
|
return errors.New("invalid JWT_TYPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if osJwtType != "" && osJwtType != algo {
|
||||||
|
if !crypto.IsHMACA(osJwtType) && !crypto.IsRSA(osJwtType) && !crypto.IsECDSA(osJwtType) {
|
||||||
|
log.Debug("Invalid JWT Algorithm")
|
||||||
|
return errors.New("invalid JWT_TYPE")
|
||||||
|
}
|
||||||
|
algo = osJwtType
|
||||||
|
envData[constants.EnvKeyJwtType] = osJwtType
|
||||||
}
|
}
|
||||||
|
|
||||||
if crypto.IsHMACA(algo) {
|
if crypto.IsHMACA(algo) {
|
||||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
if val, ok := envData[constants.EnvKeyJwtSecret]; !ok || val == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
|
envData[constants.EnvKeyJwtSecret] = osJwtSecret
|
||||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
if envData[constants.EnvKeyJwtSecret] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret], _, err = crypto.NewHMACKey(algo, clientID)
|
envData[constants.EnvKeyJwtSecret], _, err = crypto.NewHMACKey(algo, clientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if osJwtSecret != "" && envData[constants.EnvKeyJwtSecret] != osJwtSecret {
|
||||||
|
envData[constants.EnvKeyJwtSecret] = osJwtSecret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if crypto.IsRSA(algo) || crypto.IsECDSA(algo) {
|
if crypto.IsRSA(algo) || crypto.IsECDSA(algo) {
|
||||||
privateKey, publicKey := "", ""
|
privateKey, publicKey := "", ""
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
|
if val, ok := envData[constants.EnvKeyJwtPrivateKey]; !ok || val == "" {
|
||||||
privateKey = os.Getenv(constants.EnvKeyJwtPrivateKey)
|
privateKey = osJwtPrivateKey
|
||||||
|
}
|
||||||
|
if osJwtPrivateKey != "" && privateKey != osJwtPrivateKey {
|
||||||
|
privateKey = osJwtPrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
|
if val, ok := envData[constants.EnvKeyJwtPublicKey]; !ok || val == "" {
|
||||||
publicKey = os.Getenv(constants.EnvKeyJwtPublicKey)
|
publicKey = osJwtPublicKey
|
||||||
|
}
|
||||||
|
if osJwtPublicKey != "" && publicKey != osJwtPublicKey {
|
||||||
|
publicKey = osJwtPublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// if algo is RSA / ECDSA, then we need to have both private and public key
|
// if algo is RSA / ECDSA, then we need to have both private and public key
|
||||||
@@ -247,158 +285,273 @@ func InitAllEnv() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = privateKey
|
envData[constants.EnvKeyJwtPrivateKey] = privateKey
|
||||||
envData.StringEnv[constants.EnvKeyJwtPublicKey] = publicKey
|
envData[constants.EnvKeyJwtPublicKey] = publicKey
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
if val, ok := envData[constants.EnvKeyJwtRoleClaim]; !ok || val == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv(constants.EnvKeyJwtRoleClaim)
|
envData[constants.EnvKeyJwtRoleClaim] = osJwtRoleClaim
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
if envData[constants.EnvKeyJwtRoleClaim] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = "role"
|
envData[constants.EnvKeyJwtRoleClaim] = "role"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osJwtRoleClaim != "" && envData[constants.EnvKeyJwtRoleClaim] != osJwtRoleClaim {
|
||||||
|
envData[constants.EnvKeyJwtRoleClaim] = osJwtRoleClaim
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyCustomAccessTokenScript]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyCustomAccessTokenScript] = osCustomAccessTokenScript
|
||||||
|
}
|
||||||
|
if osCustomAccessTokenScript != "" && envData[constants.EnvKeyCustomAccessTokenScript] != osCustomAccessTokenScript {
|
||||||
|
envData[constants.EnvKeyCustomAccessTokenScript] = osCustomAccessTokenScript
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyGoogleClientID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyGoogleClientID] = osGoogleClientID
|
||||||
|
}
|
||||||
|
if osGoogleClientID != "" && envData[constants.EnvKeyGoogleClientID] != osGoogleClientID {
|
||||||
|
envData[constants.EnvKeyGoogleClientID] = osGoogleClientID
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyGoogleClientSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyGoogleClientSecret] = osGoogleClientSecret
|
||||||
|
}
|
||||||
|
if osGoogleClientSecret != "" && envData[constants.EnvKeyGoogleClientSecret] != osGoogleClientSecret {
|
||||||
|
envData[constants.EnvKeyGoogleClientSecret] = osGoogleClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyGithubClientID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyGithubClientID] = osGithubClientID
|
||||||
|
}
|
||||||
|
if osGithubClientID != "" && envData[constants.EnvKeyGithubClientID] != osGithubClientID {
|
||||||
|
envData[constants.EnvKeyGithubClientID] = osGithubClientID
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyGithubClientSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyGithubClientSecret] = osGithubClientSecret
|
||||||
|
}
|
||||||
|
if osGithubClientSecret != "" && envData[constants.EnvKeyGithubClientSecret] != osGithubClientSecret {
|
||||||
|
envData[constants.EnvKeyGithubClientSecret] = osGithubClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyFacebookClientID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyFacebookClientID] = osFacebookClientID
|
||||||
|
}
|
||||||
|
if osFacebookClientID != "" && envData[constants.EnvKeyFacebookClientID] != osFacebookClientID {
|
||||||
|
envData[constants.EnvKeyFacebookClientID] = osFacebookClientID
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyFacebookClientSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyFacebookClientSecret] = osFacebookClientSecret
|
||||||
|
}
|
||||||
|
if osFacebookClientSecret != "" && envData[constants.EnvKeyFacebookClientSecret] != osFacebookClientSecret {
|
||||||
|
envData[constants.EnvKeyFacebookClientSecret] = osFacebookClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyLinkedInClientID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyLinkedInClientID] = osLinkedInClientID
|
||||||
|
}
|
||||||
|
if osFacebookClientID != "" && envData[constants.EnvKeyLinkedInClientID] != osFacebookClientID {
|
||||||
|
envData[constants.EnvKeyLinkedInClientID] = osLinkedInClientID
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyLinkedInClientSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyLinkedInClientSecret] = osLinkedInClientSecret
|
||||||
|
}
|
||||||
|
if osFacebookClientSecret != "" && envData[constants.EnvKeyLinkedInClientSecret] != osFacebookClientSecret {
|
||||||
|
envData[constants.EnvKeyLinkedInClientSecret] = osLinkedInClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAppleClientID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAppleClientID] = osAppleClientID
|
||||||
|
}
|
||||||
|
if osFacebookClientID != "" && envData[constants.EnvKeyAppleClientID] != osFacebookClientID {
|
||||||
|
envData[constants.EnvKeyAppleClientID] = osAppleClientID
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyAppleClientSecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyAppleClientSecret] = osAppleClientSecret
|
||||||
|
}
|
||||||
|
if osFacebookClientSecret != "" && envData[constants.EnvKeyAppleClientSecret] != osFacebookClientSecret {
|
||||||
|
envData[constants.EnvKeyAppleClientSecret] = osAppleClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyResetPasswordURL]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(osResetPasswordURL, "/")
|
||||||
|
}
|
||||||
|
if osResetPasswordURL != "" && envData[constants.EnvKeyResetPasswordURL] != osResetPasswordURL {
|
||||||
|
envData[constants.EnvKeyResetPasswordURL] = osResetPasswordURL
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyOrganizationName]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyOrganizationName] = osOrganizationName
|
||||||
|
}
|
||||||
|
if osOrganizationName != "" && envData[constants.EnvKeyOrganizationName] != osOrganizationName {
|
||||||
|
envData[constants.EnvKeyOrganizationName] = osOrganizationName
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyOrganizationLogo]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyOrganizationLogo] = osOrganizationLogo
|
||||||
|
}
|
||||||
|
if osOrganizationLogo != "" && envData[constants.EnvKeyOrganizationLogo] != osOrganizationLogo {
|
||||||
|
envData[constants.EnvKeyOrganizationLogo] = osOrganizationLogo
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := envData[constants.EnvKeyDisableBasicAuthentication]; !ok {
|
||||||
|
envData[constants.EnvKeyDisableBasicAuthentication] = osDisableBasicAuthentication == "true"
|
||||||
|
}
|
||||||
|
if osDisableBasicAuthentication != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisableBasicAuthentication)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableBasicAuthentication].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableBasicAuthentication] = boolValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] == "" {
|
if _, ok := envData[constants.EnvKeyDisableEmailVerification]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] = os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
envData[constants.EnvKeyDisableEmailVerification] = osDisableEmailVerification == "true"
|
||||||
}
|
}
|
||||||
|
if osDisableEmailVerification != "" {
|
||||||
if envData.StringEnv[constants.EnvKeyRedisURL] == "" {
|
boolValue, err := strconv.ParseBool(osDisableEmailVerification)
|
||||||
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv(constants.EnvKeyRedisURL)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||||
if envData.StringEnv[constants.EnvKeyCookieName] == "" {
|
envData[constants.EnvKeyDisableEmailVerification] = boolValue
|
||||||
envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv(constants.EnvKeyCookieName)
|
|
||||||
if envData.StringEnv[constants.EnvKeyCookieName] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyCookieName] = "authorizer"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyGoogleClientID] == "" {
|
if _, ok := envData[constants.EnvKeyDisableMagicLinkLogin]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyGoogleClientID] = os.Getenv(constants.EnvKeyGoogleClientID)
|
envData[constants.EnvKeyDisableMagicLinkLogin] = osDisableMagicLinkLogin == "true"
|
||||||
|
}
|
||||||
|
if osDisableMagicLinkLogin != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisableMagicLinkLogin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableMagicLinkLogin].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableMagicLinkLogin] = boolValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyGoogleClientSecret] == "" {
|
if _, ok := envData[constants.EnvKeyDisableLoginPage]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyGoogleClientSecret] = os.Getenv(constants.EnvKeyGoogleClientSecret)
|
envData[constants.EnvKeyDisableLoginPage] = osDisableLoginPage == "true"
|
||||||
|
}
|
||||||
|
if osDisableLoginPage != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisableLoginPage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableLoginPage].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableLoginPage] = boolValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyGithubClientID] == "" {
|
if _, ok := envData[constants.EnvKeyDisableSignUp]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyGithubClientID] = os.Getenv(constants.EnvKeyGithubClientID)
|
envData[constants.EnvKeyDisableSignUp] = osDisableSignUp == "true"
|
||||||
|
}
|
||||||
|
if osDisableSignUp != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisableSignUp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableSignUp].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableSignUp] = boolValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyGithubClientSecret] == "" {
|
if _, ok := envData[constants.EnvKeyDisableRedisForEnv]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyGithubClientSecret] = os.Getenv(constants.EnvKeyGithubClientSecret)
|
envData[constants.EnvKeyDisableRedisForEnv] = osDisableRedisForEnv == "true"
|
||||||
|
}
|
||||||
|
if osDisableRedisForEnv != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisableRedisForEnv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableRedisForEnv].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableRedisForEnv] = boolValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyFacebookClientID] == "" {
|
if _, ok := envData[constants.EnvKeyDisableStrongPassword]; !ok {
|
||||||
envData.StringEnv[constants.EnvKeyFacebookClientID] = os.Getenv(constants.EnvKeyFacebookClientID)
|
envData[constants.EnvKeyDisableStrongPassword] = osDisableStrongPassword == "true"
|
||||||
}
|
}
|
||||||
|
if osDisableStrongPassword != "" {
|
||||||
if envData.StringEnv[constants.EnvKeyFacebookClientSecret] == "" {
|
boolValue, err := strconv.ParseBool(osDisableStrongPassword)
|
||||||
envData.StringEnv[constants.EnvKeyFacebookClientSecret] = os.Getenv(constants.EnvKeyFacebookClientSecret)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisableStrongPassword].(bool) {
|
||||||
|
envData[constants.EnvKeyDisableStrongPassword] = boolValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyResetPasswordURL] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv(constants.EnvKeyResetPasswordURL), "/")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
|
||||||
envData.BoolEnv[constants.EnvKeyDisableSignUp] = os.Getenv(constants.EnvKeyDisableSignUp) == "true"
|
|
||||||
|
|
||||||
// no need to add nil check as its already done above
|
// 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] == "" {
|
if envData[constants.EnvKeySmtpHost] == "" || envData[constants.EnvKeySmtpUsername] == "" || envData[constants.EnvKeySmtpPassword] == "" || envData[constants.EnvKeySenderEmail] == "" && envData[constants.EnvKeySmtpPort] == "" {
|
||||||
envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = true
|
envData[constants.EnvKeyDisableEmailVerification] = true
|
||||||
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true
|
envData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.BoolEnv[constants.EnvKeyDisableEmailVerification] {
|
if envData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||||
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true
|
envData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOriginsSplit := strings.Split(os.Getenv(constants.EnvKeyAllowedOrigins), ",")
|
if val, ok := envData[constants.EnvKeyAllowedOrigins]; !ok || val == "" {
|
||||||
allowedOrigins := []string{}
|
envData[constants.EnvKeyAllowedOrigins] = osAllowedOrigins
|
||||||
hasWildCard := false
|
if envData[constants.EnvKeyAllowedOrigins] == "" {
|
||||||
|
envData[constants.EnvKeyAllowedOrigins] = "*"
|
||||||
for _, val := range allowedOriginsSplit {
|
|
||||||
trimVal := strings.TrimSpace(val)
|
|
||||||
if trimVal != "" {
|
|
||||||
if trimVal != "*" {
|
|
||||||
host, port := utils.GetHostParts(trimVal)
|
|
||||||
allowedOrigins = append(allowedOrigins, host+":"+port)
|
|
||||||
} else {
|
|
||||||
hasWildCard = true
|
|
||||||
allowedOrigins = append(allowedOrigins, trimVal)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if osAllowedOrigins != "" && envData[constants.EnvKeyAllowedOrigins] != osAllowedOrigins {
|
||||||
|
envData[constants.EnvKeyAllowedOrigins] = osAllowedOrigins
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allowedOrigins) > 1 && hasWildCard {
|
if val, ok := envData[constants.EnvKeyRoles]; !ok || val == "" {
|
||||||
allowedOrigins = []string{"*"}
|
envData[constants.EnvKeyRoles] = osRoles
|
||||||
|
if envData[constants.EnvKeyRoles] == "" {
|
||||||
|
envData[constants.EnvKeyRoles] = "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osRoles != "" && envData[constants.EnvKeyRoles] != osRoles {
|
||||||
|
envData[constants.EnvKeyRoles] = osRoles
|
||||||
|
}
|
||||||
|
roles := strings.Split(envData[constants.EnvKeyRoles].(string), ",")
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyDefaultRoles]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyDefaultRoles] = osDefaultRoles
|
||||||
|
if envData[constants.EnvKeyDefaultRoles] == "" {
|
||||||
|
envData[constants.EnvKeyDefaultRoles] = "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osDefaultRoles != "" && envData[constants.EnvKeyDefaultRoles] != osDefaultRoles {
|
||||||
|
envData[constants.EnvKeyDefaultRoles] = osDefaultRoles
|
||||||
|
}
|
||||||
|
defaultRoles := strings.Split(envData[constants.EnvKeyDefaultRoles].(string), ",")
|
||||||
|
if len(defaultRoles) == 0 {
|
||||||
|
defaultRoles = []string{roles[0]}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allowedOrigins) == 0 {
|
for _, role := range defaultRoles {
|
||||||
allowedOrigins = []string{"*"}
|
if !utils.StringSliceContains(roles, role) {
|
||||||
}
|
return fmt.Errorf("Default role %s is not defined in roles", role)
|
||||||
|
|
||||||
envData.SliceEnv[constants.EnvKeyAllowedOrigins] = allowedOrigins
|
|
||||||
|
|
||||||
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(constants.EnvKeyDefaultRoles))
|
|
||||||
defaultRoleSplit := strings.Split(defaultRolesEnv, ",")
|
|
||||||
defaultRoles := []string{}
|
|
||||||
|
|
||||||
if len(defaultRolesEnv) == 0 {
|
|
||||||
defaultRoles = []string{"user"}
|
|
||||||
}
|
|
||||||
|
|
||||||
protectedRolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyProtectedRoles))
|
|
||||||
protectedRolesSplit := strings.Split(protectedRolesEnv, ",")
|
|
||||||
protectedRoles := []string{}
|
|
||||||
|
|
||||||
if len(protectedRolesEnv) > 0 {
|
|
||||||
for _, val := range protectedRolesSplit {
|
|
||||||
trimVal := strings.TrimSpace(val)
|
|
||||||
protectedRoles = append(protectedRoles, trimVal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, val := range rolesSplit {
|
if val, ok := envData[constants.EnvKeyProtectedRoles]; !ok || val == "" {
|
||||||
trimVal := strings.TrimSpace(val)
|
envData[constants.EnvKeyProtectedRoles] = osProtectedRoles
|
||||||
if trimVal != "" {
|
|
||||||
roles = append(roles, trimVal)
|
|
||||||
if utils.StringSliceContains(defaultRoleSplit, trimVal) {
|
|
||||||
defaultRoles = append(defaultRoles, trimVal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if osProtectedRoles != "" && envData[constants.EnvKeyProtectedRoles] != osProtectedRoles {
|
||||||
|
envData[constants.EnvKeyProtectedRoles] = osProtectedRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
err = memorystore.Provider.UpdateEnvStore(envData)
|
||||||
return errors.New(`invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
if err != nil {
|
||||||
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
envData.SliceEnv[constants.EnvKeyRoles] = roles
|
|
||||||
envData.SliceEnv[constants.EnvKeyDefaultRoles] = defaultRoles
|
|
||||||
envData.SliceEnv[constants.EnvKeyProtectedRoles] = protectedRoles
|
|
||||||
|
|
||||||
if os.Getenv(constants.EnvKeyOrganizationName) != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyOrganizationName] = os.Getenv(constants.EnvKeyOrganizationName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if os.Getenv(constants.EnvKeyOrganizationLogo) != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyOrganizationLogo] = os.Getenv(constants.EnvKeyOrganizationLogo)
|
|
||||||
}
|
|
||||||
|
|
||||||
envstore.EnvStoreObj.UpdateEnvStore(envData)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
171
server/env/persist_env.go
vendored
171
server/env/persist_env.go
vendored
@@ -1,69 +1,137 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func fixBackwardCompatibility(data map[string]interface{}) (bool, map[string]interface{}) {
|
||||||
|
result := data
|
||||||
|
// check if env data is stored in older format
|
||||||
|
hasOlderFormat := false
|
||||||
|
if _, ok := result["bool_env"]; ok {
|
||||||
|
for key, value := range result["bool_env"].(map[string]interface{}) {
|
||||||
|
result[key] = value
|
||||||
|
}
|
||||||
|
hasOlderFormat = true
|
||||||
|
delete(result, "bool_env")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := result["string_env"]; ok {
|
||||||
|
for key, value := range result["string_env"].(map[string]interface{}) {
|
||||||
|
result[key] = value
|
||||||
|
}
|
||||||
|
hasOlderFormat = true
|
||||||
|
delete(result, "string_env")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := result["slice_env"]; ok {
|
||||||
|
for key, value := range result["slice_env"].(map[string]interface{}) {
|
||||||
|
typeOfValue := reflect.TypeOf(value)
|
||||||
|
if strings.Contains(typeOfValue.String(), "[]string") {
|
||||||
|
result[key] = strings.Join(value.([]string), ",")
|
||||||
|
}
|
||||||
|
if strings.Contains(typeOfValue.String(), "[]interface") {
|
||||||
|
result[key] = strings.Join(utils.ConvertInterfaceToStringSlice(value), ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasOlderFormat = true
|
||||||
|
delete(result, "slice_env")
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasOlderFormat, result
|
||||||
|
}
|
||||||
|
|
||||||
// GetEnvData returns the env data from database
|
// GetEnvData returns the env data from database
|
||||||
func GetEnvData() (envstore.Store, error) {
|
func GetEnvData() (map[string]interface{}, error) {
|
||||||
var result envstore.Store
|
var result map[string]interface{}
|
||||||
env, err := db.Provider.GetEnv()
|
ctx := context.Background()
|
||||||
|
env, err := db.Provider.GetEnv(ctx)
|
||||||
// config not found in db
|
// config not found in db
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while getting env data from db: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptionKey := env.Hash
|
encryptionKey := env.Hash
|
||||||
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting encryption key: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||||
|
|
||||||
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from B64: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from AES: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(decryptedConfigs, &result)
|
err = json.Unmarshal(decryptedConfigs, &result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while unmarshalling env data: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasOlderFormat, result := fixBackwardCompatibility(result)
|
||||||
|
|
||||||
|
if hasOlderFormat {
|
||||||
|
err = memorystore.Provider.UpdateEnvStore(result)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PersistEnv persists the environment variables to the database
|
// PersistEnv persists the environment variables to the database
|
||||||
func PersistEnv() error {
|
func PersistEnv() error {
|
||||||
env, err := db.Provider.GetEnv()
|
ctx := context.Background()
|
||||||
|
env, err := db.Provider.GetEnv(ctx)
|
||||||
// config not found in db
|
// config not found in db
|
||||||
if err != nil {
|
if err != nil || env.EnvData == "" {
|
||||||
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
||||||
hash := uuid.New().String()[:36-4]
|
hash := uuid.New().String()[:36-4]
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, hash)
|
err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while updating encryption env variable: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
encodedHash := crypto.EncryptB64(hash)
|
encodedHash := crypto.EncryptB64(hash)
|
||||||
|
|
||||||
encryptedConfig, err := crypto.EncryptEnvData(envstore.EnvStoreObj.GetEnvStoreClone())
|
res, err := memorystore.Provider.GetEnvStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while getting env store: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptedConfig, err := crypto.EncryptEnvData(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while encrypting env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +140,9 @@ func PersistEnv() error {
|
|||||||
EnvData: encryptedConfig,
|
EnvData: encryptedConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err = db.Provider.AddEnv(env)
|
env, err = db.Provider.AddEnv(ctx, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while persisting env data to db: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -82,108 +151,112 @@ func PersistEnv() error {
|
|||||||
encryptionKey := env.Hash
|
encryptionKey := env.Hash
|
||||||
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting encryption key: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||||
|
|
||||||
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from B64: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from AES: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// temp store variable
|
// temp store variable
|
||||||
var storeData envstore.Store
|
storeData := map[string]interface{}{}
|
||||||
|
|
||||||
err = json.Unmarshal(decryptedConfigs, &storeData)
|
err = json.Unmarshal(decryptedConfigs, &storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while un-marshalling env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasOlderFormat, result := fixBackwardCompatibility(storeData)
|
||||||
|
if hasOlderFormat {
|
||||||
|
err = memorystore.Provider.UpdateEnvStore(result)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// if env is changed via env file or OS env
|
// if env is changed via env file or OS env
|
||||||
// give that higher preference and update db, but we don't recommend it
|
// give that higher preference and update db, but we don't recommend it
|
||||||
|
|
||||||
hasChanged := false
|
hasChanged := false
|
||||||
|
for key, value := range storeData {
|
||||||
for key, value := range storeData.StringEnv {
|
|
||||||
// don't override unexposed envs
|
// don't override unexposed envs
|
||||||
if key != constants.EnvKeyEncryptionKey {
|
|
||||||
// check only for derivative keys
|
// check only for derivative keys
|
||||||
// No need to check for ENCRYPTION_KEY which special key we use for encrypting config data
|
// No need to check for ENCRYPTION_KEY which special key we use for encrypting config data
|
||||||
// as we have removed it from json
|
// as we have removed it from json
|
||||||
|
if key != constants.EnvKeyEncryptionKey {
|
||||||
envValue := strings.TrimSpace(os.Getenv(key))
|
envValue := strings.TrimSpace(os.Getenv(key))
|
||||||
|
|
||||||
// env is not empty
|
|
||||||
if envValue != "" {
|
if envValue != "" {
|
||||||
if value != envValue {
|
switch key {
|
||||||
storeData.StringEnv[key] = envValue
|
case constants.EnvKeyIsProd, constants.EnvKeyDisableBasicAuthentication, constants.EnvKeyDisableEmailVerification, constants.EnvKeyDisableLoginPage, constants.EnvKeyDisableMagicLinkLogin, constants.EnvKeyDisableSignUp, constants.EnvKeyDisableRedisForEnv, constants.EnvKeyDisableStrongPassword:
|
||||||
|
if envValueBool, err := strconv.ParseBool(envValue); err == nil {
|
||||||
|
if value.(bool) != envValueBool {
|
||||||
|
storeData[key] = envValueBool
|
||||||
hasChanged = true
|
hasChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
default:
|
||||||
}
|
if value != nil && value.(string) != envValue {
|
||||||
|
storeData[key] = envValue
|
||||||
for key, value := range storeData.BoolEnv {
|
|
||||||
envValue := strings.TrimSpace(os.Getenv(key))
|
|
||||||
// env is not empty
|
|
||||||
if envValue != "" {
|
|
||||||
envValueBool, _ := strconv.ParseBool(envValue)
|
|
||||||
if value != envValueBool {
|
|
||||||
storeData.BoolEnv[key] = envValueBool
|
|
||||||
hasChanged = true
|
hasChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value := range storeData.SliceEnv {
|
|
||||||
envValue := strings.TrimSpace(os.Getenv(key))
|
|
||||||
// env is not empty
|
|
||||||
if envValue != "" {
|
|
||||||
envStringArr := strings.Split(envValue, ",")
|
|
||||||
if !utils.IsStringArrayEqual(value, envStringArr) {
|
|
||||||
storeData.SliceEnv[key] = envStringArr
|
|
||||||
hasChanged = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle derivative cases like disabling email verification & magic login
|
// handle derivative cases like disabling email verification & magic login
|
||||||
// in case SMTP is off but env is set to true
|
// in case SMTP is off but env is set to true
|
||||||
if storeData.StringEnv[constants.EnvKeySmtpHost] == "" || storeData.StringEnv[constants.EnvKeySmtpUsername] == "" || storeData.StringEnv[constants.EnvKeySmtpPassword] == "" || storeData.StringEnv[constants.EnvKeySenderEmail] == "" && storeData.StringEnv[constants.EnvKeySmtpPort] == "" {
|
if storeData[constants.EnvKeySmtpHost] == "" || storeData[constants.EnvKeySmtpUsername] == "" || storeData[constants.EnvKeySmtpPassword] == "" || storeData[constants.EnvKeySenderEmail] == "" && storeData[constants.EnvKeySmtpPort] == "" {
|
||||||
if !storeData.BoolEnv[constants.EnvKeyDisableEmailVerification] {
|
if !storeData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||||
storeData.BoolEnv[constants.EnvKeyDisableEmailVerification] = true
|
storeData[constants.EnvKeyDisableEmailVerification] = true
|
||||||
hasChanged = true
|
hasChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !storeData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] {
|
if !storeData[constants.EnvKeyDisableMagicLinkLogin].(bool) {
|
||||||
storeData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true
|
storeData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||||
hasChanged = true
|
hasChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvStoreObj.UpdateEnvStore(storeData)
|
err = memorystore.Provider.UpdateEnvStore(storeData)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while generating JWK: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// updating jwk
|
// updating jwk
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyJWK, jwk)
|
||||||
|
|
||||||
if hasChanged {
|
if hasChanged {
|
||||||
encryptedConfig, err := crypto.EncryptEnvData(storeData)
|
encryptedConfig, err := crypto.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while encrypting env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
env.EnvData = encryptedConfig
|
env.EnvData = encryptedConfig
|
||||||
_, err = db.Provider.UpdateEnv(env)
|
_, err = db.Provider.UpdateEnv(ctx, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
log.Debug("Failed to Update Config: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,120 +0,0 @@
|
|||||||
package envstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ARG_DB_URL is the cli arg variable for the database url
|
|
||||||
ARG_DB_URL *string
|
|
||||||
// ARG_DB_TYPE is the cli arg variable for the database type
|
|
||||||
ARG_DB_TYPE *string
|
|
||||||
// ARG_ENV_FILE is the cli arg variable for the env file
|
|
||||||
ARG_ENV_FILE *string
|
|
||||||
)
|
|
||||||
|
|
||||||
// Store data structure
|
|
||||||
type Store struct {
|
|
||||||
StringEnv map[string]string `json:"string_env"`
|
|
||||||
BoolEnv map[string]bool `json:"bool_env"`
|
|
||||||
SliceEnv map[string][]string `json:"slice_env"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnvStore struct
|
|
||||||
type EnvStore struct {
|
|
||||||
mutex sync.Mutex
|
|
||||||
store *Store
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultStore = &EnvStore{
|
|
||||||
store: &Store{
|
|
||||||
StringEnv: map[string]string{
|
|
||||||
constants.EnvKeyAdminCookieName: "authorizer-admin",
|
|
||||||
constants.EnvKeyJwtRoleClaim: "role",
|
|
||||||
constants.EnvKeyOrganizationName: "Authorizer",
|
|
||||||
constants.EnvKeyOrganizationLogo: "https://www.authorizer.dev/images/logo.png",
|
|
||||||
},
|
|
||||||
BoolEnv: map[string]bool{
|
|
||||||
constants.EnvKeyDisableBasicAuthentication: false,
|
|
||||||
constants.EnvKeyDisableMagicLinkLogin: false,
|
|
||||||
constants.EnvKeyDisableEmailVerification: false,
|
|
||||||
constants.EnvKeyDisableLoginPage: false,
|
|
||||||
constants.EnvKeyDisableSignUp: false,
|
|
||||||
},
|
|
||||||
SliceEnv: map[string][]string{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnvStoreObj.GetBoolStoreEnvVariable global variable for EnvStore
|
|
||||||
var EnvStoreObj = defaultStore
|
|
||||||
|
|
||||||
// UpdateEnvStore to update the whole env store object
|
|
||||||
func (e *EnvStore) UpdateEnvStore(store Store) {
|
|
||||||
e.mutex.Lock()
|
|
||||||
defer e.mutex.Unlock()
|
|
||||||
// just override the keys + new keys
|
|
||||||
|
|
||||||
for key, value := range store.StringEnv {
|
|
||||||
e.store.StringEnv[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range store.BoolEnv {
|
|
||||||
e.store.BoolEnv[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range store.SliceEnv {
|
|
||||||
e.store.SliceEnv[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateEnvVariable to update the particular env variable
|
|
||||||
func (e *EnvStore) UpdateEnvVariable(storeIdentifier, key string, value interface{}) {
|
|
||||||
e.mutex.Lock()
|
|
||||||
defer e.mutex.Unlock()
|
|
||||||
switch storeIdentifier {
|
|
||||||
case constants.StringStoreIdentifier:
|
|
||||||
e.store.StringEnv[key] = value.(string)
|
|
||||||
case constants.BoolStoreIdentifier:
|
|
||||||
e.store.BoolEnv[key] = value.(bool)
|
|
||||||
case constants.SliceStoreIdentifier:
|
|
||||||
e.store.SliceEnv[key] = value.([]string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStringStoreEnvVariable to get the env variable from string store object
|
|
||||||
func (e *EnvStore) GetStringStoreEnvVariable(key string) string {
|
|
||||||
// e.mutex.Lock()
|
|
||||||
// defer e.mutex.Unlock()
|
|
||||||
return e.store.StringEnv[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBoolStoreEnvVariable to get the env variable from bool store object
|
|
||||||
func (e *EnvStore) GetBoolStoreEnvVariable(key string) bool {
|
|
||||||
// e.mutex.Lock()
|
|
||||||
// defer e.mutex.Unlock()
|
|
||||||
return e.store.BoolEnv[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSliceStoreEnvVariable to get the env variable from slice store object
|
|
||||||
func (e *EnvStore) GetSliceStoreEnvVariable(key string) []string {
|
|
||||||
// e.mutex.Lock()
|
|
||||||
// defer e.mutex.Unlock()
|
|
||||||
return e.store.SliceEnv[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEnvStoreClone to get clone of current env store object
|
|
||||||
func (e *EnvStore) GetEnvStoreClone() Store {
|
|
||||||
e.mutex.Lock()
|
|
||||||
defer e.mutex.Unlock()
|
|
||||||
|
|
||||||
result := *e.store
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EnvStore) ResetStore() {
|
|
||||||
e.mutex.Lock()
|
|
||||||
defer e.mutex.Unlock()
|
|
||||||
e.store = defaultStore.store
|
|
||||||
}
|
|
@@ -20,6 +20,7 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||||
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
github.com/ugorji/go v1.2.6 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.2.0
|
github.com/vektah/gqlparser/v2 v2.2.0
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user