From 00dd080ee0f2129128c661831a01a33847ccd01d Mon Sep 17 00:00:00 2001 From: paritosh18 Date: Thu, 20 Nov 2025 16:57:10 +0530 Subject: [PATCH] Refactor registration handler to use a transaction for user creation and OTP generation; implement OTP storage and user role assignment --- src/modules/host/handlers/registration.ts | 84 +++++++++++++++-------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/src/modules/host/handlers/registration.ts b/src/modules/host/handlers/registration.ts index 4f42cdf..bb5cb0d 100644 --- a/src/modules/host/handlers/registration.ts +++ b/src/modules/host/handlers/registration.ts @@ -2,9 +2,12 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda import { PrismaService } from '../../../common/database/prisma.service'; import { safeHandler } from '../../../common/utils/handlers/safeHandler'; import ApiError from '../../../common/utils/helper/ApiError'; -import { generateOtpHelper } from '../../../common/utils/helper/sendOtp'; +import * as bcrypt from 'bcryptjs'; +import { OtpGeneratorSixDigit } from '../../../common/utils/helper/OtpGenerator'; +import { encryptUserId } from '../../../common/utils/helper/CodeGenerator'; import { HostService } from '../services/host.service'; import { sendOtpEmailForHost } from '../services/sendOTPEmail.service'; +import { ROLE } from '../../../common/utils/constants/common.constant'; const prismaService = new PrismaService(); const hostService = new HostService(prismaService); @@ -28,38 +31,61 @@ export const handler = safeHandler(async ( throw new ApiError(400, 'Email is required'); } - const user = await prismaService.user.findUnique({ - where: { emailAddress: email }, - select: { emailAddress: true, id: true, userPassword: true }, + // Use a single transaction for user creation/lookup and OTP storage + const transactionResult = await prismaService.$transaction(async (tx) => { + const user = await tx.user.findUnique({ + where: { emailAddress: email }, + select: { emailAddress: true, id: true, userPassword: true }, + }); + + if (user && user.userPassword) { + throw new ApiError(409, 'User is already registered. Please login.'); + } + + let newUserLocal; + + if (user && !user.userPassword) { + // reuse existing invited user record + newUserLocal = user; + } else { + // create new user record within the transaction + newUserLocal = await tx.user.create({ + data: { emailAddress: email, roleXid: ROLE.HOST }, + }); + } + + // Generate OTP (6-digit) and store within the same transaction + const otp = OtpGeneratorSixDigit.generateOtp(); + const hashedOtp = await bcrypt.hash(otp, 10); + const expiry = new Date(Date.now() + 5 * 60 * 1000); // 5 minutes + + // delete old active OTPs for this user/purpose + await tx.userOtp.deleteMany({ + where: { userXid: Number(newUserLocal.id), otpType: 'Register', isActive: true }, + }); + + await tx.userOtp.create({ + data: { + userXid: Number(newUserLocal.id), + otpType: 'Register', + otpCode: hashedOtp, + expiresOn: expiry, + isVerified: false, + isActive: true, + }, + }); + + const encryptedId = encryptUserId(String(newUserLocal.id)); + + return { newUser: newUserLocal, otp, encryptedId }; }); - if (user && user.userPassword) { - throw new ApiError(409, 'User is already registered. Please login.'); + if (!transactionResult || !transactionResult.otp) { + throw new ApiError(500, 'Failed to generate OTP'); } - let newUser; - - if (user && !user.userPassword) { - // ✅ User already exists but without password → reuse record - newUser = user; - } else { - // ✅ No user found → create new one - newUser = await hostService.createMinglarUser(email); - } - - const otpResult = await generateOtpHelper( - Number(newUser?.id), - newUser?.emailAddress, - 'Register', - 6, - 5 - ); - - if (!otpResult || !otpResult.otp) { - throw new ApiError(500, 'Failed to send OTP'); - } - - // await sendOtpEmailForHost(newUser?.emailAddress, otpResult.otp); + // Send OTP email outside the DB transaction + // await sendOtpEmailForHost(transactionResult.newUser.emailAddress, transactionResult.otp); return { statusCode: 200,