Compare commits
73 Commits
fix/sessio
...
1.1.55
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c80b0d7028 | ||
![]() |
55fc4b2608 | ||
![]() |
fac333e195 | ||
![]() |
edb5412c17 | ||
![]() |
87a962504f | ||
![]() |
d04f79557a | ||
![]() |
c20e9b810a | ||
![]() |
8d145bd5fe | ||
![]() |
6fa0ad1809 | ||
![]() |
abe809ca68 | ||
![]() |
07f71e883b | ||
![]() |
6cef9064c3 | ||
![]() |
9ae616b6b5 | ||
![]() |
356428ea02 | ||
![]() |
7f47177741 | ||
![]() |
9fb00544cd | ||
![]() |
2b022d1058 | ||
![]() |
1c84d9f4a8 | ||
![]() |
0838b60fae | ||
![]() |
325134466d | ||
![]() |
58d9978dd5 | ||
![]() |
801d64e2f5 | ||
![]() |
dd3cc9de3a | ||
![]() |
8dc7366182 | ||
![]() |
7749534087 | ||
![]() |
510f16e7b0 | ||
![]() |
d5e83ea14f | ||
![]() |
b4a90de1d4 | ||
![]() |
c525ad92f2 | ||
![]() |
9028682e93 | ||
![]() |
3d6bfe4480 | ||
![]() |
043af08bf0 | ||
![]() |
0af78479fc | ||
![]() |
096f686495 | ||
![]() |
c574c6a679 | ||
![]() |
6428b74e64 | ||
![]() |
aa3892025d | ||
![]() |
b2f3d6eb80 | ||
![]() |
348cbf8c38 | ||
![]() |
8ac33a085c | ||
![]() |
6c9b359081 | ||
![]() |
0fde46d274 | ||
![]() |
1a5b446894 | ||
![]() |
930c934fdb | ||
![]() |
4e7074d75b | ||
![]() |
bdfa045a43 | ||
![]() |
a258399bde | ||
![]() |
55a25436a8 | ||
![]() |
9fa402f5c8 | ||
![]() |
1111729ad4 | ||
![]() |
e56c2f58e5 | ||
![]() |
8dbd2556eb | ||
![]() |
17bb077f3e | ||
![]() |
f291417378 | ||
![]() |
f831379d27 | ||
![]() |
a50f6becbd | ||
![]() |
a6f6e0b18a | ||
![]() |
3868157e11 | ||
![]() |
d693c05483 | ||
![]() |
6f1fbf886d | ||
![]() |
b86487fda4 | ||
![]() |
28d4ddeb50 | ||
![]() |
b9ab1d3761 | ||
![]() |
a5b643e127 | ||
![]() |
691664e629 | ||
![]() |
efb67a9538 | ||
![]() |
a0f2eeba3e | ||
![]() |
d1a0ccd790 | ||
![]() |
729c23f578 | ||
![]() |
a074f85391 | ||
![]() |
4e7ec6cb7b | ||
![]() |
6d541cbfb9 | ||
![]() |
1ebba7f2b7 |
@@ -7,4 +7,9 @@ SMTP_PORT=2525
|
|||||||
SMTP_USERNAME=test
|
SMTP_USERNAME=test
|
||||||
SMTP_PASSWORD=test
|
SMTP_PASSWORD=test
|
||||||
SENDER_EMAIL="info@authorizer.dev"
|
SENDER_EMAIL="info@authorizer.dev"
|
||||||
|
TWILIO_API_KEY=test
|
||||||
|
TWILIO_API_SECRET=test
|
||||||
|
TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
TWILIO_SENDER=909921212112
|
||||||
|
SENDER_NAME="Authorizer"
|
||||||
AWS_REGION=ap-south-1
|
AWS_REGION=ap-south-1
|
230
.github/CONTRIBUTING.md
vendored
230
.github/CONTRIBUTING.md
vendored
@@ -45,12 +45,30 @@ Please ask as many questions as you need, either directly in the issue or on [Di
|
|||||||
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
|
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
|
||||||
2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
|
2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
|
||||||
3. Change directory to authorizer: `cd authorizer`
|
3. Change directory to authorizer: `cd authorizer`
|
||||||
5. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
4. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
|
||||||
6. Build Dashboard `make build-dashboard`
|
5. Build Dashboard `make build-dashboard`
|
||||||
7. Build App `make build-app`
|
6. Build App `make build-app`
|
||||||
8. Build Server `make clean && make`
|
7. Build Server `make clean && make`
|
||||||
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command. In that case you will have to build `dashboard` & `app` manually using `npm run build` on both dirs.
|
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command. In that case you will have to build `dashboard` & `app` manually using `npm run build` on both dirs.
|
||||||
9. Run binary `./build/server`
|
8. Run binary `./build/server`
|
||||||
|
|
||||||
|
### Updating GraphQL schema
|
||||||
|
|
||||||
|
- Modify `server/graph/schema.graphqls` file
|
||||||
|
- Run `make generate-graphql` this will update the models and required methods
|
||||||
|
- If a new mutation or query is added
|
||||||
|
- Write the implementation for the new resolver in `server/resolvers/NEW_RESOLVER.GO`
|
||||||
|
- Update `server/graph/schema.resolvers.go` with the new resolver method
|
||||||
|
|
||||||
|
### Adding support for new database
|
||||||
|
|
||||||
|
- Run `make generate-db-template dbname=NEW_DB_NAME`
|
||||||
|
eg `make generate-db-template dbname=dynamodb`
|
||||||
|
|
||||||
|
This command will generate a folder in server/db/providers/ with name specified in the above command.
|
||||||
|
One will have to implement methods present in that folder.
|
||||||
|
|
||||||
|
> Note: Connection for database and schema changes are written in `server/db/providers/DB_NAME/provider.go` > `NewProvider` method is called for any given db based on the env variables present.
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
@@ -87,145 +105,145 @@ For manually testing using graphql playground, you can paste following queries a
|
|||||||
|
|
||||||
```gql
|
```gql
|
||||||
mutation Signup {
|
mutation Signup {
|
||||||
signup(
|
signup(
|
||||||
params: {
|
params: {
|
||||||
email: "lakhan@yopmail.com"
|
email: "lakhan@yopmail.com"
|
||||||
password: "test"
|
password: "test"
|
||||||
confirm_password: "test"
|
confirm_password: "test"
|
||||||
given_name: "lakhan"
|
given_name: "lakhan"
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
message
|
message
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
family_name
|
family_name
|
||||||
given_name
|
given_name
|
||||||
email
|
email
|
||||||
email_verified
|
email_verified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation ResendEamil {
|
mutation ResendEamil {
|
||||||
resend_verify_email(
|
resend_verify_email(
|
||||||
params: { email: "lakhan@yopmail.com", identifier: "basic_auth_signup" }
|
params: { email: "lakhan@yopmail.com", identifier: "basic_auth_signup" }
|
||||||
) {
|
) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query GetVerifyRequests {
|
query GetVerifyRequests {
|
||||||
_verification_requests {
|
_verification_requests {
|
||||||
id
|
id
|
||||||
token
|
token
|
||||||
expires
|
expires
|
||||||
identifier
|
identifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation VerifyEmail {
|
mutation VerifyEmail {
|
||||||
verify_email(params: { token: "" }) {
|
verify_email(params: { token: "" }) {
|
||||||
access_token
|
access_token
|
||||||
expires_at
|
expires_at
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
given_name
|
given_name
|
||||||
email_verified
|
email_verified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation Login {
|
mutation Login {
|
||||||
login(params: { email: "lakhan@yopmail.com", password: "test" }) {
|
login(params: { email: "lakhan@yopmail.com", password: "test" }) {
|
||||||
access_token
|
access_token
|
||||||
expires_at
|
expires_at
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
family_name
|
family_name
|
||||||
given_name
|
given_name
|
||||||
email
|
email
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query GetSession {
|
query GetSession {
|
||||||
session {
|
session {
|
||||||
access_token
|
access_token
|
||||||
expires_at
|
expires_at
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
given_name
|
given_name
|
||||||
family_name
|
family_name
|
||||||
email
|
email
|
||||||
email_verified
|
email_verified
|
||||||
signup_methods
|
signup_methods
|
||||||
created_at
|
created_at
|
||||||
updated_at
|
updated_at
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation ForgotPassword {
|
mutation ForgotPassword {
|
||||||
forgot_password(params: { email: "lakhan@yopmail.com" }) {
|
forgot_password(params: { email: "lakhan@yopmail.com" }) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation ResetPassword {
|
mutation ResetPassword {
|
||||||
reset_password(
|
reset_password(
|
||||||
params: { token: "", password: "test", confirm_password: "test" }
|
params: { token: "", password: "test", confirm_password: "test" }
|
||||||
) {
|
) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation UpdateProfile {
|
mutation UpdateProfile {
|
||||||
update_profile(params: { family_name: "samani" }) {
|
update_profile(params: { family_name: "samani" }) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query GetUsers {
|
query GetUsers {
|
||||||
_users {
|
_users {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
email_verified
|
email_verified
|
||||||
given_name
|
given_name
|
||||||
family_name
|
family_name
|
||||||
picture
|
picture
|
||||||
signup_methods
|
signup_methods
|
||||||
phone_number
|
phone_number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation MagicLinkLogin {
|
mutation MagicLinkLogin {
|
||||||
magic_link_login(params: { email: "test@yopmail.com" }) {
|
magic_link_login(params: { email: "test@yopmail.com" }) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation Logout {
|
mutation Logout {
|
||||||
logout {
|
logout {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation UpdateUser {
|
mutation UpdateUser {
|
||||||
_update_user(
|
_update_user(
|
||||||
params: {
|
params: {
|
||||||
id: "dafc9400-d603-4ade-997c-83fcd54bbd67"
|
id: "dafc9400-d603-4ade-997c-83fcd54bbd67"
|
||||||
roles: ["user", "admin"]
|
roles: ["user", "admin"]
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
email
|
email
|
||||||
roles
|
roles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation DeleteUser {
|
mutation DeleteUser {
|
||||||
_delete_user(params: { email: "signup.test134523@yopmail.com" }) {
|
_delete_user(params: { email: "signup.test134523@yopmail.com" }) {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
5
Makefile
5
Makefile
@@ -52,5 +52,8 @@ test-all-db:
|
|||||||
docker rm -vf authorizer_arangodb
|
docker rm -vf authorizer_arangodb
|
||||||
docker rm -vf dynamodb-local-test
|
docker rm -vf dynamodb-local-test
|
||||||
docker rm -vf couchbase-local-test
|
docker rm -vf couchbase-local-test
|
||||||
generate:
|
generate-graphql:
|
||||||
cd server && go run github.com/99designs/gqlgen generate && go mod tidy
|
cd server && go run github.com/99designs/gqlgen generate && go mod tidy
|
||||||
|
generate-db-template:
|
||||||
|
cp -rf server/db/providers/provider_template server/db/providers/${dbname}
|
||||||
|
find server/db/providers/${dbname} -type f -exec sed -i -e 's/provider_template/${dbname}/g' {} \;
|
35
app/package-lock.json
generated
35
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": "^1.1.8",
|
"@authorizerdev/authorizer-react": "^1.1.11",
|
||||||
"@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",
|
||||||
@@ -27,22 +27,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-js": {
|
"node_modules/@authorizerdev/authorizer-js": {
|
||||||
"version": "1.1.4",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.3.tgz",
|
||||||
"integrity": "sha512-oLp3XMYU9xHlg5urpAOaw6NrKQ07SaI8oAi1BAMHZWivv5qi2V+6roey0y9MdvCUmsMULBBcZg87kuoMTXRJOw==",
|
"integrity": "sha512-rk/fMRIsqbp+fsy2y09etVjf7CY9/4mG6hf0RKgXgRRfxtAQa1jdkt/De23hBTNeEwAWu6hP/9BQZjcrln6KtA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-fetch": "^3.1.5"
|
"cross-fetch": "^3.1.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/authorizerdev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-react": {
|
"node_modules/@authorizerdev/authorizer-react": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.11.tgz",
|
||||||
"integrity": "sha512-5v9Zc7ZxiEQEHT1Fwj1jvEemdckcrn7mZPkdmJ/z0YOWNbF20ZpM4WsfrtJB+d293m7Rb1QKwzdFPkYINMh5tw==",
|
"integrity": "sha512-tSI/yjsoeK/RvCOMiHSf1QGOeSpaLYQZEM864LFLndKoJwk7UWCJ86qg1w6ge7B00PmZSNWqST/w5JTcQaVNpw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": "^1.1.4"
|
"@authorizerdev/authorizer-js": "^1.2.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
@@ -834,19 +837,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": {
|
"@authorizerdev/authorizer-js": {
|
||||||
"version": "1.1.4",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.3.tgz",
|
||||||
"integrity": "sha512-oLp3XMYU9xHlg5urpAOaw6NrKQ07SaI8oAi1BAMHZWivv5qi2V+6roey0y9MdvCUmsMULBBcZg87kuoMTXRJOw==",
|
"integrity": "sha512-rk/fMRIsqbp+fsy2y09etVjf7CY9/4mG6hf0RKgXgRRfxtAQa1jdkt/De23hBTNeEwAWu6hP/9BQZjcrln6KtA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"cross-fetch": "^3.1.5"
|
"cross-fetch": "^3.1.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@authorizerdev/authorizer-react": {
|
"@authorizerdev/authorizer-react": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.11.tgz",
|
||||||
"integrity": "sha512-5v9Zc7ZxiEQEHT1Fwj1jvEemdckcrn7mZPkdmJ/z0YOWNbF20ZpM4WsfrtJB+d293m7Rb1QKwzdFPkYINMh5tw==",
|
"integrity": "sha512-tSI/yjsoeK/RvCOMiHSf1QGOeSpaLYQZEM864LFLndKoJwk7UWCJ86qg1w6ge7B00PmZSNWqST/w5JTcQaVNpw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@authorizerdev/authorizer-js": "^1.1.4"
|
"@authorizerdev/authorizer-js": "^1.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
"author": "Lakhan Samani",
|
"author": "Lakhan Samani",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-react": "^1.1.9",
|
"@authorizerdev/authorizer-react": "^1.1.11",
|
||||||
"@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",
|
||||||
|
756
app/yarn.lock
756
app/yarn.lock
@@ -2,126 +2,126 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@authorizerdev/authorizer-js@^1.1.4":
|
"@authorizerdev/authorizer-js@^1.2.3":
|
||||||
version "1.1.4"
|
"integrity" "sha512-rk/fMRIsqbp+fsy2y09etVjf7CY9/4mG6hf0RKgXgRRfxtAQa1jdkt/De23hBTNeEwAWu6hP/9BQZjcrln6KtA=="
|
||||||
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.1.4.tgz"
|
"resolved" "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.3.tgz"
|
||||||
integrity sha512-oLp3XMYU9xHlg5urpAOaw6NrKQ07SaI8oAi1BAMHZWivv5qi2V+6roey0y9MdvCUmsMULBBcZg87kuoMTXRJOw==
|
"version" "1.2.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-fetch "^3.1.5"
|
"cross-fetch" "^3.1.5"
|
||||||
|
|
||||||
"@authorizerdev/authorizer-react@^1.1.8":
|
"@authorizerdev/authorizer-react@^1.1.11":
|
||||||
version "1.1.8"
|
"integrity" "sha512-tSI/yjsoeK/RvCOMiHSf1QGOeSpaLYQZEM864LFLndKoJwk7UWCJ86qg1w6ge7B00PmZSNWqST/w5JTcQaVNpw=="
|
||||||
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.8.tgz"
|
"resolved" "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.11.tgz"
|
||||||
integrity sha512-5v9Zc7ZxiEQEHT1Fwj1jvEemdckcrn7mZPkdmJ/z0YOWNbF20ZpM4WsfrtJB+d293m7Rb1QKwzdFPkYINMh5tw==
|
"version" "1.1.11"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@authorizerdev/authorizer-js" "^1.1.4"
|
"@authorizerdev/authorizer-js" "^1.2.3"
|
||||||
|
|
||||||
"@babel/code-frame@^7.16.7":
|
"@babel/code-frame@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg=="
|
||||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz"
|
||||||
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.16.7"
|
"@babel/highlight" "^7.16.7"
|
||||||
|
|
||||||
"@babel/generator@^7.16.8":
|
"@babel/generator@^7.16.8":
|
||||||
version "7.16.8"
|
"integrity" "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz"
|
||||||
integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==
|
"version" "7.16.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.8"
|
"@babel/types" "^7.16.8"
|
||||||
jsesc "^2.5.1"
|
"jsesc" "^2.5.1"
|
||||||
source-map "^0.5.0"
|
"source-map" "^0.5.0"
|
||||||
|
|
||||||
"@babel/helper-annotate-as-pure@^7.16.0":
|
"@babel/helper-annotate-as-pure@^7.16.0":
|
||||||
version "7.16.7"
|
"integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz"
|
||||||
integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-environment-visitor@^7.16.7":
|
"@babel/helper-environment-visitor@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz"
|
||||||
integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-function-name@^7.16.7":
|
"@babel/helper-function-name@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz"
|
||||||
integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-get-function-arity" "^7.16.7"
|
"@babel/helper-get-function-arity" "^7.16.7"
|
||||||
"@babel/template" "^7.16.7"
|
"@babel/template" "^7.16.7"
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-get-function-arity@^7.16.7":
|
"@babel/helper-get-function-arity@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz"
|
||||||
integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.16.7":
|
"@babel/helper-hoist-variables@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz"
|
||||||
integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.0":
|
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.0":
|
||||||
version "7.16.7"
|
"integrity" "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz"
|
||||||
integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-split-export-declaration@^7.16.7":
|
"@babel/helper-split-export-declaration@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz"
|
||||||
integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.16.7":
|
"@babel/helper-validator-identifier@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz"
|
||||||
integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
|
"version" "7.16.7"
|
||||||
|
|
||||||
"@babel/highlight@^7.16.7":
|
"@babel/highlight@^7.16.7":
|
||||||
version "7.16.10"
|
"integrity" "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz"
|
||||||
integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
|
"version" "7.16.10"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-validator-identifier" "^7.16.7"
|
"@babel/helper-validator-identifier" "^7.16.7"
|
||||||
chalk "^2.0.0"
|
"chalk" "^2.0.0"
|
||||||
js-tokens "^4.0.0"
|
"js-tokens" "^4.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.16.10", "@babel/parser@^7.16.7":
|
"@babel/parser@^7.16.10", "@babel/parser@^7.16.7":
|
||||||
version "7.16.12"
|
"integrity" "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A=="
|
||||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz"
|
||||||
integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==
|
"version" "7.16.12"
|
||||||
|
|
||||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1":
|
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1":
|
||||||
version "7.14.8"
|
"integrity" "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg=="
|
||||||
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz"
|
||||||
integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==
|
"version" "7.14.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
"regenerator-runtime" "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.16.7":
|
"@babel/template@^7.16.7":
|
||||||
version "7.16.7"
|
"integrity" "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w=="
|
||||||
resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz"
|
||||||
integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
|
"version" "7.16.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.16.7"
|
"@babel/code-frame" "^7.16.7"
|
||||||
"@babel/parser" "^7.16.7"
|
"@babel/parser" "^7.16.7"
|
||||||
"@babel/types" "^7.16.7"
|
"@babel/types" "^7.16.7"
|
||||||
|
|
||||||
"@babel/traverse@^7.4.5":
|
"@babel/traverse@^7.4.5":
|
||||||
version "7.16.10"
|
"integrity" "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw=="
|
||||||
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz"
|
||||||
integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==
|
"version" "7.16.10"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.16.7"
|
"@babel/code-frame" "^7.16.7"
|
||||||
"@babel/generator" "^7.16.8"
|
"@babel/generator" "^7.16.8"
|
||||||
@@ -131,458 +131,458 @@
|
|||||||
"@babel/helper-split-export-declaration" "^7.16.7"
|
"@babel/helper-split-export-declaration" "^7.16.7"
|
||||||
"@babel/parser" "^7.16.10"
|
"@babel/parser" "^7.16.10"
|
||||||
"@babel/types" "^7.16.8"
|
"@babel/types" "^7.16.8"
|
||||||
debug "^4.1.0"
|
"debug" "^4.1.0"
|
||||||
globals "^11.1.0"
|
"globals" "^11.1.0"
|
||||||
|
|
||||||
"@babel/types@^7.16.7", "@babel/types@^7.16.8":
|
"@babel/types@^7.16.7", "@babel/types@^7.16.8":
|
||||||
version "7.16.8"
|
"integrity" "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg=="
|
||||||
resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz"
|
"resolved" "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz"
|
||||||
integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==
|
"version" "7.16.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-validator-identifier" "^7.16.7"
|
"@babel/helper-validator-identifier" "^7.16.7"
|
||||||
to-fast-properties "^2.0.0"
|
"to-fast-properties" "^2.0.0"
|
||||||
|
|
||||||
"@emotion/is-prop-valid@^0.8.8":
|
"@emotion/is-prop-valid@^0.8.8":
|
||||||
version "0.8.8"
|
"integrity" "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA=="
|
||||||
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz"
|
"resolved" "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz"
|
||||||
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
"version" "0.8.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/memoize" "0.7.4"
|
"@emotion/memoize" "0.7.4"
|
||||||
|
|
||||||
"@emotion/memoize@0.7.4":
|
"@emotion/memoize@0.7.4":
|
||||||
version "0.7.4"
|
"integrity" "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
|
||||||
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz"
|
"resolved" "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz"
|
||||||
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
"version" "0.7.4"
|
||||||
|
|
||||||
"@emotion/stylis@^0.8.4":
|
"@emotion/stylis@^0.8.4":
|
||||||
version "0.8.5"
|
"integrity" "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
|
||||||
resolved "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz"
|
"resolved" "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz"
|
||||||
integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
|
"version" "0.8.5"
|
||||||
|
|
||||||
"@emotion/unitless@^0.7.4":
|
"@emotion/unitless@^0.7.4":
|
||||||
version "0.7.5"
|
"integrity" "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||||
resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz"
|
"resolved" "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz"
|
||||||
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
"version" "0.7.5"
|
||||||
|
|
||||||
"@types/history@*":
|
"@types/history@*":
|
||||||
version "4.7.9"
|
"integrity" "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ=="
|
||||||
resolved "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz"
|
"resolved" "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz"
|
||||||
integrity sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==
|
"version" "4.7.9"
|
||||||
|
|
||||||
"@types/hoist-non-react-statics@*":
|
"@types/hoist-non-react-statics@*":
|
||||||
version "3.3.1"
|
"integrity" "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA=="
|
||||||
resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
|
"resolved" "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
|
||||||
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
"version" "3.3.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
hoist-non-react-statics "^3.3.0"
|
"hoist-non-react-statics" "^3.3.0"
|
||||||
|
|
||||||
"@types/prop-types@*":
|
"@types/prop-types@*":
|
||||||
version "15.7.4"
|
"integrity" "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
|
||||||
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"
|
||||||
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
|
"version" "15.7.4"
|
||||||
|
|
||||||
"@types/react-dom@^17.0.9":
|
"@types/react-dom@^17.0.9":
|
||||||
version "17.0.9"
|
"integrity" "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg=="
|
||||||
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz"
|
"resolved" "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz"
|
||||||
integrity sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==
|
"version" "17.0.9"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-router-dom@^5.1.8":
|
"@types/react-router-dom@^5.1.8":
|
||||||
version "5.1.8"
|
"integrity" "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw=="
|
||||||
resolved "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz"
|
"resolved" "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz"
|
||||||
integrity sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==
|
"version" "5.1.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/history" "*"
|
"@types/history" "*"
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
"@types/react-router" "*"
|
"@types/react-router" "*"
|
||||||
|
|
||||||
"@types/react-router@*":
|
"@types/react-router@*":
|
||||||
version "5.1.16"
|
"integrity" "sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg=="
|
||||||
resolved "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.16.tgz"
|
"resolved" "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.16.tgz"
|
||||||
integrity sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==
|
"version" "5.1.16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/history" "*"
|
"@types/history" "*"
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^17.0.15":
|
"@types/react@*", "@types/react@^17.0.15":
|
||||||
version "17.0.15"
|
"integrity" "sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw=="
|
||||||
resolved "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz"
|
"resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz"
|
||||||
integrity sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw==
|
"version" "17.0.15"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types" "*"
|
"@types/prop-types" "*"
|
||||||
"@types/scheduler" "*"
|
"@types/scheduler" "*"
|
||||||
csstype "^3.0.2"
|
"csstype" "^3.0.2"
|
||||||
|
|
||||||
"@types/scheduler@*":
|
"@types/scheduler@*":
|
||||||
version "0.16.2"
|
"integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
||||||
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==
|
"version" "0.16.2"
|
||||||
|
|
||||||
"@types/styled-components@^5.1.11":
|
"@types/styled-components@^5.1.11":
|
||||||
version "5.1.25"
|
"integrity" "sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ=="
|
||||||
resolved "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.25.tgz"
|
"resolved" "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.25.tgz"
|
||||||
integrity sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ==
|
"version" "5.1.25"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/hoist-non-react-statics" "*"
|
"@types/hoist-non-react-statics" "*"
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
csstype "^3.0.2"
|
"csstype" "^3.0.2"
|
||||||
|
|
||||||
ansi-styles@^3.2.1:
|
"ansi-styles@^3.2.1":
|
||||||
version "3.2.1"
|
"integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="
|
||||||
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"
|
||||||
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
"version" "3.2.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert "^1.9.0"
|
"color-convert" "^1.9.0"
|
||||||
|
|
||||||
"babel-plugin-styled-components@>= 1.12.0":
|
"babel-plugin-styled-components@>= 1.12.0":
|
||||||
version "2.0.2"
|
"integrity" "sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw=="
|
||||||
resolved "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz"
|
"resolved" "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz"
|
||||||
integrity sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw==
|
"version" "2.0.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-annotate-as-pure" "^7.16.0"
|
"@babel/helper-annotate-as-pure" "^7.16.0"
|
||||||
"@babel/helper-module-imports" "^7.16.0"
|
"@babel/helper-module-imports" "^7.16.0"
|
||||||
babel-plugin-syntax-jsx "^6.18.0"
|
"babel-plugin-syntax-jsx" "^6.18.0"
|
||||||
lodash "^4.17.11"
|
"lodash" "^4.17.11"
|
||||||
|
|
||||||
babel-plugin-syntax-jsx@^6.18.0:
|
"babel-plugin-syntax-jsx@^6.18.0":
|
||||||
version "6.18.0"
|
"integrity" "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
|
||||||
resolved "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz"
|
"resolved" "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz"
|
||||||
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
|
"version" "6.18.0"
|
||||||
|
|
||||||
camelize@^1.0.0:
|
"camelize@^1.0.0":
|
||||||
version "1.0.0"
|
"integrity" "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
|
||||||
resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz"
|
||||||
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
|
"version" "1.0.0"
|
||||||
|
|
||||||
chalk@^2.0.0:
|
"chalk@^2.0.0":
|
||||||
version "2.4.2"
|
"integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
|
||||||
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
"resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
"version" "2.4.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles "^3.2.1"
|
"ansi-styles" "^3.2.1"
|
||||||
escape-string-regexp "^1.0.5"
|
"escape-string-regexp" "^1.0.5"
|
||||||
supports-color "^5.3.0"
|
"supports-color" "^5.3.0"
|
||||||
|
|
||||||
color-convert@^1.9.0:
|
"color-convert@^1.9.0":
|
||||||
version "1.9.3"
|
"integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="
|
||||||
resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
|
"resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
|
||||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
"version" "1.9.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name "1.1.3"
|
"color-name" "1.1.3"
|
||||||
|
|
||||||
color-name@1.1.3:
|
"color-name@1.1.3":
|
||||||
version "1.1.3"
|
"integrity" "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
"resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
"version" "1.1.3"
|
||||||
|
|
||||||
cross-fetch@^3.1.5:
|
"cross-fetch@^3.1.5":
|
||||||
version "3.1.5"
|
"integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw=="
|
||||||
resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz"
|
"resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz"
|
||||||
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
|
"version" "3.1.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
node-fetch "2.6.7"
|
"node-fetch" "2.6.7"
|
||||||
|
|
||||||
css-color-keywords@^1.0.0:
|
"css-color-keywords@^1.0.0":
|
||||||
version "1.0.0"
|
"integrity" "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
|
||||||
resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz"
|
||||||
integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
|
"version" "1.0.0"
|
||||||
|
|
||||||
css-to-react-native@^3.0.0:
|
"css-to-react-native@^3.0.0":
|
||||||
version "3.0.0"
|
"integrity" "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ=="
|
||||||
resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz"
|
||||||
integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==
|
"version" "3.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
camelize "^1.0.0"
|
"camelize" "^1.0.0"
|
||||||
css-color-keywords "^1.0.0"
|
"css-color-keywords" "^1.0.0"
|
||||||
postcss-value-parser "^4.0.2"
|
"postcss-value-parser" "^4.0.2"
|
||||||
|
|
||||||
csstype@^3.0.2:
|
"csstype@^3.0.2":
|
||||||
version "3.0.8"
|
"integrity" "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
|
||||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz"
|
"resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz"
|
||||||
integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
|
"version" "3.0.8"
|
||||||
|
|
||||||
debug@^4.1.0:
|
"debug@^4.1.0":
|
||||||
version "4.3.3"
|
"integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q=="
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz"
|
"resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz"
|
||||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
"version" "4.3.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.1.2"
|
"ms" "2.1.2"
|
||||||
|
|
||||||
esbuild@^0.12.17:
|
"esbuild@^0.12.17":
|
||||||
version "0.12.17"
|
"integrity" "sha512-GshKJyVYUnlSXIZj/NheC2O0Kblh42CS7P1wJyTbbIHevTG4jYMS9NNw8EOd8dDWD0dzydYHS01MpZoUcQXB4g=="
|
||||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.12.17.tgz"
|
"resolved" "https://registry.npmjs.org/esbuild/-/esbuild-0.12.17.tgz"
|
||||||
integrity sha512-GshKJyVYUnlSXIZj/NheC2O0Kblh42CS7P1wJyTbbIHevTG4jYMS9NNw8EOd8dDWD0dzydYHS01MpZoUcQXB4g==
|
"version" "0.12.17"
|
||||||
|
|
||||||
escape-string-regexp@^1.0.5:
|
"escape-string-regexp@^1.0.5":
|
||||||
version "1.0.5"
|
"integrity" "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
|
"resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
"version" "1.0.5"
|
||||||
|
|
||||||
globals@^11.1.0:
|
"globals@^11.1.0":
|
||||||
version "11.12.0"
|
"integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
|
||||||
resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
|
"resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
|
||||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
"version" "11.12.0"
|
||||||
|
|
||||||
has-flag@^3.0.0:
|
"has-flag@^3.0.0":
|
||||||
version "3.0.0"
|
"integrity" "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
|
||||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
"version" "3.0.0"
|
||||||
|
|
||||||
history@^4.9.0:
|
"history@^4.9.0":
|
||||||
version "4.10.1"
|
"integrity" "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew=="
|
||||||
resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz"
|
"resolved" "https://registry.npmjs.org/history/-/history-4.10.1.tgz"
|
||||||
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
|
"version" "4.10.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
loose-envify "^1.2.0"
|
"loose-envify" "^1.2.0"
|
||||||
resolve-pathname "^3.0.0"
|
"resolve-pathname" "^3.0.0"
|
||||||
tiny-invariant "^1.0.2"
|
"tiny-invariant" "^1.0.2"
|
||||||
tiny-warning "^1.0.0"
|
"tiny-warning" "^1.0.0"
|
||||||
value-equal "^1.0.1"
|
"value-equal" "^1.0.1"
|
||||||
|
|
||||||
hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
|
"hoist-non-react-statics@^3.0.0", "hoist-non-react-statics@^3.1.0", "hoist-non-react-statics@^3.3.0":
|
||||||
version "3.3.2"
|
"integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="
|
||||||
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
|
"resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
|
||||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
"version" "3.3.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
react-is "^16.7.0"
|
"react-is" "^16.7.0"
|
||||||
|
|
||||||
isarray@0.0.1:
|
"isarray@0.0.1":
|
||||||
version "0.0.1"
|
"integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||||
resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
|
"resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
|
||||||
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
"version" "0.0.1"
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0":
|
||||||
version "4.0.0"
|
"integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||||
resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
|
||||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
"version" "4.0.0"
|
||||||
|
|
||||||
jsesc@^2.5.1:
|
"jsesc@^2.5.1":
|
||||||
version "2.5.2"
|
"integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
|
||||||
resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
|
"resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
|
||||||
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
|
"version" "2.5.2"
|
||||||
|
|
||||||
lodash@^4.17.11:
|
"lodash@^4.17.11":
|
||||||
version "4.17.21"
|
"integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
"version" "4.17.21"
|
||||||
|
|
||||||
loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
"loose-envify@^1.1.0", "loose-envify@^1.2.0", "loose-envify@^1.3.1", "loose-envify@^1.4.0":
|
||||||
version "1.4.0"
|
"integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="
|
||||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
"resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
"version" "1.4.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
js-tokens "^3.0.0 || ^4.0.0"
|
"js-tokens" "^3.0.0 || ^4.0.0"
|
||||||
|
|
||||||
mini-create-react-context@^0.4.0:
|
"mini-create-react-context@^0.4.0":
|
||||||
version "0.4.1"
|
"integrity" "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ=="
|
||||||
resolved "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz"
|
"resolved" "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz"
|
||||||
integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
|
"version" "0.4.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.12.1"
|
"@babel/runtime" "^7.12.1"
|
||||||
tiny-warning "^1.0.3"
|
"tiny-warning" "^1.0.3"
|
||||||
|
|
||||||
ms@2.1.2:
|
"ms@2.1.2":
|
||||||
version "2.1.2"
|
"integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
"resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
"version" "2.1.2"
|
||||||
|
|
||||||
node-fetch@2.6.7:
|
"node-fetch@2.6.7":
|
||||||
version "2.6.7"
|
"integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="
|
||||||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz"
|
"resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz"
|
||||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
"version" "2.6.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url "^5.0.0"
|
"whatwg-url" "^5.0.0"
|
||||||
|
|
||||||
object-assign@^4.1.1:
|
"object-assign@^4.1.1":
|
||||||
version "4.1.1"
|
"integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
|
"resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
|
||||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
"version" "4.1.1"
|
||||||
|
|
||||||
path-to-regexp@^1.7.0:
|
"path-to-regexp@^1.7.0":
|
||||||
version "1.8.0"
|
"integrity" "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA=="
|
||||||
resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz"
|
"resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz"
|
||||||
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
|
"version" "1.8.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
isarray "0.0.1"
|
"isarray" "0.0.1"
|
||||||
|
|
||||||
postcss-value-parser@^4.0.2:
|
"postcss-value-parser@^4.0.2":
|
||||||
version "4.2.0"
|
"integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
"resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
"version" "4.2.0"
|
||||||
|
|
||||||
prettier@2.7.1:
|
"prettier@2.7.1":
|
||||||
version "2.7.1"
|
"integrity" "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
|
||||||
resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz"
|
"resolved" "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz"
|
||||||
integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
|
"version" "2.7.1"
|
||||||
|
|
||||||
prop-types@^15.0.0, prop-types@^15.6.2:
|
"prop-types@^15.0.0", "prop-types@^15.6.2":
|
||||||
version "15.7.2"
|
"integrity" "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ=="
|
||||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz"
|
"resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz"
|
||||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
"version" "15.7.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.4.0"
|
"loose-envify" "^1.4.0"
|
||||||
object-assign "^4.1.1"
|
"object-assign" "^4.1.1"
|
||||||
react-is "^16.8.1"
|
"react-is" "^16.8.1"
|
||||||
|
|
||||||
react-dom@^17.0.2, "react-dom@>= 16.8.0":
|
"react-dom@^17.0.2", "react-dom@>= 16.8.0":
|
||||||
version "17.0.2"
|
"integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA=="
|
||||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
|
"resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
|
||||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
"version" "17.0.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
"loose-envify" "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
"object-assign" "^4.1.1"
|
||||||
scheduler "^0.20.2"
|
"scheduler" "^0.20.2"
|
||||||
|
|
||||||
react-is@^16.6.0:
|
"react-is@^16.6.0":
|
||||||
version "16.13.1"
|
"integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
"version" "16.13.1"
|
||||||
|
|
||||||
react-is@^16.7.0:
|
"react-is@^16.7.0":
|
||||||
version "16.13.1"
|
"integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
"version" "16.13.1"
|
||||||
|
|
||||||
react-is@^16.8.1:
|
"react-is@^16.8.1":
|
||||||
version "16.13.1"
|
"integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
"version" "16.13.1"
|
||||||
|
|
||||||
react-is@^17.0.2, "react-is@>= 16.8.0":
|
"react-is@^17.0.2", "react-is@>= 16.8.0":
|
||||||
version "17.0.2"
|
"integrity" "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
|
"resolved" "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
|
||||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
"version" "17.0.2"
|
||||||
|
|
||||||
react-router-dom@^5.2.0:
|
"react-router-dom@^5.2.0":
|
||||||
version "5.2.0"
|
"integrity" "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA=="
|
||||||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz"
|
"resolved" "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz"
|
||||||
integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
|
"version" "5.2.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
history "^4.9.0"
|
"history" "^4.9.0"
|
||||||
loose-envify "^1.3.1"
|
"loose-envify" "^1.3.1"
|
||||||
prop-types "^15.6.2"
|
"prop-types" "^15.6.2"
|
||||||
react-router "5.2.0"
|
"react-router" "5.2.0"
|
||||||
tiny-invariant "^1.0.2"
|
"tiny-invariant" "^1.0.2"
|
||||||
tiny-warning "^1.0.0"
|
"tiny-warning" "^1.0.0"
|
||||||
|
|
||||||
react-router@5.2.0:
|
"react-router@5.2.0":
|
||||||
version "5.2.0"
|
"integrity" "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw=="
|
||||||
resolved "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz"
|
"resolved" "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz"
|
||||||
integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
|
"version" "5.2.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
history "^4.9.0"
|
"history" "^4.9.0"
|
||||||
hoist-non-react-statics "^3.1.0"
|
"hoist-non-react-statics" "^3.1.0"
|
||||||
loose-envify "^1.3.1"
|
"loose-envify" "^1.3.1"
|
||||||
mini-create-react-context "^0.4.0"
|
"mini-create-react-context" "^0.4.0"
|
||||||
path-to-regexp "^1.7.0"
|
"path-to-regexp" "^1.7.0"
|
||||||
prop-types "^15.6.2"
|
"prop-types" "^15.6.2"
|
||||||
react-is "^16.6.0"
|
"react-is" "^16.6.0"
|
||||||
tiny-invariant "^1.0.2"
|
"tiny-invariant" "^1.0.2"
|
||||||
tiny-warning "^1.0.0"
|
"tiny-warning" "^1.0.0"
|
||||||
|
|
||||||
"react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", react@^17.0.2, "react@>= 16.8.0", react@>=15, react@>=16, react@17.0.2:
|
"react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^17.0.2", "react@>= 16.8.0", "react@>=15", "react@>=16", "react@17.0.2":
|
||||||
version "17.0.2"
|
"integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="
|
||||||
resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
|
"resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
|
||||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
"version" "17.0.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
"loose-envify" "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
"object-assign" "^4.1.1"
|
||||||
|
|
||||||
regenerator-runtime@^0.13.4:
|
"regenerator-runtime@^0.13.4":
|
||||||
version "0.13.9"
|
"integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz"
|
"resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz"
|
||||||
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
|
"version" "0.13.9"
|
||||||
|
|
||||||
resolve-pathname@^3.0.0:
|
"resolve-pathname@^3.0.0":
|
||||||
version "3.0.0"
|
"integrity" "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
|
||||||
resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz"
|
||||||
integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
|
"version" "3.0.0"
|
||||||
|
|
||||||
scheduler@^0.20.2:
|
"scheduler@^0.20.2":
|
||||||
version "0.20.2"
|
"integrity" "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ=="
|
||||||
resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz"
|
"resolved" "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz"
|
||||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
"version" "0.20.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
"loose-envify" "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
"object-assign" "^4.1.1"
|
||||||
|
|
||||||
shallowequal@^1.1.0:
|
"shallowequal@^1.1.0":
|
||||||
version "1.1.0"
|
"integrity" "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||||
resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz"
|
"resolved" "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz"
|
||||||
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
"version" "1.1.0"
|
||||||
|
|
||||||
source-map@^0.5.0:
|
"source-map@^0.5.0":
|
||||||
version "0.5.7"
|
"integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||||
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
|
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
|
||||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
"version" "0.5.7"
|
||||||
|
|
||||||
styled-components@^5.3.0, "styled-components@>= 2":
|
"styled-components@^5.3.0", "styled-components@>= 2":
|
||||||
version "5.3.3"
|
"integrity" "sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw=="
|
||||||
resolved "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz"
|
"resolved" "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz"
|
||||||
integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==
|
"version" "5.3.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-module-imports" "^7.0.0"
|
"@babel/helper-module-imports" "^7.0.0"
|
||||||
"@babel/traverse" "^7.4.5"
|
"@babel/traverse" "^7.4.5"
|
||||||
"@emotion/is-prop-valid" "^0.8.8"
|
"@emotion/is-prop-valid" "^0.8.8"
|
||||||
"@emotion/stylis" "^0.8.4"
|
"@emotion/stylis" "^0.8.4"
|
||||||
"@emotion/unitless" "^0.7.4"
|
"@emotion/unitless" "^0.7.4"
|
||||||
babel-plugin-styled-components ">= 1.12.0"
|
"babel-plugin-styled-components" ">= 1.12.0"
|
||||||
css-to-react-native "^3.0.0"
|
"css-to-react-native" "^3.0.0"
|
||||||
hoist-non-react-statics "^3.0.0"
|
"hoist-non-react-statics" "^3.0.0"
|
||||||
shallowequal "^1.1.0"
|
"shallowequal" "^1.1.0"
|
||||||
supports-color "^5.5.0"
|
"supports-color" "^5.5.0"
|
||||||
|
|
||||||
supports-color@^5.3.0, supports-color@^5.5.0:
|
"supports-color@^5.3.0", "supports-color@^5.5.0":
|
||||||
version "5.5.0"
|
"integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
"resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
||||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
"version" "5.5.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^3.0.0"
|
"has-flag" "^3.0.0"
|
||||||
|
|
||||||
tiny-invariant@^1.0.2:
|
"tiny-invariant@^1.0.2":
|
||||||
version "1.1.0"
|
"integrity" "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
|
||||||
resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz"
|
"resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz"
|
||||||
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
|
"version" "1.1.0"
|
||||||
|
|
||||||
tiny-warning@^1.0.0, tiny-warning@^1.0.3:
|
"tiny-warning@^1.0.0", "tiny-warning@^1.0.3":
|
||||||
version "1.0.3"
|
"integrity" "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
|
||||||
resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz"
|
"resolved" "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz"
|
||||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
"version" "1.0.3"
|
||||||
|
|
||||||
to-fast-properties@^2.0.0:
|
"to-fast-properties@^2.0.0":
|
||||||
version "2.0.0"
|
"integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
|
||||||
resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
|
"resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
|
||||||
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
"version" "2.0.0"
|
||||||
|
|
||||||
tr46@~0.0.3:
|
"tr46@~0.0.3":
|
||||||
version "0.0.3"
|
"integrity" "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz"
|
"resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz"
|
||||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
"version" "0.0.3"
|
||||||
|
|
||||||
typescript@^4.3.5:
|
"typescript@^4.3.5":
|
||||||
version "4.3.5"
|
"integrity" "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz"
|
"resolved" "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz"
|
||||||
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
|
"version" "4.3.5"
|
||||||
|
|
||||||
value-equal@^1.0.1:
|
"value-equal@^1.0.1":
|
||||||
version "1.0.1"
|
"integrity" "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
|
||||||
resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz"
|
"resolved" "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz"
|
||||||
integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
|
"version" "1.0.1"
|
||||||
|
|
||||||
webidl-conversions@^3.0.0:
|
"webidl-conversions@^3.0.0":
|
||||||
version "3.0.1"
|
"integrity" "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
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 sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
"version" "3.0.1"
|
||||||
|
|
||||||
whatwg-url@^5.0.0:
|
"whatwg-url@^5.0.0":
|
||||||
version "5.0.0"
|
"integrity" "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="
|
||||||
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 sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
"version" "5.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
tr46 "~0.0.3"
|
"tr46" "~0.0.3"
|
||||||
webidl-conversions "^3.0.0"
|
"webidl-conversions" "^3.0.0"
|
||||||
|
1154
dashboard/package-lock.json
generated
1154
dashboard/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -126,6 +126,22 @@ const EmailConfigurations = ({
|
|||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Sender Name:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SENDER_NAME}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -8,86 +8,90 @@ const Features = ({ variables, setVariables }: any) => {
|
|||||||
<div>
|
<div>
|
||||||
{' '}
|
{' '}
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
Disable Features
|
Features
|
||||||
</Text>
|
</Text>
|
||||||
<Stack spacing={6}>
|
<Stack spacing={6}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Login Page:</Text>
|
<Text fontSize="sm">Login Page:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start">
|
<Flex justifyContent="start">
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Email Verification:</Text>
|
<Text fontSize="sm">Email Verification:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start">
|
<Flex justifyContent="start">
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Magic Login Link:</Text>
|
<Text fontSize="sm">Magic Login Link:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start">
|
<Flex justifyContent="start">
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Basic Authentication:</Text>
|
<Text fontSize="sm">Basic Authentication:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start">
|
<Flex justifyContent="start">
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Sign Up:</Text>
|
<Text fontSize="sm">Sign Up:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start" mb={3}>
|
<Flex justifyContent="start" mb={3}>
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="100%" justifyContent="start" alignItems="center">
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">Disable Strong Password:</Text>
|
<Text fontSize="sm">Strong Password:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="start" mb={3}>
|
<Flex justifyContent="start" mb={3}>
|
||||||
<InputField
|
<InputField
|
||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_STRONG_PASSWORD}
|
inputType={SwitchInputType.DISABLE_STRONG_PASSWORD}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
<Flex w="100%" alignItems="baseline" flexDir="column">
|
<Flex w="100%" alignItems="baseline" flexDir="column">
|
||||||
<Text fontSize="sm">
|
<Text fontSize="sm">Multi Factor Authentication (MFA):</Text>
|
||||||
Disable Multi Factor Authentication (MFA):
|
|
||||||
</Text>
|
|
||||||
<Text fontSize="x-small">
|
<Text fontSize="x-small">
|
||||||
Note: Enabling this will ignore Enforcing MFA shown below and will
|
Note: Enabling this will ignore Enforcing MFA shown below and will
|
||||||
also ignore the user MFA setting.
|
also ignore the user MFA setting.
|
||||||
@@ -98,15 +102,10 @@ const Features = ({ variables, setVariables }: any) => {
|
|||||||
variables={variables}
|
variables={variables}
|
||||||
setVariables={setVariables}
|
setVariables={setVariables}
|
||||||
inputType={SwitchInputType.DISABLE_MULTI_FACTOR_AUTHENTICATION}
|
inputType={SwitchInputType.DISABLE_MULTI_FACTOR_AUTHENTICATION}
|
||||||
|
hasReversedValue
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Stack>
|
|
||||||
<Divider paddingY={5} />
|
|
||||||
<Text fontSize="md" paddingTop={5} fontWeight="bold" mb={5}>
|
|
||||||
Enable Features
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6}>
|
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
<Flex w="100%" alignItems="baseline" flexDir="column">
|
<Flex w="100%" alignItems="baseline" flexDir="column">
|
||||||
<Text fontSize="sm">
|
<Text fontSize="sm">
|
||||||
|
@@ -48,6 +48,8 @@ const InputField = ({
|
|||||||
fieldVisibility,
|
fieldVisibility,
|
||||||
setFieldVisibility,
|
setFieldVisibility,
|
||||||
availableRoles,
|
availableRoles,
|
||||||
|
// This prop is added to improve the user experience for the boolean ENV variable having `DISABLE_` prefix, as those values need to be considered in inverted form.
|
||||||
|
hasReversedValue,
|
||||||
...downshiftProps
|
...downshiftProps
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const props = {
|
const props = {
|
||||||
@@ -398,7 +400,9 @@ const InputField = ({
|
|||||||
</Text>
|
</Text>
|
||||||
<Switch
|
<Switch
|
||||||
size="md"
|
size="md"
|
||||||
isChecked={variables[inputType]}
|
isChecked={
|
||||||
|
hasReversedValue ? !variables[inputType] : variables[inputType]
|
||||||
|
}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
setVariables({
|
setVariables({
|
||||||
...variables,
|
...variables,
|
||||||
|
@@ -19,6 +19,7 @@ export const TextInputType = {
|
|||||||
SMTP_USERNAME: 'SMTP_USERNAME',
|
SMTP_USERNAME: 'SMTP_USERNAME',
|
||||||
SMTP_LOCAL_NAME: 'SMTP_LOCAL_NAME',
|
SMTP_LOCAL_NAME: 'SMTP_LOCAL_NAME',
|
||||||
SENDER_EMAIL: 'SENDER_EMAIL',
|
SENDER_EMAIL: 'SENDER_EMAIL',
|
||||||
|
SENDER_NAME: 'SENDER_NAME',
|
||||||
ORGANIZATION_NAME: 'ORGANIZATION_NAME',
|
ORGANIZATION_NAME: 'ORGANIZATION_NAME',
|
||||||
ORGANIZATION_LOGO: 'ORGANIZATION_LOGO',
|
ORGANIZATION_LOGO: 'ORGANIZATION_LOGO',
|
||||||
DATABASE_NAME: 'DATABASE_NAME',
|
DATABASE_NAME: 'DATABASE_NAME',
|
||||||
@@ -143,6 +144,7 @@ export interface envVarTypes {
|
|||||||
SMTP_PASSWORD: string;
|
SMTP_PASSWORD: string;
|
||||||
SMTP_LOCAL_NAME: string;
|
SMTP_LOCAL_NAME: string;
|
||||||
SENDER_EMAIL: string;
|
SENDER_EMAIL: string;
|
||||||
|
SENDER_NAME: string;
|
||||||
ALLOWED_ORIGINS: [string] | [];
|
ALLOWED_ORIGINS: [string] | [];
|
||||||
ORGANIZATION_NAME: string;
|
ORGANIZATION_NAME: string;
|
||||||
ORGANIZATION_LOGO: string;
|
ORGANIZATION_LOGO: string;
|
||||||
|
@@ -50,6 +50,7 @@ export const EnvVariablesQuery = `
|
|||||||
SMTP_PASSWORD
|
SMTP_PASSWORD
|
||||||
SMTP_LOCAL_NAME
|
SMTP_LOCAL_NAME
|
||||||
SENDER_EMAIL
|
SENDER_EMAIL
|
||||||
|
SENDER_NAME
|
||||||
ALLOWED_ORIGINS
|
ALLOWED_ORIGINS
|
||||||
ORGANIZATION_NAME
|
ORGANIZATION_NAME
|
||||||
ORGANIZATION_LOGO
|
ORGANIZATION_LOGO
|
||||||
|
@@ -70,6 +70,7 @@ const Environment = () => {
|
|||||||
SMTP_PASSWORD: '',
|
SMTP_PASSWORD: '',
|
||||||
SMTP_LOCAL_NAME: '',
|
SMTP_LOCAL_NAME: '',
|
||||||
SENDER_EMAIL: '',
|
SENDER_EMAIL: '',
|
||||||
|
SENDER_NAME: '',
|
||||||
ALLOWED_ORIGINS: [],
|
ALLOWED_ORIGINS: [],
|
||||||
ORGANIZATION_NAME: '',
|
ORGANIZATION_NAME: '',
|
||||||
ORGANIZATION_LOGO: '',
|
ORGANIZATION_LOGO: '',
|
||||||
|
2781
dashboard/yarn.lock
2781
dashboard/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@ const (
|
|||||||
AuthRecipeMethodMobileBasicAuth = "mobile_basic_auth"
|
AuthRecipeMethodMobileBasicAuth = "mobile_basic_auth"
|
||||||
// AuthRecipeMethodMagicLinkLogin is the magic_link_login auth method
|
// AuthRecipeMethodMagicLinkLogin is the magic_link_login auth method
|
||||||
AuthRecipeMethodMagicLinkLogin = "magic_link_login"
|
AuthRecipeMethodMagicLinkLogin = "magic_link_login"
|
||||||
|
// AuthRecipeMethodMobileOTP is the mobile_otp auth method
|
||||||
|
AuthRecipeMethodMobileOTP = "mobile_otp"
|
||||||
// AuthRecipeMethodGoogle is the google auth method
|
// AuthRecipeMethodGoogle is the google auth method
|
||||||
AuthRecipeMethodGoogle = "google"
|
AuthRecipeMethodGoogle = "google"
|
||||||
// AuthRecipeMethodGithub is the github auth method
|
// AuthRecipeMethodGithub is the github auth method
|
||||||
|
@@ -62,8 +62,12 @@ const (
|
|||||||
EnvKeySmtpLocalName = "SMTP_LOCAL_NAME"
|
EnvKeySmtpLocalName = "SMTP_LOCAL_NAME"
|
||||||
// EnvKeySenderEmail key for env variable SENDER_EMAIL
|
// EnvKeySenderEmail key for env variable SENDER_EMAIL
|
||||||
EnvKeySenderEmail = "SENDER_EMAIL"
|
EnvKeySenderEmail = "SENDER_EMAIL"
|
||||||
|
// EnvKeySenderName key for env variable SENDER_NAME
|
||||||
|
EnvKeySenderName = "SENDER_NAME"
|
||||||
// EnvKeyIsEmailServiceEnabled key for env variable IS_EMAIL_SERVICE_ENABLED
|
// EnvKeyIsEmailServiceEnabled key for env variable IS_EMAIL_SERVICE_ENABLED
|
||||||
EnvKeyIsEmailServiceEnabled = "IS_EMAIL_SERVICE_ENABLED"
|
EnvKeyIsEmailServiceEnabled = "IS_EMAIL_SERVICE_ENABLED"
|
||||||
|
// EnvKeyIsSMSServiceEnabled key for env variable IS_SMS_SERVICE_ENABLED
|
||||||
|
EnvKeyIsSMSServiceEnabled = "IS_SMS_SERVICE_ENABLED"
|
||||||
// EnvKeyAppCookieSecure key for env variable APP_COOKIE_SECURE
|
// EnvKeyAppCookieSecure key for env variable APP_COOKIE_SECURE
|
||||||
EnvKeyAppCookieSecure = "APP_COOKIE_SECURE"
|
EnvKeyAppCookieSecure = "APP_COOKIE_SECURE"
|
||||||
// EnvKeyAdminCookieSecure key for env variable ADMIN_COOKIE_SECURE
|
// EnvKeyAdminCookieSecure key for env variable ADMIN_COOKIE_SECURE
|
||||||
@@ -156,6 +160,9 @@ const (
|
|||||||
// EnvKeyDisableMultiFactorAuthentication is key for env variable DISABLE_MULTI_FACTOR_AUTHENTICATION
|
// EnvKeyDisableMultiFactorAuthentication is key for env variable DISABLE_MULTI_FACTOR_AUTHENTICATION
|
||||||
// this variable is used to completely disable multi factor authentication. It will have no effect on profile preference
|
// this variable is used to completely disable multi factor authentication. It will have no effect on profile preference
|
||||||
EnvKeyDisableMultiFactorAuthentication = "DISABLE_MULTI_FACTOR_AUTHENTICATION"
|
EnvKeyDisableMultiFactorAuthentication = "DISABLE_MULTI_FACTOR_AUTHENTICATION"
|
||||||
|
// EnvKeyDisablePhoneVerification is key for env variable DISABLE_PHONE_VERIFICATION
|
||||||
|
// this variable is used to disable phone verification
|
||||||
|
EnvKeyDisablePhoneVerification = "DISABLE_PHONE_VERIFICATION"
|
||||||
|
|
||||||
// Slice variables
|
// Slice variables
|
||||||
// EnvKeyRoles key for env variable ROLES
|
// EnvKeyRoles key for env variable ROLES
|
||||||
@@ -174,4 +181,14 @@ const (
|
|||||||
// EnvKeyDefaultAuthorizeResponseMode key for env variable DEFAULT_AUTHORIZE_RESPONSE_MODE
|
// EnvKeyDefaultAuthorizeResponseMode key for env variable DEFAULT_AUTHORIZE_RESPONSE_MODE
|
||||||
// This env is used for setting default response mode in authorize handler
|
// This env is used for setting default response mode in authorize handler
|
||||||
EnvKeyDefaultAuthorizeResponseMode = "DEFAULT_AUTHORIZE_RESPONSE_MODE"
|
EnvKeyDefaultAuthorizeResponseMode = "DEFAULT_AUTHORIZE_RESPONSE_MODE"
|
||||||
|
|
||||||
|
// Twilio env variables
|
||||||
|
// EnvKeyTwilioAPIKey key for env variable TWILIO_API_KEY
|
||||||
|
EnvKeyTwilioAPIKey = "TWILIO_API_KEY"
|
||||||
|
// EnvKeyTwilioAPISecret key for env variable TWILIO_API_SECRET
|
||||||
|
EnvKeyTwilioAPISecret = "TWILIO_API_SECRET"
|
||||||
|
// EnvKeyTwilioAccountSID key for env variable TWILIO_ACCOUNT_SID
|
||||||
|
EnvKeyTwilioAccountSID = "TWILIO_ACCOUNT_SID"
|
||||||
|
// EnvKeyTwilioSender key for env variable TWILIO_SENDER
|
||||||
|
EnvKeyTwilioSender = "TWILIO_SENDER"
|
||||||
)
|
)
|
||||||
|
@@ -2,14 +2,15 @@ package models
|
|||||||
|
|
||||||
// Collections / Tables available for authorizer in the database
|
// Collections / Tables available for authorizer in the database
|
||||||
type CollectionList struct {
|
type CollectionList struct {
|
||||||
User string
|
User string
|
||||||
VerificationRequest string
|
VerificationRequest string
|
||||||
Session string
|
Session string
|
||||||
Env string
|
Env string
|
||||||
Webhook string
|
Webhook string
|
||||||
WebhookLog string
|
WebhookLog string
|
||||||
EmailTemplate string
|
EmailTemplate string
|
||||||
OTP string
|
OTP string
|
||||||
|
SMSVerificationRequest string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -17,13 +18,14 @@ var (
|
|||||||
Prefix = "authorizer_"
|
Prefix = "authorizer_"
|
||||||
// Collections / Tables available for authorizer in the database (used for dbs other than gorm)
|
// Collections / Tables available for authorizer in the database (used for dbs other than gorm)
|
||||||
Collections = CollectionList{
|
Collections = CollectionList{
|
||||||
User: Prefix + "users",
|
User: Prefix + "users",
|
||||||
VerificationRequest: Prefix + "verification_requests",
|
VerificationRequest: Prefix + "verification_requests",
|
||||||
Session: Prefix + "sessions",
|
Session: Prefix + "sessions",
|
||||||
Env: Prefix + "env",
|
Env: Prefix + "env",
|
||||||
Webhook: Prefix + "webhooks",
|
Webhook: Prefix + "webhooks",
|
||||||
WebhookLog: Prefix + "webhook_logs",
|
WebhookLog: Prefix + "webhook_logs",
|
||||||
EmailTemplate: Prefix + "email_templates",
|
EmailTemplate: Prefix + "email_templates",
|
||||||
OTP: Prefix + "otps",
|
OTP: Prefix + "otps",
|
||||||
|
SMSVerificationRequest: Prefix + "sms_verification_requests",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -1,14 +1,22 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FieldName email is the field name for email
|
||||||
|
FieldNameEmail = "email"
|
||||||
|
// FieldNamePhoneNumber is the field name for phone number
|
||||||
|
FieldNamePhoneNumber = "phone_number"
|
||||||
|
)
|
||||||
|
|
||||||
// OTP model for database
|
// OTP model for database
|
||||||
type OTP struct {
|
type OTP struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"`
|
||||||
Email string `gorm:"unique" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"`
|
Email string `gorm:"unique" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"`
|
||||||
Otp string `json:"otp" bson:"otp" cql:"otp" dynamo:"otp"`
|
PhoneNumber string `gorm:"index:unique_index_phone_number,unique" json:"phone_number" bson:"phone_number" cql:"phone_number" dynamo:"phone_number"`
|
||||||
ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at" dynamo:"expires_at"`
|
Otp string `json:"otp" bson:"otp" cql:"otp" dynamo:"otp"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"`
|
ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at" dynamo:"expires_at"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at" dynamo:"updated_at"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at" dynamo:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Paging struct {
|
type Paging struct {
|
||||||
|
@@ -2,6 +2,7 @@ package arangodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -12,17 +13,31 @@ import (
|
|||||||
|
|
||||||
// UpsertOTP to add or update otp
|
// UpsertOTP to add or update otp
|
||||||
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
||||||
otp, _ := p.GetOTPByEmail(ctx, otpParam.Email)
|
// check if email or phone number is present
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if uniqueField == models.FieldNameEmail {
|
||||||
|
otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
|
||||||
|
} else {
|
||||||
|
otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
|
||||||
|
}
|
||||||
shouldCreate := false
|
shouldCreate := false
|
||||||
if otp == nil {
|
if otp == nil {
|
||||||
id := uuid.NewString()
|
id := uuid.NewString()
|
||||||
otp = &models.OTP{
|
otp = &models.OTP{
|
||||||
ID: id,
|
ID: id,
|
||||||
Key: id,
|
Key: id,
|
||||||
Otp: otpParam.Otp,
|
Otp: otpParam.Otp,
|
||||||
Email: otpParam.Email,
|
Email: otpParam.Email,
|
||||||
ExpiresAt: otpParam.ExpiresAt,
|
PhoneNumber: otpParam.PhoneNumber,
|
||||||
CreatedAt: time.Now().Unix(),
|
ExpiresAt: otpParam.ExpiresAt,
|
||||||
|
CreatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
shouldCreate = true
|
shouldCreate = true
|
||||||
} else {
|
} else {
|
||||||
@@ -67,7 +82,35 @@ func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*mod
|
|||||||
for {
|
for {
|
||||||
if !cursor.HasMore() {
|
if !cursor.HasMore() {
|
||||||
if otp.Key == "" {
|
if otp.Key == "" {
|
||||||
return nil, fmt.Errorf("email template not found")
|
return nil, fmt.Errorf("otp with given email not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &otp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
var otp models.OTP
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d.phone_number == @phone_number RETURN d", models.Collections.OTP)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"phone_number": phoneNumber,
|
||||||
|
}
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if otp.Key == "" {
|
||||||
|
return nil, fmt.Errorf("otp with given phone_number not found")
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -225,16 +225,14 @@ func NewProvider() (*provider, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
otpCollection, err := arangodb.Collection(ctx, models.Collections.OTP)
|
otpCollection, err := arangodb.Collection(ctx, models.Collections.OTP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
otpCollection.EnsureHashIndex(ctx, []string{"email"}, &arangoDriver.EnsureHashIndexOptions{
|
otpCollection.EnsureHashIndex(ctx, []string{models.FieldNameEmail, models.FieldNamePhoneNumber}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Sparse: true,
|
Sparse: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: arangodb,
|
db: arangodb,
|
||||||
}, err
|
}, err
|
||||||
|
@@ -2,6 +2,7 @@ package cassandradb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -12,17 +13,31 @@ import (
|
|||||||
|
|
||||||
// UpsertOTP to add or update otp
|
// UpsertOTP to add or update otp
|
||||||
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
||||||
otp, _ := p.GetOTPByEmail(ctx, otpParam.Email)
|
// check if email or phone number is present
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if uniqueField == models.FieldNameEmail {
|
||||||
|
otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
|
||||||
|
} else {
|
||||||
|
otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
|
||||||
|
}
|
||||||
shouldCreate := false
|
shouldCreate := false
|
||||||
if otp == nil {
|
if otp == nil {
|
||||||
shouldCreate = true
|
shouldCreate = true
|
||||||
otp = &models.OTP{
|
otp = &models.OTP{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
Otp: otpParam.Otp,
|
Otp: otpParam.Otp,
|
||||||
Email: otpParam.Email,
|
Email: otpParam.Email,
|
||||||
ExpiresAt: otpParam.ExpiresAt,
|
PhoneNumber: otpParam.PhoneNumber,
|
||||||
CreatedAt: time.Now().Unix(),
|
ExpiresAt: otpParam.ExpiresAt,
|
||||||
UpdatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
|
UpdatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
otp.Otp = otpParam.Otp
|
otp.Otp = otpParam.Otp
|
||||||
@@ -32,7 +47,7 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
otp.UpdatedAt = time.Now().Unix()
|
otp.UpdatedAt = time.Now().Unix()
|
||||||
query := ""
|
query := ""
|
||||||
if shouldCreate {
|
if shouldCreate {
|
||||||
query = fmt.Sprintf(`INSERT INTO %s (id, email, otp, expires_at, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, %d, %d)`, KeySpace+"."+models.Collections.OTP, otp.ID, otp.Email, otp.Otp, otp.ExpiresAt, otp.CreatedAt, otp.UpdatedAt)
|
query = fmt.Sprintf(`INSERT INTO %s (id, email, phone_number, otp, expires_at, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)`, KeySpace+"."+models.Collections.OTP, otp.ID, otp.Email, otp.PhoneNumber, otp.Otp, otp.ExpiresAt, otp.CreatedAt, otp.UpdatedAt)
|
||||||
} else {
|
} else {
|
||||||
query = fmt.Sprintf(`UPDATE %s SET otp = '%s', expires_at = %d, updated_at = %d WHERE id = '%s'`, KeySpace+"."+models.Collections.OTP, otp.Otp, otp.ExpiresAt, otp.UpdatedAt, otp.ID)
|
query = fmt.Sprintf(`UPDATE %s SET otp = '%s', expires_at = %d, updated_at = %d WHERE id = '%s'`, KeySpace+"."+models.Collections.OTP, otp.Otp, otp.ExpiresAt, otp.UpdatedAt, otp.ID)
|
||||||
}
|
}
|
||||||
@@ -48,8 +63,19 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
// GetOTPByEmail to get otp for a given email address
|
// GetOTPByEmail to get otp for a given email address
|
||||||
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
||||||
var otp models.OTP
|
var otp models.OTP
|
||||||
query := fmt.Sprintf(`SELECT id, email, otp, expires_at, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.OTP, emailAddress)
|
query := fmt.Sprintf(`SELECT id, email, phone_number, otp, expires_at, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.OTP, emailAddress)
|
||||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&otp.ID, &otp.Email, &otp.Otp, &otp.ExpiresAt, &otp.CreatedAt, &otp.UpdatedAt)
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&otp.ID, &otp.Email, &otp.PhoneNumber, &otp.Otp, &otp.ExpiresAt, &otp.CreatedAt, &otp.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
var otp models.OTP
|
||||||
|
query := fmt.Sprintf(`SELECT id, email, phone_number, otp, expires_at, created_at, updated_at FROM %s WHERE phone_number = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.OTP, phoneNumber)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&otp.ID, &otp.Email, &otp.PhoneNumber, &otp.Otp, &otp.ExpiresAt, &otp.CreatedAt, &otp.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -254,7 +254,19 @@ func NewProvider() (*provider, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Add phone_number column to otp table
|
||||||
|
otpAlterQuery := fmt.Sprintf(`ALTER TABLE %s.%s ADD (phone_number text);`, KeySpace, models.Collections.OTP)
|
||||||
|
err = session.Query(otpAlterQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to alter table as column exists: ", err)
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
// Add phone number index
|
||||||
|
otpIndexQueryPhoneNumber := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_otp_phone_number ON %s.%s (phone_number)", KeySpace, models.Collections.OTP)
|
||||||
|
err = session.Query(otpIndexQueryPhoneNumber).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &provider{
|
return &provider{
|
||||||
db: session,
|
db: session,
|
||||||
}, err
|
}, err
|
||||||
|
@@ -2,6 +2,7 @@ package couchbase
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -12,24 +13,36 @@ import (
|
|||||||
|
|
||||||
// UpsertOTP to add or update otp
|
// UpsertOTP to add or update otp
|
||||||
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
||||||
otp, _ := p.GetOTPByEmail(ctx, otpParam.Email)
|
// check if email or phone number is present
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if uniqueField == models.FieldNameEmail {
|
||||||
|
otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
|
||||||
|
} else {
|
||||||
|
otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
|
||||||
|
}
|
||||||
shouldCreate := false
|
shouldCreate := false
|
||||||
if otp == nil {
|
if otp == nil {
|
||||||
shouldCreate = true
|
shouldCreate = true
|
||||||
otp = &models.OTP{
|
otp = &models.OTP{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
Otp: otpParam.Otp,
|
Otp: otpParam.Otp,
|
||||||
Email: otpParam.Email,
|
Email: otpParam.Email,
|
||||||
ExpiresAt: otpParam.ExpiresAt,
|
PhoneNumber: otpParam.PhoneNumber,
|
||||||
CreatedAt: time.Now().Unix(),
|
ExpiresAt: otpParam.ExpiresAt,
|
||||||
UpdatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
|
UpdatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
otp.Otp = otpParam.Otp
|
otp.Otp = otpParam.Otp
|
||||||
otp.ExpiresAt = otpParam.ExpiresAt
|
otp.ExpiresAt = otpParam.ExpiresAt
|
||||||
}
|
}
|
||||||
|
|
||||||
otp.UpdatedAt = time.Now().Unix()
|
otp.UpdatedAt = time.Now().Unix()
|
||||||
if shouldCreate {
|
if shouldCreate {
|
||||||
insertOpt := gocb.InsertOptions{
|
insertOpt := gocb.InsertOptions{
|
||||||
@@ -54,7 +67,7 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
// GetOTPByEmail to get otp for a given email address
|
// GetOTPByEmail to get otp for a given email address
|
||||||
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
||||||
otp := models.OTP{}
|
otp := models.OTP{}
|
||||||
query := fmt.Sprintf(`SELECT _id, email, otp, expires_at, created_at, updated_at FROM %s.%s WHERE email = $1 LIMIT 1`, p.scopeName, models.Collections.OTP)
|
query := fmt.Sprintf(`SELECT _id, email, phone_number, otp, expires_at, created_at, updated_at FROM %s.%s WHERE email = $1 LIMIT 1`, p.scopeName, models.Collections.OTP)
|
||||||
q, err := p.db.Query(query, &gocb.QueryOptions{
|
q, err := p.db.Query(query, &gocb.QueryOptions{
|
||||||
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
||||||
PositionalParameters: []interface{}{emailAddress},
|
PositionalParameters: []interface{}{emailAddress},
|
||||||
@@ -63,11 +76,27 @@ func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*mod
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = q.One(&otp)
|
err = q.One(&otp)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
otp := models.OTP{}
|
||||||
|
query := fmt.Sprintf(`SELECT _id, email, phone_number, otp, expires_at, created_at, updated_at FROM %s.%s WHERE phone_number = $1 LIMIT 1`, p.scopeName, models.Collections.OTP)
|
||||||
|
q, err := p.db.Query(query, &gocb.QueryOptions{
|
||||||
|
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
||||||
|
PositionalParameters: []interface{}{phoneNumber},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = q.One(&otp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &otp, nil
|
return &otp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -166,5 +166,9 @@ func GetIndex(scopeName string) map[string][]string {
|
|||||||
otpIndex1 := fmt.Sprintf("CREATE INDEX OTPEmailIndex ON %s.%s(email)", scopeName, models.Collections.OTP)
|
otpIndex1 := fmt.Sprintf("CREATE INDEX OTPEmailIndex ON %s.%s(email)", scopeName, models.Collections.OTP)
|
||||||
indices[models.Collections.OTP] = []string{otpIndex1}
|
indices[models.Collections.OTP] = []string{otpIndex1}
|
||||||
|
|
||||||
|
// OTP index
|
||||||
|
otpIndex2 := fmt.Sprintf("CREATE INDEX OTPPhoneNumberIndex ON %s.%s(phone_number)", scopeName, models.Collections.OTP)
|
||||||
|
indices[models.Collections.OTP] = []string{otpIndex2}
|
||||||
|
|
||||||
return indices
|
return indices
|
||||||
}
|
}
|
||||||
|
@@ -11,24 +11,19 @@ import (
|
|||||||
|
|
||||||
func GetSetFields(webhookMap map[string]interface{}) (string, map[string]interface{}) {
|
func GetSetFields(webhookMap map[string]interface{}) (string, map[string]interface{}) {
|
||||||
params := make(map[string]interface{}, 1)
|
params := make(map[string]interface{}, 1)
|
||||||
|
|
||||||
updateFields := ""
|
updateFields := ""
|
||||||
|
|
||||||
for key, value := range webhookMap {
|
for key, value := range webhookMap {
|
||||||
if key == "_id" {
|
if key == "_id" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == "_key" {
|
if key == "_key" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
updateFields += fmt.Sprintf("%s=$%s,", key, key)
|
updateFields += fmt.Sprintf("%s=$%s,", key, key)
|
||||||
params[key] = "null"
|
params[key] = "null"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
valueType := reflect.TypeOf(value)
|
valueType := reflect.TypeOf(value)
|
||||||
if valueType.Name() == "string" {
|
if valueType.Name() == "string" {
|
||||||
updateFields += fmt.Sprintf("%s = $%s, ", key, key)
|
updateFields += fmt.Sprintf("%s = $%s, ", key, key)
|
||||||
|
@@ -11,27 +11,39 @@ import (
|
|||||||
|
|
||||||
// UpsertOTP to add or update otp
|
// UpsertOTP to add or update otp
|
||||||
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
||||||
otp, _ := p.GetOTPByEmail(ctx, otpParam.Email)
|
// check if email or phone number is present
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if uniqueField == models.FieldNameEmail {
|
||||||
|
otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
|
||||||
|
} else {
|
||||||
|
otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
|
||||||
|
}
|
||||||
shouldCreate := false
|
shouldCreate := false
|
||||||
if otp == nil {
|
if otp == nil {
|
||||||
id := uuid.NewString()
|
id := uuid.NewString()
|
||||||
otp = &models.OTP{
|
otp = &models.OTP{
|
||||||
ID: id,
|
ID: id,
|
||||||
Key: id,
|
Key: id,
|
||||||
Otp: otpParam.Otp,
|
Otp: otpParam.Otp,
|
||||||
Email: otpParam.Email,
|
Email: otpParam.Email,
|
||||||
ExpiresAt: otpParam.ExpiresAt,
|
PhoneNumber: otpParam.PhoneNumber,
|
||||||
CreatedAt: time.Now().Unix(),
|
ExpiresAt: otpParam.ExpiresAt,
|
||||||
|
CreatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
shouldCreate = true
|
shouldCreate = true
|
||||||
} else {
|
} else {
|
||||||
otp.Otp = otpParam.Otp
|
otp.Otp = otpParam.Otp
|
||||||
otp.ExpiresAt = otpParam.ExpiresAt
|
otp.ExpiresAt = otpParam.ExpiresAt
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := p.db.Table(models.Collections.OTP)
|
collection := p.db.Table(models.Collections.OTP)
|
||||||
otp.UpdatedAt = time.Now().Unix()
|
otp.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if shouldCreate {
|
if shouldCreate {
|
||||||
err = collection.Put(otp).RunWithContext(ctx)
|
err = collection.Put(otp).RunWithContext(ctx)
|
||||||
@@ -41,7 +53,6 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return otp, nil
|
return otp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,20 +60,32 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
||||||
var otps []models.OTP
|
var otps []models.OTP
|
||||||
var otp models.OTP
|
var otp models.OTP
|
||||||
|
|
||||||
collection := p.db.Table(models.Collections.OTP)
|
collection := p.db.Table(models.Collections.OTP)
|
||||||
|
|
||||||
err := collection.Scan().Index("email").Filter("'email' = ?", emailAddress).Limit(1).AllWithContext(ctx, &otps)
|
err := collection.Scan().Index("email").Filter("'email' = ?", emailAddress).Limit(1).AllWithContext(ctx, &otps)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(otps) > 0 {
|
if len(otps) > 0 {
|
||||||
otp = otps[0]
|
otp = otps[0]
|
||||||
return &otp, nil
|
return &otp, nil
|
||||||
} else {
|
|
||||||
return nil, errors.New("no docuemnt found")
|
|
||||||
}
|
}
|
||||||
|
return nil, errors.New("no docuemnt found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
var otps []models.OTP
|
||||||
|
var otp models.OTP
|
||||||
|
collection := p.db.Table(models.Collections.OTP)
|
||||||
|
err := collection.Scan().Filter("'phone_number' = ?", phoneNumber).Limit(1).AllWithContext(ctx, &otps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(otps) > 0 {
|
||||||
|
otp = otps[0]
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("no docuemnt found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOTP to delete otp
|
// DeleteOTP to delete otp
|
||||||
@@ -75,6 +98,5 @@ func (p *provider) DeleteOTP(ctx context.Context, otp *models.OTP) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -31,11 +31,11 @@ func NewProvider() (*provider, error) {
|
|||||||
if awsRegion != "" {
|
if awsRegion != "" {
|
||||||
config.Region = aws.String(awsRegion)
|
config.Region = aws.String(awsRegion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom awsAccessKeyID, awsSecretAccessKey took first priority, if not then fetch config from aws credentials
|
// custom awsAccessKeyID, awsSecretAccessKey took first priority, if not then fetch config from aws credentials
|
||||||
if awsAccessKeyID != "" && awsSecretAccessKey != "" {
|
if awsAccessKeyID != "" && awsSecretAccessKey != "" {
|
||||||
config.Credentials = credentials.NewStaticCredentials(awsAccessKeyID, awsSecretAccessKey, "")
|
config.Credentials = credentials.NewStaticCredentials(awsAccessKeyID, awsSecretAccessKey, "")
|
||||||
} else if dbURL != "" {
|
} else if dbURL != "" {
|
||||||
|
log.Debug("Tring to use database url for dynamodb")
|
||||||
// static config in case of testing or local-setup
|
// static config in case of testing or local-setup
|
||||||
config.Credentials = credentials.NewStaticCredentials("key", "key", "")
|
config.Credentials = credentials.NewStaticCredentials("key", "key", "")
|
||||||
config.Endpoint = aws.String(dbURL)
|
config.Endpoint = aws.String(dbURL)
|
||||||
|
@@ -2,6 +2,7 @@ package mongodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -12,17 +13,31 @@ import (
|
|||||||
|
|
||||||
// UpsertOTP to add or update otp
|
// UpsertOTP to add or update otp
|
||||||
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
|
||||||
otp, _ := p.GetOTPByEmail(ctx, otpParam.Email)
|
// check if email or phone number is present
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otpParam.Email == "" && otpParam.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if uniqueField == models.FieldNameEmail {
|
||||||
|
otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
|
||||||
|
} else {
|
||||||
|
otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
|
||||||
|
}
|
||||||
shouldCreate := false
|
shouldCreate := false
|
||||||
if otp == nil {
|
if otp == nil {
|
||||||
id := uuid.NewString()
|
id := uuid.NewString()
|
||||||
otp = &models.OTP{
|
otp = &models.OTP{
|
||||||
ID: id,
|
ID: id,
|
||||||
Key: id,
|
Key: id,
|
||||||
Otp: otpParam.Otp,
|
Otp: otpParam.Otp,
|
||||||
Email: otpParam.Email,
|
Email: otpParam.Email,
|
||||||
ExpiresAt: otpParam.ExpiresAt,
|
PhoneNumber: otpParam.PhoneNumber,
|
||||||
CreatedAt: time.Now().Unix(),
|
ExpiresAt: otpParam.ExpiresAt,
|
||||||
|
CreatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
shouldCreate = true
|
shouldCreate = true
|
||||||
} else {
|
} else {
|
||||||
@@ -41,20 +56,28 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return otp, nil
|
return otp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOTPByEmail to get otp for a given email address
|
// GetOTPByEmail to get otp for a given email address
|
||||||
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
||||||
var otp models.OTP
|
var otp models.OTP
|
||||||
|
|
||||||
otpCollection := p.db.Collection(models.Collections.OTP, options.Collection())
|
otpCollection := p.db.Collection(models.Collections.OTP, options.Collection())
|
||||||
err := otpCollection.FindOne(ctx, bson.M{"email": emailAddress}).Decode(&otp)
|
err := otpCollection.FindOne(ctx, bson.M{"email": emailAddress}).Decode(&otp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
var otp models.OTP
|
||||||
|
otpCollection := p.db.Collection(models.Collections.OTP, options.Collection())
|
||||||
|
err := otpCollection.FindOne(ctx, bson.M{"phone_number": phoneNumber}).Decode(&otp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &otp, nil
|
return &otp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -118,6 +118,12 @@ func NewProvider() (*provider, error) {
|
|||||||
Options: options.Index().SetUnique(true).SetSparse(true),
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
},
|
},
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
|
otpCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.M{"phone_number": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: mongodb,
|
db: mongodb,
|
||||||
|
@@ -16,6 +16,11 @@ func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*mod
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteOTP to delete otp
|
// DeleteOTP to delete otp
|
||||||
func (p *provider) DeleteOTP(ctx context.Context, otp *models.OTP) error {
|
func (p *provider) DeleteOTP(ctx context.Context, otp *models.OTP) error {
|
||||||
return nil
|
return nil
|
||||||
|
@@ -82,6 +82,8 @@ type Provider interface {
|
|||||||
UpsertOTP(ctx context.Context, otp *models.OTP) (*models.OTP, error)
|
UpsertOTP(ctx context.Context, otp *models.OTP) (*models.OTP, error)
|
||||||
// GetOTPByEmail to get otp for a given email address
|
// GetOTPByEmail to get otp for a given email address
|
||||||
GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error)
|
GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error)
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error)
|
||||||
// DeleteOTP to delete otp
|
// DeleteOTP to delete otp
|
||||||
DeleteOTP(ctx context.Context, otp *models.OTP) error
|
DeleteOTP(ctx context.Context, otp *models.OTP) error
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package sql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -14,13 +15,19 @@ func (p *provider) UpsertOTP(ctx context.Context, otp *models.OTP) (*models.OTP,
|
|||||||
if otp.ID == "" {
|
if otp.ID == "" {
|
||||||
otp.ID = uuid.New().String()
|
otp.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
// check if email or phone number is present
|
||||||
|
if otp.Email == "" && otp.PhoneNumber == "" {
|
||||||
|
return nil, errors.New("email or phone_number is required")
|
||||||
|
}
|
||||||
|
uniqueField := models.FieldNameEmail
|
||||||
|
if otp.Email == "" && otp.PhoneNumber != "" {
|
||||||
|
uniqueField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
otp.Key = otp.ID
|
otp.Key = otp.ID
|
||||||
otp.CreatedAt = time.Now().Unix()
|
otp.CreatedAt = time.Now().Unix()
|
||||||
otp.UpdatedAt = time.Now().Unix()
|
otp.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
res := p.db.Clauses(clause.OnConflict{
|
res := p.db.Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: "email"}},
|
Columns: []clause.Column{{Name: uniqueField}},
|
||||||
DoUpdates: clause.AssignmentColumns([]string{"otp", "expires_at", "updated_at"}),
|
DoUpdates: clause.AssignmentColumns([]string{"otp", "expires_at", "updated_at"}),
|
||||||
}).Create(&otp)
|
}).Create(&otp)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
@@ -33,7 +40,6 @@ func (p *provider) UpsertOTP(ctx context.Context, otp *models.OTP) (*models.OTP,
|
|||||||
// GetOTPByEmail to get otp for a given email address
|
// GetOTPByEmail to get otp for a given email address
|
||||||
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*models.OTP, error) {
|
||||||
var otp models.OTP
|
var otp models.OTP
|
||||||
|
|
||||||
result := p.db.Where("email = ?", emailAddress).First(&otp)
|
result := p.db.Where("email = ?", emailAddress).First(&otp)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return nil, result.Error
|
return nil, result.Error
|
||||||
@@ -41,6 +47,16 @@ func (p *provider) GetOTPByEmail(ctx context.Context, emailAddress string) (*mod
|
|||||||
return &otp, nil
|
return &otp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOTPByPhoneNumber to get otp for a given phone number
|
||||||
|
func (p *provider) GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error) {
|
||||||
|
var otp models.OTP
|
||||||
|
result := p.db.Where("phone_number = ?", phoneNumber).First(&otp)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return &otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteOTP to delete otp
|
// DeleteOTP to delete otp
|
||||||
func (p *provider) DeleteOTP(ctx context.Context, otp *models.OTP) error {
|
func (p *provider) DeleteOTP(ctx context.Context, otp *models.OTP) error {
|
||||||
result := p.db.Delete(&models.OTP{
|
result := p.db.Delete(&models.OTP{
|
||||||
|
@@ -103,6 +103,12 @@ func SendEmail(to []string, event string, data map[string]interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
senderName, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySenderName)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while getting sender name from env variable: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
smtpPort, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpPort)
|
smtpPort, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error while getting smtp port from env variable: %v", err)
|
log.Errorf("Error while getting smtp port from env variable: %v", err)
|
||||||
@@ -139,7 +145,7 @@ func SendEmail(to []string, event string, data map[string]interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.SetHeader("From", senderEmail)
|
m.SetAddressHeader("From", senderEmail, senderName)
|
||||||
m.SetHeader("To", to...)
|
m.SetHeader("To", to...)
|
||||||
m.SetHeader("Subject", tmp.Subject)
|
m.SetHeader("Subject", tmp.Subject)
|
||||||
m.SetBody("text/html", tmp.Template)
|
m.SetBody("text/html", tmp.Template)
|
||||||
|
72
server/env/env.go
vendored
72
server/env/env.go
vendored
@@ -57,6 +57,7 @@ func InitAllEnv() error {
|
|||||||
osSmtpPassword := os.Getenv(constants.EnvKeySmtpPassword)
|
osSmtpPassword := os.Getenv(constants.EnvKeySmtpPassword)
|
||||||
osSmtpLocalName := os.Getenv(constants.EnvKeySmtpLocalName)
|
osSmtpLocalName := os.Getenv(constants.EnvKeySmtpLocalName)
|
||||||
osSenderEmail := os.Getenv(constants.EnvKeySenderEmail)
|
osSenderEmail := os.Getenv(constants.EnvKeySenderEmail)
|
||||||
|
osSenderName := os.Getenv(constants.EnvKeySenderName)
|
||||||
osJwtType := os.Getenv(constants.EnvKeyJwtType)
|
osJwtType := os.Getenv(constants.EnvKeyJwtType)
|
||||||
osJwtSecret := os.Getenv(constants.EnvKeyJwtSecret)
|
osJwtSecret := os.Getenv(constants.EnvKeyJwtSecret)
|
||||||
osJwtPrivateKey := os.Getenv(constants.EnvKeyJwtPrivateKey)
|
osJwtPrivateKey := os.Getenv(constants.EnvKeyJwtPrivateKey)
|
||||||
@@ -103,6 +104,13 @@ func InitAllEnv() error {
|
|||||||
osDisableStrongPassword := os.Getenv(constants.EnvKeyDisableStrongPassword)
|
osDisableStrongPassword := os.Getenv(constants.EnvKeyDisableStrongPassword)
|
||||||
osEnforceMultiFactorAuthentication := os.Getenv(constants.EnvKeyEnforceMultiFactorAuthentication)
|
osEnforceMultiFactorAuthentication := os.Getenv(constants.EnvKeyEnforceMultiFactorAuthentication)
|
||||||
osDisableMultiFactorAuthentication := os.Getenv(constants.EnvKeyDisableMultiFactorAuthentication)
|
osDisableMultiFactorAuthentication := os.Getenv(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||||
|
// phone verification var
|
||||||
|
osDisablePhoneVerification := os.Getenv(constants.EnvKeyDisablePhoneVerification)
|
||||||
|
// twilio vars
|
||||||
|
osTwilioApiKey := os.Getenv(constants.EnvKeyTwilioAPIKey)
|
||||||
|
osTwilioApiSecret := os.Getenv(constants.EnvKeyTwilioAPISecret)
|
||||||
|
osTwilioAccountSid := os.Getenv(constants.EnvKeyTwilioAccountSID)
|
||||||
|
osTwilioSender := os.Getenv(constants.EnvKeyTwilioSender)
|
||||||
|
|
||||||
// os slice vars
|
// os slice vars
|
||||||
osAllowedOrigins := os.Getenv(constants.EnvKeyAllowedOrigins)
|
osAllowedOrigins := os.Getenv(constants.EnvKeyAllowedOrigins)
|
||||||
@@ -135,6 +143,7 @@ func InitAllEnv() error {
|
|||||||
if val, ok := envData[constants.EnvAwsRegion]; !ok || val == "" {
|
if val, ok := envData[constants.EnvAwsRegion]; !ok || val == "" {
|
||||||
envData[constants.EnvAwsRegion] = osAwsRegion
|
envData[constants.EnvAwsRegion] = osAwsRegion
|
||||||
}
|
}
|
||||||
|
|
||||||
if osAwsRegion != "" && envData[constants.EnvAwsRegion] != osAwsRegion {
|
if osAwsRegion != "" && envData[constants.EnvAwsRegion] != osAwsRegion {
|
||||||
envData[constants.EnvAwsRegion] = osAwsRegion
|
envData[constants.EnvAwsRegion] = osAwsRegion
|
||||||
}
|
}
|
||||||
@@ -257,6 +266,13 @@ func InitAllEnv() error {
|
|||||||
envData[constants.EnvKeySenderEmail] = osSenderEmail
|
envData[constants.EnvKeySenderEmail] = osSenderEmail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeySenderName]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeySenderName] = osSenderName
|
||||||
|
}
|
||||||
|
if osSenderName != "" && envData[constants.EnvKeySenderName] != osSenderName {
|
||||||
|
envData[constants.EnvKeySenderName] = osSenderName
|
||||||
|
}
|
||||||
|
|
||||||
algoVal, ok := envData[constants.EnvKeyJwtType]
|
algoVal, ok := envData[constants.EnvKeyJwtType]
|
||||||
algo := ""
|
algo := ""
|
||||||
if !ok || algoVal == "" {
|
if !ok || algoVal == "" {
|
||||||
@@ -583,7 +599,7 @@ func InitAllEnv() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if boolValue != envData[constants.EnvKeyDisableMagicLinkLogin].(bool) {
|
if boolValue != envData[constants.EnvKeyDisableMagicLinkLogin] {
|
||||||
envData[constants.EnvKeyDisableMagicLinkLogin] = boolValue
|
envData[constants.EnvKeyDisableMagicLinkLogin] = boolValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -673,11 +689,11 @@ func InitAllEnv() error {
|
|||||||
envData[constants.EnvKeyIsEmailServiceEnabled] = false
|
envData[constants.EnvKeyIsEmailServiceEnabled] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData[constants.EnvKeySmtpHost] != "" || envData[constants.EnvKeySmtpUsername] != "" || envData[constants.EnvKeySmtpPassword] != "" || envData[constants.EnvKeySenderEmail] != "" && envData[constants.EnvKeySmtpPort] != "" {
|
if envData[constants.EnvKeySmtpHost] != "" && envData[constants.EnvKeySmtpUsername] != "" && envData[constants.EnvKeySmtpPassword] != "" && envData[constants.EnvKeySenderEmail] != "" && envData[constants.EnvKeySmtpPort] != "" {
|
||||||
envData[constants.EnvKeyIsEmailServiceEnabled] = true
|
envData[constants.EnvKeyIsEmailServiceEnabled] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && !envData[constants.EnvKeyIsEmailServiceEnabled].(bool) {
|
if envData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && !envData[constants.EnvKeyIsEmailServiceEnabled].(bool) && !envData[constants.EnvKeyIsSMSServiceEnabled].(bool) {
|
||||||
return errors.New("to enable multi factor authentication, please enable email service")
|
return errors.New("to enable multi factor authentication, please enable email service")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,6 +775,56 @@ func InitAllEnv() error {
|
|||||||
envData[constants.EnvKeyDefaultAuthorizeResponseMode] = osAuthorizeResponseMode
|
envData[constants.EnvKeyDefaultAuthorizeResponseMode] = osAuthorizeResponseMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyTwilioAPISecret]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyTwilioAPISecret] = osTwilioApiSecret
|
||||||
|
}
|
||||||
|
if osTwilioApiSecret != "" && envData[constants.EnvKeyTwilioAPISecret] != osTwilioApiSecret {
|
||||||
|
envData[constants.EnvKeyTwilioAPISecret] = osTwilioApiSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyTwilioAPIKey]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyTwilioAPIKey] = osTwilioApiKey
|
||||||
|
}
|
||||||
|
if osTwilioApiKey != "" && envData[constants.EnvKeyTwilioAPIKey] != osTwilioApiKey {
|
||||||
|
envData[constants.EnvKeyTwilioAPIKey] = osTwilioApiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyTwilioAccountSID]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyTwilioAccountSID] = osTwilioAccountSid
|
||||||
|
}
|
||||||
|
if osTwilioAccountSid != "" && envData[constants.EnvKeyTwilioAccountSID] != osTwilioAccountSid {
|
||||||
|
envData[constants.EnvKeyTwilioAccountSID] = osTwilioAccountSid
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := envData[constants.EnvKeyTwilioSender]; !ok || val == "" {
|
||||||
|
envData[constants.EnvKeyTwilioSender] = osTwilioSender
|
||||||
|
}
|
||||||
|
if osTwilioSender != "" && envData[constants.EnvKeyTwilioSender] != osTwilioSender {
|
||||||
|
envData[constants.EnvKeyTwilioSender] = osTwilioSender
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := envData[constants.EnvKeyDisablePhoneVerification]; !ok {
|
||||||
|
envData[constants.EnvKeyDisablePhoneVerification] = osDisablePhoneVerification == "false"
|
||||||
|
}
|
||||||
|
if osDisablePhoneVerification != "" {
|
||||||
|
boolValue, err := strconv.ParseBool(osDisablePhoneVerification)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if boolValue != envData[constants.EnvKeyDisablePhoneVerification] {
|
||||||
|
envData[constants.EnvKeyDisablePhoneVerification] = boolValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if envData[constants.EnvKeyTwilioAPIKey] == "" || envData[constants.EnvKeyTwilioAPISecret] == "" || envData[constants.EnvKeyTwilioAccountSID] == "" || envData[constants.EnvKeyTwilioSender] == "" {
|
||||||
|
envData[constants.EnvKeyDisablePhoneVerification] = true
|
||||||
|
envData[constants.EnvKeyIsSMSServiceEnabled] = false
|
||||||
|
}
|
||||||
|
if envData[constants.EnvKeyTwilioAPIKey] != "" && envData[constants.EnvKeyTwilioAPISecret] != "" && envData[constants.EnvKeyTwilioAccountSID] != "" && envData[constants.EnvKeyTwilioSender] != "" {
|
||||||
|
envData[constants.EnvKeyDisablePhoneVerification] = false
|
||||||
|
envData[constants.EnvKeyIsSMSServiceEnabled] = true
|
||||||
|
}
|
||||||
|
|
||||||
err = memorystore.Provider.UpdateEnvStore(envData)
|
err = memorystore.Provider.UpdateEnvStore(envData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error while updating env store: ", err)
|
log.Debug("Error while updating env store: ", err)
|
||||||
|
2
server/env/persist_env.go
vendored
2
server/env/persist_env.go
vendored
@@ -200,7 +200,7 @@ func PersistEnv() error {
|
|||||||
envValue := strings.TrimSpace(os.Getenv(key))
|
envValue := strings.TrimSpace(os.Getenv(key))
|
||||||
if envValue != "" {
|
if envValue != "" {
|
||||||
switch key {
|
switch key {
|
||||||
case constants.EnvKeyIsProd, constants.EnvKeyDisableBasicAuthentication, constants.EnvKeyDisableMobileBasicAuthentication, constants.EnvKeyDisableEmailVerification, constants.EnvKeyDisableLoginPage, constants.EnvKeyDisableMagicLinkLogin, constants.EnvKeyDisableSignUp, constants.EnvKeyDisableRedisForEnv, constants.EnvKeyDisableStrongPassword, constants.EnvKeyIsEmailServiceEnabled, constants.EnvKeyEnforceMultiFactorAuthentication, constants.EnvKeyDisableMultiFactorAuthentication, constants.EnvKeyAdminCookieSecure, constants.EnvKeyAppCookieSecure:
|
case constants.EnvKeyIsProd, constants.EnvKeyDisableBasicAuthentication, constants.EnvKeyDisableMobileBasicAuthentication, constants.EnvKeyDisableEmailVerification, constants.EnvKeyDisableLoginPage, constants.EnvKeyDisableMagicLinkLogin, constants.EnvKeyDisableSignUp, constants.EnvKeyDisableRedisForEnv, constants.EnvKeyDisableStrongPassword, constants.EnvKeyIsEmailServiceEnabled, constants.EnvKeyIsSMSServiceEnabled, constants.EnvKeyEnforceMultiFactorAuthentication, constants.EnvKeyDisableMultiFactorAuthentication, constants.EnvKeyAdminCookieSecure, constants.EnvKeyAppCookieSecure, constants.EnvKeyDisablePhoneVerification:
|
||||||
if envValueBool, err := strconv.ParseBool(envValue); err == nil {
|
if envValueBool, err := strconv.ParseBool(envValue); err == nil {
|
||||||
if value.(bool) != envValueBool {
|
if value.(bool) != envValueBool {
|
||||||
storeData[key] = envValueBool
|
storeData[key] = envValueBool
|
||||||
|
@@ -5,26 +5,27 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.17.20
|
github.com/99designs/gqlgen v0.17.20
|
||||||
github.com/arangodb/go-driver v1.2.1
|
github.com/arangodb/go-driver v1.2.1
|
||||||
github.com/aws/aws-sdk-go v1.44.109
|
github.com/aws/aws-sdk-go v1.44.298
|
||||||
github.com/coreos/go-oidc/v3 v3.1.0
|
github.com/coreos/go-oidc/v3 v3.1.0
|
||||||
github.com/couchbase/gocb/v2 v2.6.0
|
github.com/couchbase/gocb/v2 v2.6.0
|
||||||
github.com/gin-gonic/gin v1.8.1
|
github.com/gin-gonic/gin v1.8.1
|
||||||
github.com/glebarez/sqlite v1.5.0
|
github.com/glebarez/sqlite v1.5.0
|
||||||
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.0
|
|
||||||
github.com/goccy/go-json v0.9.11 // indirect
|
github.com/goccy/go-json v0.9.11 // indirect
|
||||||
github.com/gocql/gocql v1.2.0
|
github.com/gocql/gocql v1.2.0
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.6 // indirect
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/guregu/dynamo v1.16.0
|
github.com/guregu/dynamo v1.20.0
|
||||||
github.com/joho/godotenv v1.3.0
|
github.com/joho/godotenv v1.3.0
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.0.3 // indirect
|
github.com/redis/go-redis/v9 v9.0.3
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
|
github.com/twilio/twilio-go v1.7.2
|
||||||
github.com/vektah/gqlparser/v2 v2.5.1
|
github.com/vektah/gqlparser/v2 v2.5.1
|
||||||
go.mongodb.org/mongo-driver v1.8.1
|
go.mongodb.org/mongo-driver v1.8.1
|
||||||
golang.org/x/crypto v0.4.0
|
golang.org/x/crypto v0.4.0
|
||||||
|
@@ -51,20 +51,20 @@ github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2
|
|||||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
github.com/aws/aws-sdk-go v1.42.47/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc=
|
github.com/aws/aws-sdk-go v1.44.298 h1:5qTxdubgV7PptZJmp/2qDwD2JL187ePL7VOxsSh1i3g=
|
||||||
github.com/aws/aws-sdk-go v1.44.109 h1:+Na5JPeS0kiEHoBp5Umcuuf+IDqXqD0lXnM920E31YI=
|
github.com/aws/aws-sdk-go v1.44.298/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||||
github.com/aws/aws-sdk-go v1.44.109/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||||
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||||
|
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||||
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
@@ -100,9 +100,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
|
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
|
||||||
@@ -123,8 +120,6 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
|
|||||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
||||||
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||||
github.com/go-redis/redis/v8 v8.11.0 h1:O1Td0mQ8UFChQ3N9zFQqo6kTU2cJ+/it88gDB+zg0wo=
|
|
||||||
github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7WU5SOQ/r06M=
|
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
@@ -134,8 +129,6 @@ github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
|||||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gocql/gocql v1.2.0 h1:TZhsCd7fRuye4VyHr3WCvWwIQaZUmjsqnSIXK9FcVCE=
|
github.com/gocql/gocql v1.2.0 h1:TZhsCd7fRuye4VyHr3WCvWwIQaZUmjsqnSIXK9FcVCE=
|
||||||
github.com/gocql/gocql v1.2.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
|
github.com/gocql/gocql v1.2.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
|
||||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
@@ -156,6 +149,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -208,15 +203,14 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/guregu/dynamo v1.16.0 h1:gmI8oi1VHwYQtq7+RPBeOiSssVLgxH/Az2t+NtDtL2c=
|
github.com/guregu/dynamo v1.20.0 h1:PDdVVhRSXQFFIHlkhoKF6D8kiwI9IU6uUdz/fF6Iiy4=
|
||||||
github.com/guregu/dynamo v1.16.0/go.mod h1:W2Gqcf3MtkrS+Q6fHPGAmRtT0Dyq+TGrqfqrUC9+R/c=
|
github.com/guregu/dynamo v1.20.0/go.mod h1:YQ92BTYVSMIKpFEzhaVqmCJnnSIGxbNF5zvECUaEZRE=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
@@ -257,6 +251,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q=
|
||||||
|
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
|
||||||
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
||||||
github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
|
github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
@@ -277,16 +273,7 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
|
|||||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
|
||||||
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
|
|
||||||
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
|
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
|
||||||
github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
|
|
||||||
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||||
@@ -332,6 +319,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/twilio/twilio-go v1.7.2 h1:tX38DXbSuDWWIK+tKAE2AJSMR6d8i7lf9ksY8J29VLE=
|
||||||
|
github.com/twilio/twilio-go v1.7.2/go.mod h1:tdnfQ5TjbewoAu4lf9bMsGvfuJ/QU9gYuv9yx3TSIXU=
|
||||||
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
||||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
@@ -354,6 +343,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.mongodb.org/mongo-driver v1.8.1 h1:OZE4Wni/SJlrcmSIBRYNzunX5TKxjrTS4jKSnA99oKU=
|
go.mongodb.org/mongo-driver v1.8.1 h1:OZE4Wni/SJlrcmSIBRYNzunX5TKxjrTS4jKSnA99oKU=
|
||||||
@@ -408,12 +398,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
|||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -435,23 +425,22 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -470,10 +459,10 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 h1:ZrnxWX62AgTKOSagEqxvb3ffipvEDX2pl7E1TdqLqIc=
|
|
||||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -482,11 +471,8 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -505,9 +491,10 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -519,12 +506,16 @@ golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -534,8 +525,10 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -582,7 +575,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
|
|||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
@@ -676,10 +669,10 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod
|
|||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
|
||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||||
@@ -690,13 +683,10 @@ gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb
|
|||||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -77,6 +77,7 @@ type Env struct {
|
|||||||
SMTPPassword *string `json:"SMTP_PASSWORD"`
|
SMTPPassword *string `json:"SMTP_PASSWORD"`
|
||||||
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
|
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
|
||||||
SenderEmail *string `json:"SENDER_EMAIL"`
|
SenderEmail *string `json:"SENDER_EMAIL"`
|
||||||
|
SenderName *string `json:"SENDER_NAME"`
|
||||||
JwtType *string `json:"JWT_TYPE"`
|
JwtType *string `json:"JWT_TYPE"`
|
||||||
JwtSecret *string `json:"JWT_SECRET"`
|
JwtSecret *string `json:"JWT_SECRET"`
|
||||||
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
||||||
@@ -143,7 +144,8 @@ type GenerateJWTKeysResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetUserRequest struct {
|
type GetUserRequest struct {
|
||||||
ID string `json:"id"`
|
ID *string `json:"id"`
|
||||||
|
Email *string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InviteMemberInput struct {
|
type InviteMemberInput struct {
|
||||||
@@ -151,6 +153,11 @@ type InviteMemberInput struct {
|
|||||||
RedirectURI *string `json:"redirect_uri"`
|
RedirectURI *string `json:"redirect_uri"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InviteMembersResponse struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Users []*User `json:"Users"`
|
||||||
|
}
|
||||||
|
|
||||||
type ListWebhookLogRequest struct {
|
type ListWebhookLogRequest struct {
|
||||||
Pagination *PaginationInput `json:"pagination"`
|
Pagination *PaginationInput `json:"pagination"`
|
||||||
WebhookID *string `json:"webhook_id"`
|
WebhookID *string `json:"webhook_id"`
|
||||||
@@ -238,8 +245,9 @@ type PaginationInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ResendOTPRequest struct {
|
type ResendOTPRequest struct {
|
||||||
Email string `json:"email"`
|
Email *string `json:"email"`
|
||||||
State *string `json:"state"`
|
PhoneNumber *string `json:"phone_number"`
|
||||||
|
State *string `json:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResendVerifyEmailInput struct {
|
type ResendVerifyEmailInput struct {
|
||||||
@@ -258,6 +266,15 @@ type Response struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SMSVerificationRequests struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
CodeExpiresAt int64 `json:"code_expires_at"`
|
||||||
|
PhoneNumber string `json:"phone_number"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt *int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
type SessionQueryInput struct {
|
type SessionQueryInput struct {
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
Scope []string `json:"scope"`
|
Scope []string `json:"scope"`
|
||||||
@@ -316,6 +333,7 @@ type UpdateEnvInput struct {
|
|||||||
SMTPPassword *string `json:"SMTP_PASSWORD"`
|
SMTPPassword *string `json:"SMTP_PASSWORD"`
|
||||||
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
|
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
|
||||||
SenderEmail *string `json:"SENDER_EMAIL"`
|
SenderEmail *string `json:"SENDER_EMAIL"`
|
||||||
|
SenderName *string `json:"SENDER_NAME"`
|
||||||
JwtType *string `json:"JWT_TYPE"`
|
JwtType *string `json:"JWT_TYPE"`
|
||||||
JwtSecret *string `json:"JWT_SECRET"`
|
JwtSecret *string `json:"JWT_SECRET"`
|
||||||
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
|
||||||
@@ -438,6 +456,15 @@ type ValidateJWTTokenResponse struct {
|
|||||||
Claims map[string]interface{} `json:"claims"`
|
Claims map[string]interface{} `json:"claims"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ValidateSessionInput struct {
|
||||||
|
Cookie string `json:"cookie"`
|
||||||
|
Roles []string `json:"roles"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidateSessionResponse struct {
|
||||||
|
IsValid bool `json:"is_valid"`
|
||||||
|
}
|
||||||
|
|
||||||
type VerificationRequest struct {
|
type VerificationRequest struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Identifier *string `json:"identifier"`
|
Identifier *string `json:"identifier"`
|
||||||
@@ -461,9 +488,10 @@ type VerifyEmailInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VerifyOTPRequest struct {
|
type VerifyOTPRequest struct {
|
||||||
Email string `json:"email"`
|
Email *string `json:"email"`
|
||||||
Otp string `json:"otp"`
|
PhoneNumber *string `json:"phone_number"`
|
||||||
State *string `json:"state"`
|
Otp string `json:"otp"`
|
||||||
|
State *string `json:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Webhook struct {
|
type Webhook struct {
|
||||||
|
@@ -75,6 +75,15 @@ type VerificationRequests {
|
|||||||
verification_requests: [VerificationRequest!]!
|
verification_requests: [VerificationRequest!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SMSVerificationRequests {
|
||||||
|
id: ID!
|
||||||
|
code: String!
|
||||||
|
code_expires_at: Int64!
|
||||||
|
phone_number: String!
|
||||||
|
created_at: Int64!
|
||||||
|
updated_at: Int64
|
||||||
|
}
|
||||||
|
|
||||||
type Error {
|
type Error {
|
||||||
message: String!
|
message: String!
|
||||||
reason: String!
|
reason: String!
|
||||||
@@ -94,6 +103,11 @@ type Response {
|
|||||||
message: String!
|
message: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InviteMembersResponse {
|
||||||
|
message: String!
|
||||||
|
Users: [User!]!
|
||||||
|
}
|
||||||
|
|
||||||
type Env {
|
type Env {
|
||||||
ACCESS_TOKEN_EXPIRY_TIME: String
|
ACCESS_TOKEN_EXPIRY_TIME: String
|
||||||
ADMIN_SECRET: String
|
ADMIN_SECRET: String
|
||||||
@@ -113,6 +127,7 @@ type Env {
|
|||||||
SMTP_PASSWORD: String
|
SMTP_PASSWORD: String
|
||||||
SMTP_LOCAL_NAME: String
|
SMTP_LOCAL_NAME: String
|
||||||
SENDER_EMAIL: String
|
SENDER_EMAIL: String
|
||||||
|
SENDER_NAME: String
|
||||||
JWT_TYPE: String
|
JWT_TYPE: String
|
||||||
JWT_SECRET: String
|
JWT_SECRET: String
|
||||||
JWT_PRIVATE_KEY: String
|
JWT_PRIVATE_KEY: String
|
||||||
@@ -162,6 +177,10 @@ type ValidateJWTTokenResponse {
|
|||||||
claims: Map
|
claims: Map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ValidateSessionResponse {
|
||||||
|
is_valid: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
type GenerateJWTKeysResponse {
|
type GenerateJWTKeysResponse {
|
||||||
secret: String
|
secret: String
|
||||||
public_key: String
|
public_key: String
|
||||||
@@ -230,6 +249,7 @@ input UpdateEnvInput {
|
|||||||
SMTP_PASSWORD: String
|
SMTP_PASSWORD: String
|
||||||
SMTP_LOCAL_NAME: String
|
SMTP_LOCAL_NAME: String
|
||||||
SENDER_EMAIL: String
|
SENDER_EMAIL: String
|
||||||
|
SENDER_NAME: String
|
||||||
JWT_TYPE: String
|
JWT_TYPE: String
|
||||||
JWT_SECRET: String
|
JWT_SECRET: String
|
||||||
JWT_PRIVATE_KEY: String
|
JWT_PRIVATE_KEY: String
|
||||||
@@ -453,6 +473,11 @@ input ValidateJWTTokenInput {
|
|||||||
roles: [String!]
|
roles: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ValidateSessionInput {
|
||||||
|
cookie: String!
|
||||||
|
roles: [String!]
|
||||||
|
}
|
||||||
|
|
||||||
input GenerateJWTKeysInput {
|
input GenerateJWTKeysInput {
|
||||||
type: String!
|
type: String!
|
||||||
}
|
}
|
||||||
@@ -513,7 +538,9 @@ input DeleteEmailTemplateRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input VerifyOTPRequest {
|
input VerifyOTPRequest {
|
||||||
email: String!
|
# either email or phone_number is required
|
||||||
|
email: String
|
||||||
|
phone_number: String
|
||||||
otp: String!
|
otp: String!
|
||||||
# state is used for authorization code grant flow
|
# state is used for authorization code grant flow
|
||||||
# it is used to get code for an on-going auth process during login
|
# it is used to get code for an on-going auth process during login
|
||||||
@@ -522,7 +549,8 @@ input VerifyOTPRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input ResendOTPRequest {
|
input ResendOTPRequest {
|
||||||
email: String!
|
email: String
|
||||||
|
phone_number: String
|
||||||
# state is used for authorization code grant flow
|
# state is used for authorization code grant flow
|
||||||
# it is used to get code for an on-going auth process during login
|
# it is used to get code for an on-going auth process during login
|
||||||
# and use that code for setting `c_hash` in id_token
|
# and use that code for setting `c_hash` in id_token
|
||||||
@@ -530,7 +558,8 @@ input ResendOTPRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input GetUserRequest {
|
input GetUserRequest {
|
||||||
id: String!
|
id: String
|
||||||
|
email: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
@@ -555,7 +584,7 @@ type Mutation {
|
|||||||
_admin_login(params: AdminLoginInput!): Response!
|
_admin_login(params: AdminLoginInput!): Response!
|
||||||
_admin_logout: Response!
|
_admin_logout: Response!
|
||||||
_update_env(params: UpdateEnvInput!): Response!
|
_update_env(params: UpdateEnvInput!): Response!
|
||||||
_invite_members(params: InviteMemberInput!): Response!
|
_invite_members(params: InviteMemberInput!): InviteMembersResponse!
|
||||||
_revoke_access(param: UpdateAccessInput!): Response!
|
_revoke_access(param: UpdateAccessInput!): Response!
|
||||||
_enable_access(param: UpdateAccessInput!): Response!
|
_enable_access(param: UpdateAccessInput!): Response!
|
||||||
_generate_jwt_keys(params: GenerateJWTKeysInput!): GenerateJWTKeysResponse!
|
_generate_jwt_keys(params: GenerateJWTKeysInput!): GenerateJWTKeysResponse!
|
||||||
@@ -573,6 +602,7 @@ type Query {
|
|||||||
session(params: SessionQueryInput): AuthResponse!
|
session(params: SessionQueryInput): AuthResponse!
|
||||||
profile: User!
|
profile: User!
|
||||||
validate_jwt_token(params: ValidateJWTTokenInput!): ValidateJWTTokenResponse!
|
validate_jwt_token(params: ValidateJWTTokenInput!): ValidateJWTTokenResponse!
|
||||||
|
validate_session(params: ValidateSessionInput): ValidateSessionResponse!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_users(params: PaginatedInput): Users!
|
_users(params: PaginatedInput): Users!
|
||||||
_user(params: GetUserRequest!): User!
|
_user(params: GetUserRequest!): User!
|
||||||
|
@@ -112,7 +112,7 @@ func (r *mutationResolver) UpdateEnv(ctx context.Context, params model.UpdateEnv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InviteMembers is the resolver for the _invite_members field.
|
// InviteMembers is the resolver for the _invite_members field.
|
||||||
func (r *mutationResolver) InviteMembers(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
|
func (r *mutationResolver) InviteMembers(ctx context.Context, params model.InviteMemberInput) (*model.InviteMembersResponse, error) {
|
||||||
return resolvers.InviteMembersResolver(ctx, params)
|
return resolvers.InviteMembersResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +186,11 @@ func (r *queryResolver) ValidateJwtToken(ctx context.Context, params model.Valid
|
|||||||
return resolvers.ValidateJwtTokenResolver(ctx, params)
|
return resolvers.ValidateJwtTokenResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSession is the resolver for the validate_session field.
|
||||||
|
func (r *queryResolver) ValidateSession(ctx context.Context, params *model.ValidateSessionInput) (*model.ValidateSessionResponse, error) {
|
||||||
|
return resolvers.ValidateSessionResolver(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
// Users is the resolver for the _users field.
|
// Users is the resolver for the _users field.
|
||||||
func (r *queryResolver) Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) {
|
func (r *queryResolver) Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) {
|
||||||
return resolvers.UsersResolver(ctx, params)
|
return resolvers.UsersResolver(ctx, params)
|
||||||
|
@@ -84,9 +84,9 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
if responseMode == "" {
|
if responseMode == "" {
|
||||||
if val, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultAuthorizeResponseMode); err == nil {
|
if val, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultAuthorizeResponseMode); err == nil {
|
||||||
responseType = val
|
responseMode = val
|
||||||
} else {
|
} else {
|
||||||
responseType = constants.ResponseModeQuery
|
responseMode = constants.ResponseModeQuery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -452,7 +452,7 @@ func processFacebookUserInfo(code string) (models.User, error) {
|
|||||||
userRawData := make(map[string]interface{})
|
userRawData := make(map[string]interface{})
|
||||||
json.Unmarshal(body, &userRawData)
|
json.Unmarshal(body, &userRawData)
|
||||||
|
|
||||||
email := fmt.Sprintf("%v", userRawData["sub"])
|
email := fmt.Sprintf("%v", userRawData["email"])
|
||||||
|
|
||||||
picObject := userRawData["picture"].(map[string]interface{})["data"]
|
picObject := userRawData["picture"].(map[string]interface{})["data"]
|
||||||
picDataObject := picObject.(map[string]interface{})
|
picDataObject := picObject.(map[string]interface{})
|
||||||
|
@@ -24,21 +24,22 @@ import (
|
|||||||
// It verifies email based on JWT token in query string
|
// It verifies email based on JWT token in query string
|
||||||
func VerifyEmailHandler() gin.HandlerFunc {
|
func VerifyEmailHandler() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
redirectURL := strings.TrimSpace(c.Query("redirect_uri"))
|
||||||
errorRes := gin.H{
|
errorRes := gin.H{
|
||||||
"error": "invalid_token",
|
"error": "token is required",
|
||||||
}
|
}
|
||||||
tokenInQuery := c.Query("token")
|
tokenInQuery := c.Query("token")
|
||||||
if tokenInQuery == "" {
|
if tokenInQuery == "" {
|
||||||
log.Debug("Token is empty")
|
log.Debug("Token is empty")
|
||||||
c.JSON(400, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery)
|
verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error getting verification request: ", err)
|
log.Debug("Error getting verification request: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,23 +48,23 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
claim, err := token.ParseJWTToken(tokenInQuery)
|
claim, err := token.ParseJWTToken(tokenInQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error parsing token: ", err)
|
log.Debug("Error parsing token: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok, err := token.ValidateJWTClaims(claim, hostname, verificationRequest.Nonce, verificationRequest.Email); !ok || err != nil {
|
if ok, err := token.ValidateJWTClaims(claim, hostname, verificationRequest.Nonce, verificationRequest.Email); !ok || err != nil {
|
||||||
log.Debug("Error validating jwt claims: ", err)
|
log.Debug("Error validating jwt claims: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email)
|
user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error getting user: ", err)
|
log.Debug("Error getting user: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +80,6 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
db.Provider.DeleteVerificationRequest(c, verificationRequest)
|
db.Provider.DeleteVerificationRequest(c, verificationRequest)
|
||||||
|
|
||||||
state := strings.TrimSpace(c.Query("state"))
|
state := strings.TrimSpace(c.Query("state"))
|
||||||
redirectURL := strings.TrimSpace(c.Query("redirect_uri"))
|
|
||||||
rolesString := strings.TrimSpace(c.Query("roles"))
|
rolesString := strings.TrimSpace(c.Query("roles"))
|
||||||
var roles []string
|
var roles []string
|
||||||
if rolesString == "" {
|
if rolesString == "" {
|
||||||
@@ -125,8 +125,8 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, code)
|
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error creating auth token: ", err)
|
log.Debug("Error creating auth token: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error"] = err.Error()
|
||||||
c.JSON(500, errorRes)
|
utils.HandleRedirectORJsonResponse(c, http.StatusInternalServerError, errorRes, generateRedirectURL(redirectURL, errorRes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
// if code != "" {
|
// if code != "" {
|
||||||
// if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
// if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||||
// log.Debug("Error setting code state ", err)
|
// log.Debug("Error setting code state ", err)
|
||||||
// errorRes["error_description"] = err.Error()
|
// errorRes["error"] = err.Error()
|
||||||
// c.JSON(500, errorRes)
|
// c.JSON(500, errorRes)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@@ -189,3 +189,21 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateRedirectURL(url string, res map[string]interface{}) string {
|
||||||
|
redirectURL := url
|
||||||
|
if redirectURL == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var paramsArr []string
|
||||||
|
for key, value := range res {
|
||||||
|
paramsArr = append(paramsArr, key+"="+value.(string))
|
||||||
|
}
|
||||||
|
params := strings.Join(paramsArr, "&")
|
||||||
|
if strings.Contains(redirectURL, "?") {
|
||||||
|
redirectURL = redirectURL + "&" + params
|
||||||
|
} else {
|
||||||
|
redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&")
|
||||||
|
}
|
||||||
|
return redirectURL
|
||||||
|
}
|
||||||
|
@@ -33,6 +33,7 @@ func InitMemStore() error {
|
|||||||
constants.EnvKeyDisableSignUp: false,
|
constants.EnvKeyDisableSignUp: false,
|
||||||
constants.EnvKeyDisableStrongPassword: false,
|
constants.EnvKeyDisableStrongPassword: false,
|
||||||
constants.EnvKeyIsEmailServiceEnabled: false,
|
constants.EnvKeyIsEmailServiceEnabled: false,
|
||||||
|
constants.EnvKeyIsSMSServiceEnabled: false,
|
||||||
constants.EnvKeyEnforceMultiFactorAuthentication: false,
|
constants.EnvKeyEnforceMultiFactorAuthentication: false,
|
||||||
constants.EnvKeyDisableMultiFactorAuthentication: false,
|
constants.EnvKeyDisableMultiFactorAuthentication: false,
|
||||||
constants.EnvKeyAppCookieSecure: true,
|
constants.EnvKeyAppCookieSecure: true,
|
||||||
|
@@ -24,7 +24,7 @@ type SessionEntry struct {
|
|||||||
// SessionStore struct to store the env variables
|
// SessionStore struct to store the env variables
|
||||||
type SessionStore struct {
|
type SessionStore struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
mutex sync.RWMutex
|
mutex sync.Mutex
|
||||||
store map[string]*SessionEntry
|
store map[string]*SessionEntry
|
||||||
// stores expireTime: key to remove data when cache is full
|
// stores expireTime: key to remove data when cache is full
|
||||||
// map is sorted by key so older most entry can be deleted first
|
// map is sorted by key so older most entry can be deleted first
|
||||||
@@ -35,7 +35,7 @@ type SessionStore struct {
|
|||||||
// NewSessionStore create a new session store
|
// NewSessionStore create a new session store
|
||||||
func NewSessionStore() *SessionStore {
|
func NewSessionStore() *SessionStore {
|
||||||
store := &SessionStore{
|
store := &SessionStore{
|
||||||
mutex: sync.RWMutex{},
|
mutex: sync.Mutex{},
|
||||||
store: make(map[string]*SessionEntry),
|
store: make(map[string]*SessionEntry),
|
||||||
keyIndex: make(map[int64]string),
|
keyIndex: make(map[int64]string),
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
@@ -71,8 +71,8 @@ func (s *SessionStore) clean() {
|
|||||||
|
|
||||||
// Get returns the value of the key in state store
|
// Get returns the value of the key in state store
|
||||||
func (s *SessionStore) Get(key, subKey string) string {
|
func (s *SessionStore) Get(key, subKey string) string {
|
||||||
s.mutex.RLock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.RUnlock()
|
defer s.mutex.Unlock()
|
||||||
currentTime := time.Now().Unix()
|
currentTime := time.Now().Unix()
|
||||||
k := fmt.Sprintf("%s:%s", key, subKey)
|
k := fmt.Sprintf("%s:%s", key, subKey)
|
||||||
if v, ok := s.store[k]; ok {
|
if v, ok := s.store[k]; ok {
|
||||||
|
@@ -9,6 +9,10 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dialTimeout = 60 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// RedisClient is the interface for redis client & redis cluster client
|
// RedisClient is the interface for redis client & redis cluster client
|
||||||
type RedisClient interface {
|
type RedisClient interface {
|
||||||
HMSet(ctx context.Context, key string, values ...interface{}) *redis.BoolCmd
|
HMSet(ctx context.Context, key string, values ...interface{}) *redis.BoolCmd
|
||||||
@@ -41,8 +45,7 @@ func NewRedisProvider(redisURL string) (*provider, error) {
|
|||||||
urls := []string{opt.Addr}
|
urls := []string{opt.Addr}
|
||||||
urlList := redisURLHostPortsList[1:]
|
urlList := redisURLHostPortsList[1:]
|
||||||
urls = append(urls, urlList...)
|
urls = append(urls, urlList...)
|
||||||
clusterOpt := &redis.ClusterOptions{Addrs: urls}
|
clusterOpt := &redis.ClusterOptions{Addrs: urls, DialTimeout: dialTimeout}
|
||||||
|
|
||||||
rdb := redis.NewClusterClient(clusterOpt)
|
rdb := redis.NewClusterClient(clusterOpt)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err = rdb.Ping(ctx).Result()
|
_, err = rdb.Ping(ctx).Result()
|
||||||
@@ -62,7 +65,7 @@ func NewRedisProvider(redisURL string) (*provider, error) {
|
|||||||
log.Debug("error parsing redis url: ", err)
|
log.Debug("error parsing redis url: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
opt.DialTimeout = dialTimeout
|
||||||
rdb := redis.NewClient(opt)
|
rdb := redis.NewClient(opt)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err = rdb.Ping(ctx).Result()
|
_, err = rdb.Ping(ctx).Result()
|
||||||
|
@@ -143,7 +143,7 @@ func (c *provider) GetEnvStore() (map[string]interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for key, value := range data {
|
for key, value := range data {
|
||||||
if key == constants.EnvKeyDisableBasicAuthentication || key == constants.EnvKeyDisableMobileBasicAuthentication || key == constants.EnvKeyDisableEmailVerification || key == constants.EnvKeyDisableLoginPage || key == constants.EnvKeyDisableMagicLinkLogin || key == constants.EnvKeyDisableRedisForEnv || key == constants.EnvKeyDisableSignUp || key == constants.EnvKeyDisableStrongPassword || key == constants.EnvKeyIsEmailServiceEnabled || key == constants.EnvKeyEnforceMultiFactorAuthentication || key == constants.EnvKeyDisableMultiFactorAuthentication || key == constants.EnvKeyAppCookieSecure || key == constants.EnvKeyAdminCookieSecure {
|
if key == constants.EnvKeyDisableBasicAuthentication || key == constants.EnvKeyDisableMobileBasicAuthentication || key == constants.EnvKeyDisableEmailVerification || key == constants.EnvKeyDisableLoginPage || key == constants.EnvKeyDisableMagicLinkLogin || key == constants.EnvKeyDisableRedisForEnv || key == constants.EnvKeyDisableSignUp || key == constants.EnvKeyDisableStrongPassword || key == constants.EnvKeyIsEmailServiceEnabled || key == constants.EnvKeyIsSMSServiceEnabled || key == constants.EnvKeyEnforceMultiFactorAuthentication || key == constants.EnvKeyDisableMultiFactorAuthentication || key == constants.EnvKeyAppCookieSecure || key == constants.EnvKeyAdminCookieSecure {
|
||||||
boolValue, err := strconv.ParseBool(value)
|
boolValue, err := strconv.ParseBool(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
|
@@ -89,6 +89,9 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||||||
if val, ok := store[constants.EnvKeySenderEmail]; ok {
|
if val, ok := store[constants.EnvKeySenderEmail]; ok {
|
||||||
res.SenderEmail = refs.NewStringRef(val.(string))
|
res.SenderEmail = refs.NewStringRef(val.(string))
|
||||||
}
|
}
|
||||||
|
if val, ok := store[constants.EnvKeySenderName]; ok {
|
||||||
|
res.SenderName = refs.NewStringRef(val.(string))
|
||||||
|
}
|
||||||
if val, ok := store[constants.EnvKeySmtpLocalName]; ok {
|
if val, ok := store[constants.EnvKeySmtpLocalName]; ok {
|
||||||
res.SMTPLocalName = refs.NewStringRef(val.(string))
|
res.SMTPLocalName = refs.NewStringRef(val.(string))
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// InviteMembersResolver resolver to invite members
|
// InviteMembersResolver resolver to invite members
|
||||||
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
|
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.InviteMembersResponse, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to get GinContext: ", err)
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
@@ -178,7 +178,25 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return &model.Response{
|
InvitedUsers := []*model.User{}
|
||||||
|
|
||||||
|
for _, email := range newEmails {
|
||||||
|
user, err := db.Provider.GetUserByEmail(ctx, email)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("err: %s", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
InvitedUsers = append(InvitedUsers, &model.User{
|
||||||
|
Email: user.Email,
|
||||||
|
ID: user.ID,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.InviteMembersResponse{
|
||||||
Message: fmt.Sprintf("%d user(s) invited successfully.", len(newEmails)),
|
Message: fmt.Sprintf("%d user(s) invited successfully.", len(newEmails)),
|
||||||
|
Users: InvitedUsers,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@@ -106,7 +106,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||||
if err != nil || !isEmailServiceEnabled {
|
if err != nil || !isMFADisabled {
|
||||||
log.Debug("MFA service not enabled: ", err)
|
log.Debug("MFA service not enabled: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -224,7 +224,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
go email.SendEmail([]string{params.Email}, constants.VerificationTypeMagicLinkLogin, map[string]interface{}{
|
go email.SendEmail([]string{params.Email}, constants.VerificationTypeMagicLinkLogin, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
|
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/refs"
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/authorizerdev/authorizer/server/validators"
|
"github.com/authorizerdev/authorizer/server/validators"
|
||||||
@@ -94,55 +95,57 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
|||||||
roles = params.Roles
|
roles = params.Roles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disablePhoneVerification, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisablePhoneVerification)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error getting disable phone verification: ", err)
|
||||||
|
}
|
||||||
|
if disablePhoneVerification {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
user.PhoneNumberVerifiedAt = &now
|
||||||
|
}
|
||||||
|
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
|
||||||
|
if err != nil || !isSMSServiceEnabled {
|
||||||
|
log.Debug("SMS service not enabled: ", err)
|
||||||
|
}
|
||||||
|
if disablePhoneVerification {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
user.PhoneNumberVerifiedAt = &now
|
||||||
|
}
|
||||||
|
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||||
|
if err != nil || !isMFADisabled {
|
||||||
|
log.Debug("MFA service not enabled: ", err)
|
||||||
|
}
|
||||||
|
if !disablePhoneVerification && isSMSServiceEnabled && !isMFADisabled {
|
||||||
|
duration, _ := time.ParseDuration("10m")
|
||||||
|
smsCode := utils.GenerateOTP()
|
||||||
|
|
||||||
|
smsBody := strings.Builder{}
|
||||||
|
smsBody.WriteString("Your verification code is: ")
|
||||||
|
smsBody.WriteString(smsCode)
|
||||||
|
_, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||||
|
PhoneNumber: params.PhoneNumber,
|
||||||
|
Otp: smsCode,
|
||||||
|
ExpiresAt: time.Now().Add(duration).Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("error while upserting OTP: ", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, *user)
|
||||||
|
smsproviders.SendSMS(params.PhoneNumber, smsBody.String())
|
||||||
|
}()
|
||||||
|
return &model.AuthResponse{
|
||||||
|
Message: "Please check the OTP",
|
||||||
|
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
scope := []string{"openid", "email", "profile"}
|
scope := []string{"openid", "email", "profile"}
|
||||||
if params.Scope != nil && len(scope) > 0 {
|
if params.Scope != nil && len(scope) > 0 {
|
||||||
scope = params.Scope
|
scope = params.Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO use sms authentication for MFA
|
|
||||||
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
|
||||||
if err != nil || !isEmailServiceEnabled {
|
|
||||||
log.Debug("Email service not enabled: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
|
||||||
if err != nil || !isEmailServiceEnabled {
|
|
||||||
log.Debug("MFA service not enabled: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If email service is not enabled continue the process in any way
|
|
||||||
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && isEmailServiceEnabled && !isMFADisabled {
|
|
||||||
otp := utils.GenerateOTP()
|
|
||||||
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
|
||||||
Email: user.Email,
|
|
||||||
Otp: otp,
|
|
||||||
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("Failed to add otp: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// exec it as go routine so that we can reduce the api latency
|
|
||||||
go email.SendEmail([]string{params.PhoneNumber}, constants.VerificationTypeOTP, map[string]interface{}{
|
|
||||||
"user": user.ToMap(),
|
|
||||||
"organization": utils.GetOrganization(),
|
|
||||||
"otp": otpData.Otp,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("Failed to send otp email: ", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return &model.AuthResponse{
|
|
||||||
Message: "Please check the OTP in your inbox",
|
|
||||||
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
code := ""
|
code := ""
|
||||||
codeChallenge := ""
|
codeChallenge := ""
|
||||||
nonce := ""
|
nonce := ""
|
||||||
|
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/refs"
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/authorizerdev/authorizer/server/validators"
|
"github.com/authorizerdev/authorizer/server/validators"
|
||||||
@@ -91,7 +92,6 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to get user by email: ", err)
|
log.Debug("Failed to get user by email: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if existingUser != nil {
|
if existingUser != nil {
|
||||||
if existingUser.PhoneNumberVerifiedAt != nil {
|
if existingUser.PhoneNumberVerifiedAt != nil {
|
||||||
// email is verified
|
// email is verified
|
||||||
@@ -104,7 +104,6 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inputRoles := []string{}
|
inputRoles := []string{}
|
||||||
|
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
rolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyRoles)
|
rolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyRoles)
|
||||||
@@ -131,11 +130,9 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().Unix()
|
|
||||||
user := models.User{
|
user := models.User{
|
||||||
Email: emailInput,
|
Email: emailInput,
|
||||||
PhoneNumber: &mobile,
|
PhoneNumber: &mobile,
|
||||||
PhoneNumberVerifiedAt: &now,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Roles = strings.Join(inputRoles, ",")
|
user.Roles = strings.Join(inputRoles, ",")
|
||||||
@@ -185,12 +182,54 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
|||||||
user.IsMultiFactorAuthEnabled = refs.NewBoolRef(true)
|
user.IsMultiFactorAuthEnabled = refs.NewBoolRef(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disablePhoneVerification, _ := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisablePhoneVerification)
|
||||||
|
if disablePhoneVerification {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
user.PhoneNumberVerifiedAt = &now
|
||||||
|
}
|
||||||
|
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
|
||||||
|
if err != nil || !isSMSServiceEnabled {
|
||||||
|
log.Debug("SMS service not enabled: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
user.SignupMethods = constants.AuthRecipeMethodMobileBasicAuth
|
user.SignupMethods = constants.AuthRecipeMethodMobileBasicAuth
|
||||||
user, err = db.Provider.AddUser(ctx, user)
|
user, err = db.Provider.AddUser(ctx, user)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to add user: ", err)
|
log.Debug("Failed to add user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
if !disablePhoneVerification && isSMSServiceEnabled {
|
||||||
|
duration, _ := time.ParseDuration("10m")
|
||||||
|
smsCode := utils.GenerateOTP()
|
||||||
|
|
||||||
|
smsBody := strings.Builder{}
|
||||||
|
smsBody.WriteString("Your verification code is: ")
|
||||||
|
smsBody.WriteString(smsCode)
|
||||||
|
|
||||||
|
// TODO: For those who enabled the webhook to call their sms vendor separately - sending the otp to their api
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("error while upserting user: ", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||||
|
PhoneNumber: mobile,
|
||||||
|
Otp: smsCode,
|
||||||
|
ExpiresAt: time.Now().Add(duration).Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("error while upserting OTP: ", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
smsproviders.SendSMS(mobile, smsBody.String())
|
||||||
|
}()
|
||||||
|
return &model.AuthResponse{
|
||||||
|
Message: "Please check the OTP in your inbox",
|
||||||
|
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
userToReturn := user.AsAPIUser()
|
userToReturn := user.AsAPIUser()
|
||||||
|
|
||||||
|
@@ -12,23 +12,49 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
emailHelper "github.com/authorizerdev/authorizer/server/email"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/refs"
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResendOTPResolver is a resolver for resend otp mutation
|
// ResendOTPResolver is a resolver for resend otp mutation
|
||||||
func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error) {
|
func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error) {
|
||||||
|
email := strings.ToLower(strings.Trim(refs.StringValue(params.Email), " "))
|
||||||
|
phoneNumber := strings.Trim(refs.StringValue(params.PhoneNumber), " ")
|
||||||
log := log.WithFields(log.Fields{
|
log := log.WithFields(log.Fields{
|
||||||
"email": params.Email,
|
"email": email,
|
||||||
|
"phone_number": phoneNumber,
|
||||||
})
|
})
|
||||||
params.Email = strings.ToLower(params.Email)
|
if email == "" && phoneNumber == "" {
|
||||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
log.Debug("Email or phone number is required")
|
||||||
|
return nil, errors.New("email or phone number is required")
|
||||||
|
}
|
||||||
|
var user models.User
|
||||||
|
var err error
|
||||||
|
if email != "" {
|
||||||
|
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||||
|
if err != nil || !isEmailServiceEnabled {
|
||||||
|
log.Debug("Email service not enabled: ", err)
|
||||||
|
return nil, errors.New("email service not enabled")
|
||||||
|
}
|
||||||
|
user, err = db.Provider.GetUserByEmail(ctx, email)
|
||||||
|
} else {
|
||||||
|
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||||
|
if err != nil || !isSMSServiceEnabled {
|
||||||
|
log.Debug("Email service not enabled: ", err)
|
||||||
|
return nil, errors.New("email service not enabled")
|
||||||
|
}
|
||||||
|
// TODO fix after refs fixes
|
||||||
|
var u *models.User
|
||||||
|
u, err = db.Provider.GetUserByPhoneNumber(ctx, phoneNumber)
|
||||||
|
user = *u
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to get user by email: ", err)
|
log.Debug("Failed to get user by email: ", err)
|
||||||
return nil, fmt.Errorf(`user with this email not found`)
|
return nil, fmt.Errorf(`user with this email/phone not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.RevokedTimestamp != nil {
|
if user.RevokedTimestamp != nil {
|
||||||
@@ -36,35 +62,38 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
|
|||||||
return nil, fmt.Errorf(`user access has been revoked`)
|
return nil, fmt.Errorf(`user access has been revoked`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.EmailVerifiedAt == nil {
|
if email != "" && user.EmailVerifiedAt == nil {
|
||||||
log.Debug("User email is not verified")
|
log.Debug("User email is not verified")
|
||||||
return nil, fmt.Errorf(`email not verified`)
|
return nil, fmt.Errorf(`email not verified`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if phoneNumber != "" && user.PhoneNumberVerifiedAt == nil {
|
||||||
|
log.Debug("User phone number is not verified")
|
||||||
|
return nil, fmt.Errorf(`phone number not verified`)
|
||||||
|
}
|
||||||
|
|
||||||
if !refs.BoolValue(user.IsMultiFactorAuthEnabled) {
|
if !refs.BoolValue(user.IsMultiFactorAuthEnabled) {
|
||||||
log.Debug("User multi factor authentication is not enabled")
|
log.Debug("User multi factor authentication is not enabled")
|
||||||
return nil, fmt.Errorf(`multi factor authentication not enabled`)
|
return nil, fmt.Errorf(`multi factor authentication not enabled`)
|
||||||
}
|
}
|
||||||
|
|
||||||
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
|
||||||
if err != nil || !isEmailServiceEnabled {
|
|
||||||
log.Debug("Email service not enabled: ", err)
|
|
||||||
return nil, errors.New("email service not enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||||
if err != nil || isMFADisabled {
|
if err != nil || isMFADisabled {
|
||||||
log.Debug("MFA service not enabled: ", err)
|
log.Debug("MFA service not enabled: ", err)
|
||||||
return nil, errors.New("multi factor authentication is disabled for this instance")
|
return nil, errors.New("multi factor authentication is disabled for this instance")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get otp by email
|
// get otp by email or phone number
|
||||||
otpData, err := db.Provider.GetOTPByEmail(ctx, params.Email)
|
var otpData *models.OTP
|
||||||
|
if email != "" {
|
||||||
|
otpData, err = db.Provider.GetOTPByEmail(ctx, refs.StringValue(params.Email))
|
||||||
|
} else {
|
||||||
|
otpData, err = db.Provider.GetOTPByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to get otp for given email: ", err)
|
log.Debug("Failed to get otp for given email: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if otpData == nil {
|
if otpData == nil {
|
||||||
log.Debug("No otp found for given email: ", params.Email)
|
log.Debug("No otp found for given email: ", params.Email)
|
||||||
return &model.Response{
|
return &model.Response{
|
||||||
@@ -73,28 +102,30 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
otp := utils.GenerateOTP()
|
otp := utils.GenerateOTP()
|
||||||
otpData, err = db.Provider.UpsertOTP(ctx, &models.OTP{
|
if _, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Otp: otp,
|
Otp: otp,
|
||||||
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
log.Debug("Error upserting otp: ", err)
|
||||||
log.Debug("Error generating new otp: ", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
if email != "" {
|
||||||
// exec it as go routine so that we can reduce the api latency
|
// exec it as go routine so that we can reduce the api latency
|
||||||
go email.SendEmail([]string{params.Email}, constants.VerificationTypeOTP, map[string]interface{}{
|
go emailHelper.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"otp": otp,
|
"otp": otp,
|
||||||
})
|
})
|
||||||
if err != nil {
|
} else {
|
||||||
log.Debug("Error sending otp email: ", otp)
|
smsBody := strings.Builder{}
|
||||||
}
|
smsBody.WriteString("Your verification code is: ")
|
||||||
}()
|
smsBody.WriteString(otp)
|
||||||
|
// exec it as go routine so that we can reduce the api latency
|
||||||
|
go smsproviders.SendSMS(phoneNumber, smsBody.String())
|
||||||
|
}
|
||||||
|
log.Info("OTP has been resent")
|
||||||
return &model.Response{
|
return &model.Response{
|
||||||
Message: `OTP has been sent. Please check your inbox`,
|
Message: `OTP has been sent. Please check your inbox`,
|
||||||
}, nil
|
}, nil
|
||||||
|
@@ -83,7 +83,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||||||
go email.SendEmail([]string{params.Email}, params.Identifier, map[string]interface{}{
|
go email.SendEmail([]string{params.Email}, params.Identifier, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
|
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, verificationRequest.RedirectURI),
|
||||||
})
|
})
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
|
@@ -227,7 +227,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
email.SendEmail([]string{params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
|
email.SendEmail([]string{params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
|
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
|
||||||
})
|
})
|
||||||
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||||
}()
|
}()
|
||||||
|
@@ -267,6 +267,13 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
updatedData[constants.EnvKeyIsEmailServiceEnabled] = true
|
updatedData[constants.EnvKeyIsEmailServiceEnabled] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if updatedData[constants.EnvKeyTwilioAPIKey] == "" || updatedData[constants.EnvKeyTwilioAPISecret] == "" || updatedData[constants.EnvKeyTwilioAccountSID] == "" || updatedData[constants.EnvKeyTwilioSender] == "" {
|
||||||
|
updatedData[constants.EnvKeyIsSMSServiceEnabled] = false
|
||||||
|
if !updatedData[constants.EnvKeyIsSMSServiceEnabled].(bool) {
|
||||||
|
updatedData[constants.EnvKeyDisablePhoneVerification] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !currentData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && updatedData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && !updatedData[constants.EnvKeyDisableMultiFactorAuthentication].(bool) {
|
if !currentData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && updatedData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && !updatedData[constants.EnvKeyDisableMultiFactorAuthentication].(bool) {
|
||||||
go db.Provider.UpdateUsers(ctx, map[string]interface{}{
|
go db.Provider.UpdateUsers(ctx, map[string]interface{}{
|
||||||
"is_multi_factor_auth_enabled": true,
|
"is_multi_factor_auth_enabled": true,
|
||||||
|
@@ -259,7 +259,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||||||
go email.SendEmail([]string{user.Email}, verificationType, map[string]interface{}{
|
go email.SendEmail([]string{user.Email}, verificationType, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
|
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -164,7 +164,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||||||
go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
|
go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
|
||||||
"user": user.ToMap(),
|
"user": user.ToMap(),
|
||||||
"organization": utils.GetOrganization(),
|
"organization": utils.GetOrganization(),
|
||||||
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
|
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@@ -20,17 +21,28 @@ func UserResolver(ctx context.Context, params model.GetUserRequest) (*model.User
|
|||||||
log.Debug("Failed to get GinContext: ", err)
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
log.Debug("Not logged in as super admin.")
|
log.Debug("Not logged in as super admin.")
|
||||||
return nil, fmt.Errorf("unauthorized")
|
return nil, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
// Try getting user by ID
|
||||||
res, err := db.Provider.GetUserByID(ctx, params.ID)
|
if params.ID != nil && strings.Trim(*params.ID, " ") != "" {
|
||||||
if err != nil {
|
res, err := db.Provider.GetUserByID(ctx, *params.ID)
|
||||||
log.Debug("Failed to get users: ", err)
|
if err != nil {
|
||||||
return nil, err
|
log.Debug("Failed to get users by ID: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.AsAPIUser(), nil
|
||||||
}
|
}
|
||||||
|
// Try getting user by email
|
||||||
return res.AsAPIUser(), nil
|
if params.Email != nil && strings.Trim(*params.Email, " ") != "" {
|
||||||
|
res, err := db.Provider.GetUserByEmail(ctx, *params.Email)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get users by email: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.AsAPIUser(), nil
|
||||||
|
}
|
||||||
|
// Return error if no params are provided
|
||||||
|
return nil, fmt.Errorf("invalid params, user id or email is required")
|
||||||
}
|
}
|
||||||
|
59
server/resolvers/validate_session.go
Normal file
59
server/resolvers/validate_session.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package resolvers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateSessionResolver is used to validate a cookie session without its rotation
|
||||||
|
func ValidateSessionResolver(ctx context.Context, params *model.ValidateSessionInput) (*model.ValidateSessionResponse, error) {
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sessionToken := params.Cookie
|
||||||
|
if sessionToken == "" {
|
||||||
|
sessionToken, err = cookie.GetSession(gc)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get session token: ", err)
|
||||||
|
return nil, errors.New("unauthorized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to validate session token", err)
|
||||||
|
return nil, errors.New("unauthorized")
|
||||||
|
}
|
||||||
|
userID := claims.Subject
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"user_id": userID,
|
||||||
|
})
|
||||||
|
_, err = db.Provider.GetUserByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// refresh token has "roles" as claim
|
||||||
|
claimRoleInterface := claims.Roles
|
||||||
|
claimRoles := []string{}
|
||||||
|
claimRoles = append(claimRoles, claimRoleInterface...)
|
||||||
|
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
||||||
|
for _, v := range params.Roles {
|
||||||
|
if !utils.StringSliceContains(claimRoles, v) {
|
||||||
|
log.Debug("User does not have required role: ", claimRoles, v)
|
||||||
|
return nil, fmt.Errorf(`unauthorized`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &model.ValidateSessionResponse{
|
||||||
|
IsValid: true,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -27,36 +27,53 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
|||||||
log.Debug("Failed to get GinContext: ", err)
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
if refs.StringValue(params.Email) == "" && refs.StringValue(params.PhoneNumber) == "" {
|
||||||
otp, err := db.Provider.GetOTPByEmail(ctx, params.Email)
|
log.Debug("Email or phone number is required")
|
||||||
if err != nil {
|
return res, fmt.Errorf(`email or phone_number is required`)
|
||||||
log.Debug("Failed to get otp request by email: ", err)
|
|
||||||
return res, fmt.Errorf(`invalid email: %s`, err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentField := models.FieldNameEmail
|
||||||
|
if refs.StringValue(params.Email) == "" {
|
||||||
|
currentField = models.FieldNamePhoneNumber
|
||||||
|
}
|
||||||
|
var otp *models.OTP
|
||||||
|
if currentField == models.FieldNameEmail {
|
||||||
|
otp, err = db.Provider.GetOTPByEmail(ctx, refs.StringValue(params.Email))
|
||||||
|
} else {
|
||||||
|
otp, err = db.Provider.GetOTPByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||||
|
}
|
||||||
|
if otp == nil && err != nil {
|
||||||
|
log.Debugf("Failed to get otp request for %s: %s", currentField, err.Error())
|
||||||
|
return res, fmt.Errorf(`invalid %s: %s`, currentField, err.Error())
|
||||||
|
}
|
||||||
if params.Otp != otp.Otp {
|
if params.Otp != otp.Otp {
|
||||||
log.Debug("Failed to verify otp request: Incorrect value")
|
log.Debug("Failed to verify otp request: Incorrect value")
|
||||||
return res, fmt.Errorf(`invalid otp`)
|
return res, fmt.Errorf(`invalid otp`)
|
||||||
}
|
}
|
||||||
|
|
||||||
expiresIn := otp.ExpiresAt - time.Now().Unix()
|
expiresIn := otp.ExpiresAt - time.Now().Unix()
|
||||||
|
|
||||||
if expiresIn < 0 {
|
if expiresIn < 0 {
|
||||||
log.Debug("Failed to verify otp request: Timeout")
|
log.Debug("Failed to verify otp request: Timeout")
|
||||||
return res, fmt.Errorf("otp expired")
|
return res, fmt.Errorf("otp expired")
|
||||||
}
|
}
|
||||||
|
var user models.User
|
||||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
if currentField == models.FieldNameEmail {
|
||||||
if err != nil {
|
user, err = db.Provider.GetUserByEmail(ctx, refs.StringValue(params.Email))
|
||||||
|
} else {
|
||||||
|
// TODO fix after refs of db providers are fixed
|
||||||
|
var u *models.User
|
||||||
|
u, err = db.Provider.GetUserByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||||
|
user = *u
|
||||||
|
}
|
||||||
|
if user.ID == "" && err != nil {
|
||||||
log.Debug("Failed to get user by email: ", err)
|
log.Debug("Failed to get user by email: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
isSignUp := user.EmailVerifiedAt == nil && user.PhoneNumberVerifiedAt == nil
|
||||||
isSignUp := user.EmailVerifiedAt == nil
|
|
||||||
|
|
||||||
// TODO - Add Login method in DB when we introduce OTP for social media login
|
// TODO - Add Login method in DB when we introduce OTP for social media login
|
||||||
loginMethod := constants.AuthRecipeMethodBasicAuth
|
loginMethod := constants.AuthRecipeMethodBasicAuth
|
||||||
|
if currentField == models.FieldNamePhoneNumber {
|
||||||
|
loginMethod = constants.AuthRecipeMethodMobileOTP
|
||||||
|
}
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
scope := []string{"openid", "email", "profile"}
|
scope := []string{"openid", "email", "profile"}
|
||||||
code := ""
|
code := ""
|
||||||
|
49
server/smsproviders/twilio.go
Normal file
49
server/smsproviders/twilio.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package smsproviders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
twilio "github.com/twilio/twilio-go"
|
||||||
|
api "github.com/twilio/twilio-go/rest/api/v2010"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SendSMS util to send sms
|
||||||
|
// TODO: Should be restructured to interface when another provider is added
|
||||||
|
func SendSMS(sendTo, messageBody string) error {
|
||||||
|
twilioAPISecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwilioAPISecret)
|
||||||
|
if err != nil || twilioAPISecret == "" {
|
||||||
|
log.Debug("Failed to get api secret: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
twilioAPIKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwilioAPIKey)
|
||||||
|
if err != nil || twilioAPIKey == "" {
|
||||||
|
log.Debug("Failed to get api key: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
twilioSenderFrom, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwilioSender)
|
||||||
|
if err != nil || twilioSenderFrom == "" {
|
||||||
|
log.Debug("Failed to get sender: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// accountSID is not a must to send sms on twilio
|
||||||
|
twilioAccountSID, _ := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwilioAccountSID)
|
||||||
|
client := twilio.NewRestClientWithParams(twilio.ClientParams{
|
||||||
|
Username: twilioAPIKey,
|
||||||
|
Password: twilioAPISecret,
|
||||||
|
AccountSid: twilioAccountSID,
|
||||||
|
})
|
||||||
|
message := &api.CreateMessageParams{}
|
||||||
|
message.SetBody(messageBody)
|
||||||
|
message.SetFrom(twilioSenderFrom)
|
||||||
|
message.SetTo(sendTo)
|
||||||
|
|
||||||
|
_, err = client.Api.CreateMessage(message)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to send sms: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -46,7 +46,6 @@ func TestResolvers(t *testing.T) {
|
|||||||
|
|
||||||
for dbType, dbURL := range databases {
|
for dbType, dbURL := range databases {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseURL, dbURL)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseURL, dbURL)
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseType, dbType)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseType, dbType)
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseName, testDb)
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseName, testDb)
|
||||||
@@ -57,6 +56,11 @@ func TestResolvers(t *testing.T) {
|
|||||||
if dbType == constants.DbTypeDynamoDB {
|
if dbType == constants.DbTypeDynamoDB {
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvAwsRegion, "ap-south-1")
|
memorystore.Provider.UpdateEnvVariable(constants.EnvAwsRegion, "ap-south-1")
|
||||||
os.Setenv(constants.EnvAwsRegion, "ap-south-1")
|
os.Setenv(constants.EnvAwsRegion, "ap-south-1")
|
||||||
|
os.Unsetenv(constants.EnvAwsAccessKeyID)
|
||||||
|
os.Unsetenv(constants.EnvAwsSecretAccessKey)
|
||||||
|
// Remove aws credentials from env, so that local dynamodb can be used
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvAwsAccessKeyID, "")
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvAwsSecretAccessKey, "")
|
||||||
}
|
}
|
||||||
if dbType == constants.DbTypeCouchbaseDB {
|
if dbType == constants.DbTypeCouchbaseDB {
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseUsername, "Administrator")
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseUsername, "Administrator")
|
||||||
@@ -135,6 +139,7 @@ func TestResolvers(t *testing.T) {
|
|||||||
validateJwtTokenTest(t, s)
|
validateJwtTokenTest(t, s)
|
||||||
verifyOTPTest(t, s)
|
verifyOTPTest(t, s)
|
||||||
resendOTPTest(t, s)
|
resendOTPTest(t, s)
|
||||||
|
validateSessionTests(t, s)
|
||||||
|
|
||||||
updateAllUsersTest(t, s)
|
updateAllUsersTest(t, s)
|
||||||
webhookLogsTest(t, s) // get logs after above resolver tests are done
|
webhookLogsTest(t, s) // get logs after above resolver tests are done
|
@@ -49,6 +49,8 @@ func inviteUserTest(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, res)
|
assert.NotNil(t, res)
|
||||||
|
assert.NotNil(t, res.Message)
|
||||||
|
assert.NotNil(t, res.Users)
|
||||||
// duplicate error test
|
// duplicate error test
|
||||||
res, err = resolvers.InviteMembersResolver(ctx, model.InviteMemberInput{
|
res, err = resolvers.InviteMembersResolver(ctx, model.InviteMemberInput{
|
||||||
Emails: emails,
|
Emails: emails,
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/refs"
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
@@ -25,11 +24,6 @@ func mobileLoginTests(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, signUpRes)
|
assert.NotNil(t, signUpRes)
|
||||||
assert.Equal(t, email, signUpRes.User.Email)
|
|
||||||
assert.Equal(t, phoneNumber, refs.StringValue(signUpRes.User.PhoneNumber))
|
|
||||||
assert.True(t, strings.Contains(signUpRes.User.SignupMethods, constants.AuthRecipeMethodMobileBasicAuth))
|
|
||||||
assert.Len(t, strings.Split(signUpRes.User.SignupMethods, ","), 1)
|
|
||||||
|
|
||||||
res, err := resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
|
res, err := resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
|
||||||
PhoneNumber: phoneNumber,
|
PhoneNumber: phoneNumber,
|
||||||
Password: "random_test",
|
Password: "random_test",
|
||||||
@@ -44,15 +38,24 @@ func mobileLoginTests(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, res)
|
assert.Nil(t, res)
|
||||||
|
// should fail because phone is not verified
|
||||||
res, err = resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
|
res, err = resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
|
||||||
PhoneNumber: phoneNumber,
|
PhoneNumber: phoneNumber,
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
})
|
})
|
||||||
|
assert.NotNil(t, err, "should fail because phone is not verified")
|
||||||
|
assert.Nil(t, res)
|
||||||
|
smsRequest, err := db.Provider.GetOTPByPhoneNumber(ctx, phoneNumber)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, res.AccessToken)
|
assert.NotEmpty(t, smsRequest.Otp)
|
||||||
assert.NotEmpty(t, res.IDToken)
|
verifySMSRequest, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
||||||
|
PhoneNumber: &phoneNumber,
|
||||||
|
Otp: smsRequest.Otp,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEqual(t, verifySMSRequest.Message, "", "message should not be empty")
|
||||||
|
assert.NotEmpty(t, verifySMSRequest.AccessToken)
|
||||||
|
assert.NotEmpty(t, verifySMSRequest.IDToken)
|
||||||
cleanData(email)
|
cleanData(email)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
"github.com/authorizerdev/authorizer/server/refs"
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
@@ -65,16 +66,25 @@ func mobileSingupTest(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, res)
|
assert.Nil(t, res)
|
||||||
|
phoneNumber := "1234567890"
|
||||||
res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
|
res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
|
||||||
PhoneNumber: "1234567890",
|
PhoneNumber: phoneNumber,
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
ConfirmPassword: s.TestInfo.Password,
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, res.AccessToken)
|
assert.NotNil(t, res)
|
||||||
assert.Equal(t, "1234567890@authorizer.dev", res.User.Email)
|
assert.True(t, *res.ShouldShowOtpScreen)
|
||||||
|
// Verify with otp
|
||||||
|
otp, err := db.Provider.GetOTPByPhoneNumber(ctx, phoneNumber)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEmpty(t, otp.Otp)
|
||||||
|
otpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
||||||
|
PhoneNumber: &phoneNumber,
|
||||||
|
Otp: otp.Otp,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEmpty(t, otpRes.Message)
|
||||||
res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
|
res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
|
||||||
PhoneNumber: "1234567890",
|
PhoneNumber: "1234567890",
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
|
@@ -51,7 +51,7 @@ func resendOTPTest(t *testing.T, s TestSetup) {
|
|||||||
assert.NotNil(t, updateRes)
|
assert.NotNil(t, updateRes)
|
||||||
// Resend otp should return error as no initial opt is being sent
|
// Resend otp should return error as no initial opt is being sent
|
||||||
resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
||||||
Email: email,
|
Email: refs.NewStringRef(email),
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, resendOtpRes)
|
assert.Nil(t, resendOtpRes)
|
||||||
@@ -72,7 +72,7 @@ func resendOTPTest(t *testing.T, s TestSetup) {
|
|||||||
|
|
||||||
// resend otp
|
// resend otp
|
||||||
resendOtpRes, err = resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
resendOtpRes, err = resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
||||||
Email: email,
|
Email: refs.NewStringRef(email),
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, resendOtpRes.Message)
|
assert.NotEmpty(t, resendOtpRes.Message)
|
||||||
@@ -84,13 +84,13 @@ func resendOTPTest(t *testing.T, s TestSetup) {
|
|||||||
|
|
||||||
// Should return error for older otp
|
// Should return error for older otp
|
||||||
verifyOtpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
verifyOtpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
||||||
Email: email,
|
Email: &email,
|
||||||
Otp: otp.Otp,
|
Otp: otp.Otp,
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, verifyOtpRes)
|
assert.Nil(t, verifyOtpRes)
|
||||||
verifyOtpRes, err = resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
verifyOtpRes, err = resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
||||||
Email: email,
|
Email: &email,
|
||||||
Otp: newOtp.Otp,
|
Otp: newOtp.Otp,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@@ -126,6 +126,10 @@ func testSetup() TestSetup {
|
|||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeySmtpPassword, "test")
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeySmtpPassword, "test")
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeySenderEmail, "info@yopmail.com")
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeySenderEmail, "info@yopmail.com")
|
||||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, "admin")
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, "admin")
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyTwilioAPIKey, "test")
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyTwilioAPISecret, "test")
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyTwilioAccountSID, "test")
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyTwilioSender, "1234567890")
|
||||||
|
|
||||||
err = db.InitDB()
|
err = db.InitDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -27,7 +27,7 @@ func updateWebhookTest(t *testing.T, s TestSetup) {
|
|||||||
webhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
webhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, webhooks)
|
assert.NotNil(t, webhooks)
|
||||||
assert.Equal(t, 2, len(webhooks))
|
assert.GreaterOrEqual(t, len(webhooks), 2)
|
||||||
for _, webhook := range webhooks {
|
for _, webhook := range webhooks {
|
||||||
// it should completely replace headers
|
// it should completely replace headers
|
||||||
webhook.Headers = map[string]interface{}{
|
webhook.Headers = map[string]interface{}{
|
||||||
@@ -58,7 +58,7 @@ func updateWebhookTest(t *testing.T, s TestSetup) {
|
|||||||
// Check if webhooks with new name is as per expected len
|
// Check if webhooks with new name is as per expected len
|
||||||
accessWebhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserAccessEnabledWebhookEvent)
|
accessWebhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserAccessEnabledWebhookEvent)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 3, len(accessWebhooks))
|
assert.GreaterOrEqual(t, len(accessWebhooks), 3)
|
||||||
// Revert name change
|
// Revert name change
|
||||||
res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
||||||
ID: w.ID,
|
ID: w.ID,
|
||||||
@@ -69,7 +69,7 @@ func updateWebhookTest(t *testing.T, s TestSetup) {
|
|||||||
updatedWebhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
updatedWebhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, updatedWebhooks)
|
assert.NotNil(t, updatedWebhooks)
|
||||||
assert.Equal(t, 2, len(updatedWebhooks))
|
assert.GreaterOrEqual(t, len(updatedWebhooks), 2)
|
||||||
for _, updatedWebhook := range updatedWebhooks {
|
for _, updatedWebhook := range updatedWebhooks {
|
||||||
assert.Contains(t, refs.StringValue(updatedWebhook.EventName), constants.UserDeletedWebhookEvent)
|
assert.Contains(t, refs.StringValue(updatedWebhook.EventName), constants.UserDeletedWebhookEvent)
|
||||||
assert.Len(t, updatedWebhook.Headers, 1)
|
assert.Len(t, updatedWebhook.Headers, 1)
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -26,7 +27,7 @@ func userTest(t *testing.T, s TestSetup) {
|
|||||||
assert.NotEmpty(t, res.User)
|
assert.NotEmpty(t, res.User)
|
||||||
|
|
||||||
userRes, err := resolvers.UserResolver(ctx, model.GetUserRequest{
|
userRes, err := resolvers.UserResolver(ctx, model.GetUserRequest{
|
||||||
ID: res.User.ID,
|
ID: &res.User.ID,
|
||||||
})
|
})
|
||||||
assert.Nil(t, userRes)
|
assert.Nil(t, userRes)
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
@@ -36,14 +37,36 @@ func userTest(t *testing.T, s TestSetup) {
|
|||||||
h, err := crypto.EncryptPassword(adminSecret)
|
h, err := crypto.EncryptPassword(adminSecret)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||||
|
// Should throw error for invalid params
|
||||||
|
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{})
|
||||||
|
assert.Nil(t, userRes)
|
||||||
|
assert.NotNil(t, err, "invalid params, user id or email is required")
|
||||||
|
// Should throw error for invalid params with empty id
|
||||||
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{
|
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{
|
||||||
ID: res.User.ID,
|
ID: refs.NewStringRef(" "),
|
||||||
|
})
|
||||||
|
assert.Nil(t, userRes)
|
||||||
|
assert.NotNil(t, err, "invalid params, user id or email is required")
|
||||||
|
// Should throw error for invalid params with empty email
|
||||||
|
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{
|
||||||
|
Email: refs.NewStringRef(" "),
|
||||||
|
})
|
||||||
|
assert.Nil(t, userRes)
|
||||||
|
assert.NotNil(t, err, "invalid params, user id or email is required")
|
||||||
|
// Should get user by id
|
||||||
|
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{
|
||||||
|
ID: &res.User.ID,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, res.User.ID, userRes.ID)
|
||||||
|
assert.Equal(t, email, userRes.Email)
|
||||||
|
// Should get user by email
|
||||||
|
userRes, err = resolvers.UserResolver(ctx, model.GetUserRequest{
|
||||||
|
Email: &email,
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, res.User.ID, userRes.ID)
|
assert.Equal(t, res.User.ID, userRes.ID)
|
||||||
assert.Equal(t, email, userRes.Email)
|
assert.Equal(t, email, userRes.Email)
|
||||||
|
|
||||||
cleanData(email)
|
cleanData(email)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
61
server/test/validate_session_test.go
Normal file
61
server/test/validate_session_test.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateSessionTests tests all the validate session resolvers
|
||||||
|
func validateSessionTests(t *testing.T, s TestSetup) {
|
||||||
|
t.Helper()
|
||||||
|
t.Run(`should validate session`, func(t *testing.T) {
|
||||||
|
req, ctx := createContext(s)
|
||||||
|
email := "validate_session." + s.TestInfo.Email
|
||||||
|
|
||||||
|
resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
_, err := resolvers.ValidateSessionResolver(ctx, &model.ValidateSessionInput{})
|
||||||
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, verificationRequest)
|
||||||
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
|
Token: verificationRequest.Token,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, verifyRes)
|
||||||
|
accessToken := *verifyRes.AccessToken
|
||||||
|
assert.NotEmpty(t, accessToken)
|
||||||
|
claims, err := token.ParseJWTToken(accessToken)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, claims)
|
||||||
|
sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + verifyRes.User.ID
|
||||||
|
sessionToken, err := memorystore.Provider.GetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+claims["nonce"].(string))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, sessionToken)
|
||||||
|
cookie := fmt.Sprintf("%s=%s;", constants.AppCookieName+"_session", sessionToken)
|
||||||
|
cookie = strings.TrimSuffix(cookie, ";")
|
||||||
|
res, err := resolvers.ValidateSessionResolver(ctx, &model.ValidateSessionInput{
|
||||||
|
Cookie: sessionToken,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, res.IsValid)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
res, err = resolvers.ValidateSessionResolver(ctx, &model.ValidateSessionInput{})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, res.IsValid)
|
||||||
|
cleanData(email)
|
||||||
|
})
|
||||||
|
}
|
@@ -65,7 +65,7 @@ func verifyOTPTest(t *testing.T, s TestSetup) {
|
|||||||
assert.NotEmpty(t, otp.Otp)
|
assert.NotEmpty(t, otp.Otp)
|
||||||
|
|
||||||
verifyOtpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
verifyOtpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
||||||
Email: email,
|
Email: &email,
|
||||||
Otp: otp.Otp,
|
Otp: otp.Otp,
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
@@ -28,7 +28,7 @@ func webhookTest(t *testing.T, s TestSetup) {
|
|||||||
webhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserCreatedWebhookEvent)
|
webhooks, err := db.Provider.GetWebhookByEventName(ctx, constants.UserCreatedWebhookEvent)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, webhooks)
|
assert.NotNil(t, webhooks)
|
||||||
assert.Equal(t, 2, len(webhooks))
|
assert.GreaterOrEqual(t, len(webhooks), 2)
|
||||||
for _, webhook := range webhooks {
|
for _, webhook := range webhooks {
|
||||||
res, err := resolvers.WebhookResolver(ctx, model.WebhookRequest{
|
res, err := resolvers.WebhookResolver(ctx, model.WebhookRequest{
|
||||||
ID: webhook.ID,
|
ID: webhook.ID,
|
||||||
|
@@ -30,6 +30,6 @@ func webhooksTest(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, webhooks)
|
assert.NotEmpty(t, webhooks)
|
||||||
assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestWebhookEventTypes)*2)
|
assert.GreaterOrEqual(t, len(webhooks.Webhooks), len(s.TestInfo.TestWebhookEventTypes)*2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -92,6 +92,6 @@ func GetInviteVerificationURL(verificationURL, token, redirectURI string) string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetEmailVerificationURL to get url for invite email verification
|
// GetEmailVerificationURL to get url for invite email verification
|
||||||
func GetEmailVerificationURL(token, hostname string) string {
|
func GetEmailVerificationURL(token, hostname, redirectURI string) string {
|
||||||
return hostname + "/verify_email?token=" + token
|
return hostname + "/verify_email?token=" + token + "&redirect_uri=" + redirectURI
|
||||||
}
|
}
|
||||||
|
17
server/utils/response.go
Normal file
17
server/utils/response.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleRedirectORJsonResponse handles the response based on redirectURL
|
||||||
|
func HandleRedirectORJsonResponse(c *gin.Context, httpResponse int, response map[string]interface{}, redirectURL string) {
|
||||||
|
if strings.TrimSpace(redirectURL) == "" {
|
||||||
|
c.JSON(httpResponse, response)
|
||||||
|
} else {
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,8 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RegisterEvent util to register event
|
||||||
|
// TODO change user to user ref
|
||||||
func RegisterEvent(ctx context.Context, eventName string, authRecipe string, user models.User) error {
|
func RegisterEvent(ctx context.Context, eventName string, authRecipe string, user models.User) error {
|
||||||
webhooks, err := db.Provider.GetWebhookByEventName(ctx, eventName)
|
webhooks, err := db.Provider.GetWebhookByEventName(ctx, eventName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user