George Lambert
2f524deea0
feat(auth): password change + reset with emailed 6-digit codes for portal and admin
Customer portal:
- POST /portal/api/password/change (session): currentPassword -> emailed code;
then {code,newPassword,totpCode?}. TOTP required when enabled. Aliases
/password/change/start|confirm. Revokes all sessions, returns a new token,
sends a 'password was changed' notice. Security tab UI replaces the
'handled by support' card. Capabilities: passwordChange, loginIdentifier=email.
Admin console:
- admin_users gains email (unique, case-insensitive), totp_secret, totp_enabled
(additive migration). ADMIN_USER_EMAILS backfill env (never overwrites).
- Login by email or legacy username; optional TOTP enforced at login.
- POST /admin/api/password/forgot|reset (no enumeration, emailed code, TOTP if on).
- /admin/api/account: password change (current pw -> code -> new pw), verified
email change (code to new address), TOTP setup/enable/disable, revoke-others.
- POST /users takes {email,password}; email becomes the username.
PUT /users/:username/email for other admins. Deactivate revokes sessions.
- UI: Forgot password on sign-in, TOTP prompt, Users -> My account, Set email.
Email-as-username: admin customer create validates/lower-cases email (portal
sign-in name, dup -> 409) and the UI asks for it; portal labels updated.
Shared: src/email-codes.ts, src/admin-sessions.ts, src/admin-account.ts.
Docs: docs/PASSWORD-2FA.md. Tests: tests/password-change-2fa.test.ts.
|
2026-10-05 14:00:47 -04:00 |