forked from Yara724/api
YARA-1075
This commit is contained in:
@@ -2092,14 +2092,32 @@ export class RequestManagementService {
|
||||
(req.parties[secondIdx].person as any).phoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
// If a valid OTP is already active for this number, return 200 immediately —
|
||||
// no duplicate SMS, no unnecessary write, no error shown to the expert.
|
||||
const canonicalPhoneAdv = normalizeIranMobile(phoneNumber) ?? phoneNumber;
|
||||
const existingUserAdv = await this.userDbService.findOne(
|
||||
buildUserLookupByPhone(canonicalPhoneAdv),
|
||||
);
|
||||
if (existingUserAdv && isOtpExpiryActive(existingUserAdv.otpExpire)) {
|
||||
return {
|
||||
requestId: req._id,
|
||||
publicId: req.publicId,
|
||||
workflow: req.workflow,
|
||||
message: `OTP already sent to ${phoneNumber} and is still valid. Collect the code and call verify-party-otp.`,
|
||||
};
|
||||
}
|
||||
|
||||
// Send OTP to second party — expert collects it from them in person
|
||||
try {
|
||||
await this.userAuthService.sendOtpRequest(phoneNumber);
|
||||
} catch (e: any) {
|
||||
if (e?.message?.includes("Wait for expiry")) {
|
||||
throw new BadRequestException(
|
||||
`(${phoneNumber}): OTP was recently sent. Wait for the expiry time before requesting again.`,
|
||||
);
|
||||
return {
|
||||
requestId: req._id,
|
||||
publicId: req.publicId,
|
||||
workflow: req.workflow,
|
||||
message: `OTP already sent to ${phoneNumber} and is still valid. Collect the code and call verify-party-otp.`,
|
||||
};
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
@@ -4548,29 +4566,32 @@ export class RequestManagementService {
|
||||
);
|
||||
}
|
||||
const sent: string[] = [];
|
||||
|
||||
// Helper: send OTP or silently succeed when a valid OTP already exists.
|
||||
const sendOrSkipIfActive = async (phone: string): Promise<void> => {
|
||||
const canonical = normalizeIranMobile(phone) ?? phone;
|
||||
const existing = await this.userDbService.findOne(
|
||||
buildUserLookupByPhone(canonical),
|
||||
);
|
||||
if (existing && isOtpExpiryActive(existing.otpExpire)) {
|
||||
sent.push(phone); // already has a live OTP — treat as sent
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.userAuthService.sendOtpRequest(dto.firstPartyPhoneNumber);
|
||||
sent.push(dto.firstPartyPhoneNumber);
|
||||
await this.userAuthService.sendOtpRequest(phone);
|
||||
sent.push(phone);
|
||||
} catch (e: any) {
|
||||
if (e?.message?.includes("Wait for expiry")) {
|
||||
throw new BadRequestException(
|
||||
`First party (${dto.firstPartyPhoneNumber}): OTP was recently sent. Wait for the expiry time before requesting again.`,
|
||||
);
|
||||
sent.push(phone); // race: sendOtpRequest found it active too — treat as sent
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
await sendOrSkipIfActive(dto.firstPartyPhoneNumber);
|
||||
if (dto.secondPartyPhoneNumber) {
|
||||
try {
|
||||
await this.userAuthService.sendOtpRequest(dto.secondPartyPhoneNumber);
|
||||
sent.push(dto.secondPartyPhoneNumber);
|
||||
} catch (e: any) {
|
||||
if (e?.message?.includes("Wait for expiry")) {
|
||||
throw new BadRequestException(
|
||||
`Second party (${dto.secondPartyPhoneNumber}): OTP was recently sent. Wait for the expiry time before requesting again.`,
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
await sendOrSkipIfActive(dto.secondPartyPhoneNumber);
|
||||
}
|
||||
return {
|
||||
sent: true,
|
||||
@@ -4749,32 +4770,34 @@ export class RequestManagementService {
|
||||
new Date(event.timestamp) > twoMinutesAgo,
|
||||
);
|
||||
if (recentlySentToPhone) {
|
||||
throw new BadRequestException(
|
||||
`(${phone}): OTP was sent recently. Please wait 2 minutes before requesting again.`,
|
||||
);
|
||||
return {
|
||||
sent: true,
|
||||
message: `OTP already sent to ${phone} and is still valid. Collect the code from the party, then call verify-party-otp.`,
|
||||
};
|
||||
}
|
||||
|
||||
// --- DB-level cooldown guard (catches burst/concurrent requests before history is saved) ---
|
||||
// Read the user's otpExpire directly from the users collection. If a live
|
||||
// OTP already exists we return 400 immediately — no SMS call, no DB writes.
|
||||
const canonicalPhone =
|
||||
normalizeIranMobile(phone) ?? phone;
|
||||
// OTP already exists return 200 immediately — no duplicate SMS, no DB writes.
|
||||
const canonicalPhone = normalizeIranMobile(phone) ?? phone;
|
||||
const existingUser = await this.userDbService.findOne(
|
||||
buildUserLookupByPhone(canonicalPhone),
|
||||
);
|
||||
if (existingUser && isOtpExpiryActive(existingUser.otpExpire)) {
|
||||
throw new BadRequestException(
|
||||
`(${phone}): OTP was sent recently. Please wait before requesting again.`,
|
||||
);
|
||||
return {
|
||||
sent: true,
|
||||
message: `OTP already sent to ${phone} and is still valid. Collect the code from the party, then call verify-party-otp.`,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
await this.userAuthService.sendOtpRequest(phone);
|
||||
} catch (e: any) {
|
||||
if (e?.message?.includes("Wait for expiry")) {
|
||||
throw new BadRequestException(
|
||||
`(${phone}): OTP was recently sent. Wait for the expiry time before requesting again.`,
|
||||
);
|
||||
return {
|
||||
sent: true,
|
||||
message: `OTP already sent to ${phone} and is still valid. Collect the code from the party, then call verify-party-otp.`,
|
||||
};
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user