/* Politique de mot de passe — validation + jauge côté client. * Miroir de password_policy_check() (api/db.php) : ≥ 8 caractères et au moins * 3 types parmi minuscule / majuscule / chiffre / caractère spécial. * Expose window.PWPolicy = { check, attach }. */ (function () { 'use strict'; const MIN_LEN = 8; const MIN_CLASSES = 3; function classes(pwd) { return { lower: /[a-z]/.test(pwd), upper: /[A-Z]/.test(pwd), digit: /[0-9]/.test(pwd), special: /[^A-Za-z0-9]/.test(pwd), }; } function check(pwd) { pwd = pwd || ''; const c = classes(pwd); const nbClasses = (c.lower ? 1 : 0) + (c.upper ? 1 : 0) + (c.digit ? 1 : 0) + (c.special ? 1 : 0); const lenOk = pwd.length >= MIN_LEN; const classesOk = nbClasses >= MIN_CLASSES; const unmet = []; if (!lenOk) unmet.push(`au moins ${MIN_LEN} caractères`); if (!classesOk) unmet.push(`au moins ${MIN_CLASSES} types (minuscule, majuscule, chiffre, spécial)`); // Score 0..4 pour la jauge. let score = 0; if (lenOk) score++; if (pwd.length >= 12) score++; score += Math.max(0, nbClasses - 1); score = Math.min(4, score); return { ok: lenOk && classesOk, unmet, score, lenOk, classesOk, nbClasses }; } const LABELS = ['Très faible', 'Faible', 'Moyen', 'Bon', 'Fort']; function attach(input, meter) { if (!input || !meter) return; const render = () => { const r = check(input.value); if (!input.value) { meter.innerHTML = ''; return; } const pct = (r.score / 4) * 100; const lvl = r.ok ? Math.max(2, r.score) : Math.min(1, r.score); meter.innerHTML = `
${r.ok ? '✓ ' : ''}${LABELS[r.score]}
`; }; input.addEventListener('input', render); render(); } window.PWPolicy = { check, attach }; })();