RF-USER-003: Cambio de Email
Identificacion
| Campo |
Valor |
| ID |
RF-USER-003 |
| Modulo |
MGN-002 |
| Nombre Modulo |
Users - Gestion de Usuarios |
| Prioridad |
P1 |
| Complejidad |
Media |
| Estado |
Aprobado |
| Autor |
System |
| Fecha |
2025-12-05 |
Descripcion
El sistema debe permitir a los usuarios cambiar su direccion de email de forma segura, requiriendo verificacion del nuevo email antes de completar el cambio. Este proceso protege contra cambios no autorizados y mantiene la integridad de las comunicaciones.
Contexto de Negocio
El cambio de email es sensible porque:
- El email es el identificador principal de login
- Se usa para recuperacion de password
- Se usa para notificaciones importantes
- Debe ser verificado antes del cambio efectivo
Criterios de Aceptacion
Ejemplos de Verificacion
Scenario: Solicitar cambio de email
Given un usuario con email "viejo@empresa.com"
When solicita cambiar a "nuevo@empresa.com"
And confirma con su password actual
Then el sistema valida que "nuevo@empresa.com" no existe
And genera token de verificacion
And envia email de verificacion a "nuevo@empresa.com"
And el email actual permanece sin cambios
And responde con status 200
Scenario: Verificar nuevo email
Given una solicitud de cambio pendiente
And un token de verificacion valido
When el usuario hace clic en el link de verificacion
Then el sistema actualiza el email del usuario
And invalida todas las sesiones activas
And envia notificacion al email anterior
And redirige al login
Scenario: Token de verificacion expirado
Given un token de verificacion de mas de 24 horas
When el usuario intenta usarlo
Then el sistema responde con error
And el mensaje es "Token expirado, solicita nuevo cambio"
Scenario: Nuevo email ya existe
Given un email "existente@empresa.com" ya registrado
When un usuario intenta cambiar a ese email
Then el sistema responde con status 409
And el mensaje es "Email no disponible"
Reglas de Negocio
| ID |
Regla |
Validacion |
| RN-001 |
Requiere password actual para solicitar cambio |
Verificacion bcrypt |
| RN-002 |
Nuevo email debe ser unico en tenant |
UNIQUE constraint |
| RN-003 |
Token de verificacion expira en 24 horas |
expires_at check |
| RN-004 |
Solo una solicitud activa a la vez |
Invalidar anteriores |
| RN-005 |
Notificar al email anterior |
Email de seguridad |
| RN-006 |
Logout-all despues del cambio |
Revocar tokens |
| RN-007 |
Nuevo email formato valido |
Regex validation |
Flujo de Cambio de Email
┌─────────────────────────────────────────────────────────────────┐
│ 1. Usuario solicita cambio │
│ POST /api/v1/users/me/email/request-change │
│ Body: { newEmail, currentPassword } │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. Validaciones │
│ - Password correcto │
│ - Nuevo email formato valido │
│ - Nuevo email no existe en tenant │
│ - No hay solicitud pendiente │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. Crear solicitud │
│ - Guardar en email_change_requests │
│ - Generar token (32 bytes, hex) │
│ - expires_at = now + 24 hours │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. Enviar email de verificacion │
│ To: nuevo@email.com │
│ Link: /verify-email-change?token={token} │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 5. Usuario hace clic en link │
│ GET /api/v1/users/email/verify-change?token={token} │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 6. Aplicar cambio │
│ - Actualizar users.email │
│ - Marcar solicitud como completada │
│ - Invalidar todas las sesiones │
│ - Enviar notificacion al email anterior │
└───────────────────────────┬─────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 7. Redirigir al login │
│ - Usuario debe iniciar sesion con nuevo email │
└─────────────────────────────────────────────────────────────────┘
Impacto en Capas
Database
| Elemento |
Accion |
Descripcion |
| Tabla |
crear |
email_change_requests |
| Columna |
- |
id UUID PK |
| Columna |
- |
user_id UUID FK |
| Columna |
- |
tenant_id UUID FK |
| Columna |
- |
current_email VARCHAR(255) |
| Columna |
- |
new_email VARCHAR(255) |
| Columna |
- |
token_hash VARCHAR(255) |
| Columna |
- |
expires_at TIMESTAMPTZ |
| Columna |
- |
completed_at TIMESTAMPTZ |
| Columna |
- |
created_at TIMESTAMPTZ |
| Indice |
crear |
idx_email_change_user |
Backend
| Elemento |
Accion |
Descripcion |
| Controller |
agregar |
UsersController.requestEmailChange() |
| Controller |
agregar |
UsersController.verifyEmailChange() |
| Method |
crear |
UsersService.requestEmailChange() |
| Method |
crear |
UsersService.verifyEmailChange() |
| DTO |
crear |
RequestEmailChangeDto |
| Entity |
crear |
EmailChangeRequest |
| Endpoint |
crear |
POST /api/v1/users/me/email/request-change |
| Endpoint |
crear |
GET /api/v1/users/email/verify-change |
Frontend
| Elemento |
Accion |
Descripcion |
| Componente |
crear |
ChangeEmailForm |
| Pagina |
crear |
VerifyEmailChangePage |
| Modal |
crear |
ConfirmPasswordModal |
Dependencias
Depende de (Bloqueantes)
| ID |
Requerimiento |
Estado |
| RF-USER-001 |
CRUD Usuarios |
Tabla users |
| RF-AUTH-004 |
Logout |
Para logout-all |
Dependencias Externas
| Servicio |
Descripcion |
| Email Service |
Envio de verificacion |
Especificaciones Tecnicas
Endpoint POST /api/v1/users/me/email/request-change
// Request
{
"newEmail": "nuevo@empresa.com",
"currentPassword": "MiPasswordActual123!"
}
// Response 200
{
"message": "Se ha enviado un email de verificacion a nuevo@empresa.com",
"expiresAt": "2025-12-06T10:30:00Z"
}
// Response 400 - Password incorrecto
{
"statusCode": 400,
"message": "Password incorrecto"
}
// Response 409 - Email existe
{
"statusCode": 409,
"message": "Email no disponible"
}
Endpoint GET /api/v1/users/email/verify-change
// Request
GET /api/v1/users/email/verify-change?token=abc123...
// Response 200 (redirect)
// Redirect to: /login?emailChanged=true
// Response 400 - Token invalido
{
"statusCode": 400,
"message": "Token invalido o expirado"
}
Template de Email - Verificacion
Asunto: Verifica tu nuevo email - ERP Suite
<h2>Hola {{firstName}},</h2>
<p>Recibimos una solicitud para cambiar tu email de:</p>
<p><strong>{{currentEmail}}</strong> a <strong>{{newEmail}}</strong></p>
<p>Haz clic en el siguiente enlace para confirmar el cambio:</p>
<a href="{{verifyUrl}}">Verificar nuevo email</a>
<p><strong>Este enlace expira en 24 horas.</strong></p>
<p>Si no solicitaste este cambio, ignora este email y considera
cambiar tu password por seguridad.</p>
Template de Email - Notificacion al Email Anterior
Asunto: Tu email ha sido cambiado - ERP Suite
<h2>Hola {{firstName}},</h2>
<p>Te informamos que el email de tu cuenta ha sido cambiado.</p>
<p><strong>Email anterior:</strong> {{oldEmail}}</p>
<p><strong>Email nuevo:</strong> {{newEmail}}</p>
<p><strong>Fecha:</strong> {{changeDate}}</p>
<p>Si no realizaste este cambio, contacta inmediatamente a soporte.</p>
Datos de Prueba
| Escenario |
Entrada |
Resultado |
| Solicitud valida |
newEmail, password correcto |
200, email enviado |
| Password incorrecto |
password erroneo |
400, "Password incorrecto" |
| Email ya existe |
email de otro usuario |
409, "Email no disponible" |
| Email invalido |
"notanemail" |
400, "Email invalido" |
| Verificar token valido |
token < 24h |
200, email cambiado |
| Token expirado |
token > 24h |
400, "Token expirado" |
| Token ya usado |
solicitud completada |
400, "Token ya utilizado" |
Estimacion
| Capa |
Story Points |
Notas |
| Database |
1 |
Tabla email_change_requests |
| Backend |
3 |
Endpoints, validaciones, emails |
| Frontend |
2 |
Form y pagina verificacion |
| Total |
6 |
|
Notas Adicionales
- Considerar periodo de gracia donde se puede revertir el cambio
- Implementar notificacion push ademas de email
- Rate limiting en solicitudes (max 3 por dia)
- Log de todos los cambios de email para auditoria
Historial de Cambios
| Version |
Fecha |
Autor |
Cambios |
| 1.0 |
2025-12-05 |
System |
Creacion inicial |
Aprobaciones
| Rol |
Nombre |
Fecha |
Firma |
| Analista |
System |
2025-12-05 |
[x] |
| Tech Lead |
- |
- |
[ ] |
| Product Owner |
- |
- |
[ ] |