fix: enforce consistent password policy across all auth flows

Replace duplicated inline validation with a shared validatePassword()
utility that checks minimum length (8), rejects repetitive and common
passwords, and requires uppercase, lowercase, a digit, and a special
character.

- Add server/src/services/passwordPolicy.ts as single source of truth
- Apply to registration, password change, and admin create/edit user
  (admin routes previously had zero validation)
- Fix client min-length mismatch (6 vs 8) in RegisterPage and LoginPage
- Add client-side password length guard to AdminPage forms
- Update register.passwordTooShort and settings.passwordWeak i18n keys
  in all 12 locales to reflect the corrected requirements
This commit is contained in:
jubnl
2026-04-01 07:02:53 +02:00
parent ce8d498f2d
commit e03505dca2
18 changed files with 77 additions and 39 deletions
+27
View File
@@ -0,0 +1,27 @@
const COMMON_PASSWORDS = new Set([
'password', '12345678', '123456789', '1234567890', 'password1',
'qwerty123', 'iloveyou', 'admin123', 'letmein12', 'welcome1',
'monkey123', 'dragon12', 'master12', 'qwerty12', 'abc12345',
'trustno1', 'baseball', 'football', 'shadow12', 'michael1',
'jennifer', 'superman', 'abcdefgh', 'abcd1234', 'password123',
'admin1234', 'changeme', 'welcome123', 'passw0rd', 'p@ssword',
]);
export function validatePassword(password: string): { ok: boolean; reason?: string } {
if (password.length < 8) return { ok: false, reason: 'Password must be at least 8 characters' };
if (/^(.)\1+$/.test(password)) {
return { ok: false, reason: 'Password is too repetitive' };
}
if (COMMON_PASSWORDS.has(password.toLowerCase())) {
return { ok: false, reason: 'Password is too common. Please choose a unique password.' };
}
if (!/[A-Z]/.test(password)) return { ok: false, reason: 'Password must contain at least one uppercase letter' };
if (!/[a-z]/.test(password)) return { ok: false, reason: 'Password must contain at least one lowercase letter' };
if (!/[0-9]/.test(password)) return { ok: false, reason: 'Password must contain at least one number' };
if (!/[^A-Za-z0-9]/.test(password)) return { ok: false, reason: 'Password must contain at least one special character' };
return { ok: true };
}