feat(saas): recuperación de contraseña, freno de fuerza bruta y hardening

Bloque A de la fase SaaS:
- Recuperación por email: código de un solo uso (solo su SHA-256 en BD),
  caducidad 30 min, emitir uno nuevo invalida los anteriores, respuesta
  idéntica exista o no la cuenta (anti-enumeración) y email asíncrono;
  restablecer cierra todas las sesiones de la familia. MailService cae a
  modo log sin SMTP configurado.
- LoginAttemptService: 5 fallos -> bloqueo con backoff exponencial (429 +
  Retry-After) en login, PIN del panel y solicitudes de reset, comprobado
  ANTES de evaluar credenciales.
- Registro exige aceptar la política de privacidad (privacy_accepted_at).
- Borrado definitivo de cuenta (RGPD) con confirmación por contraseña.
- CORS por configuración; seeder demo fail-safe (matchIfMissing=false,
  activado explícito en el compose local); application-prod.yml.
- Liquibase 005 con rollback. 44 tests verdes incl. migración en Postgres.
This commit is contained in:
Jaume Garriga Maestre
2026-07-13 22:07:06 +02:00
parent 4606f71bdc
commit 203d9b0b47
27 changed files with 1181 additions and 22 deletions

View File

@@ -23,6 +23,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
// Recuperación de contraseña por email; sin spring.mail.host configurado la app
// funciona igual (MailService cae a modo log para desarrollo y tests).
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.liquibase:liquibase-core'
runtimeOnly 'org.postgresql:postgresql'
// H2 en test para los tests rápidos de servicio/web. La verificación de las