feat: added some new functions to the auth service
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
"@nestjs/common": "^11.1.28",
|
||||
"@nestjs/config": "^4.0.4",
|
||||
"@nestjs/core": "^11.1.28",
|
||||
"@nestjs/jwt": "^11.0.2",
|
||||
"@nestjs/platform-express": "^11.1.28",
|
||||
"@nestjs/swagger": "^11.4.6",
|
||||
"@nestjs/typeorm": "^11.0.3",
|
||||
@@ -32,6 +33,7 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.15.1",
|
||||
"joi": "^18.2.3",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"pg": "^8.22.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1",
|
||||
@@ -47,6 +49,7 @@
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
|
||||
Generated
+151
@@ -20,6 +20,9 @@ importers:
|
||||
'@nestjs/core':
|
||||
specifier: ^11.1.28
|
||||
version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@nestjs/jwt':
|
||||
specifier: ^11.0.2
|
||||
version: 11.0.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))
|
||||
'@nestjs/platform-express':
|
||||
specifier: ^11.1.28
|
||||
version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)
|
||||
@@ -44,6 +47,9 @@ importers:
|
||||
joi:
|
||||
specifier: ^18.2.3
|
||||
version: 18.2.3
|
||||
passport-jwt:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
pg:
|
||||
specifier: ^8.22.0
|
||||
version: 8.22.0
|
||||
@@ -84,6 +90,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^22.10.7
|
||||
version: 22.20.1
|
||||
'@types/passport-jwt':
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
'@types/supertest':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.3
|
||||
@@ -755,6 +764,11 @@ packages:
|
||||
'@nestjs/websockets':
|
||||
optional: true
|
||||
|
||||
'@nestjs/jwt@11.0.2':
|
||||
resolution: {integrity: sha512-rK8aE/3/Ma45gAWfCksAXUNbOoSOUudU0Kn3rT39htPF7wsYXtKfjALKeKKJbFrIWbLjsbqfXX5bIJNvgBugGA==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
|
||||
'@nestjs/mapped-types@2.1.1':
|
||||
resolution: {integrity: sha512-SCCoMEJ6jdeI5h/N+KCVF1+pmg/hmEkNA5nHTS8Gvww7T/LCl4o1gFLinw2iQ60w7slFkszHcGLKGdazVI4F8A==}
|
||||
peerDependencies:
|
||||
@@ -934,12 +948,27 @@ packages:
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
'@types/jsonwebtoken@9.0.10':
|
||||
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||
|
||||
'@types/methods@1.1.4':
|
||||
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
||||
|
||||
'@types/ms@2.1.0':
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
|
||||
'@types/node@22.20.1':
|
||||
resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
|
||||
|
||||
'@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/qs@6.15.1':
|
||||
resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
|
||||
|
||||
@@ -1403,6 +1432,9 @@ packages:
|
||||
bser@2.1.1:
|
||||
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:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
@@ -1653,6 +1685,9 @@ packages:
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||
|
||||
ee-first@1.1.1:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
|
||||
@@ -2315,6 +2350,16 @@ packages:
|
||||
jsonfile@6.2.1:
|
||||
resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==}
|
||||
|
||||
jsonwebtoken@9.0.3:
|
||||
resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
|
||||
jwa@2.0.1:
|
||||
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
|
||||
|
||||
jws@4.0.1:
|
||||
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
@@ -2348,12 +2393,33 @@ packages:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lodash.includes@4.3.0:
|
||||
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||
|
||||
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:
|
||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||
|
||||
lodash.isstring@4.0.1:
|
||||
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||
|
||||
lodash.memoize@4.1.2:
|
||||
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
lodash.once@4.1.1:
|
||||
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||
|
||||
lodash@4.18.1:
|
||||
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
|
||||
|
||||
@@ -2571,6 +2637,13 @@ packages:
|
||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
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'}
|
||||
|
||||
path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -4144,6 +4217,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@nestjs/platform-express': 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)
|
||||
|
||||
'@nestjs/jwt@11.0.2(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))':
|
||||
dependencies:
|
||||
'@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@types/jsonwebtoken': 9.0.10
|
||||
jsonwebtoken: 9.0.3
|
||||
|
||||
'@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)':
|
||||
dependencies:
|
||||
'@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
@@ -4337,12 +4416,33 @@ snapshots:
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/jsonwebtoken@9.0.10':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
'@types/node': 22.20.1
|
||||
|
||||
'@types/methods@1.1.4': {}
|
||||
|
||||
'@types/ms@2.1.0': {}
|
||||
|
||||
'@types/node@22.20.1':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/passport-jwt@4.0.1':
|
||||
dependencies:
|
||||
'@types/jsonwebtoken': 9.0.10
|
||||
'@types/passport-strategy': 0.2.38
|
||||
|
||||
'@types/passport-strategy@0.2.38':
|
||||
dependencies:
|
||||
'@types/express': 5.0.6
|
||||
'@types/passport': 1.0.17
|
||||
|
||||
'@types/passport@1.0.17':
|
||||
dependencies:
|
||||
'@types/express': 5.0.6
|
||||
|
||||
'@types/qs@6.15.1': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
@@ -4851,6 +4951,8 @@ snapshots:
|
||||
dependencies:
|
||||
node-int64: 0.4.0
|
||||
|
||||
buffer-equal-constant-time@1.0.1: {}
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
buffer@5.7.1:
|
||||
@@ -5052,6 +5154,10 @@ snapshots:
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
ee-first@1.1.1: {}
|
||||
|
||||
electron-to-chromium@1.5.393: {}
|
||||
@@ -5932,6 +6038,30 @@ snapshots:
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
jsonwebtoken@9.0.3:
|
||||
dependencies:
|
||||
jws: 4.0.1
|
||||
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.8.5
|
||||
|
||||
jwa@2.0.1:
|
||||
dependencies:
|
||||
buffer-equal-constant-time: 1.0.1
|
||||
ecdsa-sig-formatter: 1.0.11
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
jws@4.0.1:
|
||||
dependencies:
|
||||
jwa: 2.0.1
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
@@ -5959,10 +6089,24 @@ snapshots:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
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.memoize@4.1.2: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash.once@4.1.1: {}
|
||||
|
||||
lodash@4.18.1: {}
|
||||
|
||||
log-symbols@4.1.0:
|
||||
@@ -6149,6 +6293,13 @@ snapshots:
|
||||
|
||||
parseurl@1.3.3: {}
|
||||
|
||||
passport-jwt@4.0.1:
|
||||
dependencies:
|
||||
jsonwebtoken: 9.0.3
|
||||
passport-strategy: 1.0.0
|
||||
|
||||
passport-strategy@1.0.0: {}
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
path-is-absolute@1.0.1: {}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsString, Matches } from "class-validator";
|
||||
|
||||
export class LoginCredentialDto {
|
||||
@ApiProperty({example: '09123456789'})
|
||||
@IsString()
|
||||
@Matches(/^09\d{9}$/)
|
||||
phoneNumber: string;
|
||||
|
||||
@ApiProperty({example: 'Mystrongpassword@47'})
|
||||
@IsString()
|
||||
password: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, Matches, Length } from 'class-validator';
|
||||
|
||||
export class VerifyOtpDto {
|
||||
@ApiProperty({
|
||||
example: '09123456789',
|
||||
})
|
||||
@Matches(/^09\d{9}$/)
|
||||
phoneNumber: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: '123456',
|
||||
})
|
||||
@IsString()
|
||||
@Length(6, 6)
|
||||
code: string;
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Body, Controller, Post } from "@nestjs/common";
|
||||
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { SendOtpDto } from "./DTO/send-otp.dto";
|
||||
import { LoginCredentialDto } from "./DTO/login-credential.dto";
|
||||
import { VerifyOtpDto } from "./DTO/verify-otp.dto";
|
||||
|
||||
@ApiTags('Authentication')
|
||||
@Controller('auth')
|
||||
@@ -14,9 +16,33 @@ export class AuthController {
|
||||
@ApiOperation({
|
||||
summary: 'Send OTP to a phone number',
|
||||
})
|
||||
@ApiResponse({status: 200, description: 'Sent Otp Successfully!'})
|
||||
@ApiResponse({status: 400, description: 'Bad Request from User!'})
|
||||
async sendOtp(
|
||||
@Body() dto: SendOtpDto,
|
||||
@Body() dto: SendOtpDto
|
||||
) {
|
||||
return this.authService.sendOTP(dto.phoneNumber);
|
||||
}
|
||||
|
||||
@Post('verify-otp')
|
||||
@ApiOperation({
|
||||
summary: 'Verify OTP.'
|
||||
})
|
||||
@ApiResponse({status: 200, description: 'Verified Otp Successfully!'})
|
||||
@ApiResponse({status: 400, description: 'Bad Request from the user'})
|
||||
async verifyOtp(
|
||||
@Body() dto: VerifyOtpDto
|
||||
) {
|
||||
return this.authService.verifyOTP(dto);
|
||||
}
|
||||
|
||||
@Post('check-credential')
|
||||
@ApiOperation({summary: 'Check Login Credentials. If Valid Sends OTP'})
|
||||
@ApiResponse({status: 200, description: 'Valid Credentials!'})
|
||||
@ApiResponse({status: 400, description: 'Credentials Invalid!'})
|
||||
async checkLoginCredential(
|
||||
@Body() dto: LoginCredentialDto
|
||||
) {
|
||||
return this.authService.checkLoginCredentials(dto);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
import { UtilsModule } from 'src/utils/utils.module';
|
||||
@@ -6,9 +7,16 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { User } from 'src/users/entities/user.entity';
|
||||
import { OTP } from './entities/otp.entity';
|
||||
import { OtpRepository } from './repositories/otp.repository';
|
||||
import { UsersModule } from 'src/users/users.module';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([User, OTP]), UtilsModule],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([User, OTP]),
|
||||
JwtModule.register({}),
|
||||
UtilsModule,
|
||||
UsersModule,
|
||||
],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService, OtpRepository],
|
||||
})
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import type { ISmsConfigs } from 'src/config/sms.config';
|
||||
import { SMS_CONFIG } from 'src/utils/constants';
|
||||
import { SmsService } from 'src/utils/providers/sms.service';
|
||||
import { OtpRepository } from './repositories/otp.repository';
|
||||
import { OtpStatus } from './enums/otp-status.enum';
|
||||
import { VerifyOtpDto } from './DTO/verify-otp.dto';
|
||||
import { OTPMessages, UserMessages } from 'src/common/enums/messages.enum';
|
||||
import { LoginCredentialDto } from './DTO/login-credential.dto';
|
||||
import { UsersService } from 'src/users/users.service';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
@@ -13,6 +19,8 @@ export class AuthService {
|
||||
private readonly smsService: SmsService,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly OtpRepository: OtpRepository,
|
||||
private readonly userService: UsersService,
|
||||
private readonly jwtService: JwtService
|
||||
) {}
|
||||
|
||||
async sendOTP(phone: string) {
|
||||
@@ -35,18 +43,18 @@ export class AuthService {
|
||||
{ status: OtpStatus.EXPIRED },
|
||||
);
|
||||
|
||||
|
||||
await this.OtpRepository.save(
|
||||
this.OtpRepository.create({
|
||||
phoneNumber: phone,
|
||||
code: otp,
|
||||
expirationDate: Date.now() + 2 * 60 * 1000,
|
||||
status: OtpStatus.PENDING,
|
||||
numberOfTries: 0
|
||||
})
|
||||
phoneNumber: phone,
|
||||
code: otp,
|
||||
expirationDate: new Date(Date.now() + 2 * 60 * 1000),
|
||||
status: OtpStatus.PENDING,
|
||||
numberOfTries: 0,
|
||||
}),
|
||||
);
|
||||
|
||||
return {otp};
|
||||
|
||||
return { otp };
|
||||
} catch (error) {
|
||||
if (this.configService.get('NODE_ENV') !== 'production') {
|
||||
return { otp };
|
||||
@@ -56,7 +64,68 @@ export class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
async verifyOTP(dto: VerifyOtpDto) {
|
||||
const otp = await this.OtpRepository.findOne({
|
||||
where: { phoneNumber: dto.phoneNumber, status: OtpStatus.PENDING },
|
||||
order: {
|
||||
createdAt: 'DESC',
|
||||
},
|
||||
});
|
||||
|
||||
if (!otp) {
|
||||
throw new BadRequestException(OTPMessages.OTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (otp.expirationDate < new Date()) {
|
||||
otp.status = OtpStatus.EXPIRED;
|
||||
|
||||
await this.OtpRepository.save(otp);
|
||||
|
||||
throw new BadRequestException(OTPMessages.OTP_EXPIRED);
|
||||
}
|
||||
|
||||
if (otp.code !== dto.code) {
|
||||
otp.numberOfTries++;
|
||||
|
||||
if (otp.numberOfTries >= 3) {
|
||||
otp.status = OtpStatus.EXPIRED;
|
||||
|
||||
await this.OtpRepository.save(otp);
|
||||
|
||||
throw new BadRequestException(OTPMessages.OTP_TOO_MANY_TRIES);
|
||||
}
|
||||
|
||||
await this.OtpRepository.save(otp);
|
||||
|
||||
throw new BadRequestException(OTPMessages.OTP_INVALID);
|
||||
}
|
||||
|
||||
otp.status = OtpStatus.VERIFIED;
|
||||
|
||||
await this.OtpRepository.save(otp);
|
||||
}
|
||||
|
||||
private generateOtp(): string {
|
||||
return Math.floor(100000 + Math.random() * 900000).toString();
|
||||
}
|
||||
|
||||
async checkLoginCredentials(credential: LoginCredentialDto): Promise<void> {
|
||||
const { phoneNumber, password } = credential;
|
||||
|
||||
const user = await this.userService.findOneByPhoneOrFail(phoneNumber);
|
||||
|
||||
const isPasswordValid = await bcrypt.compare(password, user.password);
|
||||
|
||||
if (!isPasswordValid) {
|
||||
throw new BadRequestException(UserMessages.USER_PASSWORD_INVALID);
|
||||
}
|
||||
|
||||
await this.sendOTP(phoneNumber);
|
||||
}
|
||||
|
||||
// async VerifyOtpAndLogin(dto: VerifyOtpDto) {
|
||||
// await this.verifyOTP(dto);
|
||||
|
||||
// const user = await this.userService.findOneByPhoneOrFail(dto.phoneNumber);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
export enum UserMessages {
|
||||
USER_ALREADY_EXISTS = 'کاربر مورد نظر در حال حاضر وجود دارد. لطفا وارد حساب شوید!'
|
||||
USER_ALREADY_EXISTS = 'کاربر مورد نظر با این ایمیل یا شماره همراه در حال حاضر وجود دارد. لطفا وارد حساب شوید!',
|
||||
USER_NOT_FOUND = 'کاربر مورد نظر پیدا نشد!',
|
||||
USER_PASSWORD_INVALID = 'رمز وارد شده اشتباده است!',
|
||||
USER_VALID_CREDENTIALS = 'اطلاعات وارد شده صحیح میباشد!'
|
||||
}
|
||||
|
||||
export enum OTPMessages {
|
||||
OTP_NOT_FOUND = 'این کد پیدا نشد! لطفا دوباره درخواست بدهید!',
|
||||
OTP_EXPIRED = 'این کد منسوخ شده است لطفا دوباره درخواست بدهید!',
|
||||
OTP_TOO_MANY_TRIES = 'تعداد تلاش ها بیش از حد مجاز است لطفا دوباره درخواست کد بدهید!',
|
||||
OTP_INVALID = 'کد وارد شده نا معتبر است!'
|
||||
}
|
||||
@@ -23,7 +23,7 @@ export class ResponseInterceptor<T> implements NestInterceptor<
|
||||
map((data: T) => ({
|
||||
success: true,
|
||||
statusCode: response.statusCode,
|
||||
message: 'درخواست با موفقیت پاسخ داده شد!',
|
||||
message: 'درخواست موفقیت آمیز بود!',
|
||||
timestamp: new Date().toISOString(),
|
||||
data
|
||||
}))
|
||||
|
||||
@@ -15,5 +15,11 @@ export const validationSchema = Joi.object({
|
||||
SMS_API_KEY: Joi.string().required(),
|
||||
SMS_PATTERN_OTP: Joi.string().required(),
|
||||
|
||||
NODE_ENV: Joi.string().required()
|
||||
NODE_ENV: Joi.string().required(),
|
||||
|
||||
// JWT Config
|
||||
JWT_ACCESS_SECRET: Joi.string().required(),
|
||||
JWT_REFRESH_SECRET: Joi.string().required(),
|
||||
JWT_ACCESS_EXPIRES: Joi.string().required(),
|
||||
JWT_REFRESH_EXPIRES: Joi.string().required()
|
||||
});
|
||||
@@ -17,7 +17,6 @@ export class User extends BaseEntity {
|
||||
phone: string;
|
||||
|
||||
@Column({
|
||||
select: false
|
||||
})
|
||||
@Exclude()
|
||||
password: string;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { UserRepository } from './user.repository';
|
||||
import { User } from './entities/user.entity';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
@@ -9,6 +13,26 @@ import { UserMessages } from 'src/common/enums/messages.enum';
|
||||
export class UsersService {
|
||||
constructor(private readonly userRepository: UserRepository) {}
|
||||
|
||||
async findOneOrFail(id: string): Promise<User> {
|
||||
const user = await this.userRepository.findOne({ where: { id } });
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException(UserMessages.USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
async findOneByPhoneOrFail(phone: string): Promise<User> {
|
||||
const user = await this.userRepository.findOne({ where: { phone } });
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException(UserMessages.USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
async createUser(userDto: CreateUserDto): Promise<User> {
|
||||
const existingUser = await this.userRepository.findOne({
|
||||
where: [
|
||||
|
||||
Reference in New Issue
Block a user