Módulo: Recuperación de Contraseña
Scope
| Tipo de organización | Acceso |
|---|---|
| Empresa | ✅ |
| Agencia | ✅ |
| Reclutador independiente | ✅ |
| Usuario sin organización | ✅ |
Permisos por rol
| Acción | Disponible | Permiso |
|---|---|---|
| Solicitar correo de recuperación | ✅ | Público (no requiere autenticación) |
| Reenviar correo de recuperación | ✅ | Público |
| Cambiar contraseña (vía link web) | ✅ | Token del email |
¿Qué es?
Flujo de recuperación de contraseña mediante envío de correo electrónico. El usuario solicita un email con instrucciones y el cambio real de contraseña se completa a través de un link web que envía el backend, no dentro de la app Flutter.
¿Qué puede hacer el usuario?
- Solicitar un correo de recuperación ingresando su email
- Ver confirmación de envío con el email al que se mandó
- Reenviar el correo después de un cooldown de 60 segundos
- Editar el email si se equivocó (después del cooldown)
- Volver al login en cualquier momento
Flujo del usuario
1. Presiona "¿Olvidaste tu contraseña?" desde la pantalla de login
2. Ingresa su correo electrónico
3. Presiona "Enviar instrucciones"
4. Se muestra pantalla de éxito:
- Ícono de correo enviado
- Mensaje "Correo enviado"
- "Revisa tu bandeja de entrada y spam"
- Chip con el email al que se envió
- Botón de reenvío (con cooldown 60s)
5. Puede reenviar después del cooldown
6. Puede editar el email (tap en chip después del cooldown)
7. Presiona "Volver al inicio de sesión" → regresa a login
8. Recibe email → abre link web → escribe nueva contraseña (fuera de Flutter)
Reglas de negocio
- Email debe ser válido (validación regex en el formulario)
- Cooldown de 60 segundos entre reenvíos
- El backend envía el correo sin importar si el email existe (seguridad — no revela si hay cuenta)
- El cambio real de contraseña se ejecuta vía link web del backend
- No hay pantalla in-app para escribir la nueva contraseña
Requisitos para solicitar reset
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
| String | ✅ | Validado con regex (isValidEmail extension) |
Arquitectura
lib/features/auth/
├── application/
│ ├── reset_password_cubit.dart # Lógica de envío de email
│ └── reset_password_state.dart # ResetPasswordStatus enum
├── domain/
│ └── usecases/
│ └── reset_password_usecase.dart
└── presentation/
└── pages/
└── reset_password_page.dart # Formulario + estado de éxito
Endpoints API
| Método | Endpoint | Autenticación | Descripción |
|---|---|---|---|
| POST | /api/auth/request-password-reset | Público | Envía correo de recuperación |
Request body
{
"email": "usuario@ejemplo.com"
}
Response
200 OK (sin body relevante — éxito silencioso por seguridad)
Registro DI
- UseCase:
LazySingleton<ResetPasswordUseCase> - Cubit:
Factory<ResetPasswordCubit>(nueva instancia por pantalla)
getIt.registerFactory<ResetPasswordCubit>(
() => ResetPasswordCubit(resetPasswordUseCase: getIt<ResetPasswordUseCase>()),
);
Localización
✅ Completa — todos los strings usan context.l10n:
| Clave | Español | Inglés |
|---|---|---|
forgotPassword | ¿Olvidaste tu contraseña? | Forgot your password? |
resetPasswordSubtitle | Ingresa tu correo electrónico y te enviaremos las instrucciones... | Enter your email address and we will send you instructions... |
sendInstructions | Enviar instrucciones | Send instructions |
resetPasswordSuccess | Se ha enviado un correo con las instrucciones... | An email with instructions... has been sent |
resetPasswordEmailSent | Correo enviado | Email sent |
resetPasswordCheckInbox | Revisa tu bandeja de entrada y spam | Check your inbox and spam folder |
resetPasswordDidntReceive | ¿No lo recibiste? | Didn't receive it? |
resetPasswordResend | Reenviar correo | Resend email |
resetPasswordResendIn | Reenviar en {seconds}s | Resend in {seconds}s |
resetPasswordBackToLogin | Volver al inicio de sesión | Back to login |
Tests
| Archivo | Tests |
|---|---|
reset_password_cubit_test.dart | 5 — initial state, success, ServerFailure, NetworkFailure, email verification |
reset_password_usecase_test.dart | 3 — success, ServerFailure, NetworkFailure |
Estados de la UI
| Estado | Comportamiento |
|---|---|
| Initial | Formulario de email visible |
| Loading | Botón muestra spinner, deshabilitado |
| Success | Cambia a vista de éxito con email chip + reenvío + cooldown |
| Error | Muestra notificación con el mensaje del failure |
Pendientes
Ninguno — el flujo está completo. El cambio de contraseña se resuelve vía link web del backend.