'use strict'; /** * Shared validation for user account fields. * Email is MANDATORY on every account: it is how approval notifications and * system messages reach people, so an account without one cannot function. */ const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/; const USERNAME_RE = /^[A-Za-z0-9._-]{3,32}$/; /** * Normalise an email for storage: trim surrounding whitespace. * Returns '' for null/undefined so callers can treat "missing" and "blank" * the same way. */ function normaliseEmail(value) { return value === undefined || value === null ? '' : String(value).trim(); } /** * Validate a mandatory email address. * @returns {string|null} an error message, or null when valid. */ function validateEmail(value) { const email = normaliseEmail(value); if (!email) return 'An email address is required.'; if (email.length > 254) return 'That email address is too long.'; if (!EMAIL_RE.test(email)) return 'Please enter a valid email address.'; return null; } function validateUsername(value) { const username = value === undefined || value === null ? '' : String(value).trim(); if (!username) return 'A username is required.'; if (!USERNAME_RE.test(username)) { return 'Username must be 3-32 characters: letters, numbers, dot, underscore or hyphen.'; } return null; } function validatePassword(value) { const password = value === undefined || value === null ? '' : String(value); if (!password) return 'A password is required.'; if (password.length < 10) return 'Password must be at least 10 characters long.'; if (!/[A-Za-z]/.test(password) || !/[0-9]/.test(password)) { return 'Password must contain at least one letter and one number.'; } return null; } module.exports = { EMAIL_RE, USERNAME_RE, normaliseEmail, validateEmail, validateUsername, validatePassword, };