mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
chore: add loger
This commit is contained in:
@@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user