mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 21:50:57 +00:00
fix: ( iam ) allow re-registration of abandoned pending accounts
This commit is contained in:
@@ -42,11 +42,7 @@ export class PassengerAuthService {
|
||||
}
|
||||
|
||||
async register(dto: RegisterDto, req: any) {
|
||||
const existing = await this.dataSource.query<{ id: string }[]>(
|
||||
`SELECT id FROM iam.users WHERE email = $1 OR phone_number = $2 LIMIT 1`,
|
||||
[dto.email, dto.phoneNumber],
|
||||
);
|
||||
if (existing.length) throw new ConflictException('Email or phone already registered');
|
||||
await this.clearPendingOrConflict(dto.email, dto.phoneNumber);
|
||||
|
||||
const iamAuthService = await this.resolveIamAuthService(req);
|
||||
|
||||
@@ -101,11 +97,7 @@ export class PassengerAuthService {
|
||||
},
|
||||
req: any,
|
||||
): Promise<{ iamUserId: string; passengerId: string }> {
|
||||
const existing = await this.dataSource.query<{ id: string }[]>(
|
||||
`SELECT id FROM iam.users WHERE email = $1 OR phone_number = $2 LIMIT 1`,
|
||||
[dto.email, dto.phoneNumber],
|
||||
);
|
||||
if (existing.length) throw new ConflictException('Email or phone already registered');
|
||||
await this.clearPendingOrConflict(dto.email, dto.phoneNumber);
|
||||
|
||||
const iamAuthService = await this.resolveIamAuthService(req);
|
||||
await iamAuthService.signupWithPassword({
|
||||
@@ -600,6 +592,32 @@ export class PassengerAuthService {
|
||||
return `+${digits}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-signup uniqueness guard. Throws `ConflictException` only when a
|
||||
* *fully-registered* account (`has_set_password = true`) already owns the
|
||||
* email or phone. Abandoned PENDING signups — where the user received the OTP
|
||||
* but never completed `set-password` — are deleted so this fresh attempt can
|
||||
* re-create the account and re-send the code, instead of being blocked with a
|
||||
* 409 forever. Matches `resendRegistrationCode`'s `has_set_password = false`
|
||||
* notion of "still pending".
|
||||
*/
|
||||
private async clearPendingOrConflict(email: string, phoneNumber: string): Promise<void> {
|
||||
const matches = await this.dataSource.query<
|
||||
{ id: string; email: string; has_set_password: boolean }[]
|
||||
>(
|
||||
`SELECT id, email, has_set_password FROM iam.users WHERE email = $1 OR phone_number = $2`,
|
||||
[email, phoneNumber],
|
||||
);
|
||||
if (!matches.length) return;
|
||||
if (matches.some((u) => u.has_set_password)) {
|
||||
throw new ConflictException('Email or phone already registered');
|
||||
}
|
||||
// Every match is an abandoned pending signup — clean it up so the caller can proceed.
|
||||
for (const u of matches) {
|
||||
await this.compensateIamSignup(u.email);
|
||||
}
|
||||
}
|
||||
|
||||
private async compensateIamSignup(email: string): Promise<void> {
|
||||
try {
|
||||
const rows = await this.dataSource.query<{ id: string }[]>(
|
||||
|
||||
Reference in New Issue
Block a user