feat: onboarding signup journey

This commit is contained in:
Abdalhamid Alhamad
2025-07-27 13:15:54 +03:00
parent bf43e62b17
commit c493bd57e1
12 changed files with 234 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import { PASSCODE_REGEX } from '../constants';
import {
AppleLoginRequestDto,
CreateUnverifiedUserRequestDto,
CreateUnverifiedUserV2RequestDto,
DisableBiometricRequestDto,
EnableBiometricRequestDto,
ForgetPasswordRequestDto,
@ -25,6 +26,7 @@ import {
setJuniorPasswordRequestDto,
VerifyLoginOtpRequestDto,
VerifyUserRequestDto,
VerifyUserV2RequestDto,
} from '../dtos/request';
import { Roles } from '../enums';
import { IJwtPayload, ILoginResponse } from '../interfaces';
@ -59,6 +61,25 @@ export class AuthService {
});
}
async sendPhoneRegisterOtp(body: CreateUnverifiedUserV2RequestDto) {
if (body.email) {
const isEmailUsed = await this.userService.findUser({ email: body.email, isEmailVerified: true });
if (isEmailUsed) {
this.logger.error(`Email ${body.email} is already used`);
throw new BadRequestException('USER.EMAIL_ALREADY_TAKEN');
}
}
this.logger.log(`Sending OTP to ${body.countryCode + body.phoneNumber}`);
const user = await this.userService.findOrCreateByPhoneNumber(body);
return this.otpService.generateAndSendOtp({
userId: user.id,
recipient: user.fullPhoneNumber,
scope: OtpScope.VERIFY_PHONE,
otpType: OtpType.SMS,
});
}
async verifyUser(verifyUserDto: VerifyUserRequestDto): Promise<[ILoginResponse, User]> {
this.logger.log(`Verifying user with email ${verifyUserDto.email}`);
const user = await this.userService.findUserOrThrow({ email: verifyUserDto.email });
@ -89,6 +110,39 @@ export class AuthService {
return [tokens, user];
}
async verifyUserV2(verifyUserDto: VerifyUserV2RequestDto): Promise<[ILoginResponse, User]> {
this.logger.log(`Verifying user with phone number ${verifyUserDto.countryCode + verifyUserDto.phoneNumber}`);
const user = await this.userService.findUserOrThrow({
phoneNumber: verifyUserDto.phoneNumber,
countryCode: verifyUserDto.countryCode,
});
if (user.isPhoneVerified) {
this.logger.error(`User with phone number ${user.fullPhoneNumber} already verified`);
throw new BadRequestException('USER.PHONE_NUMBER_ALREADY_VERIFIED');
}
const isOtpValid = await this.otpService.verifyOtp({
userId: user.id,
scope: OtpScope.VERIFY_PHONE,
otpType: OtpType.SMS,
value: verifyUserDto.otp,
});
if (!isOtpValid) {
this.logger.error(`Invalid OTP for user with phone number ${user.fullPhoneNumber}`);
throw new BadRequestException('OTP.INVALID_OTP');
}
await this.userService.verifyUserV2(user.id, verifyUserDto);
await user.reload();
const tokens = await this.generateAuthToken(user);
this.logger.log(`User with phone number ${user.fullPhoneNumber} verified successfully`);
return [tokens, user];
}
async setEmail(userId: string, { email }: SetEmailRequestDto) {
this.logger.log(`Setting email for user with id ${userId}`);
const user = await this.userService.findUserOrThrow({ id: userId });