From 8212ede785e15f0fb365e6cc32fd58f7d95a443a Mon Sep 17 00:00:00 2001 From: radmehr Date: Thu, 26 Feb 2026 09:14:30 +0330 Subject: [PATCH] feat: add verify otp endpoint --- src/modules/auth/auth.controller.ts | 4 +-- src/modules/auth/auth.module.ts | 8 ++++- .../auth/http/verify-otp.post.endpoints.http | 7 ++++ src/modules/auth/providers/auth.service.ts | 11 +++++- .../auth/providers/verify-otp.provider.ts | 36 +++++++++++++++++++ src/modules/otp/otp.entity.ts | 1 - src/modules/otp/providers/otp.service.ts | 5 +-- 7 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 src/modules/auth/http/verify-otp.post.endpoints.http create mode 100644 src/modules/auth/providers/verify-otp.provider.ts diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index a3a4d29..2c88293 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -20,7 +20,7 @@ export class AuthController { @Post('verify-otp') @HttpCode(200) - public verifyOTP(@Body() verifyOtpDto: VerifyOtpDTO) { - return verifyOtpDto; + public async verifyOTP(@Body() verifyOtpDto: VerifyOtpDTO) { + return await this.authService.verifyOTP(verifyOtpDto); } } diff --git a/src/modules/auth/auth.module.ts b/src/modules/auth/auth.module.ts index 2620c05..fa90a4d 100644 --- a/src/modules/auth/auth.module.ts +++ b/src/modules/auth/auth.module.ts @@ -8,6 +8,7 @@ import { JwtModule } from '@nestjs/jwt'; import { ConfigService } from '@nestjs/config'; import { LoginProvider } from './providers/login.provider'; import { GenerateTokenProvider } from './providers/generate-token.provider'; +import { VerifyOTPProvider } from './providers/verify-otp.provider'; @Module({ imports: [ @@ -27,6 +28,11 @@ import { GenerateTokenProvider } from './providers/generate-token.provider'; }), ], controllers: [AuthController], - providers: [AuthService, GenerateTokenProvider, LoginProvider], + providers: [ + AuthService, + GenerateTokenProvider, + LoginProvider, + VerifyOTPProvider, + ], }) export class AuthModule {} diff --git a/src/modules/auth/http/verify-otp.post.endpoints.http b/src/modules/auth/http/verify-otp.post.endpoints.http new file mode 100644 index 0000000..de10de2 --- /dev/null +++ b/src/modules/auth/http/verify-otp.post.endpoints.http @@ -0,0 +1,7 @@ +POST http://localhost:3000/users/verify-otp +Content-Type: application/json + +{ + "phone": "09126093033", + "otp": "57903" +} \ No newline at end of file diff --git a/src/modules/auth/providers/auth.service.ts b/src/modules/auth/providers/auth.service.ts index 831bd29..077aa13 100644 --- a/src/modules/auth/providers/auth.service.ts +++ b/src/modules/auth/providers/auth.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@nestjs/common'; import { LoginDTO } from '../dtos/login.dto'; import { LoginProvider } from './login.provider'; +import { VerifyOtpDTO } from '../dtos/verify-otp.dto'; +import { VerifyOTPProvider } from './verify-otp.provider'; @Injectable() export class AuthService { @@ -9,11 +11,18 @@ export class AuthService { * Inject Login Provider */ private readonly loginProvider: LoginProvider, + + /** + * Inject Verify OTP Provider + */ + private readonly verifyOTPProvider: VerifyOTPProvider, ) {} public async logIn(loginDto: LoginDTO) { return await this.loginProvider.logIn(loginDto); } - // public async verifyOTP(verifyOtpDto: VerifyOtpDTO) {} + public async verifyOTP(verifyOtpDto: VerifyOtpDTO) { + return await this.verifyOTPProvider.verifyOTP(verifyOtpDto); + } } diff --git a/src/modules/auth/providers/verify-otp.provider.ts b/src/modules/auth/providers/verify-otp.provider.ts new file mode 100644 index 0000000..47ff49a --- /dev/null +++ b/src/modules/auth/providers/verify-otp.provider.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@nestjs/common'; +import { VerifyOtpDTO } from '../dtos/verify-otp.dto'; +import { OtpService } from '@/modules/otp/providers/otp.service'; +import { UsersService } from '@/modules/users/providers/users.service'; +import { GenerateTokenProvider } from './generate-token.provider'; +import { randomUUID } from 'crypto'; + +@Injectable() +export class VerifyOTPProvider { + constructor( + /** + * Inject OTP Service + */ + private readonly otpService: OtpService, + + /** + * Inject User Service + */ + private readonly usersService: UsersService, + + /** + * Inject Generate Token Provider + */ + private readonly generateTokenProvider: GenerateTokenProvider, + ) {} + + public async verifyOTP(verifyOtpDto: VerifyOtpDTO) { + const { phone, otp } = verifyOtpDto; + const otpInstance = await this.otpService.verifyOTP(phone, otp); + + const user = await this.usersService.createOne(otpInstance.phone); + + const jti = randomUUID(); + return await this.generateTokenProvider.generateTokens(user, jti); + } +} diff --git a/src/modules/otp/otp.entity.ts b/src/modules/otp/otp.entity.ts index 67780e6..ecfa1a3 100644 --- a/src/modules/otp/otp.entity.ts +++ b/src/modules/otp/otp.entity.ts @@ -23,7 +23,6 @@ export class OTP { @Column({ type: 'varchar', - length: 5, nullable: false, }) code: string; diff --git a/src/modules/otp/providers/otp.service.ts b/src/modules/otp/providers/otp.service.ts index 2885f9d..53a9b14 100644 --- a/src/modules/otp/providers/otp.service.ts +++ b/src/modules/otp/providers/otp.service.ts @@ -84,8 +84,9 @@ export class OtpService { throw new UnauthorizedException('OTP expired'); } - // TODO: Compared hashed otp - if (otp.code !== code) { + const isOTPCorrect = await this.hashingProvider.compare(code, otp.code); + + if (!isOTPCorrect) { throw new UnauthorizedException('Invalid OTP'); }