diff --git a/.env.local b/.env.local
index c9149bd..7d6a5c3 100644
--- a/.env.local
+++ b/.env.local
@@ -1,9 +1,21 @@
-NODE_ENV=development
-PORT=9001
-RABBITMQ_URL=amqp://admin:master123@rabbitmq:5672
-RABBITMQ_FILES_QUEUE=files_queue
-RABBITMQ_AUTH_QUEUE=auth_queue
-DATABASE_URL="postgresql://admin:master123@postgres:5432/user-db?schema=public"
-AWS_COGNITO_USER_POOL_ID=ap-south-1_gR5KggzuW
-AWS_COGNITO_CLIENT_ID=5vqpp7t39j2vl5lr9vjmcmurjq
-AWS_COGNITO_AUTHORITY=https://cognito-idp.ap-south-1.amazonaws.com
\ No newline at end of file
+APP_NAME="auth"
+APP_ENV="development"
+
+HTTP_ENABLE=true
+HTTP_HOST="0.0.0.0"
+HTTP_PORT=9001
+HTTP_VERSIONING_ENABLE=true
+HTTP_VERSION=1
+
+ACCESS_TOKEN_SECRET_KEY=1234567890
+ACCESS_TOKEN_EXPIRED="14d"
+
+RABBITMQ_URL="amqp://admin:master123@localhost:5672"
+RABBITMQ_FILES_QUEUE="files_queue"
+RABBITMQ_AUTH_QUEUE="auth_queue"
+
+DATABASE_URL="postgresql://admin:master123@localhost:5432/user-db?schema=public"
+
+AWS_COGNITO_USER_POOL_ID="ap-south-1_gR5KggzuW"
+AWS_COGNITO_CLIENT_ID="5vqpp7t39j2vl5lr9vjmcmurjq"
+AWS_COGNITO_AUTHORITY="https://cognito-idp.ap-south-1.amazonaws.com"
diff --git a/.husky/pre-commit b/.husky/pre-commit
index a1c8f7f..36af219 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
-npm run pre-commit
\ No newline at end of file
+npx lint-staged
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 460e6f6..0000000
--- a/.prettierrc
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "singleQuote": true,
- "trailingComma": "all",
- "useTabs": false,
- "tabWidth": 2,
- "overrides": [
- {
- "files": "*.yml",
- "options": {
- "tadWidth": 2,
- "printWidth": 40,
- "singleQuote": true
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/Dockerfile.dev b/Dockerfile.dev
index 1aca948..898541a 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -1,4 +1,4 @@
-FROM node:14 AS builder
+FROM node:16 AS builder
WORKDIR /app
diff --git a/junit.xml b/junit.xml
deleted file mode 100644
index 3e97577..0000000
--- a/junit.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
- TypeError: Cannot read property 'findUnique' of undefined
- at AppService.signup (/home/harsh-simform/nestjs-microservices/auth/src/app.service.ts:192:48)
- at Object.<anonymous> (/home/harsh-simform/nestjs-microservices/auth/src/app.service.spec.ts:60:36)
- at Promise.then.completed (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/utils.js:333:28)
- at new Promise (<anonymous>)
- at callAsyncCircusFn (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/utils.js:259:10)
- at _callCircusTest (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:277:40)
- at processTicksAndRejections (internal/process/task_queues.js:95:5)
- at _runTest (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:209:3)
- at _runTestsForDescribeBlock (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:97:9)
- at _runTestsForDescribeBlock (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:91:9)
-
-
- TypeError: Cannot read property 'findUnique' of undefined
- at AppService.login (/home/harsh-simform/nestjs-microservices/auth/src/app.service.ts:151:43)
- at Object.<anonymous> (/home/harsh-simform/nestjs-microservices/auth/src/app.service.spec.ts:66:36)
- at Promise.then.completed (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/utils.js:333:28)
- at new Promise (<anonymous>)
- at callAsyncCircusFn (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/utils.js:259:10)
- at _callCircusTest (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:277:40)
- at processTicksAndRejections (internal/process/task_queues.js:95:5)
- at _runTest (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:209:3)
- at _runTestsForDescribeBlock (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:97:9)
- at _runTestsForDescribeBlock (/home/harsh-simform/nestjs-microservices/auth/node_modules/jest-circus/build/run.js:91:9)
-
-
-
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 9b1980b..b233b54 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,18 +1,19 @@
{
- "name": "auth",
- "version": "0.0.1",
+ "name": "@backendworks/auth",
+ "version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "auth",
- "version": "0.0.1",
+ "name": "@backendworks/auth",
+ "version": "1.0.0",
"hasInstallScript": true,
- "license": "UNLICENSED",
"dependencies": {
"@aws-sdk/client-cognito-identity-provider": "^3.281.0",
"@nestjs/common": "^9.0.0",
+ "@nestjs/config": "^3.1.1",
"@nestjs/core": "^9.0.0",
+ "@nestjs/jwt": "^10.1.1",
"@nestjs/microservices": "^8.0.6",
"@nestjs/passport": "^9.0.3",
"@nestjs/platform-express": "^9.0.0",
@@ -134,6 +135,22 @@
}
}
},
+ "node_modules/@angular-devkit/core/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"node_modules/@angular-devkit/core/node_modules/rxjs": {
"version": "6.6.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
@@ -2002,22 +2019,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@eslint/eslintrc/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
"node_modules/@eslint/eslintrc/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -2035,12 +2036,6 @@
}
}
},
- "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"node_modules/@eslint/eslintrc/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -3605,6 +3600,40 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
+ "node_modules/@nestjs/config": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz",
+ "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==",
+ "dependencies": {
+ "dotenv": "16.3.1",
+ "dotenv-expand": "10.0.0",
+ "lodash": "4.17.21",
+ "uuid": "9.0.0"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
+ "reflect-metadata": "^0.1.13"
+ }
+ },
+ "node_modules/@nestjs/config/node_modules/dotenv": {
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
+ }
+ },
+ "node_modules/@nestjs/config/node_modules/uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/@nestjs/core": {
"version": "9.3.9",
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.9.tgz",
@@ -3647,6 +3676,18 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
+ "node_modules/@nestjs/jwt": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.1.1.tgz",
+ "integrity": "sha512-sISYylg8y1Mb7saxPx5Zh11i7v9JOh70CEC/rN6g43MrbFlJ57c1eYFrffxip1YAx3DmV4K67yXob3syKZMOew==",
+ "dependencies": {
+ "@types/jsonwebtoken": "9.0.2",
+ "jsonwebtoken": "9.0.0"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0"
+ }
+ },
"node_modules/@nestjs/mapped-types": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
@@ -4062,7 +4103,7 @@
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz",
"integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==",
- "dev": true,
+ "devOptional": true,
"hasInstallScript": true
},
"node_modules/@prisma/engines-version": {
@@ -4412,9 +4453,9 @@
"dev": true
},
"node_modules/@types/jsonwebtoken": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz",
- "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==",
"dependencies": {
"@types/node": "*"
}
@@ -5124,14 +5165,14 @@
}
},
"node_modules/ajv": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
- "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
@@ -5156,6 +5197,22 @@
}
}
},
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -5165,6 +5222,12 @@
"ajv": "^6.9.1"
}
},
+ "node_modules/ajv/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
"node_modules/amazon-cognito-identity-js": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.1.2.tgz",
@@ -6579,7 +6642,6 @@
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
"integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==",
- "dev": true,
"engines": {
"node": ">=12"
}
@@ -6955,22 +7017,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
- "node_modules/eslint/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
"node_modules/eslint/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -7034,12 +7080,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/eslint/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"node_modules/eslint/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -11042,7 +11082,7 @@
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz",
"integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==",
- "dev": true,
+ "devOptional": true,
"hasInstallScript": true,
"dependencies": {
"@prisma/engines": "4.10.1"
@@ -11638,28 +11678,6 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/schema-utils/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/schema-utils/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
@@ -13136,6 +13154,18 @@
"source-map": "0.7.4"
},
"dependencies": {
+ "ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
"rxjs": {
"version": "6.6.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
@@ -14698,18 +14728,6 @@
"strip-json-comments": "^3.1.1"
},
"dependencies": {
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -14719,12 +14737,6 @@
"ms": "2.1.2"
}
},
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -14906,7 +14918,8 @@
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz",
"integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@firebase/component": {
"version": "0.6.4",
@@ -15089,7 +15102,8 @@
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.1.tgz",
"integrity": "sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@firebase/functions": {
"version": "0.10.0",
@@ -15173,7 +15187,8 @@
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz",
"integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@firebase/logger": {
"version": "0.4.0",
@@ -15329,7 +15344,8 @@
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz",
"integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@firebase/util": {
"version": "1.9.3",
@@ -15951,6 +15967,29 @@
}
}
},
+ "@nestjs/config": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz",
+ "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==",
+ "requires": {
+ "dotenv": "16.3.1",
+ "dotenv-expand": "10.0.0",
+ "lodash": "4.17.21",
+ "uuid": "9.0.0"
+ },
+ "dependencies": {
+ "dotenv": {
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ=="
+ },
+ "uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
+ }
+ }
+ },
"@nestjs/core": {
"version": "9.3.9",
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.9.tgz",
@@ -15971,10 +16010,20 @@
}
}
},
+ "@nestjs/jwt": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.1.1.tgz",
+ "integrity": "sha512-sISYylg8y1Mb7saxPx5Zh11i7v9JOh70CEC/rN6g43MrbFlJ57c1eYFrffxip1YAx3DmV4K67yXob3syKZMOew==",
+ "requires": {
+ "@types/jsonwebtoken": "9.0.2",
+ "jsonwebtoken": "9.0.0"
+ }
+ },
"@nestjs/mapped-types": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
- "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg=="
+ "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==",
+ "requires": {}
},
"@nestjs/microservices": {
"version": "8.4.7",
@@ -15988,7 +16037,8 @@
"@nestjs/passport": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.3.tgz",
- "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg=="
+ "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==",
+ "requires": {}
},
"@nestjs/platform-express": {
"version": "9.3.9",
@@ -16170,7 +16220,7 @@
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz",
"integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==",
- "dev": true
+ "devOptional": true
},
"@prisma/engines-version": {
"version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19",
@@ -16515,9 +16565,9 @@
"dev": true
},
"@types/jsonwebtoken": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz",
- "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==",
"requires": {
"@types/node": "*"
}
@@ -17042,13 +17092,15 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "devOptional": true
+ "devOptional": true,
+ "requires": {}
},
"agent-base": {
"version": "6.0.2",
@@ -17084,15 +17136,23 @@
}
},
"ajv": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
- "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
+ },
+ "dependencies": {
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ }
}
},
"ajv-formats": {
@@ -17102,13 +17162,28 @@
"dev": true,
"requires": {
"ajv": "^8.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ }
}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"amazon-cognito-identity-js": {
"version": "6.1.2",
@@ -18155,8 +18230,7 @@
"dotenv-expand": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
- "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==",
- "dev": true
+ "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A=="
},
"duplexify": {
"version": "4.1.2",
@@ -18394,18 +18468,6 @@
"text-table": "^0.2.0"
},
"dependencies": {
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -18446,12 +18508,6 @@
"is-glob": "^4.0.3"
}
},
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -18464,7 +18520,8 @@
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz",
"integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-plugin-prettier": {
"version": "4.2.1",
@@ -20003,7 +20060,8 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"jest-regex-util": {
"version": "28.0.2",
@@ -20817,7 +20875,8 @@
"version": "8.6.7",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz",
"integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
- "optional": true
+ "optional": true,
+ "requires": {}
},
"marked": {
"version": "4.3.0",
@@ -21337,7 +21396,8 @@
"pg-pool": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz",
- "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w=="
+ "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==",
+ "requires": {}
},
"pg-protocol": {
"version": "1.6.0",
@@ -21509,7 +21569,7 @@
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz",
"integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==",
- "dev": true,
+ "devOptional": true,
"requires": {
"@prisma/engines": "4.10.1"
}
@@ -21937,26 +21997,6 @@
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
- },
- "dependencies": {
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- }
}
},
"semver": {
diff --git a/package.json b/package.json
index b88b85d..067e4a2 100644
--- a/package.json
+++ b/package.json
@@ -1,31 +1,31 @@
{
- "name": "auth",
- "version": "0.0.1",
+ "name": "@backendworks/auth",
+ "version": "1.0.0",
"private": true,
- "license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
- "postinstall": "npm run gen",
+ "postinstall": "npm run generate && npx typesync",
"build": "nest build",
"dev": "dotenv -e .env.local -- nest start --watch",
"debug": "nest start --debug --watch",
- "gen": "prisma generate",
+ "generate": "prisma generate",
"start": "node dist/main",
- "db:migrate": "dotenv -e .env.local -- prisma migrate dev --preview-feature",
- "db:migrate:prod": "prisma migrate deploy --preview-feature",
+ "migrate": "dotenv -e .env.local -- prisma migrate dev",
+ "migrate:prod": "prisma migrate deploy",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:e2e": "jest --config ./test/jest-e2e.json --forceExit",
- "prepare": "husky install",
- "pre-commit": "lint-staged"
+ "prepare": "husky install"
},
"dependencies": {
"@aws-sdk/client-cognito-identity-provider": "^3.281.0",
"@nestjs/common": "^9.0.0",
+ "@nestjs/config": "^3.1.1",
"@nestjs/core": "^9.0.0",
+ "@nestjs/jwt": "^10.1.1",
"@nestjs/microservices": "^8.0.6",
"@nestjs/passport": "^9.0.3",
"@nestjs/platform-express": "^9.0.0",
@@ -94,6 +94,22 @@
"tsconfig-paths": "^4.0.0",
"typescript": "^4.7.4"
},
+ "prettier": {
+ "singleQuote": true,
+ "trailingComma": "all",
+ "useTabs": false,
+ "tabWidth": 2,
+ "overrides": [
+ {
+ "files": "*.yml",
+ "options": {
+ "tadWidth": 2,
+ "printWidth": 40,
+ "singleQuote": true
+ }
+ }
+ ]
+ },
"jest": {
"moduleFileExtensions": [
"js",
diff --git a/prisma/migrations/20231031195314_password_added/migration.sql b/prisma/migrations/20231031195314_password_added/migration.sql
new file mode 100644
index 0000000..05edc77
--- /dev/null
+++ b/prisma/migrations/20231031195314_password_added/migration.sql
@@ -0,0 +1,8 @@
+/*
+ Warnings:
+
+ - Added the required column `password` to the `User` table without a default value. This is not possible if the table is not empty.
+
+*/
+-- AlterTable
+ALTER TABLE "User" ADD COLUMN "password" TEXT NOT NULL;
diff --git a/prisma/migrations/20231031200020_cognito_sub_optional/migration.sql b/prisma/migrations/20231031200020_cognito_sub_optional/migration.sql
new file mode 100644
index 0000000..05c5880
--- /dev/null
+++ b/prisma/migrations/20231031200020_cognito_sub_optional/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "User" ALTER COLUMN "cognito_sub" DROP NOT NULL;
diff --git a/prisma/migrations/20231031200454_password_optional/migration.sql b/prisma/migrations/20231031200454_password_optional/migration.sql
new file mode 100644
index 0000000..0b600a7
--- /dev/null
+++ b/prisma/migrations/20231031200454_password_optional/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "User" ALTER COLUMN "password" DROP NOT NULL;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 6f8bcb5..9207ebc 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -13,7 +13,8 @@ datasource db {
model User {
id Int @id @default(autoincrement())
email String @unique
- cognito_sub String @unique
+ password String?
+ cognito_sub String? @unique
first_name String
last_name String
is_verified Boolean @default(false)
diff --git a/src/app.controller.ts b/src/app.controller.ts
deleted file mode 100644
index 34b623d..0000000
--- a/src/app.controller.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Controller, Get } from '@nestjs/common';
-import { Public } from './core';
-import { PrismaService } from './services';
-import { HealthCheck, HealthCheckService } from '@nestjs/terminus';
-
-@Controller()
-export class AppController {
- constructor(
- private healthCheckService: HealthCheckService,
- private prismaService: PrismaService,
- ) {}
-
- @Get('/health')
- @HealthCheck()
- @Public()
- public async getHealth() {
- return this.healthCheckService.check([
- () => this.prismaService.isHealthy(),
- ]);
- }
-}
diff --git a/src/app/app.controller.ts b/src/app/app.controller.ts
new file mode 100644
index 0000000..06787f2
--- /dev/null
+++ b/src/app/app.controller.ts
@@ -0,0 +1,32 @@
+import { Controller, Get } from '@nestjs/common';
+import { HealthCheck, HealthCheckService } from '@nestjs/terminus';
+import { PrismaService } from 'src/common/services/prisma.service';
+import { Public } from 'src/core/decorators/public.decorator';
+
+@Controller()
+export class AppController {
+ constructor(
+ private readonly healthCheckService: HealthCheckService,
+ private readonly prismaService: PrismaService,
+ ) {}
+
+ // @MessagePattern('getUserById')
+ // public async getUserById(@Payload() data: string): Promise {
+ // const payload = JSON.parse(data);
+ // return this.authService.getUserById(payload.id);
+ // }
+
+ // @MessagePattern('validateToken')
+ // public async getUserByAccessToken(@Payload() token: string) {
+ // return this.jwtService.validateToken(token);
+ // }
+
+ @Get('/health')
+ @HealthCheck()
+ @Public()
+ public async getHealth() {
+ return this.healthCheckService.check([
+ () => this.prismaService.isHealthy(),
+ ]);
+ }
+}
diff --git a/src/app.module.ts b/src/app/app.module.ts
similarity index 56%
rename from src/app.module.ts
rename to src/app/app.module.ts
index 547aedb..86ad507 100644
--- a/src/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,23 +1,24 @@
import { Module } from '@nestjs/common';
import { join } from 'path';
-import { APP_GUARD } from '@nestjs/core';
import { TerminusModule } from '@nestjs/terminus';
import { AcceptLanguageResolver, I18nModule, QueryResolver } from 'nestjs-i18n';
-import { JwtService, PrismaService } from './services';
-import { JwtAuthGuard, RolesGuard } from './core';
import { PassportModule } from '@nestjs/passport';
import { AppController } from './app.controller';
-import { AuthModule } from './modules/v1/auth.module';
-import { ConfigService } from 'src/config/config.service';
+import { CoreModule } from 'src/core/core.module';
+import { CommonModule } from 'src/common/common.module';
+import { PrismaService } from 'src/common/services/prisma.service';
+import { UserModule } from 'src/modules/user/user.module';
@Module({
imports: [
- AuthModule,
+ CoreModule,
+ CommonModule,
+ UserModule,
PassportModule.register({ defaultStrategy: 'jwt' }),
I18nModule.forRoot({
fallbackLanguage: 'en',
loaderOptions: {
- path: join(__dirname, '/i18n/'),
+ path: join(__dirname, '../i18n/'),
watch: true,
},
resolvers: [
@@ -28,18 +29,6 @@ import { ConfigService } from 'src/config/config.service';
TerminusModule,
],
controllers: [AppController],
- providers: [
- JwtService,
- ConfigService,
- PrismaService,
- {
- provide: APP_GUARD,
- useClass: JwtAuthGuard,
- },
- {
- provide: APP_GUARD,
- useClass: RolesGuard,
- },
- ],
+ providers: [PrismaService],
})
export class AppModule {}
diff --git a/src/common/auth/auth.module.ts b/src/common/auth/auth.module.ts
new file mode 100644
index 0000000..3a155fe
--- /dev/null
+++ b/src/common/auth/auth.module.ts
@@ -0,0 +1,39 @@
+import { Module } from '@nestjs/common';
+import { AuthJwtAccessStrategy } from './strategies/jwt-access.strategy';
+import { AuthService } from './services/auth.service';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+import { JwtModule } from '@nestjs/jwt';
+import { APP_GUARD } from '@nestjs/core';
+import { AuthJwtAccessGuard } from './guards/jwt-access.guard';
+import { PrismaService } from '../services/prisma.service';
+import { HelperService } from './services/helper.service';
+import { AuthController } from './controllers/auth.controller';
+
+@Module({
+ imports: [
+ JwtModule.registerAsync({
+ inject: [ConfigService],
+ imports: [ConfigModule],
+ useFactory: (configService: ConfigService) => ({
+ secret: configService.get('auth.accessToken.secret'),
+ signOptions: {
+ expiresIn: configService.get(
+ 'auth.accessToken.expirationTime',
+ ),
+ },
+ }),
+ }),
+ ],
+ controllers: [AuthController],
+ providers: [
+ AuthJwtAccessStrategy,
+ AuthService,
+ PrismaService,
+ HelperService,
+ {
+ provide: APP_GUARD,
+ useClass: AuthJwtAccessGuard,
+ },
+ ],
+})
+export class AuthModule {}
diff --git a/src/common/auth/controllers/auth.controller.ts b/src/common/auth/controllers/auth.controller.ts
new file mode 100644
index 0000000..ecd10ac
--- /dev/null
+++ b/src/common/auth/controllers/auth.controller.ts
@@ -0,0 +1,30 @@
+import { Body, Controller, Get, Post } from '@nestjs/common';
+import { AuthUser } from 'src/core/decorators/auth-user.decorator';
+import { Public } from 'src/core/decorators/public.decorator';
+import { AuthService } from '../services/auth.service';
+import { UserCreateDto } from '../dtos/signup.dto';
+import { UserLoginDto } from '../dtos/login.dto';
+
+@Controller('auth')
+export class AuthController {
+ constructor(private readonly authService: AuthService) {
+ //
+ }
+
+ @Public()
+ @Post('login')
+ public login(@Body() payload: UserLoginDto) {
+ return this.authService.login(payload);
+ }
+
+ @Public()
+ @Post('signup')
+ public signup(@Body() payload: UserCreateDto) {
+ return this.authService.signup(payload);
+ }
+
+ @Get('me')
+ public me(@AuthUser() userId: number) {
+ return this.authService.me(userId);
+ }
+}
diff --git a/src/common/auth/dtos/login.dto.ts b/src/common/auth/dtos/login.dto.ts
new file mode 100644
index 0000000..159a129
--- /dev/null
+++ b/src/common/auth/dtos/login.dto.ts
@@ -0,0 +1,14 @@
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsString } from 'class-validator';
+
+export class UserLoginDto {
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'email not provided' })
+ public email: string;
+
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'password not provided' })
+ public password: string;
+}
diff --git a/src/common/auth/dtos/signup.dto.ts b/src/common/auth/dtos/signup.dto.ts
new file mode 100644
index 0000000..3634f51
--- /dev/null
+++ b/src/common/auth/dtos/signup.dto.ts
@@ -0,0 +1,24 @@
+import { ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsString } from 'class-validator';
+
+export class UserCreateDto {
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'email not provided' })
+ public email: string;
+
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'password not provided' })
+ public password: string;
+
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'firstname not provided' })
+ public firstName: string;
+
+ @ApiProperty()
+ @IsString()
+ @IsNotEmpty({ message: 'lastname not provided' })
+ public lastName: string;
+}
diff --git a/src/common/auth/guards/jwt-access.guard.ts b/src/common/auth/guards/jwt-access.guard.ts
new file mode 100644
index 0000000..d122d55
--- /dev/null
+++ b/src/common/auth/guards/jwt-access.guard.ts
@@ -0,0 +1,12 @@
+import { AuthGuard } from '@nestjs/passport';
+import { Injectable, UnauthorizedException } from '@nestjs/common';
+
+@Injectable()
+export class AuthJwtAccessGuard extends AuthGuard('jwt') {
+ handleRequest(err: Error, user: TUser, _info: Error): TUser {
+ if (err || !user) {
+ throw new UnauthorizedException('accessTokenUnauthorized');
+ }
+ return user;
+ }
+}
diff --git a/src/common/auth/interfaces/auth.response.interface.ts b/src/common/auth/interfaces/auth.response.interface.ts
new file mode 100644
index 0000000..6cc5662
--- /dev/null
+++ b/src/common/auth/interfaces/auth.response.interface.ts
@@ -0,0 +1,6 @@
+import { User } from '@prisma/client';
+
+export interface AuthResponse {
+ accessToken: string;
+ user: User;
+}
diff --git a/src/common/auth/interfaces/auth.service.interface.ts b/src/common/auth/interfaces/auth.service.interface.ts
new file mode 100644
index 0000000..87ef5cf
--- /dev/null
+++ b/src/common/auth/interfaces/auth.service.interface.ts
@@ -0,0 +1,10 @@
+import { User } from '@prisma/client';
+import { AuthResponse } from './auth.response.interface';
+import { UserLoginDto } from '../dtos/login.dto';
+import { UserCreateDto } from '../dtos/signup.dto';
+
+export interface IAuthService {
+ login(data: UserLoginDto): Promise;
+ signup(data: UserCreateDto): Promise;
+ me(id: number): Promise;
+}
diff --git a/src/common/auth/services/auth.service.ts b/src/common/auth/services/auth.service.ts
new file mode 100644
index 0000000..b11e8b9
--- /dev/null
+++ b/src/common/auth/services/auth.service.ts
@@ -0,0 +1,103 @@
+import {
+ HttpException,
+ HttpStatus,
+ Injectable,
+ NotFoundException,
+} from '@nestjs/common';
+import { IAuthService } from '../interfaces/auth.service.interface';
+import { ConfigService } from '@nestjs/config';
+import { JwtService } from '@nestjs/jwt';
+import { UserLoginDto } from '../dtos/login.dto';
+import { PrismaService } from 'src/common/services/prisma.service';
+import { HelperService } from './helper.service';
+import { UserCreateDto } from '../dtos/signup.dto';
+import { Role } from '@prisma/client';
+
+@Injectable()
+export class AuthService implements IAuthService {
+ private readonly accessTokenSecret: string;
+
+ constructor(
+ private readonly configService: ConfigService,
+ private readonly jwtService: JwtService,
+ private readonly prismaService: PrismaService,
+ private readonly helperService: HelperService,
+ ) {
+ this.accessTokenSecret = this.configService.get(
+ 'auth.accessToken.secret',
+ );
+ }
+
+ public async login(data: UserLoginDto) {
+ try {
+ const { email, password } = data;
+ const user = await this.prismaService.user.findUnique({
+ where: { email },
+ });
+ if (!user) {
+ throw new NotFoundException('userNotFound');
+ }
+ const match = this.helperService.match(user.password, password);
+ if (!match) {
+ throw new NotFoundException('invalidPassword');
+ }
+ const accessToken = this.jwtService.sign(
+ {
+ user: user.id,
+ },
+ {
+ secret: this.accessTokenSecret,
+ },
+ );
+ return {
+ accessToken,
+ user,
+ };
+ } catch (e) {
+ throw new Error(e);
+ }
+ }
+
+ public async signup(data: UserCreateDto) {
+ try {
+ const { email, firstName, lastName, password } = data;
+ const user = await this.prismaService.user.findUnique({
+ where: { email },
+ });
+ if (user) {
+ throw new HttpException('userExists', HttpStatus.CONFLICT);
+ }
+ const createdUser = await this.prismaService.user.create({
+ data: {
+ email,
+ password: this.helperService.createHash(password),
+ first_name: firstName.trim(),
+ last_name: lastName.trim(),
+ role: Role.USER,
+ },
+ });
+ const accessToken = this.jwtService.sign(
+ {
+ user: user.id,
+ },
+ {
+ secret: this.accessTokenSecret,
+ },
+ );
+ return {
+ accessToken,
+ user: createdUser,
+ };
+ } catch (e) {
+ throw new Error(e);
+ }
+ }
+
+ public async me(id: number) {
+ return this.prismaService.user.findUnique({
+ where: {
+ id,
+ },
+ });
+ }
+}
diff --git a/src/common/auth/services/helper.service.ts b/src/common/auth/services/helper.service.ts
new file mode 100644
index 0000000..506954e
--- /dev/null
+++ b/src/common/auth/services/helper.service.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@nestjs/common';
+import * as bcrypt from 'bcrypt';
+
+@Injectable()
+export class HelperService {
+ public salt: string;
+ constructor() {
+ this.salt = bcrypt.genSaltSync();
+ }
+
+ public createHash(password: string): string {
+ return bcrypt.hashSync(password, this.salt);
+ }
+
+ public match(hash: string, password: string): boolean {
+ return bcrypt.compareSync(password, hash);
+ }
+}
diff --git a/src/common/auth/strategies/jwt-access.strategy.ts b/src/common/auth/strategies/jwt-access.strategy.ts
new file mode 100644
index 0000000..88ad412
--- /dev/null
+++ b/src/common/auth/strategies/jwt-access.strategy.ts
@@ -0,0 +1,23 @@
+import { ExtractJwt, Strategy } from 'passport-jwt';
+import { PassportStrategy } from '@nestjs/passport';
+import { Injectable } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import { AuthService } from 'src/common/auth/services/auth.service';
+
+@Injectable()
+export class AuthJwtAccessStrategy extends PassportStrategy(Strategy, 'jwt') {
+ constructor(
+ private readonly configService: ConfigService,
+ private readonly authService: AuthService,
+ ) {
+ super({
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+ ignoreExpiration: false,
+ secretOrKey: configService.get('auth.accessToken.secret'),
+ });
+ }
+
+ async validate({ data }: Record): Promise> {
+ return data;
+ }
+}
diff --git a/src/common/common.module.ts b/src/common/common.module.ts
new file mode 100644
index 0000000..04d8e16
--- /dev/null
+++ b/src/common/common.module.ts
@@ -0,0 +1,23 @@
+import configs from '../config';
+import { Module } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
+import { AuthModule } from './auth/auth.module';
+import { PrismaService } from './services/prisma.service';
+import { CognitoAuthModule } from './congnito-auth/cognito-auth.module';
+
+@Module({
+ controllers: [],
+ imports: [
+ AuthModule,
+ CognitoAuthModule,
+ ConfigModule.forRoot({
+ load: configs,
+ isGlobal: true,
+ cache: true,
+ envFilePath: ['.env'],
+ expandVariables: true,
+ }),
+ ],
+ providers: [PrismaService],
+})
+export class CommonModule {}
diff --git a/src/modules/v1/auth.module.ts b/src/common/congnito-auth/cognito-auth.module.ts
similarity index 55%
rename from src/modules/v1/auth.module.ts
rename to src/common/congnito-auth/cognito-auth.module.ts
index 7870cc3..2f0a8f2 100644
--- a/src/modules/v1/auth.module.ts
+++ b/src/common/congnito-auth/cognito-auth.module.ts
@@ -1,14 +1,15 @@
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
-import { ConfigService } from '../../config/config.service';
-import { ConfigModule } from '../../config/config.module';
-import { AuthService } from './auth.service';
-import { AuthController } from './auth.controller';
-import { CognitoService, JwtService, PrismaService } from '../../services';
+import { CongnitoAuthService } from './services/cognito-auth.service';
+import { CongitoAuthController } from './controllers/cognito-auth.controller';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+import { APP_GUARD } from '@nestjs/core';
+import { JwtAuthGuard } from './guards/cognito-auth.guard';
+import { PrismaService } from '../services/prisma.service';
+import { CognitoService } from './services/cognito.service';
@Module({
imports: [
- ConfigModule,
ClientsModule.registerAsync([
{
name: 'MAIL_SERVICE',
@@ -16,8 +17,8 @@ import { CognitoService, JwtService, PrismaService } from '../../services';
useFactory: (configService: ConfigService) => ({
transport: Transport.RMQ,
options: {
- urls: [`${configService.get('rb_url')}`],
- queue: `${configService.get('mailer_queue')}`,
+ urls: [`${configService.get('rmq.uri')}`],
+ queue: `${configService.get('rmq.mailer')}`,
queueOptions: {
durable: false,
},
@@ -33,8 +34,8 @@ import { CognitoService, JwtService, PrismaService } from '../../services';
useFactory: (configService: ConfigService) => ({
transport: Transport.RMQ,
options: {
- urls: [`${configService.get('rb_url')}`],
- queue: `${configService.get('files_queue')}`,
+ urls: [`${configService.get('rmq.uri')}`],
+ queue: `${configService.get('rmq.files')}`,
queueOptions: {
durable: false,
},
@@ -50,8 +51,8 @@ import { CognitoService, JwtService, PrismaService } from '../../services';
useFactory: (configService: ConfigService) => ({
transport: Transport.RMQ,
options: {
- urls: [`${configService.get('rb_url')}`],
- queue: `${configService.get('notification_queue')}`,
+ urls: [`${configService.get('rmq.uri')}`],
+ queue: `${configService.get('rmq.notification')}`,
queueOptions: {
durable: false,
},
@@ -61,7 +62,15 @@ import { CognitoService, JwtService, PrismaService } from '../../services';
},
]),
],
- controllers: [AuthController],
- providers: [AuthService, PrismaService, CognitoService, JwtService],
+ controllers: [CongitoAuthController],
+ providers: [
+ CongnitoAuthService,
+ PrismaService,
+ CognitoService,
+ {
+ provide: APP_GUARD,
+ useClass: JwtAuthGuard,
+ },
+ ],
})
-export class AuthModule {}
+export class CognitoAuthModule {}
diff --git a/src/common/congnito-auth/controllers/cognito-auth.controller.ts b/src/common/congnito-auth/controllers/cognito-auth.controller.ts
new file mode 100644
index 0000000..725cec3
--- /dev/null
+++ b/src/common/congnito-auth/controllers/cognito-auth.controller.ts
@@ -0,0 +1,47 @@
+import { Body, Controller, Get, HttpCode, Post } from '@nestjs/common';
+import { User } from '@prisma/client';
+import { CongnitoAuthService } from '../services/cognito-auth.service';
+import { Public } from 'src/core/decorators/public.decorator';
+import { AuthUser } from 'src/core/decorators/auth-user.decorator';
+import { LoginDto } from '../dtos/cognito-login.dto';
+import { CreateUserDto } from '../dtos/cognito-signup.dto';
+import { GetOtpDto, VerifyDto } from '../dtos/cognito-verify.dto';
+
+@Controller({
+ version: '1',
+ path: '/cognito/auth',
+})
+export class CongitoAuthController {
+ constructor(private cognitoAuthService: CongnitoAuthService) {}
+
+ @Public()
+ @Post('/login')
+ login(@Body() data: LoginDto) {
+ return this.cognitoAuthService.login(data);
+ }
+
+ @Public()
+ @Post('/signup')
+ signup(@Body() data: CreateUserDto) {
+ return this.cognitoAuthService.signup(data);
+ }
+
+ @Public()
+ @Post('/verify')
+ @HttpCode(200)
+ verifyUser(@Body() data: VerifyDto) {
+ return this.cognitoAuthService.verifySignup(data);
+ }
+
+ @Public()
+ @Post('/otp')
+ @HttpCode(201)
+ getOtp(@Body() data: GetOtpDto) {
+ return this.cognitoAuthService.getOtp(data);
+ }
+
+ @Get('/me')
+ me(@AuthUser() user: User) {
+ return this.cognitoAuthService.getUserByEmail(user.email);
+ }
+}
diff --git a/src/core/dtos/login.dto.ts b/src/common/congnito-auth/dtos/cognito-login.dto.ts
similarity index 100%
rename from src/core/dtos/login.dto.ts
rename to src/common/congnito-auth/dtos/cognito-login.dto.ts
diff --git a/src/core/dtos/signup.dto.ts b/src/common/congnito-auth/dtos/cognito-signup.dto.ts
similarity index 100%
rename from src/core/dtos/signup.dto.ts
rename to src/common/congnito-auth/dtos/cognito-signup.dto.ts
diff --git a/src/core/dtos/verify.dto.ts b/src/common/congnito-auth/dtos/cognito-verify.dto.ts
similarity index 100%
rename from src/core/dtos/verify.dto.ts
rename to src/common/congnito-auth/dtos/cognito-verify.dto.ts
diff --git a/src/core/guards/auth.guard.ts b/src/common/congnito-auth/guards/cognito-auth.guard.ts
similarity index 89%
rename from src/core/guards/auth.guard.ts
rename to src/common/congnito-auth/guards/cognito-auth.guard.ts
index db3f8bc..98270ce 100644
--- a/src/core/guards/auth.guard.ts
+++ b/src/common/congnito-auth/guards/cognito-auth.guard.ts
@@ -1,7 +1,7 @@
import { ExecutionContext, Injectable } from '@nestjs/common';
-import { IS_PUBLIC_KEY } from '../decorators';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
+import { IS_PUBLIC_KEY } from 'src/core/decorators/public.decorator';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
diff --git a/src/modules/v1/auth.service.ts b/src/common/congnito-auth/services/cognito-auth.service.ts
similarity index 68%
rename from src/modules/v1/auth.service.ts
rename to src/common/congnito-auth/services/cognito-auth.service.ts
index 409727c..6a843d1 100644
--- a/src/modules/v1/auth.service.ts
+++ b/src/common/congnito-auth/services/cognito-auth.service.ts
@@ -7,24 +7,35 @@ import {
} from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { Prisma } from '@prisma/client';
-import { CognitoService, PrismaService } from '../../services';
-import { VerifyDto, GetOtpDto, LoginDto, CreateUserDto } from '../../core';
+import { PrismaService } from 'src/common/services/prisma.service';
+import { CognitoService } from './cognito.service';
+import { GetOtpDto, VerifyDto } from '../dtos/cognito-verify.dto';
+import { LoginDto } from '../dtos/cognito-login.dto';
+import { CreateUserDto } from '../dtos/cognito-signup.dto';
@Injectable()
-export class AuthService {
+export class CongnitoAuthService {
constructor(
@Inject('FILES_SERVICE') private readonly fileClient: ClientProxy,
- private prisma: PrismaService,
- private cognitoService: CognitoService,
+ private readonly prismaService: PrismaService,
+ private readonly cognitoService: CognitoService,
) {
this.fileClient.connect();
}
+ public async getUserByEmail(email) {
+ return this.prismaService.user.findUnique({ where: { email } });
+ }
+
+ public async getUserById(id: number) {
+ return this.prismaService.user.findUnique({ where: { id } });
+ }
+
public async verifySignup(data: VerifyDto) {
try {
const { email, otp } = data;
const response = await this.cognitoService.verify(email, otp);
- await this.prisma.user.update({
+ await this.prismaService.user.update({
where: { email },
data: {
is_verified: true,
@@ -52,7 +63,9 @@ export class AuthService {
email,
password,
});
- const user = await this.prisma.user.findUnique({ where: { email } });
+ const user = await this.prismaService.user.findUnique({
+ where: { email },
+ });
return {
...authResponse,
user,
@@ -69,7 +82,7 @@ export class AuthService {
email,
password,
});
- const user = await this.prisma.user.create({
+ const user = await this.prismaService.user.create({
data: {
email,
first_name: firstName?.trim(),
@@ -83,19 +96,11 @@ export class AuthService {
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2002') {
- throw new HttpException('user_exists', HttpStatus.CONFLICT);
+ throw new HttpException('userExists', HttpStatus.CONFLICT);
}
} else {
throw new BadRequestException(e.message);
}
}
}
-
- public me(email) {
- return this.prisma.user.findUnique({ where: { email } });
- }
-
- public getUserById(id: number) {
- return this.prisma.user.findUnique({ where: { id } });
- }
}
diff --git a/src/services/jwt.service.ts b/src/common/congnito-auth/services/cognito-jwt.service.ts
similarity index 72%
rename from src/services/jwt.service.ts
rename to src/common/congnito-auth/services/cognito-jwt.service.ts
index d2d1cdf..d247340 100644
--- a/src/services/jwt.service.ts
+++ b/src/common/congnito-auth/services/cognito-jwt.service.ts
@@ -3,11 +3,11 @@ import { PassportStrategy } from '@nestjs/passport';
import { passportJwtSecret } from 'jwks-rsa';
import { CognitoJwtVerifier } from 'aws-jwt-verify';
import { ExtractJwt, Strategy } from 'passport-jwt';
-import { ConfigService } from 'src/config/config.service';
-import { PrismaService } from './prisma.service';
+import { PrismaService } from '../../services/prisma.service';
+import { ConfigService } from '@nestjs/config';
@Injectable()
-export class JwtService extends PassportStrategy(Strategy) {
+export class CognitoJwtService extends PassportStrategy(Strategy) {
constructor(
private configService: ConfigService,
private prisma: PrismaService,
@@ -17,21 +17,20 @@ export class JwtService extends PassportStrategy(Strategy) {
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 3,
- jwksUri: `${configService.get('authority')}/${configService.get(
- 'cognitoUserPoolId',
- )}/.well-known/jwks.json`,
+ jwksUri: `${configService.get(
+ 'auth.cognito.authority',
+ )}/${configService.get('auth.cognito.poolId')}/.well-known/jwks.json`,
}),
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
- audience: configService.get('cognitoClientId'),
- issuer: `${configService.get('authority')}/${configService.get(
- 'cognitoUserPoolId',
- )}`,
+ audience: configService.get('auth.cognito.clientId'),
+ issuer: `${configService.get(
+ 'auth.cognito.authority',
+ )}/${configService.get('auth.cognito.poolId')}`,
algorithms: ['RS256'],
});
}
public async validate(payload: any) {
- // console.debug('JWT VALIDATION', payload);
const user = await this.prisma.user.findUnique({
where: { cognito_sub: payload?.sub },
});
@@ -41,7 +40,7 @@ export class JwtService extends PassportStrategy(Strategy) {
return user;
}
- async validateToken(accessToken: string) {
+ public async validateToken(accessToken: string) {
try {
const verifier = CognitoJwtVerifier.create({
userPoolId: this.configService.get('cognitoUserPoolId'),
diff --git a/src/services/cognito.service.ts b/src/common/congnito-auth/services/cognito.service.ts
similarity index 85%
rename from src/services/cognito.service.ts
rename to src/common/congnito-auth/services/cognito.service.ts
index 5fd2b4d..24ed201 100644
--- a/src/services/cognito.service.ts
+++ b/src/common/congnito-auth/services/cognito.service.ts
@@ -1,11 +1,11 @@
import { Injectable } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
import {
AuthenticationDetails,
CognitoUser,
CognitoUserPool,
ISignUpResult,
} from 'amazon-cognito-identity-js';
-import { ConfigService } from '../config/config.service';
@Injectable()
export class CognitoService {
@@ -13,12 +13,12 @@ export class CognitoService {
constructor(private readonly configService: ConfigService) {
this.userPool = new CognitoUserPool({
- UserPoolId: this.configService.get('cognitoUserPoolId'),
- ClientId: this.configService.get('cognitoClientId'),
+ UserPoolId: this.configService.get('auth.cognito.poolId'),
+ ClientId: this.configService.get('auth.cognito.clientId'),
});
}
- registerUser(registerRequest: {
+ public async registerUser(registerRequest: {
email: string;
password: string;
}): Promise {
@@ -31,7 +31,7 @@ export class CognitoService {
});
}
- verify(email: string, otp: string) {
+ public async verify(email: string, otp: string) {
return new Promise((resolve, reject) => {
const userData = {
Username: email,
@@ -45,7 +45,7 @@ export class CognitoService {
});
}
- sendOtpRequest(email: string) {
+ public async sendOtpRequest(email: string) {
return new Promise((resolve, reject) => {
const userData = {
Username: email,
@@ -59,7 +59,7 @@ export class CognitoService {
});
}
- authenticateUser(data: {
+ public async authenticateUser(data: {
email: string;
password: string;
}): Promise<{ accessToken: string; refreshToken: string }> {
diff --git a/src/services/prisma.service.ts b/src/common/services/prisma.service.ts
similarity index 100%
rename from src/services/prisma.service.ts
rename to src/common/services/prisma.service.ts
diff --git a/src/config/app.config.ts b/src/config/app.config.ts
new file mode 100644
index 0000000..3316799
--- /dev/null
+++ b/src/config/app.config.ts
@@ -0,0 +1,22 @@
+import { registerAs } from '@nestjs/config';
+
+export default registerAs(
+ 'app',
+ (): Record => ({
+ name: process.env.APP_NAME ?? 'auth',
+ env: process.env.APP_ENV ?? 'development',
+ versioning: {
+ enable: process.env.HTTP_VERSIONING_ENABLE === 'true' ?? false,
+ prefix: 'v',
+ version: process.env.HTTP_VERSION ?? '1',
+ },
+ globalPrefix: '/api',
+ http: {
+ enable: process.env.HTTP_ENABLE === 'true' ?? false,
+ host: process.env.HTTP_HOST ?? '0.0.0.0',
+ port: process.env.HTTP_PORT
+ ? Number.parseInt(process.env.HTTP_PORT)
+ : 9001,
+ },
+ }),
+);
diff --git a/src/config/auth.config.ts b/src/config/auth.config.ts
new file mode 100644
index 0000000..b569195
--- /dev/null
+++ b/src/config/auth.config.ts
@@ -0,0 +1,21 @@
+import { registerAs } from '@nestjs/config';
+import ms from 'ms';
+
+function seconds(msValue: string): number {
+ return ms(msValue) / 1000;
+}
+
+export default registerAs(
+ 'auth',
+ (): Record => ({
+ accessToken: {
+ secret: process.env.ACCESS_TOKEN_SECRET_KEY,
+ expirationTime: seconds(process.env.ACCESS_TOKEN_EXPIRED ?? '1h'),
+ },
+ cognito: {
+ poolId: process.env.AWS_COGNITO_USER_POOL_ID,
+ clientId: process.env.AWS_COGNITO_CLIENT_ID,
+ authority: process.env.AWS_COGNITO_AUTHORITY,
+ },
+ }),
+);
diff --git a/src/config/config.module.ts b/src/config/config.module.ts
deleted file mode 100644
index 1bc2456..0000000
--- a/src/config/config.module.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Module } from '@nestjs/common';
-import { ConfigService } from './config.service';
-
-@Module({
- imports: [],
- providers: [ConfigService],
- exports: [ConfigService],
-})
-export class ConfigModule {}
diff --git a/src/config/config.service.ts b/src/config/config.service.ts
deleted file mode 100644
index bb79cac..0000000
--- a/src/config/config.service.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Injectable } from '@nestjs/common';
-import { config } from 'dotenv';
-config();
-
-interface Config {
- env: string;
- servicePort: string;
- rb_url: string;
- auth_queue: string;
- mailer_queue: string;
- files_queue: string;
- notification_queue: string;
- cognitoUserPoolId: string;
- cognitoClientId: string;
- authority: string;
-}
-
-@Injectable()
-export class ConfigService {
- private config = {} as Config;
- constructor() {
- this.config.env = process.env.NODE_ENV;
- this.config.servicePort = process.env.PORT;
- this.config.rb_url = process.env.RABBITMQ_URL;
- this.config.auth_queue = process.env.RABBITMQ_AUTH_QUEUE;
- this.config.files_queue = process.env.RABBITMQ_FILES_QUEUE;
- this.config.cognitoClientId = process.env.AWS_COGNITO_CLIENT_ID;
- this.config.cognitoUserPoolId = process.env.AWS_COGNITO_USER_POOL_ID;
- this.config.authority = process.env.AWS_COGNITO_AUTHORITY;
- }
-
- public get(key: keyof Config): any {
- return this.config[key];
- }
-}
diff --git a/src/config/doc.config.ts b/src/config/doc.config.ts
new file mode 100644
index 0000000..62e97b9
--- /dev/null
+++ b/src/config/doc.config.ts
@@ -0,0 +1,11 @@
+import { registerAs } from '@nestjs/config';
+
+export default registerAs(
+ 'doc',
+ (): Record => ({
+ name: `${process.env.APP_NAME} APIs Specification`,
+ description: 'Auth APIs description',
+ version: '1.0',
+ prefix: '/docs',
+ }),
+);
diff --git a/src/config/index.ts b/src/config/index.ts
new file mode 100644
index 0000000..57ae122
--- /dev/null
+++ b/src/config/index.ts
@@ -0,0 +1,6 @@
+import AppConfig from './app.config';
+import AuthConfig from './auth.config';
+import DocConfig from './doc.config';
+import RmqConfig from './rmq.config';
+
+export default [AppConfig, AuthConfig, DocConfig, RmqConfig];
diff --git a/src/config/rmq.config.ts b/src/config/rmq.config.ts
new file mode 100644
index 0000000..cf05908
--- /dev/null
+++ b/src/config/rmq.config.ts
@@ -0,0 +1,10 @@
+import { registerAs } from '@nestjs/config';
+
+export default registerAs(
+ 'rmq',
+ (): Record => ({
+ uri: process.env.RABBITMQ_URL,
+ files: process.env.RABBITMQ_FILES_QUEUE,
+ auth: process.env.RABBITMQ_AUTH_QUEUE,
+ }),
+);
diff --git a/src/core/core.module.ts b/src/core/core.module.ts
new file mode 100644
index 0000000..c01b70a
--- /dev/null
+++ b/src/core/core.module.ts
@@ -0,0 +1,25 @@
+import { Module } from '@nestjs/common';
+import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
+import { RolesGuard } from './guards/roles.guard';
+import { ResponseInterceptor } from './interceptors/response.interceptor';
+import { HttpExceptionFilter } from './interceptors/exception.interceptor';
+
+@Module({
+ controllers: [],
+ imports: [],
+ providers: [
+ {
+ provide: APP_GUARD,
+ useClass: RolesGuard,
+ },
+ {
+ provide: APP_INTERCEPTOR,
+ useClass: ResponseInterceptor,
+ },
+ {
+ provide: APP_INTERCEPTOR,
+ useClass: HttpExceptionFilter,
+ },
+ ],
+})
+export class CoreModule {}
diff --git a/src/core/decorators/user.decorator.ts b/src/core/decorators/auth-user.decorator.ts
similarity index 80%
rename from src/core/decorators/user.decorator.ts
rename to src/core/decorators/auth-user.decorator.ts
index 7919497..2f6e6fc 100644
--- a/src/core/decorators/user.decorator.ts
+++ b/src/core/decorators/auth-user.decorator.ts
@@ -1,6 +1,6 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
-export const CurrentUser = createParamDecorator(
+export const AuthUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
diff --git a/src/core/decorators/index.ts b/src/core/decorators/index.ts
deleted file mode 100644
index fe8a871..0000000
--- a/src/core/decorators/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './allow.decorator';
-export * from './role.decorator';
-export * from './user.decorator';
diff --git a/src/core/decorators/allow.decorator.ts b/src/core/decorators/public.decorator.ts
similarity index 100%
rename from src/core/decorators/allow.decorator.ts
rename to src/core/decorators/public.decorator.ts
diff --git a/src/core/dtos/index.ts b/src/core/dtos/index.ts
deleted file mode 100644
index 5d4672d..0000000
--- a/src/core/dtos/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './login.dto';
-export * from './signup.dto';
-export * from './verify.dto';
diff --git a/src/core/guards/index.ts b/src/core/guards/index.ts
deleted file mode 100644
index 4ae679c..0000000
--- a/src/core/guards/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './auth.guard';
-export * from './roles.guard';
diff --git a/src/core/index.ts b/src/core/index.ts
deleted file mode 100644
index ee8e8ed..0000000
--- a/src/core/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './decorators';
-export * from './dtos';
-export * from './guards';
-export * from './interceptor';
diff --git a/src/core/interceptor/index.ts b/src/core/interceptor/index.ts
deleted file mode 100644
index 3133e8c..0000000
--- a/src/core/interceptor/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './exception.interceptor';
-export * from './response.interceptor';
diff --git a/src/core/interceptor/exception.interceptor.ts b/src/core/interceptors/exception.interceptor.ts
similarity index 100%
rename from src/core/interceptor/exception.interceptor.ts
rename to src/core/interceptors/exception.interceptor.ts
diff --git a/src/core/interceptor/response.interceptor.ts b/src/core/interceptors/response.interceptor.ts
similarity index 100%
rename from src/core/interceptor/response.interceptor.ts
rename to src/core/interceptors/response.interceptor.ts
diff --git a/src/i18n/en/translation.json b/src/i18n/en/translation.json
index 8b6c126..fd4846a 100644
--- a/src/i18n/en/translation.json
+++ b/src/i18n/en/translation.json
@@ -1,3 +1,4 @@
{
- "user_exists": "An account with email is already exists."
+ "userExists": "An account with email is already exists.",
+ "accessTokenUnauthorized": "Token is unauthorized"
}
diff --git a/src/main.ts b/src/main.ts
index 3f562c6..7f8267d 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,70 +1,55 @@
-import {
- ClassSerializerInterceptor,
- Logger,
- ValidationPipe,
-} from '@nestjs/common';
-import { NestFactory, Reflector } from '@nestjs/core';
+import { Logger, ValidationPipe, VersioningType } from '@nestjs/common';
+import { NestFactory } from '@nestjs/core';
+import { ConfigService } from '@nestjs/config';
import { Transport } from '@nestjs/microservices';
-import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
-import { AppModule } from './app.module';
-import { HttpExceptionFilter, ResponseInterceptor } from './core';
-import { ConfigService } from './config/config.service';
import { ExpressAdapter } from '@nestjs/platform-express';
-import * as express from 'express';
+import { AppModule } from './app/app.module';
+import { setupSwagger } from './swagger';
+import express from 'express';
import helmet from 'helmet';
-function configureSwagger(app): void {
- const config = new DocumentBuilder()
- .setTitle('auth-service')
- .setVersion('1.0')
- .build();
- const document = SwaggerModule.createDocument(app, config);
- SwaggerModule.setup('/api/docs', app, document);
-}
-
async function bootstrap() {
const logger = new Logger();
const app = await NestFactory.create(
AppModule,
new ExpressAdapter(express()),
{
- bufferLogs: true,
cors: true,
},
);
- app.setGlobalPrefix('/api');
- app.use(helmet());
const configService = app.get(ConfigService);
- const moduleRef = app.select(AppModule);
- const reflector = moduleRef.get(Reflector);
- app.useGlobalInterceptors(
- new ResponseInterceptor(reflector),
- new ClassSerializerInterceptor(reflector),
+ const port: number = configService.get('app.http.port');
+ const host: string = configService.get('app.http.host');
+ const globalPrefix: string = configService.get('app.globalPrefix');
+ const versioningPrefix: string = configService.get(
+ 'app.versioning.prefix',
);
- app.useGlobalFilters(new HttpExceptionFilter());
- app.useGlobalPipes(
- new ValidationPipe({
- whitelist: true,
- forbidNonWhitelisted: true,
- transform: true,
- }),
+ const version: string = configService.get('app.versioning.version');
+ const versionEnable: string = configService.get(
+ 'app.versioning.enable',
);
- configureSwagger(app);
+ app.use(helmet());
+ app.useGlobalPipes(new ValidationPipe());
+ app.setGlobalPrefix(globalPrefix);
+ if (versionEnable) {
+ app.enableVersioning({
+ type: VersioningType.URI,
+ defaultVersion: version,
+ prefix: versioningPrefix,
+ });
+ }
+ setupSwagger(app);
app.connectMicroservice({
transport: Transport.RMQ,
options: {
- urls: [`${configService.get('rb_url')}`],
- queue: `${configService.get('auth_queue')}`,
+ urls: [`${configService.get('rmq.uri')}`],
+ queue: `${configService.get('rmq.auth')}`,
queueOptions: { durable: false },
prefetchCount: 1,
},
});
await app.startAllMicroservices();
- await app.listen(configService.get('servicePort'));
- logger.log(
- `🚀 Auth service started successfully on port ${configService.get(
- 'servicePort',
- )}`,
- );
+ await app.listen(port, host);
+ logger.log(`🚀 Auth service started successfully on port ${port}`);
}
bootstrap();
diff --git a/src/modules/user/controllers/auth.controller.ts b/src/modules/user/controllers/auth.controller.ts
new file mode 100644
index 0000000..2f892fb
--- /dev/null
+++ b/src/modules/user/controllers/auth.controller.ts
@@ -0,0 +1,8 @@
+import { Controller } from '@nestjs/common';
+
+@Controller()
+export class AuthController {
+ constructor() {
+ //
+ }
+}
diff --git a/src/modules/user/controllers/user.controller.ts b/src/modules/user/controllers/user.controller.ts
new file mode 100644
index 0000000..512af07
--- /dev/null
+++ b/src/modules/user/controllers/user.controller.ts
@@ -0,0 +1,8 @@
+import { Controller } from '@nestjs/common';
+
+@Controller()
+export class UserController {
+ constructor() {
+ //
+ }
+}
diff --git a/src/modules/user/services/user.service.ts b/src/modules/user/services/user.service.ts
new file mode 100644
index 0000000..2d2b594
--- /dev/null
+++ b/src/modules/user/services/user.service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class UserService {
+ constructor() {
+ //
+ }
+}
diff --git a/src/modules/user/user.module.ts b/src/modules/user/user.module.ts
new file mode 100644
index 0000000..cb53831
--- /dev/null
+++ b/src/modules/user/user.module.ts
@@ -0,0 +1,11 @@
+import { Module } from '@nestjs/common';
+import { AuthController } from './controllers/auth.controller';
+import { UserController } from './controllers/user.controller';
+import { UserService } from './services/user.service';
+
+@Module({
+ controllers: [AuthController, UserController],
+ imports: [],
+ providers: [UserService],
+})
+export class UserModule {}
diff --git a/src/modules/v1/auth.controller.ts b/src/modules/v1/auth.controller.ts
deleted file mode 100644
index 5418f72..0000000
--- a/src/modules/v1/auth.controller.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { Body, Controller, Get, HttpCode, Post } from '@nestjs/common';
-import { MessagePattern, Payload } from '@nestjs/microservices';
-import { User } from '@prisma/client';
-import { AuthService } from './auth.service';
-import { JwtService } from '../../services';
-import {
- CreateUserDto,
- CurrentUser,
- GetOtpDto,
- LoginDto,
- Public,
- VerifyDto,
-} from '../../core';
-
-@Controller('v1')
-export class AuthController {
- constructor(private authService: AuthService, private jwt: JwtService) {}
-
- @Public()
- @Post('/login')
- login(@Body() data: LoginDto) {
- return this.authService.login(data);
- }
-
- @Public()
- @Post('/signup')
- signup(@Body() data: CreateUserDto) {
- return this.authService.signup(data);
- }
-
- @Public()
- @Post('/verify')
- @HttpCode(200)
- verifyUser(@Body() data: VerifyDto) {
- return this.authService.verifySignup(data);
- }
-
- @Public()
- @Post('/otp')
- @HttpCode(201)
- getOtp(@Body() data: GetOtpDto) {
- return this.authService.getOtp(data);
- }
-
- @Get('/me')
- me(@CurrentUser() user: User) {
- return this.authService.me(user.email);
- }
-
- @MessagePattern('get_user_by_id')
- public async getUserById(@Payload() data: string): Promise {
- const payload = JSON.parse(data);
- return this.authService.getUserById(payload.id);
- }
-
- @MessagePattern('validate_token')
- public async getUserByAccessToken(@Payload() token: string) {
- return this.jwt.validateToken(token);
- }
-}
diff --git a/src/services/firebase.service.ts b/src/services/firebase.service.ts
deleted file mode 100644
index a59a4de..0000000
--- a/src/services/firebase.service.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Injectable } from '@nestjs/common';
-import * as firebase from 'firebase-admin';
-// import * as firebaseConfig from '../../firebase.config.json';
-
-@Injectable()
-export class FirebaseService {
- private firebaseAdmin: firebase.app.App;
- constructor() {
- // const params = {
- // type: firebaseConfig.type,
- // projectId: firebaseConfig.project_id,
- // privateKeyId: firebaseConfig.private_key_id,
- // privateKey: firebaseConfig.private_key,
- // clientEmail: firebaseConfig.client_email,
- // clientId: firebaseConfig.client_id,
- // authUri: firebaseConfig.auth_uri,
- // tokenUri: firebaseConfig.token_uri,
- // authProviderX509CertUrl: firebaseConfig.auth_provider_x509_cert_url,
- // clientC509CertUrl: firebaseConfig.client_x509_cert_url,
- // };
- // this.firebaseAdmin = firebase.initializeApp({
- // credential: firebase.credential.cert(params),
- // });
- }
-
- signUp(data: {
- firstName: string;
- lastName: string;
- email: string;
- password: string;
- }) {
- const { firstName, lastName, email, password } = data;
- return this.firebaseAdmin.auth().createUser({
- displayName: `${firstName} ${lastName}`,
- email,
- emailVerified: false,
- password,
- });
- }
-}
diff --git a/src/services/index.ts b/src/services/index.ts
deleted file mode 100644
index 1d01585..0000000
--- a/src/services/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './prisma.service';
-export * from './cognito.service';
-export * from './jwt.service';
-export * from './firebase.service';
diff --git a/src/swagger.ts b/src/swagger.ts
new file mode 100644
index 0000000..ed9eb93
--- /dev/null
+++ b/src/swagger.ts
@@ -0,0 +1,44 @@
+import { Logger } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import { INestApplication } from '@nestjs/common';
+import {
+ DocumentBuilder,
+ SwaggerCustomOptions,
+ SwaggerModule,
+} from '@nestjs/swagger';
+
+export const setupSwagger = async (app: INestApplication) => {
+ const configService = app.get(ConfigService);
+ const logger = new Logger();
+
+ const docName: string = configService.get('doc.name');
+ const docDesc: string = configService.get('doc.description');
+ const docVersion: string = configService.get('doc.version');
+ const docPrefix: string = configService.get('doc.prefix');
+
+ const documentBuild = new DocumentBuilder()
+ .setTitle(docName)
+ .setDescription(docDesc)
+ .setVersion(docVersion)
+ .addTag("API's")
+ .addBearerAuth(
+ { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },
+ 'accessToken',
+ )
+ .build();
+
+ const document = SwaggerModule.createDocument(app, documentBuild, {
+ deepScanRoutes: true,
+ });
+ const customOptions: SwaggerCustomOptions = {
+ swaggerOptions: {
+ persistAuthorization: true,
+ },
+ };
+ SwaggerModule.setup(docPrefix, app, document, {
+ explorer: true,
+ customSiteTitle: docName,
+ ...customOptions,
+ });
+ logger.log(`Docs will serve on ${docPrefix}`, 'NestApplication');
+};
diff --git a/src/types/index.ts b/src/types/index.ts
deleted file mode 100644
index ad4dc96..0000000
--- a/src/types/index.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { User } from '@prisma/client';
-
-interface PaylaodType {
- emails: string[];
- subject: string;
- data: any;
-}
-
-export interface IDecodeTokenPayload {
- token: string;
-}
-
-export interface ICreateTokenPayload {
- userId: number;
-}
-
-export interface IMailPayload {
- template: keyof typeof EmailTemplates;
- payload: PaylaodType;
-}
-
-export interface IResponse {
- data: T[];
-}
-
-export interface IAuthResponse {
- accessToken: string;
- refreshToken: string;
- // user: User;
-}
-
-export interface IAuthPayload {
- userId: number;
- role: string;
-}
-
-enum EmailTemplates {
- FORGOT_PASSWORD = 'forgot-password',
-}
diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts
index f3aa9c5..43aeb95 100644
--- a/test/app.e2e-spec.ts
+++ b/test/app.e2e-spec.ts
@@ -1,9 +1,9 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HttpStatus, INestApplication } from '@nestjs/common';
import * as request from 'supertest';
-import { AppModule } from '../src/app.module';
+import { AppModule } from '../src/app/app.module';
import { faker } from '@faker-js/faker';
-import { PrismaService } from '../src/services';
+import { PrismaService } from '../src/common/services';
describe('AppController (e2e)', () => {
let app: INestApplication;
diff --git a/tsconfig.json b/tsconfig.json
index 7a64609..e31a108 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,17 +6,19 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
- "target": "es2017",
+ "useDefineForClassFields": false,
+ "target": "ESNext",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
- "strictNullChecks": false,
- "noImplicitAny": false,
- "strictBindCallApply": false,
- "forceConsistentCasingInFileNames": false,
- "noFallthroughCasesInSwitch": false,
- "resolveJsonModule": true
- }
+ "allowJs": false,
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": ["node"]
+ },
+ "include": ["src", "test"],
+ "exclude": ["node_modules", "dist", "*coverage"]
}