UNPKG

@open-tender/utils

Version:

A library of utils for use with Open Tender applications that utilize our cloud-based Order API.

97 lines (96 loc) 3.31 kB
/** * Password validation utility matching backend password policy * * Requirements: * - Minimum 10 characters * - At least one uppercase letter * - At least one lowercase letter * - At least one number * - At least one special character from allowed set: !@#$%^&_-+=<> * * Backend regex: ^[A-Za-z0-9\!\@\#\$\%\^\&\_\-\+\=\<\>]*$ */ // Constants const MIN_LENGTH = 10; const ALLOWED_SPECIAL_CHARS = '!@#$%^&_-+=<>'; // Regex patterns - DRY principle const REGEX = { ALLOWED_CHARS: /^[A-Za-z0-9!@#$%^&_\-+=<>]*$/, UPPERCASE: /[A-Z]/, LOWERCASE: /[a-z]/, NUMBER: /[0-9]/, SPECIAL_CHAR: /[!@#$%^&_\-+=<>]/, }; // Error messages - DRY principle const ERROR_MESSAGES = { MIN_LENGTH: `Password must be at least ${MIN_LENGTH} characters long`, INVALID_CHARS: `Password contains invalid characters. Only letters, numbers, and (${ALLOWED_SPECIAL_CHARS}) are allowed`, UPPERCASE: 'Password must include at least one uppercase letter', LOWERCASE: 'Password must include at least one lowercase letter', NUMBER: 'Password must include at least one number', SPECIAL_CHAR: `Password must include at least one special character (${ALLOWED_SPECIAL_CHARS})`, }; // SRP: Individual validation functions const hasMinLength = (password) => password.length >= MIN_LENGTH; const hasOnlyAllowedChars = (password) => REGEX.ALLOWED_CHARS.test(password); const hasUppercase = (password) => REGEX.UPPERCASE.test(password); const hasLowercase = (password) => REGEX.LOWERCASE.test(password); const hasNumber = (password) => REGEX.NUMBER.test(password); const hasSpecialChar = (password) => REGEX.SPECIAL_CHAR.test(password); export const validatePassword = (password) => { const errors = []; if (!password || !hasMinLength(password)) { errors.push(ERROR_MESSAGES.MIN_LENGTH); } if (!hasOnlyAllowedChars(password)) { errors.push(ERROR_MESSAGES.INVALID_CHARS); } if (!hasUppercase(password)) { errors.push(ERROR_MESSAGES.UPPERCASE); } if (!hasLowercase(password)) { errors.push(ERROR_MESSAGES.LOWERCASE); } if (!hasNumber(password)) { errors.push(ERROR_MESSAGES.NUMBER); } if (!hasSpecialChar(password)) { errors.push(ERROR_MESSAGES.SPECIAL_CHAR); } return { isValid: errors.length === 0, errors, }; }; export const getPasswordRequirements = (password) => { const requirements = [ { met: hasMinLength(password), message: `At least ${MIN_LENGTH} characters`, }, { met: hasUppercase(password), message: 'One uppercase letter', }, { met: hasLowercase(password), message: 'One lowercase letter', }, { met: hasNumber(password), message: 'One number', }, { met: hasOnlyAllowedChars(password) && hasSpecialChar(password), message: `One special character from: ${ALLOWED_SPECIAL_CHARS}`, }, ]; return requirements; }; export const getPasswordErrorMessage = (password) => { const validation = validatePassword(password); if (validation.isValid) return ''; // Return all errors as a single message return validation.errors.join('. '); };