chore: add user get profile and check validity route
This commit is contained in:
@@ -28,3 +28,6 @@ MAIL_FROM=
|
|||||||
|
|
||||||
REDIS_URI=redis://:@localhost:6379/0
|
REDIS_URI=redis://:@localhost:6379/0
|
||||||
CACHE_TTL=120000
|
CACHE_TTL=120000
|
||||||
|
|
||||||
|
THROTTLE_TTL=300000
|
||||||
|
THROTTLE_LIMIT=10
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
name: Build and Deploy Docker Images
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEP_SERVER: "https://captain.run.danakcorp.com"
|
||||||
|
APP_TOKEN: 443dca14bd870283926a9ab3a0c6b41c463cb9423c654e9fbd9069059df9021a
|
||||||
|
APP_NAME: danak-dsc-api
|
||||||
|
GITHUB_TOKEN: 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
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repositorys
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: zmihamid
|
||||||
|
password: ${{ env.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Preset Image Name
|
||||||
|
run: echo "IMAGE_URL=$(echo ghcr.io/zmihamid/${{ github.event.repository.name }}:$(echo ${{ github.sha }} | cut -c1-7) | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build and push Docker Image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ env.IMAGE_URL }}
|
||||||
|
|
||||||
|
- name: Install CapRover CLI
|
||||||
|
run: npm install -g caprover
|
||||||
|
|
||||||
|
- name: deploy to server
|
||||||
|
run: |
|
||||||
|
caprover deploy -a $CAPROVER_APP_NAME -u $DANAK_SERVER --appToken $APP_TOKEN -i "$IMAGE_URL"
|
||||||
@@ -29,13 +29,17 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/static": "^7.0.4",
|
"@fastify/static": "^7.0.4",
|
||||||
"@keyv/redis": "^4.2.0",
|
"@keyv/redis": "^4.2.0",
|
||||||
|
"@nest-lab/throttler-storage-redis": "^1.0.0",
|
||||||
"@nestjs-modules/mailer": "^2.0.2",
|
"@nestjs-modules/mailer": "^2.0.2",
|
||||||
"@nestjs/cache-manager": "^3.0.0",
|
"@nestjs/cache-manager": "^3.0.0",
|
||||||
"@nestjs/common": "^10.4.15",
|
"@nestjs/common": "^10.4.15",
|
||||||
"@nestjs/config": "^4.0.0",
|
"@nestjs/config": "^4.0.0",
|
||||||
"@nestjs/core": "^10.4.15",
|
"@nestjs/core": "^10.4.15",
|
||||||
|
"@nestjs/jwt": "^11.0.0",
|
||||||
|
"@nestjs/passport": "^11.0.4",
|
||||||
"@nestjs/platform-fastify": "^10.4.15",
|
"@nestjs/platform-fastify": "^10.4.15",
|
||||||
"@nestjs/swagger": "^8.1.1",
|
"@nestjs/swagger": "^8.1.1",
|
||||||
|
"@nestjs/throttler": "^6.3.0",
|
||||||
"@nestjs/typeorm": "^10.0.2",
|
"@nestjs/typeorm": "^10.0.2",
|
||||||
"@types/bcrypt": "^5.0.2",
|
"@types/bcrypt": "^5.0.2",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
@@ -46,6 +50,7 @@
|
|||||||
"fastify": "^5.2.1",
|
"fastify": "^5.2.1",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"nodemailer": "^6.9.16",
|
"nodemailer": "^6.9.16",
|
||||||
|
"passport-jwt": "^4.0.1",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
@@ -60,6 +65,7 @@
|
|||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^20.17.14",
|
"@types/node": "^20.17.14",
|
||||||
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||||
"@typescript-eslint/parser": "^8.20.0",
|
"@typescript-eslint/parser": "^8.20.0",
|
||||||
|
|||||||
Generated
+276
-5
@@ -14,6 +14,9 @@ importers:
|
|||||||
'@keyv/redis':
|
'@keyv/redis':
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
|
'@nest-lab/throttler-storage-redis':
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/throttler@6.3.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2))(ioredis@5.4.2)(reflect-metadata@0.2.2)
|
||||||
'@nestjs-modules/mailer':
|
'@nestjs-modules/mailer':
|
||||||
specifier: ^2.0.2
|
specifier: ^2.0.2
|
||||||
version: 2.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(nodemailer@6.9.16)
|
version: 2.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(nodemailer@6.9.16)
|
||||||
@@ -29,15 +32,24 @@ importers:
|
|||||||
'@nestjs/core':
|
'@nestjs/core':
|
||||||
specifier: ^10.4.15
|
specifier: ^10.4.15
|
||||||
version: 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
version: 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@nestjs/jwt':
|
||||||
|
specifier: ^11.0.0
|
||||||
|
version: 11.0.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))
|
||||||
|
'@nestjs/passport':
|
||||||
|
specifier: ^11.0.4
|
||||||
|
version: 11.0.4(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(passport@0.7.0)
|
||||||
'@nestjs/platform-fastify':
|
'@nestjs/platform-fastify':
|
||||||
specifier: ^10.4.15
|
specifier: ^10.4.15
|
||||||
version: 10.4.15(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))
|
version: 10.4.15(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))
|
||||||
'@nestjs/swagger':
|
'@nestjs/swagger':
|
||||||
specifier: ^8.1.1
|
specifier: ^8.1.1
|
||||||
version: 8.1.1(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
|
version: 8.1.1(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
|
||||||
|
'@nestjs/throttler':
|
||||||
|
specifier: ^6.3.0
|
||||||
|
version: 6.3.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)
|
||||||
'@nestjs/typeorm':
|
'@nestjs/typeorm':
|
||||||
specifier: ^10.0.2
|
specifier: ^10.0.2
|
||||||
version: 10.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)(typeorm@0.3.20(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)))
|
version: 10.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)(typeorm@0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)))
|
||||||
'@types/bcrypt':
|
'@types/bcrypt':
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.2
|
||||||
version: 5.0.2
|
version: 5.0.2
|
||||||
@@ -65,6 +77,9 @@ importers:
|
|||||||
nodemailer:
|
nodemailer:
|
||||||
specifier: ^6.9.16
|
specifier: ^6.9.16
|
||||||
version: 6.9.16
|
version: 6.9.16
|
||||||
|
passport-jwt:
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1
|
||||||
pg:
|
pg:
|
||||||
specifier: ^8.13.1
|
specifier: ^8.13.1
|
||||||
version: 8.13.1
|
version: 8.13.1
|
||||||
@@ -76,7 +91,7 @@ importers:
|
|||||||
version: 7.8.1
|
version: 7.8.1
|
||||||
typeorm:
|
typeorm:
|
||||||
specifier: ^0.3.20
|
specifier: ^0.3.20
|
||||||
version: 0.3.20(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3))
|
version: 0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@commitlint/cli':
|
'@commitlint/cli':
|
||||||
specifier: ^19.6.1
|
specifier: ^19.6.1
|
||||||
@@ -102,6 +117,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20.17.14
|
specifier: ^20.17.14
|
||||||
version: 20.17.14
|
version: 20.17.14
|
||||||
|
'@types/passport-jwt':
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1
|
||||||
'@types/supertest':
|
'@types/supertest':
|
||||||
specifier: ^6.0.2
|
specifier: ^6.0.2
|
||||||
version: 6.0.2
|
version: 6.0.2
|
||||||
@@ -567,6 +585,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
||||||
deprecated: Use @eslint/object-schema instead
|
deprecated: Use @eslint/object-schema instead
|
||||||
|
|
||||||
|
'@ioredis/commands@1.2.0':
|
||||||
|
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
'@isaacs/cliui@8.0.2':
|
||||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -695,6 +716,15 @@ packages:
|
|||||||
'@microsoft/tsdoc@0.15.1':
|
'@microsoft/tsdoc@0.15.1':
|
||||||
resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
|
resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
|
||||||
|
|
||||||
|
'@nest-lab/throttler-storage-redis@1.0.0':
|
||||||
|
resolution: {integrity: sha512-k0eVe1yzTF8kgi5xQ+httwVBsNGDcq2liBLYK++ROpqiHUb7QxXet3JgERTQ4PWusyacPKz5DCtw9ijmGBx5YQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||||
|
'@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||||
|
'@nestjs/throttler': '>=6.0.0'
|
||||||
|
ioredis: '>=5.0.0'
|
||||||
|
reflect-metadata: ^0.2.1
|
||||||
|
|
||||||
'@nestjs-modules/mailer@2.0.2':
|
'@nestjs-modules/mailer@2.0.2':
|
||||||
resolution: {integrity: sha512-+z4mADQasg0H1ZaGu4zZTuKv2pu+XdErqx99PLFPzCDNTN/q9U59WPgkxVaHnsvKHNopLj5Xap7G4ZpptduoYw==}
|
resolution: {integrity: sha512-+z4mADQasg0H1ZaGu4zZTuKv2pu+XdErqx99PLFPzCDNTN/q9U59WPgkxVaHnsvKHNopLj5Xap7G4ZpptduoYw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -759,6 +789,11 @@ packages:
|
|||||||
'@nestjs/websockets':
|
'@nestjs/websockets':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@nestjs/jwt@11.0.0':
|
||||||
|
resolution: {integrity: sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||||
|
|
||||||
'@nestjs/mapped-types@2.0.6':
|
'@nestjs/mapped-types@2.0.6':
|
||||||
resolution: {integrity: sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==}
|
resolution: {integrity: sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -772,6 +807,12 @@ packages:
|
|||||||
class-validator:
|
class-validator:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@nestjs/passport@11.0.4':
|
||||||
|
resolution: {integrity: sha512-XpqLKPlo6yt0tFSAKgh1Q2j442UWhaL8qPh6GoMVTi5MsvK/uYD2aaMr3wrwyFIpH0/hjOqKC7TI5+Dw9e7/ng==}
|
||||||
|
peerDependencies:
|
||||||
|
'@nestjs/common': ^10.0.0 || ^11.0.0
|
||||||
|
passport: ^0.5.0 || ^0.6.0 || ^0.7.0
|
||||||
|
|
||||||
'@nestjs/platform-fastify@10.4.15':
|
'@nestjs/platform-fastify@10.4.15':
|
||||||
resolution: {integrity: sha512-h1raWeoQEI3Q1wLOLDTbwpObFBMbdq22DlJNyTNY1pyNDyc5K99mnhFnk+eAiM/Di+pjewv5Nh2CzPUZIguA/g==}
|
resolution: {integrity: sha512-h1raWeoQEI3Q1wLOLDTbwpObFBMbdq22DlJNyTNY1pyNDyc5K99mnhFnk+eAiM/Di+pjewv5Nh2CzPUZIguA/g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -820,6 +861,13 @@ packages:
|
|||||||
'@nestjs/platform-express':
|
'@nestjs/platform-express':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@nestjs/throttler@6.3.0':
|
||||||
|
resolution: {integrity: sha512-IqTMbl5Iyxjts7NwbVriDND0Cnr8rwNqAPpF5HJE+UV+2VrVUBwCfDXKEiXu47vzzaQLlWPYegBsGO9OXxa+oQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||||
|
'@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||||
|
reflect-metadata: ^0.1.13 || ^0.2.0
|
||||||
|
|
||||||
'@nestjs/typeorm@10.0.2':
|
'@nestjs/typeorm@10.0.2':
|
||||||
resolution: {integrity: sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==}
|
resolution: {integrity: sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -988,6 +1036,9 @@ packages:
|
|||||||
'@types/json5@0.0.29':
|
'@types/json5@0.0.29':
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.7':
|
||||||
|
resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==}
|
||||||
|
|
||||||
'@types/methods@1.1.4':
|
'@types/methods@1.1.4':
|
||||||
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
||||||
|
|
||||||
@@ -1003,6 +1054,15 @@ packages:
|
|||||||
'@types/node@20.17.14':
|
'@types/node@20.17.14':
|
||||||
resolution: {integrity: sha512-w6qdYetNL5KRBiSClK/KWai+2IMEJuAj+EujKCumalFOwXtvOXaEan9AuwcRID2IcOIAWSIfR495hBtgKlx2zg==}
|
resolution: {integrity: sha512-w6qdYetNL5KRBiSClK/KWai+2IMEJuAj+EujKCumalFOwXtvOXaEan9AuwcRID2IcOIAWSIfR495hBtgKlx2zg==}
|
||||||
|
|
||||||
|
'@types/passport-jwt@4.0.1':
|
||||||
|
resolution: {integrity: sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==}
|
||||||
|
|
||||||
|
'@types/passport-strategy@0.2.38':
|
||||||
|
resolution: {integrity: sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==}
|
||||||
|
|
||||||
|
'@types/passport@1.0.17':
|
||||||
|
resolution: {integrity: sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==}
|
||||||
|
|
||||||
'@types/pug@2.0.10':
|
'@types/pug@2.0.10':
|
||||||
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
|
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
|
||||||
|
|
||||||
@@ -1403,6 +1463,9 @@ packages:
|
|||||||
bser@2.1.1:
|
bser@2.1.1:
|
||||||
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@@ -1776,6 +1839,10 @@ packages:
|
|||||||
delegates@1.0.0:
|
delegates@1.0.0:
|
||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
|
|
||||||
|
denque@2.1.0:
|
||||||
|
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
depd@2.0.0:
|
depd@2.0.0:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -1871,6 +1938,9 @@ packages:
|
|||||||
eastasianwidth@0.2.0:
|
eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
editorconfig@1.0.4:
|
editorconfig@1.0.4:
|
||||||
resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==}
|
resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -2553,6 +2623,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
ioredis@5.4.2:
|
||||||
|
resolution: {integrity: sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==}
|
||||||
|
engines: {node: '>=12.22.0'}
|
||||||
|
|
||||||
ipaddr.js@1.9.1:
|
ipaddr.js@1.9.1:
|
||||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@@ -2981,6 +3055,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
||||||
engines: {'0': node >= 0.2.0}
|
engines: {'0': node >= 0.2.0}
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.2:
|
||||||
|
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
||||||
|
engines: {node: '>=12', npm: '>=6'}
|
||||||
|
|
||||||
jstransformer@1.0.0:
|
jstransformer@1.0.0:
|
||||||
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
||||||
|
|
||||||
@@ -2989,6 +3067,12 @@ packages:
|
|||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
jwa@1.4.1:
|
||||||
|
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
|
||||||
|
|
||||||
|
jws@3.2.2:
|
||||||
|
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
@@ -3071,9 +3155,30 @@ packages:
|
|||||||
lodash.camelcase@4.3.0:
|
lodash.camelcase@4.3.0:
|
||||||
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
||||||
|
|
||||||
|
lodash.defaults@4.2.0:
|
||||||
|
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
|
||||||
|
|
||||||
|
lodash.includes@4.3.0:
|
||||||
|
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||||
|
|
||||||
|
lodash.isarguments@3.1.0:
|
||||||
|
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3:
|
||||||
|
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4:
|
||||||
|
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3:
|
||||||
|
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||||
|
|
||||||
lodash.isplainobject@4.0.6:
|
lodash.isplainobject@4.0.6:
|
||||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||||
|
|
||||||
lodash.kebabcase@4.1.1:
|
lodash.kebabcase@4.1.1:
|
||||||
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
|
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
|
||||||
|
|
||||||
@@ -3086,6 +3191,9 @@ packages:
|
|||||||
lodash.mergewith@4.6.2:
|
lodash.mergewith@4.6.2:
|
||||||
resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==}
|
resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==}
|
||||||
|
|
||||||
|
lodash.once@4.1.1:
|
||||||
|
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||||
|
|
||||||
lodash.snakecase@4.1.1:
|
lodash.snakecase@4.1.1:
|
||||||
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
|
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
|
||||||
|
|
||||||
@@ -3580,6 +3688,17 @@ packages:
|
|||||||
parseley@0.12.1:
|
parseley@0.12.1:
|
||||||
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
|
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
|
||||||
|
|
||||||
|
passport-jwt@4.0.1:
|
||||||
|
resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==}
|
||||||
|
|
||||||
|
passport-strategy@1.0.0:
|
||||||
|
resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
|
passport@0.7.0:
|
||||||
|
resolution: {integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
path-exists@4.0.0:
|
path-exists@4.0.0:
|
||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -3621,6 +3740,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
pause@0.0.1:
|
||||||
|
resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
|
||||||
|
|
||||||
peberminta@0.9.0:
|
peberminta@0.9.0:
|
||||||
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
|
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
|
||||||
|
|
||||||
@@ -3839,6 +3961,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
|
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
|
||||||
engines: {node: '>= 12.13.0'}
|
engines: {node: '>= 12.13.0'}
|
||||||
|
|
||||||
|
redis-errors@1.2.0:
|
||||||
|
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
redis-parser@3.0.0:
|
||||||
|
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
redis@4.7.0:
|
redis@4.7.0:
|
||||||
resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==}
|
resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==}
|
||||||
|
|
||||||
@@ -4110,6 +4240,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
|
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
standard-as-callback@2.1.0:
|
||||||
|
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
|
||||||
|
|
||||||
statuses@2.0.1:
|
statuses@2.0.1:
|
||||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -4512,6 +4645,10 @@ packages:
|
|||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
|
utils-merge@1.0.1:
|
||||||
|
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
uuid@9.0.1:
|
uuid@9.0.1:
|
||||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -5183,6 +5320,8 @@ snapshots:
|
|||||||
|
|
||||||
'@humanwhocodes/object-schema@2.0.3': {}
|
'@humanwhocodes/object-schema@2.0.3': {}
|
||||||
|
|
||||||
|
'@ioredis/commands@1.2.0': {}
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
'@isaacs/cliui@8.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width: 5.1.2
|
string-width: 5.1.2
|
||||||
@@ -5426,6 +5565,15 @@ snapshots:
|
|||||||
|
|
||||||
'@microsoft/tsdoc@0.15.1': {}
|
'@microsoft/tsdoc@0.15.1': {}
|
||||||
|
|
||||||
|
'@nest-lab/throttler-storage-redis@1.0.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/throttler@6.3.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2))(ioredis@5.4.2)(reflect-metadata@0.2.2)':
|
||||||
|
dependencies:
|
||||||
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@nestjs/throttler': 6.3.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)
|
||||||
|
ioredis: 5.4.2
|
||||||
|
reflect-metadata: 0.2.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@nestjs-modules/mailer@2.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(nodemailer@6.9.16)':
|
'@nestjs-modules/mailer@2.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(nodemailer@6.9.16)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@css-inline/css-inline': 0.14.1
|
'@css-inline/css-inline': 0.14.1
|
||||||
@@ -5512,6 +5660,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
|
|
||||||
|
'@nestjs/jwt@11.0.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))':
|
||||||
|
dependencies:
|
||||||
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@types/jsonwebtoken': 9.0.7
|
||||||
|
jsonwebtoken: 9.0.2
|
||||||
|
|
||||||
'@nestjs/mapped-types@2.0.6(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
|
'@nestjs/mapped-types@2.0.6(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
@@ -5520,6 +5674,11 @@ snapshots:
|
|||||||
class-transformer: 0.5.1
|
class-transformer: 0.5.1
|
||||||
class-validator: 0.14.1
|
class-validator: 0.14.1
|
||||||
|
|
||||||
|
'@nestjs/passport@11.0.4(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(passport@0.7.0)':
|
||||||
|
dependencies:
|
||||||
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
passport: 0.7.0
|
||||||
|
|
||||||
'@nestjs/platform-fastify@10.4.15(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))':
|
'@nestjs/platform-fastify@10.4.15(@fastify/static@7.0.4)(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fastify/cors': 9.0.1
|
'@fastify/cors': 9.0.1
|
||||||
@@ -5578,13 +5737,19 @@ snapshots:
|
|||||||
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@nestjs/typeorm@10.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)(typeorm@0.3.20(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)))':
|
'@nestjs/throttler@6.3.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)':
|
||||||
|
dependencies:
|
||||||
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
reflect-metadata: 0.2.2
|
||||||
|
|
||||||
|
'@nestjs/typeorm@10.0.2(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)(typeorm@0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
'@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
reflect-metadata: 0.2.2
|
reflect-metadata: 0.2.2
|
||||||
rxjs: 7.8.1
|
rxjs: 7.8.1
|
||||||
typeorm: 0.3.20(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3))
|
typeorm: 0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3))
|
||||||
uuid: 9.0.1
|
uuid: 9.0.1
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
@@ -5765,6 +5930,10 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json5@0.0.29': {}
|
'@types/json5@0.0.29': {}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.7':
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 20.17.14
|
||||||
|
|
||||||
'@types/methods@1.1.4': {}
|
'@types/methods@1.1.4': {}
|
||||||
|
|
||||||
'@types/mime@1.3.5': {}
|
'@types/mime@1.3.5': {}
|
||||||
@@ -5781,6 +5950,20 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.19.8
|
undici-types: 6.19.8
|
||||||
|
|
||||||
|
'@types/passport-jwt@4.0.1':
|
||||||
|
dependencies:
|
||||||
|
'@types/jsonwebtoken': 9.0.7
|
||||||
|
'@types/passport-strategy': 0.2.38
|
||||||
|
|
||||||
|
'@types/passport-strategy@0.2.38':
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 5.0.0
|
||||||
|
'@types/passport': 1.0.17
|
||||||
|
|
||||||
|
'@types/passport@1.0.17':
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 5.0.0
|
||||||
|
|
||||||
'@types/pug@2.0.10':
|
'@types/pug@2.0.10':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -6300,6 +6483,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
node-int64: 0.4.0
|
node-int64: 0.4.0
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
@@ -6693,6 +6878,8 @@ snapshots:
|
|||||||
|
|
||||||
delegates@1.0.0: {}
|
delegates@1.0.0: {}
|
||||||
|
|
||||||
|
denque@2.1.0: {}
|
||||||
|
|
||||||
depd@2.0.0: {}
|
depd@2.0.0: {}
|
||||||
|
|
||||||
dequal@2.0.3: {}
|
dequal@2.0.3: {}
|
||||||
@@ -6797,6 +6984,10 @@ snapshots:
|
|||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
editorconfig@1.0.4:
|
editorconfig@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@one-ini/wasm': 0.1.1
|
'@one-ini/wasm': 0.1.1
|
||||||
@@ -7683,6 +7874,20 @@ snapshots:
|
|||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
side-channel: 1.1.0
|
side-channel: 1.1.0
|
||||||
|
|
||||||
|
ioredis@5.4.2:
|
||||||
|
dependencies:
|
||||||
|
'@ioredis/commands': 1.2.0
|
||||||
|
cluster-key-slot: 1.1.2
|
||||||
|
debug: 4.4.0
|
||||||
|
denque: 2.1.0
|
||||||
|
lodash.defaults: 4.2.0
|
||||||
|
lodash.isarguments: 3.1.0
|
||||||
|
redis-errors: 1.2.0
|
||||||
|
redis-parser: 3.0.0
|
||||||
|
standard-as-callback: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
ipaddr.js@1.9.1: {}
|
ipaddr.js@1.9.1: {}
|
||||||
|
|
||||||
ipaddr.js@2.2.0: {}
|
ipaddr.js@2.2.0: {}
|
||||||
@@ -8290,6 +8495,19 @@ snapshots:
|
|||||||
|
|
||||||
jsonparse@1.3.1: {}
|
jsonparse@1.3.1: {}
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.2:
|
||||||
|
dependencies:
|
||||||
|
jws: 3.2.2
|
||||||
|
lodash.includes: 4.3.0
|
||||||
|
lodash.isboolean: 3.0.3
|
||||||
|
lodash.isinteger: 4.0.4
|
||||||
|
lodash.isnumber: 3.0.3
|
||||||
|
lodash.isplainobject: 4.0.6
|
||||||
|
lodash.isstring: 4.0.1
|
||||||
|
lodash.once: 4.1.1
|
||||||
|
ms: 2.1.3
|
||||||
|
semver: 7.6.3
|
||||||
|
|
||||||
jstransformer@1.0.0:
|
jstransformer@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-promise: 2.2.2
|
is-promise: 2.2.2
|
||||||
@@ -8307,6 +8525,17 @@ snapshots:
|
|||||||
- encoding
|
- encoding
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
jwa@1.4.1:
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
jws@3.2.2:
|
||||||
|
dependencies:
|
||||||
|
jwa: 1.4.1
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
@@ -8409,8 +8638,22 @@ snapshots:
|
|||||||
|
|
||||||
lodash.camelcase@4.3.0: {}
|
lodash.camelcase@4.3.0: {}
|
||||||
|
|
||||||
|
lodash.defaults@4.2.0: {}
|
||||||
|
|
||||||
|
lodash.includes@4.3.0: {}
|
||||||
|
|
||||||
|
lodash.isarguments@3.1.0: {}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3: {}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4: {}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3: {}
|
||||||
|
|
||||||
lodash.isplainobject@4.0.6: {}
|
lodash.isplainobject@4.0.6: {}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1: {}
|
||||||
|
|
||||||
lodash.kebabcase@4.1.1: {}
|
lodash.kebabcase@4.1.1: {}
|
||||||
|
|
||||||
lodash.memoize@4.1.2: {}
|
lodash.memoize@4.1.2: {}
|
||||||
@@ -8419,6 +8662,8 @@ snapshots:
|
|||||||
|
|
||||||
lodash.mergewith@4.6.2: {}
|
lodash.mergewith@4.6.2: {}
|
||||||
|
|
||||||
|
lodash.once@4.1.1: {}
|
||||||
|
|
||||||
lodash.snakecase@4.1.1: {}
|
lodash.snakecase@4.1.1: {}
|
||||||
|
|
||||||
lodash.startcase@4.4.0: {}
|
lodash.startcase@4.4.0: {}
|
||||||
@@ -9152,6 +9397,19 @@ snapshots:
|
|||||||
peberminta: 0.9.0
|
peberminta: 0.9.0
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
passport-jwt@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
jsonwebtoken: 9.0.2
|
||||||
|
passport-strategy: 1.0.0
|
||||||
|
|
||||||
|
passport-strategy@1.0.0: {}
|
||||||
|
|
||||||
|
passport@0.7.0:
|
||||||
|
dependencies:
|
||||||
|
passport-strategy: 1.0.0
|
||||||
|
pause: 0.0.1
|
||||||
|
utils-merge: 1.0.1
|
||||||
|
|
||||||
path-exists@4.0.0: {}
|
path-exists@4.0.0: {}
|
||||||
|
|
||||||
path-exists@5.0.0: {}
|
path-exists@5.0.0: {}
|
||||||
@@ -9178,6 +9436,8 @@ snapshots:
|
|||||||
|
|
||||||
path-type@4.0.0: {}
|
path-type@4.0.0: {}
|
||||||
|
|
||||||
|
pause@0.0.1: {}
|
||||||
|
|
||||||
peberminta@0.9.0:
|
peberminta@0.9.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -9437,6 +9697,12 @@ snapshots:
|
|||||||
|
|
||||||
real-require@0.2.0: {}
|
real-require@0.2.0: {}
|
||||||
|
|
||||||
|
redis-errors@1.2.0: {}
|
||||||
|
|
||||||
|
redis-parser@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
redis-errors: 1.2.0
|
||||||
|
|
||||||
redis@4.7.0:
|
redis@4.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@redis/bloom': 1.2.0(@redis/client@1.6.0)
|
'@redis/bloom': 1.2.0(@redis/client@1.6.0)
|
||||||
@@ -9723,6 +9989,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp: 2.0.0
|
escape-string-regexp: 2.0.0
|
||||||
|
|
||||||
|
standard-as-callback@2.1.0: {}
|
||||||
|
|
||||||
statuses@2.0.1: {}
|
statuses@2.0.1: {}
|
||||||
|
|
||||||
string-argv@0.3.2: {}
|
string-argv@0.3.2: {}
|
||||||
@@ -10036,7 +10304,7 @@ snapshots:
|
|||||||
possible-typed-array-names: 1.0.0
|
possible-typed-array-names: 1.0.0
|
||||||
reflect.getprototypeof: 1.0.10
|
reflect.getprototypeof: 1.0.10
|
||||||
|
|
||||||
typeorm@0.3.20(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)):
|
typeorm@0.3.20(ioredis@5.4.2)(pg@8.13.1)(redis@4.7.0)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sqltools/formatter': 1.2.5
|
'@sqltools/formatter': 1.2.5
|
||||||
app-root-path: 3.1.0
|
app-root-path: 3.1.0
|
||||||
@@ -10054,6 +10322,7 @@ snapshots:
|
|||||||
uuid: 9.0.1
|
uuid: 9.0.1
|
||||||
yargs: 17.7.2
|
yargs: 17.7.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
ioredis: 5.4.2
|
||||||
pg: 8.13.1
|
pg: 8.13.1
|
||||||
redis: 4.7.0
|
redis: 4.7.0
|
||||||
ts-node: 10.9.2(@types/node@20.17.14)(typescript@5.7.3)
|
ts-node: 10.9.2(@types/node@20.17.14)(typescript@5.7.3)
|
||||||
@@ -10102,6 +10371,8 @@ snapshots:
|
|||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
|
utils-merge@1.0.1: {}
|
||||||
|
|
||||||
uuid@9.0.1: {}
|
uuid@9.0.1: {}
|
||||||
|
|
||||||
v8-compile-cache-lib@3.0.1: {}
|
v8-compile-cache-lib@3.0.1: {}
|
||||||
|
|||||||
+5
-2
@@ -1,10 +1,12 @@
|
|||||||
import { CacheModule } from "@nestjs/cache-manager";
|
import { CacheModule } from "@nestjs/cache-manager";
|
||||||
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
|
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
|
||||||
import { ConfigModule } from "@nestjs/config";
|
import { ConfigModule } from "@nestjs/config";
|
||||||
|
import { ThrottlerModule } from "@nestjs/throttler";
|
||||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
|
|
||||||
import { cacheConfig } from "./configs/cache.config";
|
import { cacheConfig } from "./configs/cache.config";
|
||||||
import { DatabaseConfigs } from "./configs/typeorm.config";
|
import { rateLimitConfig } from "./configs/rateLimit.config";
|
||||||
|
import { databaseConfigs } from "./configs/typeorm.config";
|
||||||
import { HTTPLogger } from "./core/middlewares/logger.middleware";
|
import { HTTPLogger } from "./core/middlewares/logger.middleware";
|
||||||
import { AuthModule } from "./modules/auth/auth.module";
|
import { AuthModule } from "./modules/auth/auth.module";
|
||||||
import { TicketsModule } from "./modules/tickets/tickets.module";
|
import { TicketsModule } from "./modules/tickets/tickets.module";
|
||||||
@@ -12,9 +14,10 @@ import { UsersModule } from "./modules/users/users.module";
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
ThrottlerModule.forRootAsync(rateLimitConfig()),
|
||||||
ConfigModule.forRoot({ cache: true, isGlobal: true }),
|
ConfigModule.forRoot({ cache: true, isGlobal: true }),
|
||||||
CacheModule.registerAsync(cacheConfig()),
|
CacheModule.registerAsync(cacheConfig()),
|
||||||
TypeOrmModule.forRootAsync(DatabaseConfigs()),
|
TypeOrmModule.forRootAsync(databaseConfigs()),
|
||||||
UsersModule,
|
UsersModule,
|
||||||
TicketsModule,
|
TicketsModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// export const AUTH_THROTTLE = "AUTH_THROTTLE";
|
||||||
|
export const AUTH_THROTTLE_TTL = 5 * 60 * 1000;
|
||||||
|
export const AUTH_THROTTLE_LIMIT = 5;
|
||||||
|
export const JWT_STRATEGY_NAME = "jwt_Strategy";
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { UseGuards, applyDecorators } from "@nestjs/common";
|
||||||
|
import { ApiBearerAuth } from "@nestjs/swagger";
|
||||||
|
|
||||||
|
import { JwtAuthGuard } from "../../modules/auth/guards/auth.guard";
|
||||||
|
import { RoleGuard } from "../../modules/auth/guards/role.guard";
|
||||||
|
|
||||||
|
export function AuthGuards() {
|
||||||
|
return applyDecorators(UseGuards(JwtAuthGuard, RoleGuard), ApiBearerAuth("authorization"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { SetMetadata } from "@nestjs/common";
|
||||||
|
|
||||||
|
export const ROLES_KEY = "roles";
|
||||||
|
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { ExecutionContext, createParamDecorator } from "@nestjs/common";
|
||||||
|
import { FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
import { User } from "../../modules/users/entities/user.entity";
|
||||||
|
|
||||||
|
declare module "fastify" {
|
||||||
|
interface FastifyRequest {
|
||||||
|
user?: Omit<User, "password">;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UserDec = createParamDecorator((_data: unknown, ctx: ExecutionContext) => {
|
||||||
|
const req = ctx.switchToHttp().getRequest<FastifyRequest>();
|
||||||
|
return req.user;
|
||||||
|
});
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export const enum AuthMessage {
|
export const enum AuthMessage {
|
||||||
|
UNAUTHORIZED_ACCESS = "شما دسترسی لازم برای این عملیات را ندارید.",
|
||||||
PHONE_REGISTERED = "شماره ثبت شد",
|
PHONE_REGISTERED = "شماره ثبت شد",
|
||||||
INVALID_PHONE_FORMAT = "فرمت شماره تلفن صحیح نیست",
|
INVALID_PHONE_FORMAT = "فرمت شماره تلفن صحیح نیست",
|
||||||
OTP_SENT = "کد یکبار مصرف به شماره شما ارسال شد.",
|
OTP_SENT = "کد یکبار مصرف به شماره شما ارسال شد.",
|
||||||
@@ -20,7 +21,7 @@ export const enum AuthMessage {
|
|||||||
USER_EXISTS = "با این شماره قبلا ثبت نام شده است",
|
USER_EXISTS = "با این شماره قبلا ثبت نام شده است",
|
||||||
USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود",
|
USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود",
|
||||||
INVALID_USER = "کاربری با این مشخصات یافت نشد",
|
INVALID_USER = "کاربری با این مشخصات یافت نشد",
|
||||||
PHONE_NOT_FOUND = "کاربری با این آیدی یافت نشد",
|
PHONE_NOT_FOUND = "کاربری با این شماره یافت نشد",
|
||||||
TOKEN_EXPIRED = "توکن منقضی شده است",
|
TOKEN_EXPIRED = "توکن منقضی شده است",
|
||||||
TOKEN_INVALID = "توکن نامعتبر است",
|
TOKEN_INVALID = "توکن نامعتبر است",
|
||||||
BANNED = "در حال حاضر شما امکان دسترسی به این سرویس را ندارید",
|
BANNED = "در حال حاضر شما امکان دسترسی به این سرویس را ندارید",
|
||||||
@@ -46,9 +47,19 @@ export const enum AuthMessage {
|
|||||||
BIRTH_DATE_NOT_EMPTY = "تاریخ تولد نمیتواند خالی باشد",
|
BIRTH_DATE_NOT_EMPTY = "تاریخ تولد نمیتواند خالی باشد",
|
||||||
NATIONAL_CODE_INCORRECT = "کد ملی باید ۱۰ رقمی باشد",
|
NATIONAL_CODE_INCORRECT = "کد ملی باید ۱۰ رقمی باشد",
|
||||||
NATIONAL_NOT_EMPTY = "کد ملی نمیتواند خالی باشد",
|
NATIONAL_NOT_EMPTY = "کد ملی نمیتواند خالی باشد",
|
||||||
|
OTP_ALREADY_SENT = "کد یکبار مصرف قبلا ارسال شده است",
|
||||||
|
TOO_MANY_REQUESTS = "تعداد درخواست های شما بیش از حد مجاز است",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum UserMessage {
|
export const enum UserMessage {
|
||||||
USER_NOT_FOUND = "کاربری با این مشخصات یافت نشد",
|
USER_NOT_FOUND = "کاربری با این مشخصات یافت نشد",
|
||||||
EMAIL_EXIST = "ایمیل قبلا ثبت شده است",
|
EMAIL_EXIST = "ایمیل قبلا ثبت شده است",
|
||||||
|
ROLE_NOT_FOUND = "نقش یافت نشد",
|
||||||
|
USER_EXISTS = "کاربر با این مشخصات وجود دارد",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum CommonMessage {
|
||||||
|
VALIDITY_TYPE_REQUIRED = "نوع اعتبار سنجی مورد نیاز است",
|
||||||
|
THIS_FILED_IS_REQUIRED = "این فیلد الزامی است",
|
||||||
|
VALID_FOR_CHOOSE = "معتبر برای انتخاب",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
import { JwtModuleAsyncOptions } from "@nestjs/jwt";
|
||||||
|
|
||||||
|
export function jwtConfig(): JwtModuleAsyncOptions {
|
||||||
|
return {
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: (configService: ConfigService) => ({
|
||||||
|
secret: configService.getOrThrow<string>("JWT_SECRET_KEY"),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { ThrottlerStorageRedisService } from "@nest-lab/throttler-storage-redis";
|
||||||
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
import { ThrottlerAsyncOptions } from "@nestjs/throttler";
|
||||||
|
|
||||||
|
import { AuthMessage } from "../common/enums/message.enum";
|
||||||
|
|
||||||
|
export function rateLimitConfig(): ThrottlerAsyncOptions {
|
||||||
|
return {
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: (configService: ConfigService) => ({
|
||||||
|
throttlers: [
|
||||||
|
{
|
||||||
|
ttl: configService.getOrThrow("THROTTLE_TTL"),
|
||||||
|
limit: configService.getOrThrow("THROTTLE_LIMIT"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
errorMessage: AuthMessage.TOO_MANY_REQUESTS,
|
||||||
|
storage: new ThrottlerStorageRedisService(configService.getOrThrow("REDIS_URI")),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
|
||||||
export function SmsConfigs() {
|
export function smsConfigs() {
|
||||||
return {
|
return {
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
useFactory(configService: ConfigService) {
|
useFactory(configService: ConfigService) {
|
||||||
|
|||||||
@@ -5,6 +5,17 @@ export function getSwaggerDocument(app: NestFastifyApplication) {
|
|||||||
const swaggerConfig = new DocumentBuilder()
|
const swaggerConfig = new DocumentBuilder()
|
||||||
.setTitle("The Danak dsc api document")
|
.setTitle("The Danak dsc api document")
|
||||||
.setDescription("The Danak dsc API description")
|
.setDescription("The Danak dsc API description")
|
||||||
|
.addBearerAuth(
|
||||||
|
{
|
||||||
|
type: "http",
|
||||||
|
scheme: "bearer",
|
||||||
|
bearerFormat: "JWT",
|
||||||
|
name: "authorization",
|
||||||
|
in: "header",
|
||||||
|
},
|
||||||
|
"authorization",
|
||||||
|
)
|
||||||
|
|
||||||
.setVersion("1.0.0")
|
.setVersion("1.0.0")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
import { TypeOrmModuleAsyncOptions } from "@nestjs/typeorm";
|
import { TypeOrmModuleAsyncOptions } from "@nestjs/typeorm";
|
||||||
|
|
||||||
export function DatabaseConfigs(): TypeOrmModuleAsyncOptions {
|
export function databaseConfigs(): TypeOrmModuleAsyncOptions {
|
||||||
return {
|
return {
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
useFactory(configService: ConfigService) {
|
useFactory(configService: ConfigService) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from "@nestjs/common";
|
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from "@nestjs/common";
|
||||||
import { FastifyReply, FastifyRequest } from "fastify";
|
import { FastifyReply } from "fastify";
|
||||||
|
|
||||||
@Catch(HttpException)
|
@Catch(HttpException)
|
||||||
export class HttpExceptionFilter implements ExceptionFilter {
|
export class HttpExceptionFilter implements ExceptionFilter {
|
||||||
catch(exception: HttpException, host: ArgumentsHost) {
|
catch(exception: HttpException, host: ArgumentsHost) {
|
||||||
const ctx = host.switchToHttp();
|
const ctx = host.switchToHttp();
|
||||||
const reply = ctx.getResponse<FastifyReply>();
|
const reply = ctx.getResponse<FastifyReply>();
|
||||||
const request = ctx.getRequest<FastifyRequest>();
|
// const request = ctx.getRequest<FastifyRequest>();
|
||||||
const status = exception.getStatus() || HttpStatus.INTERNAL_SERVER_ERROR;
|
const status = exception.getStatus() || HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
const exceptionResponse = exception.getResponse();
|
const exceptionResponse = exception.getResponse();
|
||||||
@@ -18,7 +18,7 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
|||||||
error: {
|
error: {
|
||||||
message,
|
message,
|
||||||
// timestamp: new Date().toISOString(),
|
// timestamp: new Date().toISOString(),
|
||||||
path: request.url,
|
// path: request.url,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ApiProperty } from "@nestjs/swagger";
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { IsEmail, IsMobilePhone, IsNotEmpty, IsNumberString, IsString, Length, MinLength } from "class-validator";
|
import { IsMobilePhone, IsNotEmpty, IsNumberString, IsString, Length, MinLength } from "class-validator";
|
||||||
|
|
||||||
import { AuthMessage } from "../../../common/enums/message.enum";
|
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
@@ -27,10 +27,10 @@ export class CompleteRegistrationDto {
|
|||||||
@ApiProperty({ description: "Last name", example: "jamshidi" })
|
@ApiProperty({ description: "Last name", example: "jamshidi" })
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
|
||||||
@IsNotEmpty({ message: AuthMessage.EMAIL_NOT_EMPTY })
|
// @IsNotEmpty({ message: AuthMessage.EMAIL_NOT_EMPTY })
|
||||||
@IsEmail({}, { message: AuthMessage.INVALID_EMAIL_FORMAT })
|
// @IsEmail({}, { message: AuthMessage.INVALID_EMAIL_FORMAT })
|
||||||
@ApiProperty({ description: "Email", example: "ma@gmail.com" })
|
// @ApiProperty({ description: "Email", example: "ma@gmail.com" })
|
||||||
email: string;
|
// email: string;
|
||||||
|
|
||||||
@IsNotEmpty({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
|
||||||
@IsString({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
|
@IsString({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsMobilePhone, IsNotEmpty, IsNumberString, Length } from "class-validator";
|
||||||
|
|
||||||
|
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
|
export class VerifyOtpDto {
|
||||||
|
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||||
|
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||||
|
@ApiProperty({ description: "phone number", default: "09123456789" })
|
||||||
|
phone: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: "OTP code received via SMS", example: "56893" })
|
||||||
|
@IsNotEmpty({ message: AuthMessage.OTP_NOT_EMPTY })
|
||||||
|
@IsNumberString(undefined, { message: AuthMessage.OTP_FORMAT_INVALID })
|
||||||
|
@Length(5, 5, { message: AuthMessage.OTP_FORMAT_INVALID })
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
@@ -1,41 +1,54 @@
|
|||||||
import { Body, Controller, Post } from "@nestjs/common";
|
import { Body, Controller, HttpCode, HttpStatus, Post, UseGuards } from "@nestjs/common";
|
||||||
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||||
|
import { Throttle, ThrottlerGuard } from "@nestjs/throttler";
|
||||||
|
|
||||||
import { AuthService } from "./auth.service";
|
|
||||||
import { CompleteRegistrationDto } from "./DTO/complete-register.dto";
|
import { CompleteRegistrationDto } from "./DTO/complete-register.dto";
|
||||||
|
import { LoginPasswordDTO } from "./DTO/loginPassword.dto";
|
||||||
import { RequestOtpDto } from "./DTO/request-otp.dto";
|
import { RequestOtpDto } from "./DTO/request-otp.dto";
|
||||||
|
import { VerifyOtpDto } from "./DTO/verify-otp.dto";
|
||||||
|
import { AuthService } from "./providers/auth.service";
|
||||||
|
import { AUTH_THROTTLE_LIMIT, AUTH_THROTTLE_TTL } from "../../common/constants";
|
||||||
|
|
||||||
@ApiTags("Auth")
|
@ApiTags("Auth")
|
||||||
@Controller("auth")
|
@Controller("auth")
|
||||||
|
@Throttle({ default: { limit: AUTH_THROTTLE_LIMIT, ttl: AUTH_THROTTLE_TTL } })
|
||||||
|
@UseGuards(ThrottlerGuard)
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(private authService: AuthService) {}
|
constructor(private authService: AuthService) {}
|
||||||
|
|
||||||
@ApiOperation({ summary: "Initiate registration" })
|
@ApiOperation({ summary: "Initiate registration" })
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
@Post("register/initiate")
|
@Post("register/initiate")
|
||||||
async register(@Body() registerDto: RequestOtpDto) {
|
register(@Body() registerDto: RequestOtpDto) {
|
||||||
return this.authService.initiateRegistration(registerDto);
|
return this.authService.initiateRegistration(registerDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "complete registration ==> step 2" })
|
@ApiOperation({ summary: "complete registration ==> step 2" })
|
||||||
@Post("register/complete")
|
@Post("register/complete")
|
||||||
async completeRegistration(@Body() completeRegistrationDto: CompleteRegistrationDto) {
|
completeRegistration(@Body() completeRegistrationDto: CompleteRegistrationDto) {
|
||||||
return this.authService.completeRegistration(completeRegistrationDto);
|
return this.authService.completeRegistration(completeRegistrationDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Post("login")
|
@ApiOperation({ summary: "request to login with otp" })
|
||||||
// async login(@Body() loginDto: LoginDto) {
|
@HttpCode(HttpStatus.OK)
|
||||||
// return this.authService.login(loginDto);
|
@Post("otp/send")
|
||||||
// }
|
sendOtp(@Body() requestOtpDto: RequestOtpDto) {
|
||||||
|
return this.authService.requestLoginOtp(requestOtpDto);
|
||||||
|
}
|
||||||
|
|
||||||
// @Post("otp/register/send")
|
@ApiOperation({ summary: "verify otp for login" })
|
||||||
// async sendOtp(@Body() sendOtpDto: RequestOtpDto) {
|
@HttpCode(HttpStatus.OK)
|
||||||
// return this.authService.requestRegisterOTP(sendOtpDto);
|
@Post("otp/verify")
|
||||||
// }
|
verifyOtp(@Body() verifyOtpDto: VerifyOtpDto) {
|
||||||
|
return this.authService.verifyLoginOtp(verifyOtpDto);
|
||||||
|
}
|
||||||
|
|
||||||
// @Post("otp/verify")
|
@ApiOperation({ summary: "login with password" })
|
||||||
// async verifyOtp(@Body() verifyOtpDto: VerifyOtpDto) {
|
@HttpCode(HttpStatus.OK)
|
||||||
// return this.authService.verifyOtp(verifyOtpDto);
|
@Post("login/password")
|
||||||
// }
|
loginWithPassword(@Body() loginPasswordDto: LoginPasswordDTO) {
|
||||||
|
return this.authService.loginWithPassword(loginPasswordDto);
|
||||||
|
}
|
||||||
|
|
||||||
// @Post("forgot-password")
|
// @Post("forgot-password")
|
||||||
// async forgotPassword(@Body() forgotPasswordDto: ForgotPasswordDto) {
|
// async forgotPassword(@Body() forgotPasswordDto: ForgotPasswordDto) {
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
import { JwtModule } from "@nestjs/jwt";
|
||||||
|
import { PassportModule } from "@nestjs/passport";
|
||||||
|
|
||||||
import { AuthController } from "./auth.controller";
|
import { AuthController } from "./auth.controller";
|
||||||
import { AuthService } from "./auth.service";
|
import { jwtConfig } from "../../configs/jwt.config";
|
||||||
import { UsersModule } from "../users/users.module";
|
import { UsersModule } from "../users/users.module";
|
||||||
import { UtilsModule } from "../utils/utils.module";
|
import { UtilsModule } from "../utils/utils.module";
|
||||||
|
import { AuthService } from "./providers/auth.service";
|
||||||
|
import { TokensService } from "./providers/tokens.service";
|
||||||
|
import { JwtStrategy } from "./strategies/jwt.strategy";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [UtilsModule, UsersModule],
|
imports: [UtilsModule, UsersModule, PassportModule, JwtModule.registerAsync(jwtConfig())],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
providers: [AuthService],
|
providers: [AuthService, TokensService, JwtStrategy],
|
||||||
|
exports: [AuthService],
|
||||||
})
|
})
|
||||||
export class AuthModule {}
|
export class AuthModule {}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
|
||||||
|
|
||||||
import { CompleteRegistrationDto } from "./DTO/complete-register.dto";
|
|
||||||
import { LoginPasswordDTO } from "./DTO/loginPassword.dto";
|
|
||||||
import { RequestOtpDto } from "./DTO/request-otp.dto";
|
|
||||||
import { AuthMessage, UserMessage } from "../../common/enums/message.enum";
|
|
||||||
import { UsersService } from "../users/providers/users.service";
|
|
||||||
import { OTPService } from "../utils/providers/otp.service";
|
|
||||||
import { PasswordService } from "../utils/providers/password.service";
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AuthService {
|
|
||||||
private readonly logger = new Logger(AuthService.name);
|
|
||||||
constructor(
|
|
||||||
private readonly userService: UsersService,
|
|
||||||
private readonly passwordService: PasswordService,
|
|
||||||
private readonly otpService: OTPService,
|
|
||||||
) {}
|
|
||||||
//****************** */
|
|
||||||
async initiateRegistration(requestOtpDto: RequestOtpDto) {
|
|
||||||
const { phone } = requestOtpDto;
|
|
||||||
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
|
||||||
// await SmsService.sendOtp(phone, otpCode);
|
|
||||||
this.logger.log(`OTP sent to ${phone}: ${otpCode}`);
|
|
||||||
|
|
||||||
return {
|
|
||||||
message: AuthMessage.OTP_SENT,
|
|
||||||
otpCode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//****************** */
|
|
||||||
async completeRegistration(completeRegistrationDto: CompleteRegistrationDto) {
|
|
||||||
const { phone, code } = completeRegistrationDto;
|
|
||||||
const isValid = await this.otpService.verifyOtp(phone, code, "REGISTER");
|
|
||||||
|
|
||||||
if (!isValid) throw new BadRequestException(AuthMessage.INVALID_OTP);
|
|
||||||
|
|
||||||
await this.otpService.delOtpFormCache(phone, "REGISTER");
|
|
||||||
const hashedPassword = await this.passwordService.hashPassword(completeRegistrationDto.password);
|
|
||||||
const user = await this.userService.createUser(completeRegistrationDto, hashedPassword);
|
|
||||||
|
|
||||||
return {
|
|
||||||
message: AuthMessage.USER_REGISTER_SUCCESS,
|
|
||||||
user,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//****************** */
|
|
||||||
|
|
||||||
async loginWithPassword(loginDto: LoginPasswordDTO) {
|
|
||||||
const { email, password } = loginDto;
|
|
||||||
|
|
||||||
const user = await this.userService.findOneWithEmail(email);
|
|
||||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
|
||||||
|
|
||||||
const passCompare = await this.passwordService.comparePassword(password, user.password);
|
|
||||||
if (!passCompare) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { AuthGuard } from "@nestjs/passport";
|
||||||
|
|
||||||
|
import { JWT_STRATEGY_NAME } from "../../../common/constants";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class JwtAuthGuard extends AuthGuard(JWT_STRATEGY_NAME) {}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from "@nestjs/common";
|
||||||
|
import { Reflector } from "@nestjs/core";
|
||||||
|
import { FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
import { ROLES_KEY } from "../../../common/decorators/roles.decorator";
|
||||||
|
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { RoleEnum } from "../../users/enums/role.enum";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RoleGuard implements CanActivate {
|
||||||
|
constructor(private reflector: Reflector) {}
|
||||||
|
|
||||||
|
canActivate(context: ExecutionContext): boolean {
|
||||||
|
const requiredRole = this.reflector.getAllAndOverride<RoleEnum[]>(ROLES_KEY, [context.getHandler(), context.getClass()]);
|
||||||
|
if (!requiredRole) return true;
|
||||||
|
|
||||||
|
const req = context.switchToHttp().getRequest<FastifyRequest>();
|
||||||
|
const user = req.user;
|
||||||
|
|
||||||
|
if (!user) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
|
||||||
|
|
||||||
|
const hasRequiredRole = requiredRole.includes(user.role.name);
|
||||||
|
if (!hasRequiredRole) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { RoleEnum } from "../../users/enums/role.enum";
|
||||||
|
|
||||||
|
export interface ITokenPayload {
|
||||||
|
sub: string;
|
||||||
|
role: RoleEnum;
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { TokensService } from "./tokens.service";
|
||||||
|
import { AuthMessage, UserMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { UsersService } from "../../users/providers/users.service";
|
||||||
|
import { OTPService } from "../../utils/providers/otp.service";
|
||||||
|
import { PasswordService } from "../../utils/providers/password.service";
|
||||||
|
import { CompleteRegistrationDto } from "../DTO/complete-register.dto";
|
||||||
|
import { LoginPasswordDTO } from "../DTO/loginPassword.dto";
|
||||||
|
import { RequestOtpDto } from "../DTO/request-otp.dto";
|
||||||
|
import { VerifyOtpDto } from "../DTO/verify-otp.dto";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {
|
||||||
|
private readonly logger = new Logger(AuthService.name);
|
||||||
|
constructor(
|
||||||
|
private readonly usersService: UsersService,
|
||||||
|
private readonly passwordService: PasswordService,
|
||||||
|
private readonly otpService: OTPService,
|
||||||
|
private readonly tokensService: TokensService,
|
||||||
|
) {}
|
||||||
|
//****************** */
|
||||||
|
async initiateRegistration(requestOtpDto: RequestOtpDto) {
|
||||||
|
const { phone } = requestOtpDto;
|
||||||
|
const existUser = await this.usersService.findOneWithPhone(phone);
|
||||||
|
if (existUser) throw new BadRequestException(AuthMessage.PHONE_EXISTS);
|
||||||
|
|
||||||
|
const existCode = await this.otpService.checkExistOtp(phone, "REGISTER");
|
||||||
|
if (existCode) {
|
||||||
|
return {
|
||||||
|
message: AuthMessage.OTP_ALREADY_SENT,
|
||||||
|
ttlSecond: existCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
||||||
|
// await SmsService.sendOtp(phone, otpCode);
|
||||||
|
this.logger.log(`OTP sent to ${phone}: ${otpCode}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: AuthMessage.OTP_SENT,
|
||||||
|
otpCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//****************** */
|
||||||
|
async completeRegistration(completeRegistrationDto: CompleteRegistrationDto) {
|
||||||
|
const { phone, code } = completeRegistrationDto;
|
||||||
|
const isValid = await this.otpService.verifyOtp(phone, code, "REGISTER");
|
||||||
|
|
||||||
|
if (!isValid) throw new BadRequestException(AuthMessage.INVALID_OTP);
|
||||||
|
|
||||||
|
await this.otpService.delOtpFormCache(phone, "REGISTER");
|
||||||
|
const hashedPassword = await this.passwordService.hashPassword(completeRegistrationDto.password);
|
||||||
|
const user = await this.usersService.createUser(completeRegistrationDto, hashedPassword);
|
||||||
|
|
||||||
|
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: AuthMessage.USER_REGISTER_SUCCESS,
|
||||||
|
...tokens,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//****************** */
|
||||||
|
|
||||||
|
async loginWithPassword(loginDto: LoginPasswordDTO) {
|
||||||
|
const { email, password } = loginDto;
|
||||||
|
|
||||||
|
const user = await this.usersService.findOneWithEmail(email);
|
||||||
|
if (!user) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
|
||||||
|
|
||||||
|
const passCompare = await this.passwordService.comparePassword(password, user.password);
|
||||||
|
if (!passCompare) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
|
||||||
|
|
||||||
|
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: AuthMessage.PASSWORD_LOGIN_SUCCESS,
|
||||||
|
...tokens,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************** */
|
||||||
|
|
||||||
|
async requestLoginOtp(requestOtpDto: RequestOtpDto) {
|
||||||
|
const { phone } = requestOtpDto;
|
||||||
|
const user = await this.usersService.findOneWithPhone(phone);
|
||||||
|
if (!user) throw new BadRequestException(AuthMessage.PHONE_NOT_FOUND);
|
||||||
|
|
||||||
|
const existCode = await this.otpService.checkExistOtp(phone, "LOGIN");
|
||||||
|
if (existCode) {
|
||||||
|
return {
|
||||||
|
message: AuthMessage.OTP_ALREADY_SENT,
|
||||||
|
ttlSecond: existCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const otpCode = await this.otpService.generateAndSetInCache(phone, "LOGIN");
|
||||||
|
// await SmsService.sendOtp(phone, otpCode);
|
||||||
|
this.logger.log(`OTP sent to ${phone}: ${otpCode}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: AuthMessage.OTP_SENT,
|
||||||
|
otpCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************** */
|
||||||
|
async verifyLoginOtp(verifyOtpDto: VerifyOtpDto) {
|
||||||
|
const { code, phone } = verifyOtpDto;
|
||||||
|
|
||||||
|
const isValid = await this.otpService.verifyOtp(phone, code, "LOGIN");
|
||||||
|
if (!isValid) throw new BadRequestException(AuthMessage.INVALID_OTP);
|
||||||
|
|
||||||
|
await this.otpService.delOtpFormCache(phone, "LOGIN");
|
||||||
|
|
||||||
|
const user = await this.usersService.findOneWithPhone(phone);
|
||||||
|
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||||
|
|
||||||
|
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
|
||||||
|
return {
|
||||||
|
message: AuthMessage.LOGIN_SUCCESS,
|
||||||
|
...tokens,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//****************** */
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
import { JwtService } from "@nestjs/jwt";
|
||||||
|
|
||||||
|
import { ITokenPayload } from "../interfaces/IToken-payload";
|
||||||
|
// import { UserRepository } from "../users/providers/users.repository";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TokensService {
|
||||||
|
constructor(
|
||||||
|
private readonly configService: ConfigService,
|
||||||
|
private readonly jwtService: JwtService,
|
||||||
|
// private readonly userRepository: UserRepository,
|
||||||
|
) {}
|
||||||
|
// ----------- generate token -----------------
|
||||||
|
generateAccessAndRefreshToken(payload: ITokenPayload) {
|
||||||
|
const access_expire = this.configService.getOrThrow<number>("ACCESS_TOKEN_EXPIRE");
|
||||||
|
const refresh_expire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
|
||||||
|
|
||||||
|
const accessToken = this.jwtService.sign(payload, { expiresIn: `${access_expire}h` });
|
||||||
|
|
||||||
|
const refreshToken = this.jwtService.sign(payload, { expiresIn: `${refresh_expire}d` });
|
||||||
|
|
||||||
|
return {
|
||||||
|
accessToken: { token: accessToken, expire: Date.now() + 1000 * 60 * 60 * access_expire },
|
||||||
|
refreshToken: { token: refreshToken, expire: Date.now() + 1000 * 60 * 60 * 24 * refresh_expire },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************************** */
|
||||||
|
// validateRefreshToken(token: string) {
|
||||||
|
// const { sub } = this.verifyToken(token, "refresh");
|
||||||
|
// return this.generateAccessAndRefreshToken({ sub: sub });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// verifyToken(token: string, type: "access" | "refresh"): ITokenPayload {
|
||||||
|
// try {
|
||||||
|
// if (type === "access") {
|
||||||
|
// return this.jwtService.verify(token, {
|
||||||
|
// secret: process.env.ACCESS_TOKEN_SECRET,
|
||||||
|
// ignoreExpiration: false,
|
||||||
|
// });
|
||||||
|
// } else if (type === "refresh") {
|
||||||
|
// return this.jwtService.verify(token, {
|
||||||
|
// secret: process.env.REFRESH_TOKEN_SECRET,
|
||||||
|
// ignoreExpiration: false,
|
||||||
|
// });
|
||||||
|
// } else throw new Error("Invalid token type => access / refresh");
|
||||||
|
// } catch {
|
||||||
|
// throw new HttpException(AuthMessage.LoginAgain, HttpStatus.UNAUTHORIZED);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
import { PassportStrategy } from "@nestjs/passport";
|
||||||
|
import { ExtractJwt, Strategy } from "passport-jwt";
|
||||||
|
|
||||||
|
import { JWT_STRATEGY_NAME } from "../../../common/constants";
|
||||||
|
import { ITokenPayload } from "../interfaces/IToken-payload";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class JwtStrategy extends PassportStrategy(Strategy, JWT_STRATEGY_NAME) {
|
||||||
|
constructor(configService: ConfigService) {
|
||||||
|
super({
|
||||||
|
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||||
|
ignoreExpiration: false,
|
||||||
|
secretOrKey: configService.getOrThrow<string>("JWT_SECRET_KEY"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(payload: ITokenPayload) {
|
||||||
|
return { id: payload.sub, role: payload.role };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsEnum, IsNotEmpty, IsString } from "class-validator";
|
||||||
|
|
||||||
|
import { CommonMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { ValidityType } from "../enums/validity-type.enum";
|
||||||
|
|
||||||
|
export class CheckValidityDTO {
|
||||||
|
@IsNotEmpty({ message: CommonMessage.VALIDITY_TYPE_REQUIRED })
|
||||||
|
@IsEnum(ValidityType)
|
||||||
|
@ApiProperty({ enum: ValidityType, example: ValidityType.USERNAME })
|
||||||
|
type: ValidityType;
|
||||||
|
|
||||||
|
@IsNotEmpty({ message: CommonMessage.THIS_FILED_IS_REQUIRED })
|
||||||
|
@IsString({ message: CommonMessage.THIS_FILED_IS_REQUIRED })
|
||||||
|
@ApiProperty({ example: "mahyargdz" })
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export class UpdateProfileDto {
|
||||||
|
userName: string;
|
||||||
|
}
|
||||||
@@ -5,6 +5,6 @@ import { RoleEnum } from "../enums/role.enum";
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Role extends BaseEntity {
|
export class Role extends BaseEntity {
|
||||||
@Column({ type: "enum", enum: RoleEnum, default: RoleEnum.USER, nullable: false })
|
@Column({ type: "enum", enum: RoleEnum, default: RoleEnum.USER, nullable: false, unique: true })
|
||||||
name: RoleEnum;
|
name: RoleEnum;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import { BaseEntity } from "../../../common/entities/base.entity";
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class User extends BaseEntity {
|
export class User extends BaseEntity {
|
||||||
@Column({ type: "varchar", length: 150, unique: true, nullable: true })
|
@Column({ type: "varchar", length: 150, nullable: true })
|
||||||
email: string;
|
email: string;
|
||||||
|
|
||||||
@Column({ type: "varchar", length: 11, unique: true, nullable: true })
|
@Column({ type: "varchar", length: 11, unique: true, nullable: false })
|
||||||
phoneNumber: string;
|
phone: string;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 150, unique: true, nullable: true })
|
||||||
|
userName: string;
|
||||||
|
|
||||||
@Column({ type: "varchar", length: 150 })
|
@Column({ type: "varchar", length: 150 })
|
||||||
password: string;
|
password: string;
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export enum ValidityType {
|
||||||
|
USERNAME = "userName",
|
||||||
|
}
|
||||||
@@ -11,8 +11,14 @@ export class UserRepository extends Repository<User> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findOneWithEmail(email: string): Promise<User | null> {
|
async findOneWithEmail(email: string): Promise<User | null> {
|
||||||
return await this.findOneBy({
|
return this.findOneBy({
|
||||||
email,
|
email,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findOneWithPhone(phone: string): Promise<User | null> {
|
||||||
|
return this.findOneBy({
|
||||||
|
phone,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,35 +3,82 @@ import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
|||||||
import { RoleRepository } from "./roles.repository";
|
import { RoleRepository } from "./roles.repository";
|
||||||
import { UserRepository } from "./users.repository";
|
import { UserRepository } from "./users.repository";
|
||||||
import { roles } from "../../../../db/seeders/role.seeder";
|
import { roles } from "../../../../db/seeders/role.seeder";
|
||||||
import { UserMessage } from "../../../common/enums/message.enum";
|
import { CommonMessage, UserMessage } from "../../../common/enums/message.enum";
|
||||||
import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto";
|
import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto";
|
||||||
|
import { CheckValidityDTO } from "../DTO/check-validity.dto";
|
||||||
import { User } from "../entities/user.entity";
|
import { User } from "../entities/user.entity";
|
||||||
|
import { RoleEnum } from "../enums/role.enum";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UsersService {
|
export class UsersService {
|
||||||
|
private readonly userSelect = {
|
||||||
|
id: true,
|
||||||
|
phone: true,
|
||||||
|
email: true,
|
||||||
|
userName: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
nationalCode: true,
|
||||||
|
birthDate: true,
|
||||||
|
role: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
private logger = new Logger(UsersService.name);
|
private logger = new Logger(UsersService.name);
|
||||||
constructor(
|
constructor(
|
||||||
private userRepository: UserRepository,
|
private userRepository: UserRepository,
|
||||||
private roleRepository: RoleRepository,
|
private roleRepository: RoleRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
/************************************************************ */
|
||||||
|
|
||||||
|
async getMe(userId: string) {
|
||||||
|
const user = await this.userRepository.findOne({ where: { id: userId }, select: this.userSelect });
|
||||||
|
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||||
|
return { user };
|
||||||
|
}
|
||||||
|
/************************************************************ */
|
||||||
|
|
||||||
async findOneWithEmail(email: string): Promise<User> {
|
async findOneWithEmail(email: string): Promise<User> {
|
||||||
const user = await this.userRepository.findOneWithEmail(email);
|
const user = await this.userRepository.findOneWithEmail(email);
|
||||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
/************************************************************ */
|
||||||
|
|
||||||
|
async findOneWithPhone(phone: string): Promise<User | null> {
|
||||||
|
const user = await this.userRepository.findOneWithPhone(phone);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************ */
|
||||||
|
|
||||||
|
async createUser(registerDto: CompleteRegistrationDto, hashedPassword: string): Promise<User> {
|
||||||
|
// const existEmail = await this.userRepository.findOneWithEmail(registerDto.email);
|
||||||
|
// if (existEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST);
|
||||||
|
|
||||||
|
const role = await this.roleRepository.findOneBy({ name: RoleEnum.USER });
|
||||||
|
if (!role) throw new BadRequestException(UserMessage.ROLE_NOT_FOUND);
|
||||||
|
|
||||||
|
const user = this.userRepository.create({ ...registerDto, password: hashedPassword, role });
|
||||||
|
return await this.userRepository.save(user);
|
||||||
|
}
|
||||||
|
/************************************************************ */
|
||||||
|
|
||||||
|
async checkValidity(checkDto: CheckValidityDTO) {
|
||||||
|
const { type, value } = checkDto;
|
||||||
|
const user = await this.userRepository.findOneBy({ [type]: value });
|
||||||
|
if (user) throw new BadRequestException(UserMessage.USER_EXISTS);
|
||||||
|
return { message: CommonMessage.VALID_FOR_CHOOSE };
|
||||||
|
}
|
||||||
|
|
||||||
|
///****************************************************** */
|
||||||
async roleSeeder() {
|
async roleSeeder() {
|
||||||
|
const countRole = await this.roleRepository.count();
|
||||||
|
if (countRole > 0) return;
|
||||||
const createdRoles = await this.roleRepository.insert(roles);
|
const createdRoles = await this.roleRepository.insert(roles);
|
||||||
this.logger.log({ createdRoles });
|
this.logger.log({ createdRoles });
|
||||||
return createdRoles;
|
return createdRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUser(registerDto: CompleteRegistrationDto, hashedPassword: string): Promise<User> {
|
|
||||||
const existEmail = await this.userRepository.findOneWithEmail(registerDto.email);
|
|
||||||
if (existEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST);
|
|
||||||
|
|
||||||
const user = this.userRepository.create({ ...registerDto, password: hashedPassword });
|
|
||||||
return await this.userRepository.save(user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,31 @@
|
|||||||
import { Controller } from "@nestjs/common";
|
import { Body, Controller, Get, Patch, Post } from "@nestjs/common";
|
||||||
import { ApiTags } from "@nestjs/swagger";
|
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||||
|
|
||||||
|
import { CheckValidityDTO } from "./DTO/check-validity.dto";
|
||||||
|
import { User } from "./entities/user.entity";
|
||||||
|
import { UsersService } from "./providers/users.service";
|
||||||
|
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||||
|
import { UserDec } from "../../common/decorators/user.decorator";
|
||||||
|
|
||||||
@Controller("users")
|
@Controller("users")
|
||||||
@ApiTags("users")
|
@ApiTags("users")
|
||||||
export class UsersController {}
|
export class UsersController {
|
||||||
|
constructor(private usersService: UsersService) {}
|
||||||
|
|
||||||
|
@AuthGuards()
|
||||||
|
@ApiOperation({ summary: "Get user profile" })
|
||||||
|
@Get("me")
|
||||||
|
getMe(@UserDec() user: User) {
|
||||||
|
return this.usersService.getMe(user.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch("update-profile")
|
||||||
|
updateProfile() {}
|
||||||
|
|
||||||
|
@AuthGuards()
|
||||||
|
@ApiOperation({ summary: "Check validity of user field" })
|
||||||
|
@Post("check-validity")
|
||||||
|
checkValidity(@Body() checkValidityDto: CheckValidityDTO) {
|
||||||
|
return this.usersService.checkValidity(checkValidityDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { TypeOrmModule } from "@nestjs/typeorm";
|
|||||||
|
|
||||||
import { Role } from "./entities/role.entity";
|
import { Role } from "./entities/role.entity";
|
||||||
import { User } from "./entities/user.entity";
|
import { User } from "./entities/user.entity";
|
||||||
|
import { RoleRepository } from "./providers/roles.repository";
|
||||||
import { UserRepository } from "./providers/users.repository";
|
import { UserRepository } from "./providers/users.repository";
|
||||||
import { UsersService } from "./providers/users.service";
|
import { UsersService } from "./providers/users.service";
|
||||||
import { UsersController } from "./users.controller";
|
import { UsersController } from "./users.controller";
|
||||||
import { RoleRepository } from "./providers/roles.repository";
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User, Role])],
|
imports: [TypeOrmModule.forFeature([User, Role])],
|
||||||
@@ -15,8 +15,8 @@ import { RoleRepository } from "./providers/roles.repository";
|
|||||||
exports: [UsersService, TypeOrmModule],
|
exports: [UsersService, TypeOrmModule],
|
||||||
})
|
})
|
||||||
export class UsersModule implements OnApplicationBootstrap {
|
export class UsersModule implements OnApplicationBootstrap {
|
||||||
constructor(private userService: UsersService) {}
|
// constructor(private userService: UsersService) {}
|
||||||
async onApplicationBootstrap() {
|
async onApplicationBootstrap() {
|
||||||
await this.userService.roleSeeder();
|
// await this.userService.roleSeeder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,8 @@ export class CacheService {
|
|||||||
async del(key: string) {
|
async del(key: string) {
|
||||||
await this.cacheManager.del(key);
|
await this.cacheManager.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTtl(key: string) {
|
||||||
|
return await this.cacheManager.ttl(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,28 +12,33 @@ export class OTPService {
|
|||||||
private generateOTP(): string {
|
private generateOTP(): string {
|
||||||
return randomInt(10000, 99999).toString();
|
return randomInt(10000, 99999).toString();
|
||||||
}
|
}
|
||||||
|
//
|
||||||
async generateAndSetInCache(identifier: string, cacheKey: OtpCacheKeyType) {
|
async generateAndSetInCache(identifier: string, cacheKey: OtpCacheKeyType) {
|
||||||
const otp = this.generateOTP();
|
const otp = this.generateOTP();
|
||||||
const key = `${identifier}:${cacheKey}:OTP`;
|
const key = `${identifier}:${cacheKey}:OTP`;
|
||||||
await this.cacheService.set(key, otp);
|
await this.cacheService.set(key, otp);
|
||||||
return otp;
|
return otp;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
async verifyOtp(identifier: string, otpCode: string, cacheKey: OtpCacheKeyType) {
|
async verifyOtp(identifier: string, otpCode: string, cacheKey: OtpCacheKeyType) {
|
||||||
const key = `${identifier}:${cacheKey}:OTP`;
|
const key = `${identifier}:${cacheKey}:OTP`;
|
||||||
const codeInCache = await this.cacheService.get<string | null>(key);
|
const codeInCache = await this.cacheService.get<string | null>(key);
|
||||||
return codeInCache && otpCode === codeInCache;
|
return codeInCache && otpCode === codeInCache;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
async delOtpFormCache(identifier: string, cacheKey: OtpCacheKeyType) {
|
async delOtpFormCache(identifier: string, cacheKey: OtpCacheKeyType) {
|
||||||
const key = `${identifier}:${cacheKey}:OTP`;
|
const key = `${identifier}:${cacheKey}:OTP`;
|
||||||
await this.cacheService.del(key);
|
await this.cacheService.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// async verify(identifier: string, otp: string): Promise<boolean> {
|
async checkExistOtp(identifier: string, cacheKey: OtpCacheKeyType) {
|
||||||
// // Here you would typically verify the OTP against stored value
|
const key = `${identifier}:${cacheKey}:OTP`;
|
||||||
// // and check if it's not expired
|
const codeInCache = await this.cacheService.get<string | null>(key);
|
||||||
// return true; // Placeholder implementation
|
|
||||||
// }
|
if (!codeInCache) return null;
|
||||||
|
|
||||||
|
const ttlInMsSeconds = await this.cacheService.getTtl(key);
|
||||||
|
|
||||||
|
return Math.floor((ttlInMsSeconds! - Date.now()) / 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CacheService } from "./providers/cache.service";
|
|||||||
import { OTPService } from "./providers/otp.service";
|
import { OTPService } from "./providers/otp.service";
|
||||||
import { PasswordService } from "./providers/password.service";
|
import { PasswordService } from "./providers/password.service";
|
||||||
import { SmsService } from "./providers/sms.service";
|
import { SmsService } from "./providers/sms.service";
|
||||||
import { SmsConfigs } from "../../configs/sms.config";
|
import { smsConfigs } from "../../configs/sms.config";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -15,8 +15,8 @@ import { SmsConfigs } from "../../configs/sms.config";
|
|||||||
SmsService,
|
SmsService,
|
||||||
{
|
{
|
||||||
provide: SMS_CONFIG,
|
provide: SMS_CONFIG,
|
||||||
useFactory: SmsConfigs().useFactory,
|
useFactory: smsConfigs().useFactory,
|
||||||
inject: SmsConfigs().inject,
|
inject: smsConfigs().inject,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exports: [SMS_CONFIG, OTPService, PasswordService, CacheService, SmsService],
|
exports: [SMS_CONFIG, OTPService, PasswordService, CacheService, SmsService],
|
||||||
|
|||||||
Reference in New Issue
Block a user