import bcrypt from 'bcryptjs' const SALT_ROUNDS = 12 /** * Hash a password using bcrypt */ export async function hashPassword(password: string): Promise { return bcrypt.hash(password, SALT_ROUNDS) } /** * Verify a password against a hash */ export async function verifyPassword( password: string, hash: string ): Promise { return bcrypt.compare(password, hash) } interface PasswordValidation { valid: boolean errors: string[] } /** * Validate password meets requirements: * - Minimum 8 characters * - At least one uppercase letter * - At least one lowercase letter * - At least one number */ export function validatePassword(password: string): PasswordValidation { const errors: string[] = [] if (password.length < 8) { errors.push('Password must be at least 8 characters long') } if (!/[A-Z]/.test(password)) { errors.push('Password must contain at least one uppercase letter') } if (!/[a-z]/.test(password)) { errors.push('Password must contain at least one lowercase letter') } if (!/[0-9]/.test(password)) { errors.push('Password must contain at least one number') } return { valid: errors.length === 0, errors, } } /** * Get password strength score (0-4) * 0 = very weak, 4 = very strong */ export function getPasswordStrength(password: string): { score: number label: 'Very Weak' | 'Weak' | 'Fair' | 'Strong' | 'Very Strong' } { let score = 0 // Length if (password.length >= 8) score++ if (password.length >= 12) score++ // Character variety if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score++ if (/[0-9]/.test(password)) score++ if (/[^a-zA-Z0-9]/.test(password)) score++ // Normalize to 0-4 const normalizedScore = Math.min(4, score) const labels: Record = { 0: 'Very Weak', 1: 'Weak', 2: 'Fair', 3: 'Strong', 4: 'Very Strong', } return { score: normalizedScore, label: labels[normalizedScore], } }