const { z } = require('zod'); function errorsToString(errors) { return errors .map((error) => { let field = error.path.join('.'); let message = error.message; return `${field}: ${message}`; }) .join(' '); } const allowedCharactersRegex = /^[a-zA-Z0-9_.@#$%&*()\p{Script=Latin}\p{Script=Common}]+$/u; const injectionPatternsRegex = /('|--|\$ne|\$gt|\$lt|\$or|\{|\}|\*|;|<|>|\/|=)/i; const usernameSchema = z .string() .min(2) .max(80) .refine((value) => allowedCharactersRegex.test(value), { message: 'Invalid characters in username', }) .refine((value) => !injectionPatternsRegex.test(value), { message: 'Potential injection attack detected', }); const loginSchema = z.object({ email: z.string().email(), password: z .string() .min(8) .max(128) .refine((value) => value.trim().length > 0, { message: 'Password cannot be only spaces', }), }); const registerSchema = z .object({ name: z.string().min(3).max(80), username: z .union([z.literal(''), usernameSchema]) .transform((value) => (value === '' ? null : value)) .optional() .nullable(), email: z.string().email(), password: z .string() .min(8) .max(128) .refine((value) => value.trim().length > 0, { message: 'Password cannot be only spaces', }), confirm_password: z .string() .min(8) .max(128) .refine((value) => value.trim().length > 0, { message: 'Password cannot be only spaces', }), }) .superRefine(({ confirm_password, password }, ctx) => { if (confirm_password !== password) { ctx.addIssue({ code: 'custom', message: 'The passwords did not match', }); } }); module.exports = { loginSchema, registerSchema, errorsToString, };