Compare commits
132 Commits
feat/loggi
...
0.38.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
891c885f20 | ||
![]() |
89606615dc | ||
![]() |
ecab47b2ea | ||
![]() |
882756ef3a | ||
![]() |
a208c87c29 | ||
![]() |
70ea463f60 | ||
![]() |
79c94fcaf0 | ||
![]() |
3b925bb072 | ||
![]() |
df17ea8f40 | ||
![]() |
94066d4408 | ||
![]() |
41468b5b60 | ||
![]() |
1c61fcc17a | ||
![]() |
a102924fd7 | ||
![]() |
390846c85f | ||
![]() |
a48b809a89 | ||
![]() |
cd46da60a0 | ||
![]() |
50f52a99b4 | ||
![]() |
150b1e5712 | ||
![]() |
1f7eee43e2 | ||
![]() |
7c441fff14 | ||
![]() |
647cc1d9bf | ||
![]() |
97b1d8d66f | ||
![]() |
2cce1c4e93 | ||
![]() |
8b1511a07b | ||
![]() |
a69dd95992 | ||
![]() |
d3260f4f32 | ||
![]() |
301bde4da2 | ||
![]() |
913c5c94fb | ||
![]() |
610896b6f5 | ||
![]() |
33f79872be | ||
![]() |
8fc52d76dc | ||
![]() |
aa12757155 | ||
![]() |
847c364ad1 | ||
![]() |
eabc943452 | ||
![]() |
41a0f15e16 | ||
![]() |
e2294c24d0 | ||
![]() |
a3c0a0422c | ||
![]() |
d837b1590a | ||
![]() |
283e570ebb | ||
![]() |
14c74f6566 | ||
![]() |
8e655daa71 | ||
![]() |
fed092bb65 | ||
![]() |
6d28290605 | ||
![]() |
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 | ||
![]() |
a638f02014 |
@@ -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
|
||||||
|
11
Makefile
11
Makefile
@@ -10,7 +10,16 @@ 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 && TEST_DBS="sqlite" go test -p 1 -v ./test
|
||||||
|
test-all-db:
|
||||||
|
rm -rf server/test/test.db && rm -rf test.db
|
||||||
|
docker run -d --name authorizer_scylla_db -p 9042:9042 scylladb/scylla
|
||||||
|
docker run -d --name authorizer_mongodb_db -p 27017:27017 mongo:4.4.15
|
||||||
|
docker run -d --name authorizer_arangodb -p 8529:8529 -e ARANGO_NO_AUTH=1 arangodb/arangodb:3.8.4
|
||||||
|
cd server && go clean --testcache && TEST_DBS="sqlite,mongodb,arangodb,scylladb" go test -p 1 -v ./test
|
||||||
|
docker rm -vf authorizer_mongodb_db
|
||||||
|
docker rm -vf authorizer_scylla_db
|
||||||
|
docker rm -vf authorizer_arangodb
|
||||||
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,17 +94,24 @@ export default function Root({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<></>}>
|
<Suspense fallback={<></>}>
|
||||||
<Switch>
|
<ThemeProvider theme={theme}>
|
||||||
<Route path="/app" exact>
|
<Wrapper>
|
||||||
<Login />
|
<Switch>
|
||||||
</Route>
|
<Route path="/app" exact>
|
||||||
<Route path="/app/reset-password">
|
<Login urlProps={urlProps} />
|
||||||
<ResetPassword />
|
</Route>
|
||||||
</Route>
|
<Route path="/app/signup" exact>
|
||||||
<Route path="/app/setup-password">
|
<SignUp urlProps={urlProps} />
|
||||||
<SetupPassword />
|
</Route>
|
||||||
</Route>
|
<Route path="/app/reset-password">
|
||||||
</Switch>
|
<ResetPassword />
|
||||||
|
</Route>
|
||||||
|
<Route path="/app/setup-password">
|
||||||
|
<SetupPassword />
|
||||||
|
</Route>
|
||||||
|
</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';
|
||||||
|
12
dashboard/package-lock.json
generated
12
dashboard/package-lock.json
generated
@@ -2529,7 +2529,8 @@
|
|||||||
"@chakra-ui/css-reset": {
|
"@chakra-ui/css-reset": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
|
||||||
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg=="
|
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@chakra-ui/descendant": {
|
"@chakra-ui/descendant": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
@@ -3133,7 +3134,8 @@
|
|||||||
"@graphql-typed-document-node/core": {
|
"@graphql-typed-document-node/core": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
||||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
|
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@popperjs/core": {
|
"@popperjs/core": {
|
||||||
"version": "2.11.0",
|
"version": "2.11.0",
|
||||||
@@ -3843,7 +3845,8 @@
|
|||||||
"react-icons": {
|
"react-icons": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
|
||||||
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
|
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
@@ -4029,7 +4032,8 @@
|
|||||||
"use-callback-ref": {
|
"use-callback-ref": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
|
||||||
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
|
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"use-sidecar": {
|
"use-sidecar": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
|
@@ -23,7 +23,6 @@ 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',
|
outline: 'none',
|
||||||
},
|
},
|
||||||
|
106
dashboard/src/components/DeleteWebhookModal.tsx
Normal file
106
dashboard/src/components/DeleteWebhookModal.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Flex,
|
||||||
|
MenuItem,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
useDisclosure,
|
||||||
|
Text,
|
||||||
|
useToast,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { useClient } from 'urql';
|
||||||
|
import { FaRegTrashAlt } from 'react-icons/fa';
|
||||||
|
import { DeleteWebhook } from '../graphql/mutation';
|
||||||
|
import { capitalizeFirstLetter } from '../utils';
|
||||||
|
|
||||||
|
interface deleteWebhookModalInputPropTypes {
|
||||||
|
webhookId: string;
|
||||||
|
eventName: string;
|
||||||
|
fetchWebookData: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeleteWebhookModal = ({
|
||||||
|
webhookId,
|
||||||
|
eventName,
|
||||||
|
fetchWebookData,
|
||||||
|
}: deleteWebhookModalInputPropTypes) => {
|
||||||
|
const client = useClient();
|
||||||
|
const toast = useToast();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
|
||||||
|
const deleteHandler = async () => {
|
||||||
|
const res = await client
|
||||||
|
.mutation(DeleteWebhook, { params: { id: webhookId } })
|
||||||
|
.toPromise();
|
||||||
|
if (res.error) {
|
||||||
|
toast({
|
||||||
|
title: capitalizeFirstLetter(res.error.message),
|
||||||
|
isClosable: true,
|
||||||
|
status: 'error',
|
||||||
|
position: 'bottom-right',
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (res.data?._delete_webhook) {
|
||||||
|
toast({
|
||||||
|
title: capitalizeFirstLetter(res.data?._delete_webhook.message),
|
||||||
|
isClosable: true,
|
||||||
|
status: 'success',
|
||||||
|
position: 'bottom-right',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onClose();
|
||||||
|
fetchWebookData();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MenuItem onClick={onOpen}>Delete</MenuItem>
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>Delete Webhook</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<Text fontSize="md">Are you sure?</Text>
|
||||||
|
<Flex
|
||||||
|
padding="5%"
|
||||||
|
marginTop="5%"
|
||||||
|
marginBottom="2%"
|
||||||
|
border="1px solid #ff7875"
|
||||||
|
borderRadius="5px"
|
||||||
|
flexDirection="column"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">
|
||||||
|
Webhook for event <b>{eventName}</b> will be deleted
|
||||||
|
permanently!
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
leftIcon={<FaRegTrashAlt />}
|
||||||
|
colorScheme="red"
|
||||||
|
variant="solid"
|
||||||
|
onClick={deleteHandler}
|
||||||
|
isDisabled={false}
|
||||||
|
>
|
||||||
|
<Center h="100%" pt="5%">
|
||||||
|
Delete
|
||||||
|
</Center>
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteWebhookModal;
|
@@ -1,88 +1,89 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
|
|
||||||
import InputField from "../../components/InputField";
|
import InputField from '../../components/InputField';
|
||||||
import { TextInputType } from "../../constants";
|
import { TextInputType } from '../../constants';
|
||||||
|
|
||||||
const DatabaseCredentials = ({ variables, setVariables }: any) => {
|
const DatabaseCredentials = ({ variables, setVariables }: any) => {
|
||||||
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{" "}
|
{' '}
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
Database Credentials
|
Database Credentials
|
||||||
</Text>
|
</Text>
|
||||||
<Stack spacing={6} padding="3% 0">
|
<Stack spacing={6} padding="3% 0">
|
||||||
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
||||||
Note: Database related environment variables cannot be updated from
|
Note: Database related environment variables cannot be updated from
|
||||||
dashboard :(
|
dashboard. Please use .env file or OS environment variables to update
|
||||||
</Text>
|
it.
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
</Text>
|
||||||
<Flex
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
w={isNotSmallerScreen ? "30%" : "40%"}
|
<Flex
|
||||||
justifyContent="start"
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
alignItems="center"
|
justifyContent="start"
|
||||||
>
|
alignItems="center"
|
||||||
<Text fontSize="sm">DataBase Name:</Text>
|
>
|
||||||
</Flex>
|
<Text fontSize="sm">DataBase Name:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "3"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
>
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
<InputField
|
>
|
||||||
borderRadius={5}
|
<InputField
|
||||||
variables={variables}
|
borderRadius={5}
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={TextInputType.DATABASE_NAME}
|
setVariables={setVariables}
|
||||||
isDisabled={true}
|
inputType={TextInputType.DATABASE_NAME}
|
||||||
/>
|
isDisabled={true}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
</Flex>
|
||||||
<Flex
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
w={isNotSmallerScreen ? "30%" : "40%"}
|
<Flex
|
||||||
justifyContent="start"
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
alignItems="center"
|
justifyContent="start"
|
||||||
>
|
alignItems="center"
|
||||||
<Text fontSize="sm">DataBase Type:</Text>
|
>
|
||||||
</Flex>
|
<Text fontSize="sm">DataBase Type:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "3"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
>
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
<InputField
|
>
|
||||||
borderRadius={5}
|
<InputField
|
||||||
variables={variables}
|
borderRadius={5}
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={TextInputType.DATABASE_TYPE}
|
setVariables={setVariables}
|
||||||
isDisabled={true}
|
inputType={TextInputType.DATABASE_TYPE}
|
||||||
/>
|
isDisabled={true}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
</Flex>
|
||||||
<Flex
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
w={isNotSmallerScreen ? "30%" : "40%"}
|
<Flex
|
||||||
justifyContent="start"
|
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||||
alignItems="center"
|
justifyContent="start"
|
||||||
>
|
alignItems="center"
|
||||||
<Text fontSize="sm">DataBase URL:</Text>
|
>
|
||||||
</Flex>
|
<Text fontSize="sm">DataBase URL:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "3"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
>
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
<InputField
|
>
|
||||||
borderRadius={5}
|
<InputField
|
||||||
variables={variables}
|
borderRadius={5}
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={TextInputType.DATABASE_URL}
|
setVariables={setVariables}
|
||||||
isDisabled={true}
|
inputType={TextInputType.DATABASE_URL}
|
||||||
/>
|
isDisabled={true}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
</Stack>
|
</Flex>
|
||||||
</div>
|
</Stack>
|
||||||
);
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DatabaseCredentials;
|
export default DatabaseCredentials;
|
@@ -3,7 +3,7 @@ import { Flex, Stack, Text } from '@chakra-ui/react';
|
|||||||
import InputField from '../InputField';
|
import InputField from '../InputField';
|
||||||
import { SwitchInputType } from '../../constants';
|
import { SwitchInputType } from '../../constants';
|
||||||
|
|
||||||
const UICustomization = ({ variables, setVariables }: any) => {
|
const Features = ({ variables, setVariables }: any) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{' '}
|
{' '}
|
||||||
@@ -71,9 +71,21 @@ const UICustomization = ({ variables, setVariables }: any) => {
|
|||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</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>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UICustomization;
|
export default Features;
|
@@ -9,7 +9,13 @@ import {
|
|||||||
Divider,
|
Divider,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { FaGoogle, FaGithub, FaFacebookF } from 'react-icons/fa';
|
import {
|
||||||
|
FaGoogle,
|
||||||
|
FaGithub,
|
||||||
|
FaFacebookF,
|
||||||
|
FaLinkedin,
|
||||||
|
FaApple,
|
||||||
|
} from 'react-icons/fa';
|
||||||
import { TextInputType, HiddenInputType } from '../../constants';
|
import { TextInputType, HiddenInputType } from '../../constants';
|
||||||
|
|
||||||
const OAuthConfig = ({
|
const OAuthConfig = ({
|
||||||
@@ -23,7 +29,7 @@ const OAuthConfig = ({
|
|||||||
<div>
|
<div>
|
||||||
<Box>
|
<Box>
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={6}>
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={6}>
|
||||||
Your instance information
|
Authorizer Config
|
||||||
</Text>
|
</Text>
|
||||||
<Stack spacing={6} padding="2% 0%">
|
<Stack spacing={6} padding="2% 0%">
|
||||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
@@ -182,6 +188,82 @@ const OAuthConfig = ({
|
|||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Flex>
|
</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>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,67 +1,68 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
import { ArrayInputType } from "../../constants";
|
import { ArrayInputType } from '../../constants';
|
||||||
import InputField from "../InputField";
|
import InputField from '../InputField';
|
||||||
|
|
||||||
const Roles = ({ variables, setVariables }: any) => {
|
const Roles = ({ variables, setVariables }: any) => {
|
||||||
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
|
||||||
<div>
|
return (
|
||||||
{" "}
|
<div>
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
{' '}
|
||||||
Roles
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
</Text>
|
Roles
|
||||||
<Stack spacing={6} padding="2% 0%">
|
</Text>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
<Stack spacing={6} padding="2% 0%">
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
<Text fontSize="sm">Roles:</Text>
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
</Flex>
|
<Text fontSize="sm">Roles:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "2"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
overflow="hidden"
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
>
|
overflow="hidden"
|
||||||
<InputField
|
>
|
||||||
borderRadius={7}
|
<InputField
|
||||||
variables={variables}
|
borderRadius={7}
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={ArrayInputType.ROLES}
|
setVariables={setVariables}
|
||||||
/>
|
inputType={ArrayInputType.ROLES}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
</Flex>
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
<Text fontSize="sm">Default Roles:</Text>
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
</Flex>
|
<Text fontSize="sm">Default Roles:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "2"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
>
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
<InputField
|
>
|
||||||
variables={variables}
|
<InputField
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={ArrayInputType.DEFAULT_ROLES}
|
setVariables={setVariables}
|
||||||
/>
|
inputType={ArrayInputType.DEFAULT_ROLES}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
</Flex>
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
<Text fontSize="sm">Protected Roles:</Text>
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
</Flex>
|
<Text fontSize="sm">Protected Roles:</Text>
|
||||||
<Center
|
</Flex>
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Center
|
||||||
mt={isNotSmallerScreen ? "0" : "2"}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
>
|
mt={isNotSmallerScreen ? '0' : '2'}
|
||||||
<InputField
|
>
|
||||||
variables={variables}
|
<InputField
|
||||||
setVariables={setVariables}
|
variables={variables}
|
||||||
inputType={ArrayInputType.PROTECTED_ROLES}
|
setVariables={setVariables}
|
||||||
/>
|
inputType={ArrayInputType.PROTECTED_ROLES}
|
||||||
</Center>
|
/>
|
||||||
</Flex>
|
</Center>
|
||||||
</Stack>
|
</Flex>
|
||||||
</div>
|
</Stack>
|
||||||
);
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Roles;
|
export default Roles;
|
@@ -1,36 +1,42 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react';
|
||||||
import InputField from "../InputField";
|
import InputField from '../InputField';
|
||||||
|
|
||||||
const SessionStorage = ({ variables, setVariables, RedisURL }: any) => {
|
const SessionStorage = ({ variables, setVariables, RedisURL }: any) => {
|
||||||
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{" "}
|
{' '}
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
Session Storage
|
Session Storage
|
||||||
</Text>
|
</Text>
|
||||||
<Stack spacing={6} padding="2% 0%">
|
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
||||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
Note: Redis related environment variables cannot be updated from
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
dashboard. Please use .env file or OS environment variables to update
|
||||||
<Text fontSize="sm">Redis URL:</Text>
|
it.
|
||||||
</Flex>
|
</Text>
|
||||||
<Center
|
<Stack spacing={6} padding="2% 0%">
|
||||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
mt={isNotSmallerScreen ? "0" : "3"}
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
>
|
<Text fontSize="sm">Redis URL:</Text>
|
||||||
<InputField
|
</Flex>
|
||||||
borderRadius={5}
|
<Center
|
||||||
variables={variables}
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
setVariables={setVariables}
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
inputType={RedisURL}
|
>
|
||||||
placeholder="Redis URL"
|
<InputField
|
||||||
/>
|
disabled
|
||||||
</Center>
|
borderRadius={5}
|
||||||
</Flex>
|
variables={variables}
|
||||||
</Stack>
|
setVariables={setVariables}
|
||||||
</div>
|
inputType={RedisURL}
|
||||||
);
|
placeholder="Redis URL"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SessionStorage;
|
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,
|
||||||
@@ -179,14 +180,14 @@ const InputField = ({
|
|||||||
if (Object.values(ArrayInputType).includes(inputType)) {
|
if (Object.values(ArrayInputType).includes(inputType)) {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
border="1px solid #e2e8f0"
|
border="1px solid #e2e8f0"
|
||||||
w="100%"
|
w="100%"
|
||||||
borderRadius={5}
|
borderRadius={5}
|
||||||
paddingTop="0.5%"
|
paddingTop="0.5%"
|
||||||
overflowX={variables[inputType].length > 3 ? "scroll" : "hidden"}
|
overflowX={variables[inputType].length > 3 ? 'scroll' : 'hidden'}
|
||||||
overflowY="hidden"
|
overflowY="hidden"
|
||||||
justifyContent="start"
|
justifyContent="start"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
>
|
>
|
||||||
{variables[inputType].map((role: string, index: number) => (
|
{variables[inputType].map((role: string, index: number) => (
|
||||||
<Box key={index} margin="0.5%" role="group">
|
<Box key={index} margin="0.5%" role="group">
|
||||||
@@ -301,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]}
|
||||||
@@ -312,7 +315,9 @@ const InputField = ({
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Code h="75%">On</Code>
|
<Text h="75%" fontWeight="bold" marginLeft="2">
|
||||||
|
On
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ import {
|
|||||||
InputRightElement,
|
InputRightElement,
|
||||||
Text,
|
Text,
|
||||||
Link,
|
Link,
|
||||||
Tooltip
|
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';
|
||||||
@@ -187,22 +187,22 @@ const InviteMembersModal = ({
|
|||||||
isDisabled={disabled}
|
isDisabled={disabled}
|
||||||
size="sm"
|
size="sm"
|
||||||
>
|
>
|
||||||
<Center h="100%">
|
<Center h="100%">
|
||||||
{disabled ? (
|
{disabled ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
mr={8}
|
mr={8}
|
||||||
mt={1}
|
mt={1}
|
||||||
hasArrow
|
hasArrow
|
||||||
bg="gray.300"
|
bg="gray.300"
|
||||||
color="black"
|
color="black"
|
||||||
label="Email verification is disabled, refer to 'UI Customization' tab within 'Environment' to enable it."
|
label="Email verification is disabled, refer to 'Features' tab within 'Environment' to enable it."
|
||||||
>
|
>
|
||||||
Invite Members
|
Invite Members
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : (
|
) : (
|
||||||
"Invite Members"
|
'Invite Members'
|
||||||
)}
|
)}
|
||||||
</Center>{" "}
|
</Center>{' '}
|
||||||
</Button>
|
</Button>
|
||||||
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
|
@@ -30,6 +30,7 @@ import {
|
|||||||
FiMenu,
|
FiMenu,
|
||||||
FiUsers,
|
FiUsers,
|
||||||
FiChevronDown,
|
FiChevronDown,
|
||||||
|
FiLink,
|
||||||
} from 'react-icons/fi';
|
} from 'react-icons/fi';
|
||||||
import { BiCustomize } from 'react-icons/bi';
|
import { BiCustomize } from 'react-icons/bi';
|
||||||
import { AiOutlineKey } from 'react-icons/ai';
|
import { AiOutlineKey } from 'react-icons/ai';
|
||||||
@@ -98,9 +99,9 @@ const LinkItems: Array<LinkItemProps> = [
|
|||||||
},
|
},
|
||||||
{ name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
|
{ name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
|
||||||
{
|
{
|
||||||
name: 'UI Customization',
|
name: 'Features',
|
||||||
icon: BiCustomize,
|
icon: BiCustomize,
|
||||||
route: '/ui-customization',
|
route: '/features',
|
||||||
},
|
},
|
||||||
{ name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
|
{ name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
|
||||||
{
|
{
|
||||||
@@ -111,6 +112,7 @@ const LinkItems: Array<LinkItemProps> = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ name: 'Users', icon: FiUsers, route: '/users' },
|
{ name: 'Users', icon: FiUsers, route: '/users' },
|
||||||
|
{ name: 'Webhooks', icon: FiLink, route: '/webhooks' },
|
||||||
];
|
];
|
||||||
|
|
||||||
interface SidebarProps extends BoxProps {
|
interface SidebarProps extends BoxProps {
|
||||||
@@ -119,7 +121,7 @@ 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)');
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -127,7 +129,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
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}
|
||||||
@@ -137,7 +139,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
mx="18"
|
mx="18"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
flexDirection="column"
|
flexDirection="row"
|
||||||
>
|
>
|
||||||
<NavLink to="/">
|
<NavLink to="/">
|
||||||
<Flex alignItems="center" mt="6">
|
<Flex alignItems="center" mt="6">
|
||||||
@@ -298,7 +300,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"
|
||||||
|
599
dashboard/src/components/UpdateWebhookModal.tsx
Normal file
599
dashboard/src/components/UpdateWebhookModal.tsx
Normal file
@@ -0,0 +1,599 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Flex,
|
||||||
|
Input,
|
||||||
|
InputGroup,
|
||||||
|
InputRightElement,
|
||||||
|
MenuItem,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { FaMinusCircle, FaPlus } from 'react-icons/fa';
|
||||||
|
import { useClient } from 'urql';
|
||||||
|
import {
|
||||||
|
webhookEventNames,
|
||||||
|
ArrayInputOperations,
|
||||||
|
WebhookInputDataFields,
|
||||||
|
WebhookInputHeaderFields,
|
||||||
|
UpdateWebhookModalViews,
|
||||||
|
webhookVerifiedStatus,
|
||||||
|
} from '../constants';
|
||||||
|
import { capitalizeFirstLetter, validateURI } from '../utils';
|
||||||
|
import { AddWebhook, EditWebhook, TestEndpoint } from '../graphql/mutation';
|
||||||
|
import { rest } from 'lodash';
|
||||||
|
import { BiCheckCircle, BiError, BiErrorCircle } from 'react-icons/bi';
|
||||||
|
|
||||||
|
interface headersDataType {
|
||||||
|
[WebhookInputHeaderFields.KEY]: string;
|
||||||
|
[WebhookInputHeaderFields.VALUE]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface headersValidatorDataType {
|
||||||
|
[WebhookInputHeaderFields.KEY]: boolean;
|
||||||
|
[WebhookInputHeaderFields.VALUE]: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface selecetdWebhookDataTypes {
|
||||||
|
[WebhookInputDataFields.ID]: string;
|
||||||
|
[WebhookInputDataFields.EVENT_NAME]: string;
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: string;
|
||||||
|
[WebhookInputDataFields.ENABLED]: boolean;
|
||||||
|
[WebhookInputDataFields.HEADERS]?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateWebhookModalInputPropTypes {
|
||||||
|
view: UpdateWebhookModalViews;
|
||||||
|
selectedWebhook?: selecetdWebhookDataTypes;
|
||||||
|
fetchWebookData: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initHeadersData: headersDataType = {
|
||||||
|
[WebhookInputHeaderFields.KEY]: '',
|
||||||
|
[WebhookInputHeaderFields.VALUE]: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const initHeadersValidatorData: headersValidatorDataType = {
|
||||||
|
[WebhookInputHeaderFields.KEY]: true,
|
||||||
|
[WebhookInputHeaderFields.VALUE]: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
interface webhookDataType {
|
||||||
|
[WebhookInputDataFields.EVENT_NAME]: string;
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: string;
|
||||||
|
[WebhookInputDataFields.ENABLED]: boolean;
|
||||||
|
[WebhookInputDataFields.HEADERS]: headersDataType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface validatorDataType {
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: boolean;
|
||||||
|
[WebhookInputDataFields.HEADERS]: headersValidatorDataType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initWebhookData: webhookDataType = {
|
||||||
|
[WebhookInputDataFields.EVENT_NAME]: webhookEventNames.USER_LOGIN,
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: '',
|
||||||
|
[WebhookInputDataFields.ENABLED]: true,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [{ ...initHeadersData }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const initWebhookValidatorData: validatorDataType = {
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: true,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [{ ...initHeadersValidatorData }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const UpdateWebhookModal = ({
|
||||||
|
view,
|
||||||
|
selectedWebhook,
|
||||||
|
fetchWebookData,
|
||||||
|
}: UpdateWebhookModalInputPropTypes) => {
|
||||||
|
const client = useClient();
|
||||||
|
const toast = useToast();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [verifyingEndpoint, setVerifyingEndpoint] = useState<boolean>(false);
|
||||||
|
const [webhook, setWebhook] = useState<webhookDataType>({
|
||||||
|
...initWebhookData,
|
||||||
|
});
|
||||||
|
const [validator, setValidator] = useState<validatorDataType>({
|
||||||
|
...initWebhookValidatorData,
|
||||||
|
});
|
||||||
|
const [verifiedStatus, setVerifiedStatus] = useState<webhookVerifiedStatus>(
|
||||||
|
webhookVerifiedStatus.PENDING
|
||||||
|
);
|
||||||
|
const inputChangehandler = (
|
||||||
|
inputType: string,
|
||||||
|
value: any,
|
||||||
|
headerInputType: string = WebhookInputHeaderFields.KEY,
|
||||||
|
headerIndex: number = 0
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
verifiedStatus !== webhookVerifiedStatus.PENDING &&
|
||||||
|
inputType !== WebhookInputDataFields.ENABLED
|
||||||
|
) {
|
||||||
|
setVerifiedStatus(webhookVerifiedStatus.PENDING);
|
||||||
|
}
|
||||||
|
switch (inputType) {
|
||||||
|
case WebhookInputDataFields.EVENT_NAME:
|
||||||
|
setWebhook({ ...webhook, [inputType]: value });
|
||||||
|
break;
|
||||||
|
case WebhookInputDataFields.ENDPOINT:
|
||||||
|
setWebhook({ ...webhook, [inputType]: value });
|
||||||
|
setValidator({
|
||||||
|
...validator,
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: validateURI(value),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case WebhookInputDataFields.ENABLED:
|
||||||
|
setWebhook({ ...webhook, [inputType]: value });
|
||||||
|
break;
|
||||||
|
case WebhookInputDataFields.HEADERS:
|
||||||
|
const updatedHeaders: any = [
|
||||||
|
...webhook[WebhookInputDataFields.HEADERS],
|
||||||
|
];
|
||||||
|
const updatedHeadersValidatorData: any = [
|
||||||
|
...validator[WebhookInputDataFields.HEADERS],
|
||||||
|
];
|
||||||
|
const otherHeaderInputType =
|
||||||
|
headerInputType === WebhookInputHeaderFields.KEY
|
||||||
|
? WebhookInputHeaderFields.VALUE
|
||||||
|
: WebhookInputHeaderFields.KEY;
|
||||||
|
updatedHeaders[headerIndex][headerInputType] = value;
|
||||||
|
updatedHeadersValidatorData[headerIndex][headerInputType] =
|
||||||
|
value.length > 0
|
||||||
|
? updatedHeaders[headerIndex][otherHeaderInputType].length > 0
|
||||||
|
: updatedHeaders[headerIndex][otherHeaderInputType].length === 0;
|
||||||
|
updatedHeadersValidatorData[headerIndex][otherHeaderInputType] =
|
||||||
|
value.length > 0
|
||||||
|
? updatedHeaders[headerIndex][otherHeaderInputType].length > 0
|
||||||
|
: updatedHeaders[headerIndex][otherHeaderInputType].length === 0;
|
||||||
|
setWebhook({ ...webhook, [inputType]: updatedHeaders });
|
||||||
|
setValidator({
|
||||||
|
...validator,
|
||||||
|
[inputType]: updatedHeadersValidatorData,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const updateHeaders = (operation: string, index: number = 0) => {
|
||||||
|
if (verifiedStatus !== webhookVerifiedStatus.PENDING) {
|
||||||
|
setVerifiedStatus(webhookVerifiedStatus.PENDING);
|
||||||
|
}
|
||||||
|
switch (operation) {
|
||||||
|
case ArrayInputOperations.APPEND:
|
||||||
|
setWebhook({
|
||||||
|
...webhook,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [
|
||||||
|
...(webhook?.[WebhookInputDataFields.HEADERS] || []),
|
||||||
|
{ ...initHeadersData },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
setValidator({
|
||||||
|
...validator,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [
|
||||||
|
...(validator?.[WebhookInputDataFields.HEADERS] || []),
|
||||||
|
{ ...initHeadersValidatorData },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ArrayInputOperations.REMOVE:
|
||||||
|
if (webhook?.[WebhookInputDataFields.HEADERS]?.length) {
|
||||||
|
const updatedHeaders = [...webhook[WebhookInputDataFields.HEADERS]];
|
||||||
|
updatedHeaders.splice(index, 1);
|
||||||
|
setWebhook({
|
||||||
|
...webhook,
|
||||||
|
[WebhookInputDataFields.HEADERS]: updatedHeaders,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (validator?.[WebhookInputDataFields.HEADERS]?.length) {
|
||||||
|
const updatedHeadersData = [
|
||||||
|
...validator[WebhookInputDataFields.HEADERS],
|
||||||
|
];
|
||||||
|
updatedHeadersData.splice(index, 1);
|
||||||
|
setValidator({
|
||||||
|
...validator,
|
||||||
|
[WebhookInputDataFields.HEADERS]: updatedHeadersData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const validateData = () => {
|
||||||
|
return (
|
||||||
|
!loading &&
|
||||||
|
!verifyingEndpoint &&
|
||||||
|
webhook[WebhookInputDataFields.EVENT_NAME].length > 0 &&
|
||||||
|
webhook[WebhookInputDataFields.ENDPOINT].length > 0 &&
|
||||||
|
validator[WebhookInputDataFields.ENDPOINT] &&
|
||||||
|
!validator[WebhookInputDataFields.HEADERS].some(
|
||||||
|
(headerData: headersValidatorDataType) =>
|
||||||
|
!headerData.key || !headerData.value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const getParams = () => {
|
||||||
|
let params: any = {
|
||||||
|
[WebhookInputDataFields.EVENT_NAME]:
|
||||||
|
webhook[WebhookInputDataFields.EVENT_NAME],
|
||||||
|
[WebhookInputDataFields.ENDPOINT]:
|
||||||
|
webhook[WebhookInputDataFields.ENDPOINT],
|
||||||
|
[WebhookInputDataFields.ENABLED]: webhook[WebhookInputDataFields.ENABLED],
|
||||||
|
[WebhookInputDataFields.HEADERS]: {},
|
||||||
|
};
|
||||||
|
if (webhook[WebhookInputDataFields.HEADERS].length) {
|
||||||
|
const headers = webhook[WebhookInputDataFields.HEADERS].reduce(
|
||||||
|
(acc, data) => {
|
||||||
|
return data.key ? { ...acc, [data.key]: data.value } : acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
if (Object.keys(headers).length) {
|
||||||
|
params[WebhookInputDataFields.HEADERS] = headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
const saveData = async () => {
|
||||||
|
if (!validateData()) return;
|
||||||
|
setLoading(true);
|
||||||
|
const params = getParams();
|
||||||
|
let res: any = {};
|
||||||
|
if (
|
||||||
|
view === UpdateWebhookModalViews.Edit &&
|
||||||
|
selectedWebhook?.[WebhookInputDataFields.ID]
|
||||||
|
) {
|
||||||
|
res = await client
|
||||||
|
.mutation(EditWebhook, {
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
id: selectedWebhook[WebhookInputDataFields.ID],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.toPromise();
|
||||||
|
} else {
|
||||||
|
res = await client.mutation(AddWebhook, { params }).toPromise();
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
if (res.error) {
|
||||||
|
toast({
|
||||||
|
title: capitalizeFirstLetter(res.error.message),
|
||||||
|
isClosable: true,
|
||||||
|
status: 'error',
|
||||||
|
position: 'bottom-right',
|
||||||
|
});
|
||||||
|
} else if (res.data?._add_webhook || res.data?._update_webhook) {
|
||||||
|
toast({
|
||||||
|
title: capitalizeFirstLetter(
|
||||||
|
res.data?._add_webhook?.message || res.data?._update_webhook?.message
|
||||||
|
),
|
||||||
|
isClosable: true,
|
||||||
|
status: 'success',
|
||||||
|
position: 'bottom-right',
|
||||||
|
});
|
||||||
|
setWebhook({
|
||||||
|
...initWebhookData,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [{ ...initHeadersData }],
|
||||||
|
});
|
||||||
|
setValidator({ ...initWebhookValidatorData });
|
||||||
|
fetchWebookData();
|
||||||
|
}
|
||||||
|
view === UpdateWebhookModalViews.ADD && onClose();
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
isOpen &&
|
||||||
|
view === UpdateWebhookModalViews.Edit &&
|
||||||
|
selectedWebhook &&
|
||||||
|
Object.keys(selectedWebhook || {}).length
|
||||||
|
) {
|
||||||
|
const { headers, ...rest } = selectedWebhook;
|
||||||
|
const headerItems = Object.entries(headers || {});
|
||||||
|
if (headerItems.length) {
|
||||||
|
let formattedHeadersData = headerItems.map((headerData) => {
|
||||||
|
return {
|
||||||
|
[WebhookInputHeaderFields.KEY]: headerData[0],
|
||||||
|
[WebhookInputHeaderFields.VALUE]: headerData[1],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setWebhook({
|
||||||
|
...rest,
|
||||||
|
[WebhookInputDataFields.HEADERS]: formattedHeadersData,
|
||||||
|
});
|
||||||
|
setValidator({
|
||||||
|
...validator,
|
||||||
|
[WebhookInputDataFields.HEADERS]: new Array(
|
||||||
|
formattedHeadersData.length
|
||||||
|
)
|
||||||
|
.fill({})
|
||||||
|
.map(() => ({ ...initHeadersValidatorData })),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setWebhook({
|
||||||
|
...rest,
|
||||||
|
[WebhookInputDataFields.HEADERS]: [{ ...initHeadersData }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
const verifyEndpoint = async () => {
|
||||||
|
if (!validateData()) return;
|
||||||
|
setVerifyingEndpoint(true);
|
||||||
|
const { [WebhookInputDataFields.ENABLED]: _, ...params } = getParams();
|
||||||
|
const res = await client.mutation(TestEndpoint, { params }).toPromise();
|
||||||
|
if (
|
||||||
|
res.data?._test_endpoint?.http_status >= 200 &&
|
||||||
|
res.data?._test_endpoint?.http_status < 400
|
||||||
|
) {
|
||||||
|
setVerifiedStatus(webhookVerifiedStatus.VERIFIED);
|
||||||
|
} else {
|
||||||
|
setVerifiedStatus(webhookVerifiedStatus.NOT_VERIFIED);
|
||||||
|
}
|
||||||
|
setVerifyingEndpoint(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{view === UpdateWebhookModalViews.ADD ? (
|
||||||
|
<Button
|
||||||
|
leftIcon={<FaPlus />}
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="solid"
|
||||||
|
onClick={onOpen}
|
||||||
|
isDisabled={false}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<Center h="100%">Add Webhook</Center>{' '}
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<MenuItem onClick={onOpen}>Edit</MenuItem>
|
||||||
|
)}
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose} size="3xl">
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>
|
||||||
|
{view === UpdateWebhookModalViews.ADD
|
||||||
|
? 'Add New Webhook'
|
||||||
|
: 'Edit Webhook'}
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<Flex
|
||||||
|
flexDirection="column"
|
||||||
|
border="1px"
|
||||||
|
borderRadius="md"
|
||||||
|
borderColor="gray.200"
|
||||||
|
p="5"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
marginBottom="2%"
|
||||||
|
>
|
||||||
|
<Flex flex="1">Event Name</Flex>
|
||||||
|
<Flex flex="3">
|
||||||
|
<Select
|
||||||
|
size="md"
|
||||||
|
value={webhook[WebhookInputDataFields.EVENT_NAME]}
|
||||||
|
onChange={(e) =>
|
||||||
|
inputChangehandler(
|
||||||
|
WebhookInputDataFields.EVENT_NAME,
|
||||||
|
e.currentTarget.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Object.entries(webhookEventNames).map(
|
||||||
|
([key, value]: any) => (
|
||||||
|
<option value={value} key={key}>
|
||||||
|
{key}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
width="100%"
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
marginBottom="5%"
|
||||||
|
>
|
||||||
|
<Flex flex="1">Endpoint</Flex>
|
||||||
|
<Flex flex="3">
|
||||||
|
<InputGroup size="md">
|
||||||
|
<Input
|
||||||
|
pr="4.5rem"
|
||||||
|
type="text"
|
||||||
|
placeholder="https://domain.com/webhook"
|
||||||
|
value={webhook[WebhookInputDataFields.ENDPOINT]}
|
||||||
|
isInvalid={!validator[WebhookInputDataFields.ENDPOINT]}
|
||||||
|
onChange={(e) =>
|
||||||
|
inputChangehandler(
|
||||||
|
WebhookInputDataFields.ENDPOINT,
|
||||||
|
e.currentTarget.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
marginBottom="5%"
|
||||||
|
>
|
||||||
|
<Flex flex="1">Enabled</Flex>
|
||||||
|
<Flex w="25%" justifyContent="space-between">
|
||||||
|
<Text h="75%" fontWeight="bold" marginRight="2">
|
||||||
|
Off
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
size="md"
|
||||||
|
isChecked={webhook[WebhookInputDataFields.ENABLED]}
|
||||||
|
onChange={() =>
|
||||||
|
inputChangehandler(
|
||||||
|
WebhookInputDataFields.ENABLED,
|
||||||
|
!webhook[WebhookInputDataFields.ENABLED]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Text h="75%" fontWeight="bold" marginLeft="2">
|
||||||
|
On
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
marginBottom="2%"
|
||||||
|
>
|
||||||
|
<Flex>Headers</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Button
|
||||||
|
leftIcon={<FaPlus />}
|
||||||
|
colorScheme="blue"
|
||||||
|
h="1.75rem"
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
paddingRight="0"
|
||||||
|
onClick={() => updateHeaders(ArrayInputOperations.APPEND)}
|
||||||
|
>
|
||||||
|
Add more Headers
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex flexDirection="column" maxH={220} overflowY="scroll">
|
||||||
|
{webhook[WebhookInputDataFields.HEADERS]?.map(
|
||||||
|
(headerData, index) => (
|
||||||
|
<Flex
|
||||||
|
key={`header-data-${index}`}
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<InputGroup size="md" marginBottom="2.5%">
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder="key"
|
||||||
|
value={headerData[WebhookInputHeaderFields.KEY]}
|
||||||
|
isInvalid={
|
||||||
|
!validator[WebhookInputDataFields.HEADERS][index]?.[
|
||||||
|
WebhookInputHeaderFields.KEY
|
||||||
|
]
|
||||||
|
}
|
||||||
|
onChange={(e) =>
|
||||||
|
inputChangehandler(
|
||||||
|
WebhookInputDataFields.HEADERS,
|
||||||
|
e.target.value,
|
||||||
|
WebhookInputHeaderFields.KEY,
|
||||||
|
index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
width="30%"
|
||||||
|
marginRight="2%"
|
||||||
|
/>
|
||||||
|
<Center marginRight="2%">
|
||||||
|
<Text fontWeight="bold">:</Text>
|
||||||
|
</Center>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder="value"
|
||||||
|
value={headerData[WebhookInputHeaderFields.VALUE]}
|
||||||
|
isInvalid={
|
||||||
|
!validator[WebhookInputDataFields.HEADERS][index]?.[
|
||||||
|
WebhookInputHeaderFields.VALUE
|
||||||
|
]
|
||||||
|
}
|
||||||
|
onChange={(e) =>
|
||||||
|
inputChangehandler(
|
||||||
|
WebhookInputDataFields.HEADERS,
|
||||||
|
e.target.value,
|
||||||
|
WebhookInputHeaderFields.VALUE,
|
||||||
|
index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
width="65%"
|
||||||
|
/>
|
||||||
|
<InputRightElement width="3rem">
|
||||||
|
<Button
|
||||||
|
width="6rem"
|
||||||
|
colorScheme="blackAlpha"
|
||||||
|
variant="ghost"
|
||||||
|
padding="0"
|
||||||
|
onClick={() =>
|
||||||
|
updateHeaders(ArrayInputOperations.REMOVE, index)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaMinusCircle />
|
||||||
|
</Button>
|
||||||
|
</InputRightElement>
|
||||||
|
</InputGroup>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme={
|
||||||
|
verifiedStatus === webhookVerifiedStatus.VERIFIED
|
||||||
|
? 'green'
|
||||||
|
: verifiedStatus === webhookVerifiedStatus.PENDING
|
||||||
|
? 'yellow'
|
||||||
|
: 'red'
|
||||||
|
}
|
||||||
|
variant="outline"
|
||||||
|
onClick={verifyEndpoint}
|
||||||
|
isLoading={verifyingEndpoint}
|
||||||
|
isDisabled={!validateData()}
|
||||||
|
marginRight="5"
|
||||||
|
leftIcon={
|
||||||
|
verifiedStatus === webhookVerifiedStatus.VERIFIED ? (
|
||||||
|
<BiCheckCircle />
|
||||||
|
) : verifiedStatus === webhookVerifiedStatus.PENDING ? (
|
||||||
|
<BiErrorCircle />
|
||||||
|
) : (
|
||||||
|
<BiError />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{verifiedStatus === webhookVerifiedStatus.VERIFIED
|
||||||
|
? 'Endpoint Verified'
|
||||||
|
: verifiedStatus === webhookVerifiedStatus.PENDING
|
||||||
|
? 'Test Endpoint'
|
||||||
|
: 'Endpoint Not Verified'}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="solid"
|
||||||
|
onClick={saveData}
|
||||||
|
isDisabled={!validateData()}
|
||||||
|
>
|
||||||
|
<Center h="100%" pt="5%">
|
||||||
|
Save
|
||||||
|
</Center>
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UpdateWebhookModal;
|
426
dashboard/src/components/ViewWebhookLogsModal.tsx
Normal file
426
dashboard/src/components/ViewWebhookLogsModal.tsx
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Flex,
|
||||||
|
MenuItem,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
useDisclosure,
|
||||||
|
Text,
|
||||||
|
Spinner,
|
||||||
|
Table,
|
||||||
|
Th,
|
||||||
|
Thead,
|
||||||
|
Tr,
|
||||||
|
Tbody,
|
||||||
|
IconButton,
|
||||||
|
NumberDecrementStepper,
|
||||||
|
NumberIncrementStepper,
|
||||||
|
NumberInput,
|
||||||
|
NumberInputField,
|
||||||
|
NumberInputStepper,
|
||||||
|
Select,
|
||||||
|
TableCaption,
|
||||||
|
Tooltip,
|
||||||
|
Td,
|
||||||
|
Tag,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { useClient } from 'urql';
|
||||||
|
import {
|
||||||
|
FaAngleDoubleLeft,
|
||||||
|
FaAngleDoubleRight,
|
||||||
|
FaAngleLeft,
|
||||||
|
FaAngleRight,
|
||||||
|
FaExclamationCircle,
|
||||||
|
FaRegClone,
|
||||||
|
} from 'react-icons/fa';
|
||||||
|
import { copyTextToClipboard } from '../utils';
|
||||||
|
import { WebhookLogsQuery } from '../graphql/queries';
|
||||||
|
import { pageLimits } from '../constants';
|
||||||
|
|
||||||
|
interface paginationPropTypes {
|
||||||
|
limit: number;
|
||||||
|
page: number;
|
||||||
|
offset: number;
|
||||||
|
total: number;
|
||||||
|
maxPages: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface deleteWebhookModalInputPropTypes {
|
||||||
|
webhookId: string;
|
||||||
|
eventName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface webhookLogsDataTypes {
|
||||||
|
id: string;
|
||||||
|
http_status: number;
|
||||||
|
request: string;
|
||||||
|
response: string;
|
||||||
|
created_at: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ViewWebhookLogsModal = ({
|
||||||
|
webhookId,
|
||||||
|
eventName,
|
||||||
|
}: deleteWebhookModalInputPropTypes) => {
|
||||||
|
const client = useClient();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [webhookLogs, setWebhookLogs] = useState<webhookLogsDataTypes[]>([]);
|
||||||
|
const [paginationProps, setPaginationProps] = useState<paginationPropTypes>({
|
||||||
|
limit: 5,
|
||||||
|
page: 1,
|
||||||
|
offset: 0,
|
||||||
|
total: 0,
|
||||||
|
maxPages: 1,
|
||||||
|
});
|
||||||
|
const getMaxPages = (pagination: paginationPropTypes) => {
|
||||||
|
const { limit, total } = pagination;
|
||||||
|
if (total > 1) {
|
||||||
|
return total % limit === 0
|
||||||
|
? total / limit
|
||||||
|
: parseInt(`${total / limit}`) + 1;
|
||||||
|
} else return 1;
|
||||||
|
};
|
||||||
|
const fetchWebhookLogsData = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const res = await client
|
||||||
|
.query(WebhookLogsQuery, {
|
||||||
|
params: {
|
||||||
|
webhook_id: webhookId,
|
||||||
|
pagination: {
|
||||||
|
limit: paginationProps.limit,
|
||||||
|
page: paginationProps.page,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.toPromise();
|
||||||
|
if (res.data?._webhook_logs) {
|
||||||
|
const { pagination, webhook_logs } = res.data?._webhook_logs;
|
||||||
|
const maxPages = getMaxPages(pagination);
|
||||||
|
if (webhook_logs?.length) {
|
||||||
|
setWebhookLogs(webhook_logs);
|
||||||
|
setPaginationProps({ ...paginationProps, ...pagination, maxPages });
|
||||||
|
} else {
|
||||||
|
if (paginationProps.page !== 1) {
|
||||||
|
setPaginationProps({
|
||||||
|
...paginationProps,
|
||||||
|
...pagination,
|
||||||
|
maxPages,
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
const paginationHandler = (value: Record<string, number>) => {
|
||||||
|
setPaginationProps({ ...paginationProps, ...value });
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
isOpen && fetchWebhookLogsData();
|
||||||
|
}, [isOpen, paginationProps.page, paginationProps.limit]);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MenuItem onClick={onOpen}>View Logs</MenuItem>
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose} size="4xl">
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>Webhook Logs - {eventName}</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<Flex
|
||||||
|
flexDirection="column"
|
||||||
|
border="1px"
|
||||||
|
borderRadius="md"
|
||||||
|
borderColor="gray.200"
|
||||||
|
p="5"
|
||||||
|
>
|
||||||
|
{!loading ? (
|
||||||
|
webhookLogs.length ? (
|
||||||
|
<Table variant="simple">
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>ID</Th>
|
||||||
|
<Th>Created At</Th>
|
||||||
|
<Th>Http Status</Th>
|
||||||
|
<Th>Request</Th>
|
||||||
|
<Th>Response</Th>
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{webhookLogs.map((logData: webhookLogsDataTypes) => (
|
||||||
|
<Tr key={logData.id} style={{ fontSize: 14 }}>
|
||||||
|
<Td>
|
||||||
|
<Text fontSize="sm">{`${logData.id.substring(
|
||||||
|
0,
|
||||||
|
5
|
||||||
|
)}***${logData.id.substring(
|
||||||
|
logData.id.length - 5,
|
||||||
|
logData.id.length
|
||||||
|
)}`}</Text>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
{dayjs(logData.created_at * 1000).format(
|
||||||
|
'MMM DD, YYYY'
|
||||||
|
)}
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Tag
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
colorScheme={
|
||||||
|
logData.http_status >= 400 ? 'red' : 'green'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{logData.http_status}
|
||||||
|
</Tag>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Flex alignItems="center">
|
||||||
|
<Tooltip
|
||||||
|
bg="gray.300"
|
||||||
|
color="black"
|
||||||
|
label={logData.request || 'null'}
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
colorScheme={
|
||||||
|
logData.request ? 'gray' : 'yellow'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{logData.request ? 'Payload' : 'No Data'}
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
{logData.request && (
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
variant="outline"
|
||||||
|
marginLeft="5px"
|
||||||
|
h="21px"
|
||||||
|
onClick={() =>
|
||||||
|
copyTextToClipboard(logData.request)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegClone color="#bfbfbf" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Flex alignItems="center">
|
||||||
|
<Tooltip
|
||||||
|
bg="gray.300"
|
||||||
|
color="black"
|
||||||
|
label={logData.response || 'null'}
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
colorScheme={
|
||||||
|
logData.response ? 'gray' : 'yellow'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{logData.response ? 'Preview' : 'No Data'}
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
{logData.response && (
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
variant="outline"
|
||||||
|
marginLeft="5px"
|
||||||
|
h="21px"
|
||||||
|
onClick={() =>
|
||||||
|
copyTextToClipboard(logData.response)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegClone color="#bfbfbf" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
{(paginationProps.maxPages > 1 ||
|
||||||
|
paginationProps.total >= 5) && (
|
||||||
|
<TableCaption>
|
||||||
|
<Flex
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
m="2% 0"
|
||||||
|
>
|
||||||
|
<Flex flex="1">
|
||||||
|
<Tooltip label="First Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={paginationProps.page <= 1}
|
||||||
|
mr={4}
|
||||||
|
icon={<FaAngleDoubleLeft />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label="Previous Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.page - 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={paginationProps.page <= 1}
|
||||||
|
icon={<FaAngleLeft />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
flex="8"
|
||||||
|
justifyContent="space-evenly"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text mr={8}>
|
||||||
|
Page{' '}
|
||||||
|
<Text fontWeight="bold" as="span">
|
||||||
|
{paginationProps.page}
|
||||||
|
</Text>{' '}
|
||||||
|
of{' '}
|
||||||
|
<Text fontWeight="bold" as="span">
|
||||||
|
{paginationProps.maxPages}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
<Flex alignItems="center">
|
||||||
|
<Text flexShrink="0">Go to page:</Text>{' '}
|
||||||
|
<NumberInput
|
||||||
|
ml={2}
|
||||||
|
mr={8}
|
||||||
|
w={28}
|
||||||
|
min={1}
|
||||||
|
max={paginationProps.maxPages}
|
||||||
|
onChange={(value) =>
|
||||||
|
paginationHandler({
|
||||||
|
page: parseInt(value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
value={paginationProps.page}
|
||||||
|
>
|
||||||
|
<NumberInputField />
|
||||||
|
<NumberInputStepper>
|
||||||
|
<NumberIncrementStepper />
|
||||||
|
<NumberDecrementStepper />
|
||||||
|
</NumberInputStepper>
|
||||||
|
</NumberInput>
|
||||||
|
</Flex>
|
||||||
|
<Select
|
||||||
|
w={32}
|
||||||
|
value={paginationProps.limit}
|
||||||
|
onChange={(e) =>
|
||||||
|
paginationHandler({
|
||||||
|
page: 1,
|
||||||
|
limit: parseInt(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{pageLimits.map((pageSize) => (
|
||||||
|
<option key={pageSize} value={pageSize}>
|
||||||
|
Show {pageSize}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Flex>
|
||||||
|
<Flex flex="1">
|
||||||
|
<Tooltip label="Next Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.page + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={
|
||||||
|
paginationProps.page >=
|
||||||
|
paginationProps.maxPages
|
||||||
|
}
|
||||||
|
icon={<FaAngleRight />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label="Last Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.maxPages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={
|
||||||
|
paginationProps.page >=
|
||||||
|
paginationProps.maxPages
|
||||||
|
}
|
||||||
|
ml={4}
|
||||||
|
icon={<FaAngleDoubleRight />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</TableCaption>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
) : (
|
||||||
|
<Flex
|
||||||
|
flexDirection="column"
|
||||||
|
minH="25vh"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Center w="50px" marginRight="1.5%">
|
||||||
|
<FaExclamationCircle
|
||||||
|
style={{ color: '#f0f0f0', fontSize: 70 }}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Text
|
||||||
|
fontSize="2xl"
|
||||||
|
paddingRight="1%"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="#d9d9d9"
|
||||||
|
>
|
||||||
|
No Data
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Center minH="25vh">
|
||||||
|
<Spinner />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="solid"
|
||||||
|
onClick={onClose}
|
||||||
|
isDisabled={false}
|
||||||
|
>
|
||||||
|
<Center h="100%" pt="5%">
|
||||||
|
Close
|
||||||
|
</Center>
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewWebhookLogsModal;
|
@@ -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,6 +132,7 @@ 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;
|
||||||
@@ -138,7 +149,42 @@ export const envSubViews = {
|
|||||||
WHITELIST_VARIABLES: 'whitelist-variables',
|
WHITELIST_VARIABLES: 'whitelist-variables',
|
||||||
ORGANIZATION_INFO: 'organization-info',
|
ORGANIZATION_INFO: 'organization-info',
|
||||||
ACCESS_TOKEN: 'access-token',
|
ACCESS_TOKEN: 'access-token',
|
||||||
UI_CUSTOMIZATION: 'ui-customization',
|
FEATURES: 'features',
|
||||||
ADMIN_SECRET: 'admin-secret',
|
ADMIN_SECRET: 'admin-secret',
|
||||||
DB_CRED: 'db-cred',
|
DB_CRED: 'db-cred',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum WebhookInputDataFields {
|
||||||
|
ID = 'id',
|
||||||
|
EVENT_NAME = 'event_name',
|
||||||
|
ENDPOINT = 'endpoint',
|
||||||
|
ENABLED = 'enabled',
|
||||||
|
HEADERS = 'headers',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum WebhookInputHeaderFields {
|
||||||
|
KEY = 'key',
|
||||||
|
VALUE = 'value',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum UpdateWebhookModalViews {
|
||||||
|
ADD = 'add',
|
||||||
|
Edit = 'edit',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pageLimits: number[] = [5, 10, 15];
|
||||||
|
|
||||||
|
export const webhookEventNames = {
|
||||||
|
USER_SIGNUP: 'user.signup',
|
||||||
|
USER_CREATED: 'user.created',
|
||||||
|
USER_LOGIN: 'user.login',
|
||||||
|
USER_DELETED: 'user.deleted',
|
||||||
|
USER_ACCESS_ENABLED: 'user.access_enabled',
|
||||||
|
USER_ACCESS_REVOKED: 'user.access_revoked',
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum webhookVerifiedStatus {
|
||||||
|
VERIFIED = 'verified',
|
||||||
|
NOT_VERIFIED = 'not_verified',
|
||||||
|
PENDING = 'verification_pending',
|
||||||
|
}
|
||||||
|
@@ -79,3 +79,36 @@ export const GenerateKeys = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const AddWebhook = `
|
||||||
|
mutation addWebhook($params: AddWebhookRequest!) {
|
||||||
|
_add_webhook(params: $params) {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const EditWebhook = `
|
||||||
|
mutation editWebhook($params: UpdateWebhookRequest!) {
|
||||||
|
_update_webhook(params: $params) {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DeleteWebhook = `
|
||||||
|
mutation deleteWebhook($params: WebhookRequest!) {
|
||||||
|
_delete_webhook(params: $params) {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TestEndpoint = `
|
||||||
|
mutation testEndpoint($params: TestEndpointRequest!) {
|
||||||
|
_test_endpoint(params: $params) {
|
||||||
|
http_status
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@@ -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,
|
||||||
@@ -95,3 +101,43 @@ export const EmailVerificationQuery = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const WebhooksDataQuery = `
|
||||||
|
query getWebhooksData($params: PaginatedInput!) {
|
||||||
|
_webhooks(params: $params){
|
||||||
|
webhooks{
|
||||||
|
id
|
||||||
|
event_name
|
||||||
|
endpoint
|
||||||
|
enabled
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
pagination{
|
||||||
|
limit
|
||||||
|
page
|
||||||
|
offset
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const WebhookLogsQuery = `
|
||||||
|
query getWebhookLogs($params: ListWebhookLogRequest!) {
|
||||||
|
_webhook_logs(params: $params) {
|
||||||
|
webhook_logs {
|
||||||
|
id
|
||||||
|
http_status
|
||||||
|
request
|
||||||
|
response
|
||||||
|
created_at
|
||||||
|
}
|
||||||
|
pagination {
|
||||||
|
limit
|
||||||
|
page
|
||||||
|
offset
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@@ -20,6 +20,7 @@ export function AuthLayout({ children }: { children: React.ReactNode }) {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
direction={['column', 'column']}
|
direction={['column', 'column']}
|
||||||
|
padding={['2%', '2%', '2%', '2%']}
|
||||||
>
|
>
|
||||||
<Flex alignItems="center" maxW="100%">
|
<Flex alignItems="center" maxW="100%">
|
||||||
<Image
|
<Image
|
||||||
|
@@ -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'}
|
||||||
|
@@ -25,7 +25,7 @@ import EmailConfigurations from '../components/EnvComponents/EmailConfiguration'
|
|||||||
import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting';
|
import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting';
|
||||||
import OrganizationInfo from '../components/EnvComponents/OrganizationInfo';
|
import OrganizationInfo from '../components/EnvComponents/OrganizationInfo';
|
||||||
import AccessToken from '../components/EnvComponents/AccessToken';
|
import AccessToken from '../components/EnvComponents/AccessToken';
|
||||||
import UICustomization from '../components/EnvComponents/UICustomization';
|
import Features from '../components/EnvComponents/Features';
|
||||||
import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret';
|
import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret';
|
||||||
import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials';
|
import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials';
|
||||||
|
|
||||||
@@ -46,6 +46,10 @@ const 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: [],
|
||||||
@@ -70,6 +74,7 @@ const 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: '',
|
||||||
@@ -83,6 +88,8 @@ const 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,
|
||||||
@@ -259,12 +266,9 @@ const Environment = () => {
|
|||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case envSubViews.UI_CUSTOMIZATION:
|
case envSubViews.FEATURES:
|
||||||
return (
|
return (
|
||||||
<UICustomization
|
<Features variables={envVariables} setVariables={setEnvVariables} />
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
case envSubViews.ADMIN_SECRET:
|
case envSubViews.ADMIN_SECRET:
|
||||||
return (
|
return (
|
||||||
|
370
dashboard/src/pages/Webhooks.tsx
Normal file
370
dashboard/src/pages/Webhooks.tsx
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useClient } from 'urql';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Flex,
|
||||||
|
IconButton,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuItem,
|
||||||
|
MenuList,
|
||||||
|
NumberDecrementStepper,
|
||||||
|
NumberIncrementStepper,
|
||||||
|
NumberInput,
|
||||||
|
NumberInputField,
|
||||||
|
NumberInputStepper,
|
||||||
|
Select,
|
||||||
|
Spinner,
|
||||||
|
Table,
|
||||||
|
TableCaption,
|
||||||
|
Tag,
|
||||||
|
Tbody,
|
||||||
|
Td,
|
||||||
|
Text,
|
||||||
|
Th,
|
||||||
|
Thead,
|
||||||
|
Tooltip,
|
||||||
|
Tr,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import {
|
||||||
|
FaAngleDoubleLeft,
|
||||||
|
FaAngleDoubleRight,
|
||||||
|
FaAngleDown,
|
||||||
|
FaAngleLeft,
|
||||||
|
FaAngleRight,
|
||||||
|
FaExclamationCircle,
|
||||||
|
} from 'react-icons/fa';
|
||||||
|
import UpdateWebhookModal from '../components/UpdateWebhookModal';
|
||||||
|
import {
|
||||||
|
pageLimits,
|
||||||
|
WebhookInputDataFields,
|
||||||
|
UpdateWebhookModalViews,
|
||||||
|
} from '../constants';
|
||||||
|
import { WebhooksDataQuery } from '../graphql/queries';
|
||||||
|
import DeleteWebhookModal from '../components/DeleteWebhookModal';
|
||||||
|
import ViewWebhookLogsModal from '../components/ViewWebhookLogsModal';
|
||||||
|
|
||||||
|
interface paginationPropTypes {
|
||||||
|
limit: number;
|
||||||
|
page: number;
|
||||||
|
offset: number;
|
||||||
|
total: number;
|
||||||
|
maxPages: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface webhookDataTypes {
|
||||||
|
[WebhookInputDataFields.ID]: string;
|
||||||
|
[WebhookInputDataFields.EVENT_NAME]: string;
|
||||||
|
[WebhookInputDataFields.ENDPOINT]: string;
|
||||||
|
[WebhookInputDataFields.ENABLED]: boolean;
|
||||||
|
[WebhookInputDataFields.HEADERS]?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Webhooks = () => {
|
||||||
|
const client = useClient();
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [webhookData, setWebhookData] = useState<webhookDataTypes[]>([]);
|
||||||
|
const [paginationProps, setPaginationProps] = useState<paginationPropTypes>({
|
||||||
|
limit: 5,
|
||||||
|
page: 1,
|
||||||
|
offset: 0,
|
||||||
|
total: 0,
|
||||||
|
maxPages: 1,
|
||||||
|
});
|
||||||
|
const getMaxPages = (pagination: paginationPropTypes) => {
|
||||||
|
const { limit, total } = pagination;
|
||||||
|
if (total > 1) {
|
||||||
|
return total % limit === 0
|
||||||
|
? total / limit
|
||||||
|
: parseInt(`${total / limit}`) + 1;
|
||||||
|
} else return 1;
|
||||||
|
};
|
||||||
|
const fetchWebookData = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const res = await client
|
||||||
|
.query(WebhooksDataQuery, {
|
||||||
|
params: {
|
||||||
|
pagination: {
|
||||||
|
limit: paginationProps.limit,
|
||||||
|
page: paginationProps.page,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.toPromise();
|
||||||
|
if (res.data?._webhooks) {
|
||||||
|
const { pagination, webhooks } = res.data?._webhooks;
|
||||||
|
const maxPages = getMaxPages(pagination);
|
||||||
|
if (webhooks?.length) {
|
||||||
|
setWebhookData(webhooks);
|
||||||
|
setPaginationProps({ ...paginationProps, ...pagination, maxPages });
|
||||||
|
} else {
|
||||||
|
if (paginationProps.page !== 1) {
|
||||||
|
setPaginationProps({
|
||||||
|
...paginationProps,
|
||||||
|
...pagination,
|
||||||
|
maxPages,
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
const paginationHandler = (value: Record<string, number>) => {
|
||||||
|
setPaginationProps({ ...paginationProps, ...value });
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
fetchWebookData();
|
||||||
|
}, [paginationProps.page, paginationProps.limit]);
|
||||||
|
return (
|
||||||
|
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
||||||
|
<Flex margin="2% 0" justifyContent="space-between" alignItems="center">
|
||||||
|
<Text fontSize="md" fontWeight="bold">
|
||||||
|
Webhooks
|
||||||
|
</Text>
|
||||||
|
<UpdateWebhookModal
|
||||||
|
view={UpdateWebhookModalViews.ADD}
|
||||||
|
fetchWebookData={fetchWebookData}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
{!loading ? (
|
||||||
|
webhookData.length ? (
|
||||||
|
<Table variant="simple">
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>Event Name</Th>
|
||||||
|
<Th>Endpoint</Th>
|
||||||
|
<Th>Enabled</Th>
|
||||||
|
<Th>Headers</Th>
|
||||||
|
<Th>Actions</Th>
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{webhookData.map((webhook: webhookDataTypes) => (
|
||||||
|
<Tr
|
||||||
|
key={webhook[WebhookInputDataFields.ID]}
|
||||||
|
style={{ fontSize: 14 }}
|
||||||
|
>
|
||||||
|
<Td maxW="300">
|
||||||
|
{webhook[WebhookInputDataFields.EVENT_NAME]}
|
||||||
|
</Td>
|
||||||
|
<Td>{webhook[WebhookInputDataFields.ENDPOINT]}</Td>
|
||||||
|
<Td>
|
||||||
|
<Tag
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
colorScheme={
|
||||||
|
webhook[WebhookInputDataFields.ENABLED]
|
||||||
|
? 'green'
|
||||||
|
: 'yellow'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{webhook[WebhookInputDataFields.ENABLED].toString()}
|
||||||
|
</Tag>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Tooltip
|
||||||
|
bg="gray.300"
|
||||||
|
color="black"
|
||||||
|
label={JSON.stringify(
|
||||||
|
webhook[WebhookInputDataFields.HEADERS],
|
||||||
|
null,
|
||||||
|
' '
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Tag size="sm" variant="outline" colorScheme="gray">
|
||||||
|
{Object.keys(
|
||||||
|
webhook[WebhookInputDataFields.HEADERS] || {}
|
||||||
|
)?.length.toString()}
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Menu>
|
||||||
|
<MenuButton as={Button} variant="unstyled" size="sm">
|
||||||
|
<Flex
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm" fontWeight="light">
|
||||||
|
Menu
|
||||||
|
</Text>
|
||||||
|
<FaAngleDown style={{ marginLeft: 10 }} />
|
||||||
|
</Flex>
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList>
|
||||||
|
<UpdateWebhookModal
|
||||||
|
view={UpdateWebhookModalViews.Edit}
|
||||||
|
selectedWebhook={webhook}
|
||||||
|
fetchWebookData={fetchWebookData}
|
||||||
|
/>
|
||||||
|
<DeleteWebhookModal
|
||||||
|
webhookId={webhook[WebhookInputDataFields.ID]}
|
||||||
|
eventName={webhook[WebhookInputDataFields.EVENT_NAME]}
|
||||||
|
fetchWebookData={fetchWebookData}
|
||||||
|
/>
|
||||||
|
<ViewWebhookLogsModal
|
||||||
|
webhookId={webhook[WebhookInputDataFields.ID]}
|
||||||
|
eventName={webhook[WebhookInputDataFields.EVENT_NAME]}
|
||||||
|
/>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
{(paginationProps.maxPages > 1 || paginationProps.total >= 5) && (
|
||||||
|
<TableCaption>
|
||||||
|
<Flex
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
m="2% 0"
|
||||||
|
>
|
||||||
|
<Flex flex="1">
|
||||||
|
<Tooltip label="First Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={paginationProps.page <= 1}
|
||||||
|
mr={4}
|
||||||
|
icon={<FaAngleDoubleLeft />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label="Previous Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.page - 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={paginationProps.page <= 1}
|
||||||
|
icon={<FaAngleLeft />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
flex="8"
|
||||||
|
justifyContent="space-evenly"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text mr={8}>
|
||||||
|
Page{' '}
|
||||||
|
<Text fontWeight="bold" as="span">
|
||||||
|
{paginationProps.page}
|
||||||
|
</Text>{' '}
|
||||||
|
of{' '}
|
||||||
|
<Text fontWeight="bold" as="span">
|
||||||
|
{paginationProps.maxPages}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
<Flex alignItems="center">
|
||||||
|
<Text flexShrink="0">Go to page:</Text>{' '}
|
||||||
|
<NumberInput
|
||||||
|
ml={2}
|
||||||
|
mr={8}
|
||||||
|
w={28}
|
||||||
|
min={1}
|
||||||
|
max={paginationProps.maxPages}
|
||||||
|
onChange={(value) =>
|
||||||
|
paginationHandler({
|
||||||
|
page: parseInt(value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
value={paginationProps.page}
|
||||||
|
>
|
||||||
|
<NumberInputField />
|
||||||
|
<NumberInputStepper>
|
||||||
|
<NumberIncrementStepper />
|
||||||
|
<NumberDecrementStepper />
|
||||||
|
</NumberInputStepper>
|
||||||
|
</NumberInput>
|
||||||
|
</Flex>
|
||||||
|
<Select
|
||||||
|
w={32}
|
||||||
|
value={paginationProps.limit}
|
||||||
|
onChange={(e) =>
|
||||||
|
paginationHandler({
|
||||||
|
page: 1,
|
||||||
|
limit: parseInt(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{pageLimits.map((pageSize) => (
|
||||||
|
<option key={pageSize} value={pageSize}>
|
||||||
|
Show {pageSize}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Flex>
|
||||||
|
<Flex flex="1">
|
||||||
|
<Tooltip label="Next Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.page + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={
|
||||||
|
paginationProps.page >= paginationProps.maxPages
|
||||||
|
}
|
||||||
|
icon={<FaAngleRight />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label="Last Page">
|
||||||
|
<IconButton
|
||||||
|
aria-label="icon button"
|
||||||
|
onClick={() =>
|
||||||
|
paginationHandler({
|
||||||
|
page: paginationProps.maxPages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isDisabled={
|
||||||
|
paginationProps.page >= paginationProps.maxPages
|
||||||
|
}
|
||||||
|
ml={4}
|
||||||
|
icon={<FaAngleDoubleRight />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</TableCaption>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
) : (
|
||||||
|
<Flex
|
||||||
|
flexDirection="column"
|
||||||
|
minH="25vh"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Center w="50px" marginRight="1.5%">
|
||||||
|
<FaExclamationCircle style={{ color: '#f0f0f0', fontSize: 70 }} />
|
||||||
|
</Center>
|
||||||
|
<Text
|
||||||
|
fontSize="2xl"
|
||||||
|
paddingRight="1%"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="#d9d9d9"
|
||||||
|
>
|
||||||
|
No Data
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Center minH="25vh">
|
||||||
|
<Spinner />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Webhooks;
|
@@ -8,32 +8,34 @@ const Auth = lazy(() => import('../pages/Auth'));
|
|||||||
const Environment = lazy(() => import('../pages/Environment'));
|
const Environment = lazy(() => import('../pages/Environment'));
|
||||||
const Home = lazy(() => import('../pages/Home'));
|
const Home = lazy(() => import('../pages/Home'));
|
||||||
const Users = lazy(() => import('../pages/Users'));
|
const Users = lazy(() => import('../pages/Users'));
|
||||||
|
const Webhooks = lazy(() => import('../pages/Webhooks'));
|
||||||
|
|
||||||
export const AppRoutes = () => {
|
export const AppRoutes = () => {
|
||||||
const { isLoggedIn } = useAuthContext();
|
const { isLoggedIn } = useAuthContext();
|
||||||
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Suspense fallback={<></>}>
|
<Suspense fallback={<></>}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
element={
|
element={
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Route path="/" element={<Outlet />}>
|
<Route path="/" element={<Outlet />}>
|
||||||
<Route index element={<Environment />} />
|
<Route index element={<Environment />} />
|
||||||
<Route path="/:sec" element={<Environment />} />
|
<Route path="/:sec" element={<Environment />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="users" element={<Users />} />
|
<Route path="users" element={<Users />} />
|
||||||
<Route path="*" element={<Home />} />
|
<Route path="webhooks" element={<Webhooks />} />
|
||||||
</Route>
|
<Route path="*" element={<Home />} />
|
||||||
</Routes>
|
</Route>
|
||||||
</Suspense>
|
</Routes>
|
||||||
</div>
|
</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,10 @@ 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"
|
||||||
|
// Get github user emails when user info email is empty Ref: https://stackoverflow.com/a/35387123
|
||||||
|
GithubUserEmails = "https://api/github.com/user/emails"
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"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
|
||||||
@@ -18,13 +18,15 @@ 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: ", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType))
|
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)
|
log.Fatal("Failed to initialize SQL driver: ", err)
|
||||||
|
33
server/db/models/email_templates.go
Normal file
33
server/db/models/email_templates.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmailTemplate model for database
|
||||||
|
type EmailTemplate 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"`
|
||||||
|
Template string `gorm:"type:text" json:"template" bson:"template" cql:"template"`
|
||||||
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsAPIEmailTemplate to return email template as graphql response object
|
||||||
|
func (e *EmailTemplate) AsAPIEmailTemplate() *model.EmailTemplate {
|
||||||
|
id := e.ID
|
||||||
|
if strings.Contains(id, Collections.EmailTemplate+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.EmailTemplate+"/")
|
||||||
|
}
|
||||||
|
return &model.EmailTemplate{
|
||||||
|
ID: id,
|
||||||
|
EventName: e.EventName,
|
||||||
|
Template: e.Template,
|
||||||
|
CreatedAt: refs.NewInt64Ref(e.CreatedAt),
|
||||||
|
UpdatedAt: refs.NewInt64Ref(e.UpdatedAt),
|
||||||
|
}
|
||||||
|
}
|
@@ -6,6 +6,9 @@ type CollectionList struct {
|
|||||||
VerificationRequest string
|
VerificationRequest string
|
||||||
Session string
|
Session string
|
||||||
Env string
|
Env string
|
||||||
|
Webhook string
|
||||||
|
WebhookLog string
|
||||||
|
EmailTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -17,5 +20,8 @@ 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",
|
||||||
|
EmailTemplate: Prefix + "email_template",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -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"`
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
@@ -35,12 +36,13 @@ type User struct {
|
|||||||
func (user *User) AsAPIUser() *model.User {
|
func (user *User) AsAPIUser() *model.User {
|
||||||
isEmailVerified := user.EmailVerifiedAt != nil
|
isEmailVerified := user.EmailVerifiedAt != nil
|
||||||
isPhoneVerified := user.PhoneNumberVerifiedAt != nil
|
isPhoneVerified := user.PhoneNumberVerifiedAt != nil
|
||||||
email := user.Email
|
|
||||||
createdAt := user.CreatedAt
|
id := user.ID
|
||||||
updatedAt := user.UpdatedAt
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
revokedTimestamp := user.RevokedTimestamp
|
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,
|
||||||
@@ -48,15 +50,15 @@ func (user *User) AsAPIUser() *model.User {
|
|||||||
FamilyName: user.FamilyName,
|
FamilyName: user.FamilyName,
|
||||||
MiddleName: user.MiddleName,
|
MiddleName: user.MiddleName,
|
||||||
Nickname: user.Nickname,
|
Nickname: user.Nickname,
|
||||||
PreferredUsername: &email,
|
PreferredUsername: refs.NewStringRef(user.Email),
|
||||||
Gender: user.Gender,
|
Gender: user.Gender,
|
||||||
Birthdate: user.Birthdate,
|
Birthdate: user.Birthdate,
|
||||||
PhoneNumber: user.PhoneNumber,
|
PhoneNumber: user.PhoneNumber,
|
||||||
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: refs.NewInt64Ref(user.CreatedAt),
|
||||||
UpdatedAt: &updatedAt,
|
UpdatedAt: refs.NewInt64Ref(user.UpdatedAt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/authorizerdev/authorizer/server/graph/model"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
@@ -19,23 +24,20 @@ type VerificationRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
||||||
token := v.Token
|
id := v.ID
|
||||||
createdAt := v.CreatedAt
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
updatedAt := v.UpdatedAt
|
id = strings.TrimPrefix(id, Collections.WebhookLog+"/")
|
||||||
email := v.Email
|
}
|
||||||
nonce := v.Nonce
|
|
||||||
redirectURI := v.RedirectURI
|
|
||||||
expires := v.ExpiresAt
|
|
||||||
identifier := v.Identifier
|
|
||||||
return &model.VerificationRequest{
|
return &model.VerificationRequest{
|
||||||
ID: v.ID,
|
ID: id,
|
||||||
Token: &token,
|
Token: refs.NewStringRef(v.Token),
|
||||||
Identifier: &identifier,
|
Identifier: refs.NewStringRef(v.Identifier),
|
||||||
Expires: &expires,
|
Expires: refs.NewInt64Ref(v.ExpiresAt),
|
||||||
Email: &email,
|
Email: refs.NewStringRef(v.Email),
|
||||||
Nonce: &nonce,
|
Nonce: refs.NewStringRef(v.Nonce),
|
||||||
RedirectURI: &redirectURI,
|
RedirectURI: refs.NewStringRef(v.RedirectURI),
|
||||||
CreatedAt: &createdAt,
|
CreatedAt: refs.NewInt64Ref(v.CreatedAt),
|
||||||
UpdatedAt: &updatedAt,
|
UpdatedAt: refs.NewInt64Ref(v.UpdatedAt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
server/db/models/webhook.go
Normal file
44
server/db/models/webhook.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsAPIWebhook to return webhook as graphql response object
|
||||||
|
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: refs.NewStringRef(w.EventName),
|
||||||
|
Endpoint: refs.NewStringRef(w.EndPoint),
|
||||||
|
Headers: headersMap,
|
||||||
|
Enabled: refs.NewBoolRef(w.Enabled),
|
||||||
|
CreatedAt: refs.NewInt64Ref(w.CreatedAt),
|
||||||
|
UpdatedAt: refs.NewInt64Ref(w.UpdatedAt),
|
||||||
|
}
|
||||||
|
}
|
39
server/db/models/webhook_log.go
Normal file
39
server/db/models/webhook_log.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsAPIWebhookLog to return webhook log as graphql response object
|
||||||
|
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: refs.NewInt64Ref(w.HttpStatus),
|
||||||
|
Response: refs.NewStringRef(w.Response),
|
||||||
|
Request: refs.NewStringRef(w.Request),
|
||||||
|
WebhookID: refs.NewStringRef(w.WebhookID),
|
||||||
|
CreatedAt: refs.NewInt64Ref(w.CreatedAt),
|
||||||
|
UpdatedAt: refs.NewInt64Ref(w.UpdatedAt),
|
||||||
|
}
|
||||||
|
}
|
151
server/db/providers/arangodb/email_template.go
Normal file
151
server/db/providers/arangodb/email_template.go
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
_, err := emailTemplateCollection.CreateDocument(ctx, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
meta, err := emailTemplateCollection.UpdateDocument(ctx, emailTemplate.Key, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = meta.Key
|
||||||
|
emailTemplate.ID = meta.ID.String()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
emailTemplates := []*model.EmailTemplate{}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.EmailTemplate, 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 emailTemplate models.EmailTemplate
|
||||||
|
meta, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
|
||||||
|
if arangoDriver.IsNoMoreDocuments(err) {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.Key != "" {
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d._key == @email_template_id RETURN d", models.Collections.EmailTemplate)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"email_template_id": emailTemplateID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if emailTemplate.Key == "" {
|
||||||
|
return nil, fmt.Errorf("email template not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.EmailTemplate)
|
||||||
|
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 emailTemplate.Key == "" {
|
||||||
|
return nil, fmt.Errorf("email template not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
eventTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
_, err := eventTemplateCollection.RemoveDocument(ctx, emailTemplate.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package arangodb
|
package arangodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -11,15 +12,15 @@ 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 {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
@@ -29,10 +30,10 @@ 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 {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
@@ -43,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
|
||||||
}
|
}
|
||||||
@@ -60,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
|
||||||
}
|
}
|
||||||
|
@@ -6,9 +6,8 @@ import (
|
|||||||
"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 {
|
||||||
@@ -22,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
|
||||||
@@ -37,16 +37,16 @@ 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 {
|
||||||
arangodb, err = arangoClient.Database(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb, err = arangoClient.Database(nil, dbName)
|
||||||
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
|
||||||
}
|
}
|
||||||
@@ -107,6 +107,47 @@ func NewProvider() (*provider, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
|
||||||
|
emailTemplateCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.EmailTemplate)
|
||||||
|
if !emailTemplateCollectionExists {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.EmailTemplate, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := arangodb.Collection(nil, models.Collections.EmailTemplate)
|
||||||
|
emailTemplateCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: arangodb,
|
db: arangodb,
|
||||||
}, err
|
}, err
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package arangodb
|
package arangodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -9,31 +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 {
|
||||||
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,32 +3,35 @@ package arangodb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"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 {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -39,10 +42,10 @@ 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 {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -53,24 +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 {
|
||||||
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
|
||||||
}
|
}
|
||||||
@@ -81,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
|
||||||
@@ -101,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)
|
||||||
@@ -109,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
|
||||||
}
|
}
|
||||||
@@ -122,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
|
||||||
}
|
}
|
||||||
@@ -132,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)
|
||||||
@@ -140,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
|
||||||
}
|
}
|
||||||
@@ -153,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
|
||||||
}
|
}
|
||||||
|
@@ -12,15 +12,15 @@ 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 {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -31,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
|
||||||
}
|
}
|
||||||
@@ -51,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
|
||||||
}
|
}
|
||||||
@@ -61,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)
|
||||||
@@ -70,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
|
||||||
}
|
}
|
||||||
@@ -83,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
|
||||||
}
|
}
|
||||||
@@ -93,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
|
||||||
}
|
}
|
||||||
@@ -109,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
|
||||||
@@ -130,7 +130,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 {
|
||||||
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 {
|
||||||
|
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
|
||||||
|
}
|
159
server/db/providers/cassandradb/email_template.go
Normal file
159
server/db/providers/cassandradb/email_template.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
existingEmailTemplate, _ := p.GetEmailTemplateByEventName(ctx, emailTemplate.EventName)
|
||||||
|
if existingEmailTemplate != nil {
|
||||||
|
return nil, fmt.Errorf("Email template with %s event_name already exists", emailTemplate.EventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, template, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.EmailTemplate, emailTemplate.ID, emailTemplate.EventName, emailTemplate.Template, emailTemplate.CreatedAt, emailTemplate.UpdatedAt)
|
||||||
|
err := p.db.Query(insertQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(emailTemplate)
|
||||||
|
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()
|
||||||
|
emailTemplateMap := map[string]interface{}{}
|
||||||
|
err = decoder.Decode(&emailTemplateMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields := ""
|
||||||
|
for key, value := range emailTemplateMap {
|
||||||
|
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.EmailTemplate, updateFields, emailTemplate.ID)
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
emailTemplates := []*model.EmailTemplate{}
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.EmailTemplate)
|
||||||
|
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, template, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.EmailTemplate, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
err := scanner.Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, template, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.EmailTemplate, emailTemplateID)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, template, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.EmailTemplate, eventName)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.EmailTemplate, emailTemplate.ID)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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)
|
||||||
|
@@ -5,11 +5,12 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@@ -23,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, ",")
|
||||||
@@ -39,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
|
||||||
}
|
}
|
||||||
@@ -84,6 +97,8 @@ 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 {
|
||||||
@@ -128,6 +143,11 @@ func NewProvider() (*provider, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 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
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
||||||
@@ -162,6 +182,39 @@ func NewProvider() (*provider, error) {
|
|||||||
return nil, 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
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplateCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, event_name text, template text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.EmailTemplate)
|
||||||
|
err = session.Query(emailTemplateCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplateIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_email_template_event_name ON %s.%s (event_name)", KeySpace, models.Collections.EmailTemplate)
|
||||||
|
err = session.Query(emailTemplateIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: session,
|
db: session,
|
||||||
}, err
|
}, 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()
|
||||||
return err
|
if err != nil {
|
||||||
|
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,6 +1,7 @@
|
|||||||
package cassandradb
|
package cassandradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -11,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()
|
||||||
}
|
}
|
||||||
@@ -28,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)
|
||||||
|
|
||||||
@@ -40,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)
|
||||||
|
|
||||||
@@ -53,7 +54,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
|
||||||
|
|
||||||
paginationClone := pagination
|
paginationClone := pagination
|
||||||
@@ -89,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
|
||||||
|
}
|
115
server/db/providers/mongodb/email_template.go
Normal file
115
server/db/providers/mongodb/email_template.go
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.InsertOne(ctx, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": emailTemplate.ID}}, bson.M{"$set": emailTemplate}, options.MergeUpdateOptions())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
var emailTemplates []*model.EmailTemplate
|
||||||
|
opts := options.Find()
|
||||||
|
opts.SetLimit(pagination.Limit)
|
||||||
|
opts.SetSkip(pagination.Offset)
|
||||||
|
opts.SetSort(bson.M{"created_at": -1})
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
count, err := emailTemplateCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone.Total = count
|
||||||
|
|
||||||
|
cursor, err := emailTemplateCollection.Find(ctx, bson.M{}, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
|
for cursor.Next(ctx) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
err := cursor.Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
err := emailTemplateCollection.FindOne(ctx, bson.M{"_id": emailTemplateID}).Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
err := emailTemplateCollection.FindOne(ctx, bson.M{"event_name": eventName}).Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.DeleteOne(nil, bson.M{"_id": emailTemplate.ID}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -11,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()
|
||||||
}
|
}
|
||||||
@@ -20,7 +21,7 @@ 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 {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
@@ -28,10 +29,10 @@ 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()
|
||||||
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 {
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
@@ -39,14 +40,14 @@ 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
|
||||||
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,33 @@ 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())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.EmailTemplate, options.CreateCollection())
|
||||||
|
emailTemplateCollection := mongodb.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
emailTemplateCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.M{"event_name": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: mongodb,
|
db: mongodb,
|
||||||
}, nil
|
}, nil
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"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()
|
||||||
}
|
}
|
||||||
@@ -19,17 +19,7 @@ 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 {
|
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -1,32 +1,36 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
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"
|
||||||
"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 {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -35,10 +39,10 @@ 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 {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
@@ -46,9 +50,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 {
|
||||||
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 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -57,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)
|
||||||
@@ -65,23 +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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
@@ -97,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
|
||||||
}
|
}
|
||||||
@@ -109,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,6 +1,7 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -11,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()
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ 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 {
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
@@ -29,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
|
||||||
}
|
}
|
||||||
@@ -42,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
|
||||||
}
|
}
|
||||||
@@ -55,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()
|
||||||
@@ -65,17 +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 {
|
||||||
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 {
|
||||||
@@ -91,9 +92,9 @@ 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 {
|
||||||
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
|
||||||
|
}
|
48
server/db/providers/provider_template/email_template.go
Normal file
48
server/db/providers/provider_template/email_template.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
return 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,75 @@
|
|||||||
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)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error)
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error)
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error)
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error)
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error)
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error
|
||||||
}
|
}
|
||||||
|
100
server/db/providers/sql/email_template.go
Normal file
100
server/db/providers/sql/email_template.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
res := p.db.Create(&emailTemplate)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
res := p.db.Save(&emailTemplate)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
var emailTemplates []models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&emailTemplates)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
totalRes := p.db.Model(&models.EmailTemplate{}).Count(&total)
|
||||||
|
if totalRes.Error != nil {
|
||||||
|
return nil, totalRes.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = total
|
||||||
|
|
||||||
|
responseEmailTemplates := []*model.EmailTemplate{}
|
||||||
|
for _, w := range emailTemplates {
|
||||||
|
responseEmailTemplates = append(responseEmailTemplates, w.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: responseEmailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Where("id = ?", emailTemplateID).First(&emailTemplate)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Where("event_name = ?", eventName).First(&emailTemplate)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
result := p.db.Delete(&models.EmailTemplate{
|
||||||
|
ID: emailTemplate.ID,
|
||||||
|
})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
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()
|
||||||
}
|
}
|
||||||
@@ -25,7 +26,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()
|
||||||
result := p.db.Save(&env)
|
result := p.db.Save(&env)
|
||||||
|
|
||||||
@@ -36,7 +37,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
|
||||||
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{}, models.EmailTemplate{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
@@ -26,13 +27,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 {
|
|
||||||
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
|
||||||
|
|
||||||
if result.Error != nil {
|
|
||||||
return result.Error
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -1,25 +1,29 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
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"
|
||||||
"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()
|
||||||
@@ -39,7 +43,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()
|
||||||
|
|
||||||
result := p.db.Save(&user)
|
result := p.db.Save(&user)
|
||||||
@@ -52,18 +56,23 @@ 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 {
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = p.db.Where("user_id = ?", user.ID).Delete(&models.Session{})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.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) {
|
||||||
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 {
|
||||||
@@ -91,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
|
||||||
}
|
}
|
||||||
@@ -103,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,6 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -10,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()
|
||||||
}
|
}
|
||||||
@@ -31,7 +32,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
|
||||||
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
||||||
|
|
||||||
@@ -43,7 +44,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
|
||||||
|
|
||||||
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
||||||
@@ -56,7 +57,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 []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)
|
||||||
@@ -85,7 +86,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 {
|
||||||
result := p.db.Delete(&verificationRequest)
|
result := p.db.Delete(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
|
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
|
||||||
|
}
|
@@ -11,7 +11,7 @@ import (
|
|||||||
gomail "gopkg.in/mail.v2"
|
gomail "gopkg.in/mail.v2"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"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
|
||||||
@@ -33,17 +33,57 @@ 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 {
|
||||||
|
@@ -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")
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
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
|
||||||
@@ -70,7 +70,7 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
|
|||||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||||
<p>Hi there 👋</p>
|
<p>Hi there 👋</p>
|
||||||
<p>Join us! You are invited to sign-up for <b>{{.org_name}}</b>. Please accept the invitation by clicking the clicking the button below.</p> <br/>
|
<p>Join us! You are invited to sign-up for <b>{{.org_name}}</b>. Please accept the invitation by clicking the button below.</p> <br/>
|
||||||
<a
|
<a
|
||||||
clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Get Started</a>
|
clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Get Started</a>
|
||||||
</td>
|
</td>
|
||||||
@@ -99,13 +99,20 @@ 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.Warn("error sending email: ", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
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,13 +99,20 @@ 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.Warn("error sending email: ", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
|
707
server/env/env.go
vendored
707
server/env/env.go
vendored
@@ -2,212 +2,247 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/joho/godotenv"
|
|
||||||
log "github.com/sirupsen/logrus"
|
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
log.Info("env path: ", envPath)
|
|
||||||
|
|
||||||
err := godotenv.Load(envPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("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 == "" {
|
|
||||||
log.Debug("DATABASE_TYPE is not set")
|
|
||||||
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 == "" {
|
|
||||||
log.Debug("DATABASE_URL is not set")
|
|
||||||
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.Info("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
|
||||||
|
} else {
|
||||||
|
clientID = cid.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientSecret := envData.StringEnv[constants.EnvKeyClientSecret]
|
// unique client secret for each instance
|
||||||
// unique client id for each instance
|
if val, ok := envData[constants.EnvKeyClientSecret]; !ok || val != "" {
|
||||||
if clientSecret == "" {
|
envData[constants.EnvKeyClientSecret] = uuid.New().String()
|
||||||
clientSecret = uuid.New().String()
|
|
||||||
envData.StringEnv[constants.EnvKeyClientSecret] = clientSecret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
// os string envs
|
||||||
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
|
osEnv := os.Getenv(constants.EnvKeyEnv)
|
||||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
osAppURL := os.Getenv(constants.EnvKeyAppURL)
|
||||||
envData.StringEnv[constants.EnvKeyEnv] = "production"
|
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.EnvKeyEnv] == "production" {
|
if envData[constants.EnvKeyEnv] == "production" {
|
||||||
envData.BoolEnv[constants.EnvKeyIsProd] = true
|
envData[constants.EnvKeyIsProd] = true
|
||||||
} else {
|
} else {
|
||||||
envData.BoolEnv[constants.EnvKeyIsProd] = false
|
envData[constants.EnvKeyIsProd] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if osEnv != "" && osEnv != envData[constants.EnvKeyEnv] {
|
||||||
if envData.StringEnv[constants.EnvKeyAppURL] == "" {
|
envData[constants.EnvKeyEnv] = osEnv
|
||||||
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
if envData[constants.EnvKeyEnv] == "production" {
|
||||||
}
|
envData[constants.EnvKeyIsProd] = true
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyAuthorizerURL] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyAuthorizerURL] = os.Getenv(constants.EnvKeyAuthorizerURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
|
|
||||||
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 !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
|
||||||
log.Debug("Invalid JWT Algorithm")
|
|
||||||
return errors.New("invalid JWT_TYPE")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
log.Debug("Invalid JWT Algorithm")
|
||||||
|
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
|
||||||
@@ -250,159 +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 envData.StringEnv[constants.EnvKeyCookieName] == "" {
|
if boolValue != envData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||||
envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv(constants.EnvKeyCookieName)
|
envData[constants.EnvKeyDisableEmailVerification] = boolValue
|
||||||
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] = "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if osAllowedOrigins != "" && envData[constants.EnvKeyAllowedOrigins] != osAllowedOrigins {
|
||||||
|
envData[constants.EnvKeyAllowedOrigins] = osAllowedOrigins
|
||||||
|
}
|
||||||
|
|
||||||
for _, val := range allowedOriginsSplit {
|
if val, ok := envData[constants.EnvKeyRoles]; !ok || val == "" {
|
||||||
trimVal := strings.TrimSpace(val)
|
envData[constants.EnvKeyRoles] = osRoles
|
||||||
if trimVal != "" {
|
if envData[constants.EnvKeyRoles] == "" {
|
||||||
if trimVal != "*" {
|
envData[constants.EnvKeyRoles] = "user"
|
||||||
host, port := utils.GetHostParts(trimVal)
|
}
|
||||||
allowedOrigins = append(allowedOrigins, host+":"+port)
|
}
|
||||||
} else {
|
if osRoles != "" && envData[constants.EnvKeyRoles] != osRoles {
|
||||||
hasWildCard = true
|
envData[constants.EnvKeyRoles] = osRoles
|
||||||
allowedOrigins = append(allowedOrigins, trimVal)
|
}
|
||||||
break
|
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]}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, role := range defaultRoles {
|
||||||
|
if !utils.StringSliceContains(roles, role) {
|
||||||
|
return fmt.Errorf("Default role %s is not defined in roles", role)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allowedOrigins) > 1 && hasWildCard {
|
if val, ok := envData[constants.EnvKeyProtectedRoles]; !ok || val == "" {
|
||||||
allowedOrigins = []string{"*"}
|
envData[constants.EnvKeyProtectedRoles] = osProtectedRoles
|
||||||
|
}
|
||||||
|
if osProtectedRoles != "" && envData[constants.EnvKeyProtectedRoles] != osProtectedRoles {
|
||||||
|
envData[constants.EnvKeyProtectedRoles] = osProtectedRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allowedOrigins) == 0 {
|
err = memorystore.Provider.UpdateEnvStore(envData)
|
||||||
allowedOrigins = []string{"*"}
|
if err != nil {
|
||||||
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|
||||||
trimVal := strings.TrimSpace(val)
|
|
||||||
if trimVal != "" {
|
|
||||||
roles = append(roles, trimVal)
|
|
||||||
if utils.StringSliceContains(defaultRoleSplit, trimVal) {
|
|
||||||
defaultRoles = append(defaultRoles, trimVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
|
||||||
log.Debug("Default roles not found in roles list. It can be one from ROLES only")
|
|
||||||
return errors.New(`invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user