File size: 2,373 Bytes
f0743f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | const { z } = require('zod');
const MIN_PASSWORD_LENGTH = parseInt(process.env.MIN_PASSWORD_LENGTH, 10) || 8;
const allowedCharactersRegex = new RegExp(
'^[' +
'a-zA-Z0-9_.@#$%&*()' + // Basic Latin characters and symbols
'\\p{Script=Latin}' + // Latin script characters
'\\p{Script=Common}' + // Characters common across scripts
'\\p{Script=Cyrillic}' + // Cyrillic script for Russian, etc.
'\\p{Script=Devanagari}' + // Devanagari script for Hindi, etc.
'\\p{Script=Han}' + // Han script for Chinese characters, etc.
'\\p{Script=Arabic}' + // Arabic script
'\\p{Script=Hiragana}' + // Hiragana script for Japanese
'\\p{Script=Katakana}' + // Katakana script for Japanese
'\\p{Script=Hangul}' + // Hangul script for Korean
']+$', // End of string
'u', // Use Unicode mode
);
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(MIN_PASSWORD_LENGTH)
.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(MIN_PASSWORD_LENGTH)
.max(128)
.refine((value) => value.trim().length > 0, {
message: 'Password cannot be only spaces',
}),
confirm_password: z
.string()
.min(MIN_PASSWORD_LENGTH)
.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,
};
|