made register and login apis for host
This commit is contained in:
@@ -8,7 +8,8 @@ import config from '../../../config/config';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
interface DecodedToken {
|
||||
id: number;
|
||||
id?: number;
|
||||
sub?: string | number;
|
||||
role?: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
@@ -26,7 +27,59 @@ declare module 'express-serve-static-core' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 3)
|
||||
* Core authentication function - verifies JWT and validates Host user
|
||||
* Can be used by both Express middleware and Lambda handlers
|
||||
*/
|
||||
export async function verifyHostToken(token: string): Promise<{ id: number; role?: string }> {
|
||||
if (!token) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate');
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret) as unknown as DecodedToken;
|
||||
|
||||
const userId = decoded.id ?? (decoded.sub ? Number(decoded.sub) : null);
|
||||
|
||||
if (!userId) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload');
|
||||
}
|
||||
|
||||
// ✅ Fetch user from Prisma (Host user only)
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { role: true },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||
}
|
||||
|
||||
// ✅ Check if user is active
|
||||
if (user.isActive === false) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.');
|
||||
}
|
||||
|
||||
// ✅ Check Host role (role_xid = 4)
|
||||
if (user.roleXid !== 4) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only');
|
||||
}
|
||||
|
||||
return { id: user.id, role: user.role?.roleName };
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.');
|
||||
}
|
||||
|
||||
if (error instanceof ApiError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 4)
|
||||
*/
|
||||
const verifyCallback = async (
|
||||
req: Request,
|
||||
@@ -35,62 +88,22 @@ const verifyCallback = async (
|
||||
) => {
|
||||
const token = req.header('x-auth-token') || req.cookies?.accessToken;
|
||||
|
||||
if (!token) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate'));
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret) as DecodedToken;
|
||||
|
||||
if (!decoded?.id) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload'));
|
||||
}
|
||||
|
||||
// ✅ Fetch user from Prisma (Host user only)
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: decoded.id },
|
||||
include: { role: true },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'User not found'));
|
||||
}
|
||||
|
||||
// ✅ Check if user is active
|
||||
if (!user.isActive) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.')
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ Check Host role (role_xid = 3)
|
||||
if (user.roleXid !== 3) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only')
|
||||
);
|
||||
}
|
||||
|
||||
const userInfo = await verifyHostToken(token);
|
||||
|
||||
// Attach user to request
|
||||
req.user = { id: user.id.toString(), role: user.role?.roleName };
|
||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.')
|
||||
);
|
||||
}
|
||||
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.')
|
||||
);
|
||||
return reject(error as Error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Express middleware — use as `auth()` in routes
|
||||
*/
|
||||
const auth =
|
||||
const authForHost =
|
||||
() =>
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -100,4 +113,4 @@ const auth =
|
||||
.catch((err) => next(err));
|
||||
};
|
||||
|
||||
export default auth;
|
||||
export default authForHost;
|
||||
|
||||
@@ -26,24 +26,19 @@ declare module 'express-serve-static-core' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 3)
|
||||
* Core authentication function - verifies JWT and validates Host user
|
||||
* Can be used by both Express middleware and Lambda handlers
|
||||
*/
|
||||
const verifyCallback = async (
|
||||
req: Request,
|
||||
resolve: (value?: unknown) => void,
|
||||
reject: (reason?: Error) => void
|
||||
) => {
|
||||
const token = req.header('x-auth-token') || req.cookies?.accessToken;
|
||||
|
||||
export async function verifyHostToken(token: string): Promise<{ id: number; role?: string }> {
|
||||
if (!token) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate');
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret) as DecodedToken;
|
||||
|
||||
if (!decoded?.id) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload');
|
||||
}
|
||||
|
||||
// ✅ Fetch user from Prisma (Host user only)
|
||||
@@ -53,44 +48,59 @@ const verifyCallback = async (
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'User not found'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||
}
|
||||
|
||||
// ✅ Check if user is active
|
||||
if (!user.isActive) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.')
|
||||
);
|
||||
if (user.isActive === false) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.');
|
||||
}
|
||||
|
||||
// ✅ Check Admin role (role_xid = 2)
|
||||
if (user.roleXid !== 2) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only')
|
||||
);
|
||||
// ✅ Check Host role (role_xid = 1)
|
||||
if (user.roleXid !== 1) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only');
|
||||
}
|
||||
|
||||
return { id: user.id, role: user.role?.roleName };
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.');
|
||||
}
|
||||
|
||||
if (error instanceof ApiError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 4)
|
||||
*/
|
||||
const verifyCallback = async (
|
||||
req: Request,
|
||||
resolve: (value?: unknown) => void,
|
||||
reject: (reason?: Error) => void
|
||||
) => {
|
||||
const token = req.header('x-auth-token') || req.cookies?.accessToken;
|
||||
|
||||
try {
|
||||
const userInfo = await verifyHostToken(token);
|
||||
|
||||
// Attach user to request
|
||||
req.user = { id: user.id.toString(), role: user.role?.roleName };
|
||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.')
|
||||
);
|
||||
}
|
||||
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.')
|
||||
);
|
||||
return reject(error as Error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Express middleware — use as `auth()` in routes
|
||||
*/
|
||||
const auth =
|
||||
const authForHost =
|
||||
() =>
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -100,4 +110,4 @@ const auth =
|
||||
.catch((err) => next(err));
|
||||
};
|
||||
|
||||
export default auth;
|
||||
export default authForHost;
|
||||
|
||||
@@ -26,24 +26,19 @@ declare module 'express-serve-static-core' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 3)
|
||||
* Core authentication function - verifies JWT and validates Host user
|
||||
* Can be used by both Express middleware and Lambda handlers
|
||||
*/
|
||||
const verifyCallback = async (
|
||||
req: Request,
|
||||
resolve: (value?: unknown) => void,
|
||||
reject: (reason?: Error) => void
|
||||
) => {
|
||||
const token = req.header('x-auth-token') || req.cookies?.accessToken;
|
||||
|
||||
export async function verifyHostToken(token: string): Promise<{ id: number; role?: string }> {
|
||||
if (!token) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate');
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, config.jwt.secret) as DecodedToken;
|
||||
|
||||
if (!decoded?.id) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload');
|
||||
}
|
||||
|
||||
// ✅ Fetch user from Prisma (Host user only)
|
||||
@@ -53,44 +48,59 @@ const verifyCallback = async (
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'User not found'));
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||
}
|
||||
|
||||
// ✅ Check if user is active
|
||||
if (!user.isActive) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.')
|
||||
);
|
||||
if (user.isActive === false) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Your account is deactivated by admin.');
|
||||
}
|
||||
|
||||
// ✅ Check User role (role_xid = 1)
|
||||
if (user.roleXid !== 1) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only')
|
||||
);
|
||||
// ✅ Check Host role (role_xid = 6)
|
||||
if (user.roleXid !== 6) {
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Access restricted to host users only');
|
||||
}
|
||||
|
||||
return { id: user.id, role: user.role?.roleName };
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.');
|
||||
}
|
||||
|
||||
if (error instanceof ApiError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies JWT and validates Host user (role_xid = 4)
|
||||
*/
|
||||
const verifyCallback = async (
|
||||
req: Request,
|
||||
resolve: (value?: unknown) => void,
|
||||
reject: (reason?: Error) => void
|
||||
) => {
|
||||
const token = req.header('x-auth-token') || req.cookies?.accessToken;
|
||||
|
||||
try {
|
||||
const userInfo = await verifyHostToken(token);
|
||||
|
||||
// Attach user to request
|
||||
req.user = { id: user.id.toString(), role: user.role?.roleName };
|
||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
return reject(
|
||||
new ApiError(httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.')
|
||||
);
|
||||
}
|
||||
|
||||
return reject(
|
||||
new ApiError(httpStatus.FORBIDDEN, 'Invalid or expired authentication token.')
|
||||
);
|
||||
return reject(error as Error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Express middleware — use as `auth()` in routes
|
||||
*/
|
||||
const auth =
|
||||
const authForHost =
|
||||
() =>
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -100,4 +110,4 @@ const auth =
|
||||
.catch((err) => next(err));
|
||||
};
|
||||
|
||||
export default auth;
|
||||
export default authForHost;
|
||||
|
||||
37
src/common/utils/helper/CodeGenerator.ts
Normal file
37
src/common/utils/helper/CodeGenerator.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const algorithm = 'aes-256-cbc';
|
||||
const secretKey = crypto.scryptSync('your-secret-password', 'salt', 32);
|
||||
const ivLength = 16;
|
||||
|
||||
// Encrypt function
|
||||
export function encryptUserId(id: string): string {
|
||||
const iv = crypto.randomBytes(ivLength);
|
||||
const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
|
||||
let encrypted = cipher.update(id, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
return `${iv.toString('hex')}:${encrypted}`;
|
||||
}
|
||||
|
||||
// Decrypt function
|
||||
export function decryptUserId(encryptedId: string): string | null {
|
||||
try {
|
||||
const parts = encryptedId.split(':');
|
||||
if (parts.length !== 2) {
|
||||
console.error('Invalid encryptedId format:', encryptedId);
|
||||
return null;
|
||||
}
|
||||
|
||||
const iv = Buffer.from(parts[0], 'hex');
|
||||
const encryptedText = Buffer.from(parts[1], 'hex');
|
||||
|
||||
const decipher = crypto.createDecipheriv(algorithm, secretKey, iv);
|
||||
let decrypted = decipher.update(encryptedText);
|
||||
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
||||
|
||||
return decrypted.toString('utf8');
|
||||
} catch (error) {
|
||||
console.error('Decryption failed:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
18
src/common/utils/helper/OtpGenerator.ts
Normal file
18
src/common/utils/helper/OtpGenerator.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import config from '../../../config/config';
|
||||
|
||||
export class OtpGenerator {
|
||||
static generateOtp(): string {
|
||||
if (config.byPassOTP) {
|
||||
return '1234';
|
||||
}
|
||||
return Math.floor(1000 + Math.random() * 9000).toString();
|
||||
}
|
||||
}
|
||||
export class OtpGeneratorSixDigit {
|
||||
static generateOtp(): string {
|
||||
if (config.byPassOTP) {
|
||||
return '123456';
|
||||
}
|
||||
return Math.floor(100000 + Math.random() * 900000).toString();
|
||||
}
|
||||
}
|
||||
91
src/common/utils/helper/sendOtp.ts
Normal file
91
src/common/utils/helper/sendOtp.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import * as bcrypt from "bcryptjs";
|
||||
import { OtpGenerator, OtpGeneratorSixDigit } from "./OtpGenerator";
|
||||
import { encryptUserId } from "./CodeGenerator";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export interface OtpResult {
|
||||
otp: string; // Plain OTP (for sending)
|
||||
hashedOtp: string; // Hashed OTP (for DB storage)
|
||||
expiry: Date; // Expiry timestamp
|
||||
encryptedId: string; // Encrypted user ID
|
||||
emailMessage: string; // Message body for email
|
||||
emailSubject: string; // Subject line for email
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate OTP, store it in DB, and send email.
|
||||
* @param userId The user’s ID
|
||||
* @param email Recipient email
|
||||
* @param emailPurpose For which flow (e.g. "Register", "Login", "ForgotPassword")
|
||||
* @param otpLength OTP length (4 or 6)
|
||||
* @param expiryMinutes Expiry time in minutes
|
||||
*/
|
||||
export async function generateOtpHelper(
|
||||
userId: number,
|
||||
email: string,
|
||||
emailPurpose: "Register" | "Login" | "ForgotPassword",
|
||||
otpLength: 4 | 6 = 4,
|
||||
expiryMinutes: number = 5
|
||||
): Promise<OtpResult> {
|
||||
// Generate OTP
|
||||
const otp =
|
||||
otpLength === 6
|
||||
? OtpGeneratorSixDigit.generateOtp()
|
||||
: OtpGenerator.generateOtp();
|
||||
console.log("Generated OTP:", otp);
|
||||
// Hash OTP
|
||||
const hashedOtp = await bcrypt.hash(otp, 10);
|
||||
|
||||
// Expiry time
|
||||
const expiry = new Date(Date.now() + expiryMinutes * 60 * 1000);
|
||||
|
||||
// Encrypt user ID
|
||||
const encryptedId = encryptUserId(userId.toString());
|
||||
|
||||
// 🔹 First delete old OTPs for this user & purpose
|
||||
await prisma.userOtp.deleteMany({
|
||||
where: {
|
||||
userXid: userId,
|
||||
otpType: emailPurpose,
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Save OTP into user_otps table
|
||||
await prisma.userOtp.create({
|
||||
data: {
|
||||
userXid: userId,
|
||||
otpType: emailPurpose,
|
||||
otpCode: hashedOtp,
|
||||
expiresOn: expiry,
|
||||
isVerified: false,
|
||||
isActive: true,
|
||||
// sendOn will default to now()
|
||||
// createdAt will default to now()
|
||||
},
|
||||
});
|
||||
|
||||
// Build email content
|
||||
const emailSubject = `${emailPurpose} OTP Verification`;
|
||||
const emailMessage = `Your OTP for ${emailPurpose} is ${otp}. It will expire in ${expiryMinutes} minutes.`;
|
||||
|
||||
// Send email
|
||||
// await sendBulkEmailForOTP([
|
||||
// {
|
||||
// to: [{ email: email }],
|
||||
// subject: emailSubject,
|
||||
// htmlContent: emailMessage,
|
||||
// },
|
||||
// ]);
|
||||
|
||||
return {
|
||||
otp,
|
||||
hashedOtp,
|
||||
expiry,
|
||||
encryptedId,
|
||||
emailMessage,
|
||||
emailSubject,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// validations/hostBankDetails.validation.ts
|
||||
import { z } from "zod";
|
||||
|
||||
export const hostBankDetailsSchema = z.object({
|
||||
accountNumber: z
|
||||
.number()
|
||||
.int({ message: "Account number must be an integer" })
|
||||
.positive({ message: "Account number must be a positive number" }),
|
||||
|
||||
accountHolderName: z
|
||||
.string()
|
||||
.nonempty("Account holder name is required")
|
||||
.min(2, { message: "Account holder name must be at least 2 characters" }),
|
||||
|
||||
ifscCode: z
|
||||
.string()
|
||||
.nonempty("IFSC code is required")
|
||||
.regex(/^[A-Z]{4}0[A-Z0-9]{6}$/, { message: "Invalid IFSC code format" }),
|
||||
|
||||
bankXid: z
|
||||
.number()
|
||||
.int({ message: "Bank ID must be an integer" })
|
||||
.positive({ message: "Bank ID must be a positive number" }),
|
||||
|
||||
hostXid: z
|
||||
.number()
|
||||
.int({ message: "Host ID must be an integer" })
|
||||
.positive({ message: "Host ID must be a positive number" }),
|
||||
|
||||
bankBranchXid: z
|
||||
.number()
|
||||
.int({ message: "Bank branch ID must be an integer" })
|
||||
.positive({ message: "Bank branch ID must be a positive number" }),
|
||||
});
|
||||
|
||||
export type HostBankDetailsSchema = z.infer<typeof hostBankDetailsSchema>;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// Allowed document types (must match your DocumentType master table IDs)
|
||||
export const REQUIRED_DOC_TYPES = {
|
||||
PAN: 1,
|
||||
GST: 2,
|
||||
REGISTRATION: 3,
|
||||
AADHAAR: 4,
|
||||
};
|
||||
|
||||
export const hostCompanyDetailsSchema = z.object({
|
||||
companyName: z.string().min(1, "Company name is required"),
|
||||
address1: z.string().min(1, "Address1 is required"),
|
||||
address2: z.string().optional(),
|
||||
hostRefNumber: z.string().min(1, "Host reference number is required"),
|
||||
cityXid: z.number().min(1, "City is required"),
|
||||
stateXid: z.number().min(1, "State is required"),
|
||||
countryXid: z.number().min(1,"Country is required"),
|
||||
pinCode: z.string().min(4, "Pincode/Zipcode is required"),
|
||||
logoPath: z.string().optional(),
|
||||
isSubsidairy: z.boolean(),
|
||||
registrationNumber: z.string().min(1, "Registration number is required"),
|
||||
panNumber: z.string().min(1, "PAN number is required"),
|
||||
gstNumber: z.string().optional(),
|
||||
formationDate: z.string().refine((val) => !isNaN(Date.parse(val)), {
|
||||
message: "Formation date must be a valid date",
|
||||
}),
|
||||
companyType: z.string().min(1, "Company type is required"),
|
||||
websiteUrl: z.url().optional(),
|
||||
instagramUrl: z.url().optional(),
|
||||
facebookUrl: z.url().optional(),
|
||||
linkedinUrl: z.url().optional(),
|
||||
twitterUrl: z.url().optional(),
|
||||
currencyXid: z.number().min(1, "Currency is required"),
|
||||
});
|
||||
|
||||
// Validation for documents
|
||||
export const hostDocumentsSchema = z.array(
|
||||
z.object({
|
||||
documentTypeXid: z.number(),
|
||||
documentName: z.string(),
|
||||
filePath: z.string(),
|
||||
})
|
||||
);
|
||||
20
src/common/utils/validation/host/login.validation.ts
Normal file
20
src/common/utils/validation/host/login.validation.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// validations/hostBankDetails.validation.ts
|
||||
import { z } from "zod";
|
||||
|
||||
export const loginForHostSchema = z.object({
|
||||
|
||||
|
||||
emailAddress : z
|
||||
.string()
|
||||
.nonempty("Email is required"),
|
||||
|
||||
userPassword : z
|
||||
.string()
|
||||
.nonempty("Password is required")
|
||||
.min(8, { message: "Password must be at least 8 characters" }),
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
export type loginForHostSchema = z.infer<typeof loginForHostSchema>;
|
||||
Reference in New Issue
Block a user