import { HttpError } from 'wasp/server'; export const PASSWORD_FIELD = 'password'; const USERNAME_FIELD = 'username'; const EMAIL_FIELD = 'email'; const TOKEN_FIELD = 'token'; // PUBLIC API export function ensureValidEmail(args: object): void { validate(args, [ { validates: EMAIL_FIELD, message: 'email must be present', validator: email => !!email }, { validates: EMAIL_FIELD, message: 'email must be a valid email', validator: email => isValidEmail(email) }, ]); } // PUBLIC API export function ensureValidUsername(args: object): void { validate(args, [ { validates: USERNAME_FIELD, message: 'username must be present', validator: username => !!username } ]); } // PUBLIC API export function ensurePasswordIsPresent(args: object): void { validate(args, [ { validates: PASSWORD_FIELD, message: 'password must be present', validator: password => !!password }, ]); } // PUBLIC API export function ensureValidPassword(args: object): void { validate(args, [ { validates: PASSWORD_FIELD, message: 'password must be at least 8 characters', validator: password => isMinLength(password, 8) }, { validates: PASSWORD_FIELD, message: 'password must contain a number', validator: password => containsNumber(password) }, ]); } // PUBLIC API export function ensureTokenIsPresent(args: object): void { validate(args, [ { validates: TOKEN_FIELD, message: 'token must be present', validator: token => !!token }, ]); } // PRIVATE API export function throwValidationError(message: string): void { throw new HttpError(422, 'Validation failed', { message }) } function validate(args: object, validators: { validates: string, message: string, validator: (value: unknown) => boolean }[]): void { for (const { validates, message, validator } of validators) { if (!validator(args[validates])) { throwValidationError(message); } } } // NOTE(miho): it would be good to replace our custom validations with e.g. Zod const validEmailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/ function isValidEmail(input: unknown): boolean { if (typeof input !== 'string') { return false } return input.match(validEmailRegex) !== null } function isMinLength(input: unknown, minLength: number): boolean { if (typeof input !== 'string') { return false } return input.length >= minLength } function containsNumber(input: unknown): boolean { if (typeof input !== 'string') { return false } return /\d/.test(input) }