diff --git a/apps/edr-freight-api/src/modules/otp/otp.service.ts b/apps/edr-freight-api/src/modules/otp/otp.service.ts index 436f34411..67fbdec9b 100644 --- a/apps/edr-freight-api/src/modules/otp/otp.service.ts +++ b/apps/edr-freight-api/src/modules/otp/otp.service.ts @@ -1,9 +1,6 @@ // otp.service.ts -import { - BadRequestException, - Injectable, -} from "@nestjs/common"; +import { BadRequestException, Injectable, Logger } from "@nestjs/common"; import { OtpRepository } from "./otp.repository"; @@ -16,20 +13,19 @@ export type OtpTarget = { phone?: string; email?: string }; @Injectable() export class OtpService { + logger = new Logger(OtpService.name); constructor( private readonly otpRepository: OtpRepository, private readonly smsClient: SmsClientService, - private readonly emailClient: EmailClientService - ) {} + private readonly emailClient: EmailClientService, + ) { } // --------------------------------------------------------------------------- // Generate OTP // --------------------------------------------------------------------------- generateOtp(): string { - return Math.floor( - 100000 + Math.random() * 900000 - ).toString(); + return Math.floor(100000 + Math.random() * 900000).toString(); } // --------------------------------------------------------------------------- @@ -44,23 +40,14 @@ export class OtpService { const otp = this.generateOtp(); // find existing row for this channel - const existing = - await this.otpRepository.findByTarget( - target - ); + const existing = await this.otpRepository.findByTarget(target); // update existing otp if (existing) { - await this.otpRepository.updateOtp( - existing, - otp - ); + await this.otpRepository.updateOtp(existing, otp); } else { // create new otp - await this.otpRepository.createOtp( - target, - otp - ); + await this.otpRepository.createOtp(target, otp); } if (target.email) { @@ -78,18 +65,16 @@ export class OtpService { }); } + this.logger.log(`OTP send for ${target.email ?? target.phone}: ${otp}`); return { success: true, - message: - "OTP sent successfully", + message: "OTP sent successfully", }; } catch (error) { console.log(error); - throw new BadRequestException( - "Failed to send OTP" - ); + throw new BadRequestException("Failed to send OTP"); } } @@ -97,44 +82,31 @@ export class OtpService { // Verify OTP // --------------------------------------------------------------------------- - async verifyOtp( - target: OtpTarget, - otp: string - ) { + async verifyOtp(target: OtpTarget, otp: string) { // find the channel's row - const otpData = - await this.otpRepository.findByTarget( - target - ); + const otpData = await this.otpRepository.findByTarget(target); // not found if (!otpData) { throw new BadRequestException( - target.email - ? "Email address not found" - : "Phone number not found" + target.email ? "Email address not found" : "Phone number not found", ); } // invalid otp if (otpData.otp !== otp) { - throw new BadRequestException( - "Invalid OTP" - ); + throw new BadRequestException("Invalid OTP"); } // mark verified - await this.otpRepository.markVerified( - otpData - ); + await this.otpRepository.markVerified(otpData); return { success: true, - message: - target.email - ? "Email verified successfully" - : "Phone verified successfully", + message: target.email + ? "Email verified successfully" + : "Phone verified successfully", }; } @@ -146,51 +118,34 @@ export class OtpService { // contract signature). Unlike verifyOtp above — which marks a phone verified // and leaves the code in place — this enforces a short TTL and consumes the // code on success so it can never be replayed. - private readonly ACTION_OTP_TTL_MS = - 5 * 60 * 1000; + private readonly ACTION_OTP_TTL_MS = 5 * 60 * 1000; - async verifyOtpForAction( - phone: string, - otp: string - ) { - const otpData = - await this.otpRepository.findByPhone( - phone - ); + async verifyOtpForAction(phone: string, otp: string) { + const otpData = await this.otpRepository.findByPhone(phone); if (!otpData) { throw new BadRequestException( - "No verification code was requested for this phone" + "No verification code was requested for this phone", ); } - const ageMs = - Date.now() - - new Date( - otpData.updatedAt - ).getTime(); + const ageMs = Date.now() - new Date(otpData.updatedAt).getTime(); if (ageMs > this.ACTION_OTP_TTL_MS) { - await this.otpRepository.deleteOtp( - otpData - ); + await this.otpRepository.deleteOtp(otpData); throw new BadRequestException( - "Verification code has expired. Request a new one." + "Verification code has expired. Request a new one.", ); } if (otpData.otp !== otp) { - throw new BadRequestException( - "Invalid verification code" - ); + throw new BadRequestException("Invalid verification code"); } // single-use: consume on success - await this.otpRepository.deleteOtp( - otpData - ); + await this.otpRepository.deleteOtp(otpData); return { success: true }; } -} \ No newline at end of file +}