- Updated `resendOtp.ts` to parse and validate request body using Zod. - Refactored `createPassword.ts` to utilize Zod for body validation. - Modified `getAMDetail_ById.ts` to implement Zod for path parameter validation. - Changed `acceptHostApplication.ts` to use Zod for request body validation. - Updated `addPQQSuggestion.ts` to validate request body with Zod. - Refactored `addSuggestion.ts` to use Zod for body validation. - Modified `getAllHostApplicationForAM.ts` to implement Zod for query parameter validation. - Changed `getByIdHostDetails.ts` to use Zod for path parameter validation. - Updated `rejectHostApplicationAM.ts` to validate request body with Zod. - Refactored `rejectPQQbyAM.ts` to use Zod for body validation. - Modified `acceptHostAppMinglar.ts` to implement Zod for request body validation. - Changed `assignAM.ts` to use Zod for request body validation. - Updated `editAgreementDetails.ts` to validate request body with Zod. - Refactored `getAllActivityOfHost.ts` to implement Zod for path and query parameter validation. - Changed `rejectHostApplication.ts` to use Zod for request body validation. - Updated `loginForMinglar.ts` to validate request body with Zod. - Refactored `registration.ts` to implement Zod for request body validation. - Modified `getAllCoadminAndAM.ts` to use Zod for query parameter validation. - Changed `getAllInvitationDetails.ts` to implement Zod for query parameter validation. - Updated `getAllInvitedCoadminAndAM.ts` to validate query parameters with Zod. - Refactored `inviteTeammate.ts` to use Zod for request body validation. - Modified `getBranchByBank.ts` to implement Zod for query parameter validation. - Changed `getCityByState.ts` to use Zod for query parameter validation.
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
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 * 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';
|
|
import { parseBody } from '../../../../../common/utils/validation/validation.utils';
|
|
import { hostSignUpSchema } from '../../../../../common/utils/validation/host/auth.validation';
|
|
|
|
const prismaService = new PrismaService();
|
|
const hostService = new HostService(prismaService);
|
|
|
|
export async function generateHostRefNumber(tx: any) {
|
|
const lastrecord = await tx.user.findFirst({
|
|
orderBy: {
|
|
id: 'desc',
|
|
},
|
|
select: {
|
|
id: true,
|
|
},
|
|
});
|
|
|
|
const nextId = lastrecord ? lastrecord.id + 1 : 1;
|
|
|
|
return `HS-${String(nextId).padStart(6, '0')}`;;
|
|
}
|
|
|
|
export const handler = safeHandler(async (
|
|
event: APIGatewayProxyEvent,
|
|
context?: Context
|
|
): Promise<APIGatewayProxyResult> => {
|
|
// Parse and validate request body using Zod
|
|
const { email } = parseBody(event.body, hostSignUpSchema);
|
|
|
|
// 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;
|
|
|
|
const referenceNumber = await generateHostRefNumber(tx);
|
|
|
|
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, userRefNumber: referenceNumber },
|
|
});
|
|
}
|
|
|
|
// 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 (!transactionResult || !transactionResult.otp) {
|
|
throw new ApiError(500, 'Failed to generate OTP');
|
|
}
|
|
|
|
// Send OTP email outside the DB transaction
|
|
// await sendOtpEmailForHost(transactionResult.newUser.emailAddress, transactionResult.otp);
|
|
|
|
return {
|
|
statusCode: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Access-Control-Allow-Origin': '*',
|
|
},
|
|
body: JSON.stringify({
|
|
success: true,
|
|
message: 'OTP sent successfully.',
|
|
data: {},
|
|
}),
|
|
};
|
|
});
|
|
|