US-MGN002-005: Cambio de Email
Identificacion
| Campo |
Valor |
| ID |
US-MGN002-005 |
| Modulo |
MGN-002 Users |
| Sprint |
Sprint 3 |
| Prioridad |
P1 - Alta |
| Story Points |
6 |
| Estado |
Ready |
| Autor |
System |
| Fecha |
2025-12-06 |
| RF Asociado |
RF-USER-003 |
Historia de Usuario
Como usuario autenticado del sistema
Quiero poder cambiar mi direccion de email de forma segura
Para mantener mi cuenta actualizada y proteger el acceso a mi informacion
Descripcion
El usuario necesita un proceso seguro para cambiar su email registrado. El sistema debe verificar la identidad del usuario con su password actual y validar la propiedad del nuevo email antes de aplicar el cambio. Esto protege contra cambios no autorizados.
Contexto
- El email es el identificador principal de login
- Se usa para recuperacion de password y notificaciones
- Requiere doble verificacion por seguridad (password + email)
- Todas las sesiones se invalidan despues del cambio
Criterios de Aceptacion
Escenario 1: Solicitar cambio de email exitosamente
Given un usuario autenticado con email "viejo@empresa.com"
When solicita cambiar a "nuevo@empresa.com"
And confirma con su password actual
And el nuevo email no esta registrado
Then el sistema 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
And el body contiene "expiresAt" con fecha +24h
Escenario 2: Verificar nuevo email
Given un usuario con solicitud de cambio pendiente
And un token de verificacion valido (< 24 horas)
When hace clic en enlace 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 con mensaje de exito
Escenario 3: Nuevo email ya registrado
Given un email "existente@empresa.com" ya en uso
When un usuario intenta cambiar a ese email
Then el sistema responde con status 409
And el mensaje es "Email no disponible"
Escenario 4: Password incorrecto
Given un usuario autenticado
When solicita cambio de email con password incorrecto
Then el sistema responde con status 400
And el mensaje es "Password incorrecto"
And no se crea solicitud de cambio
Escenario 5: Token de verificacion expirado
Given un token de verificacion emitido hace mas de 24 horas
When el usuario intenta usarlo
Then el sistema responde con status 400
And el mensaje es "Token expirado, solicita nuevo cambio"
Escenario 6: Cancelar solicitud pendiente
Given un usuario con cambio de email pendiente
When solicita un nuevo cambio
Then la solicitud anterior se invalida
And se crea nueva solicitud con nuevo token
Mockup / Wireframe
Pagina: Mi Perfil - Seccion Email
┌──────────────────────────────────────────────────────────────────┐
│ Email actual: juan@empresa.com │
│ [Cambiar Email] │
└──────────────────────────────────────────────────────────────────┘
Modal: Cambiar Email
┌──────────────────────────────────────────────────────────────────┐
│ CAMBIAR EMAIL │
├──────────────────────────────────────────────────────────────────┤
│ │
│ Email actual juan@empresa.com (no editable) │
│ │
│ Nuevo email* [_______________________________] │
│ │
│ Confirmar password* [_______________________________] │
│ │
│ ⚠️ Se enviara un link de verificacion al nuevo email. │
│ Tu email no cambiara hasta que verifiques el enlace. │
│ Todas tus sesiones seran cerradas despues del cambio. │
│ │
│ [ Cancelar ] [ Enviar Verificacion ] │
└──────────────────────────────────────────────────────────────────┘
Pagina: Verificacion Exitosa
┌──────────────────────────────────────────────────────────────────┐
│ │
│ ✅ Email Actualizado │
│ │
│ Tu email ha sido cambiado a: nuevo@empresa.com │
│ │
│ Por seguridad, todas tus sesiones han sido cerradas. │
│ │
│ [ Ir al Login ] │
│ │
└──────────────────────────────────────────────────────────────────┘
Notas Tecnicas
API Endpoints
// Solicitar cambio de email
POST /api/v1/users/me/email/request-change
{
"newEmail": "nuevo@empresa.com",
"currentPassword": "MiPasswordActual123!"
}
// Response 200
{
"message": "Se ha enviado un email de verificacion a nuevo@empresa.com",
"expiresAt": "2025-12-07T10:30:00Z"
}
// Response 400 - Password incorrecto
{
"statusCode": 400,
"message": "Password incorrecto"
}
// Response 409 - Email existe
{
"statusCode": 409,
"message": "Email no disponible"
}
// Verificar cambio de email
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"
}
Permisos Requeridos
| Accion |
Permiso |
| Solicitar cambio |
Autenticado (propio email) |
| Verificar cambio |
Token valido |
Schema de Base de Datos
CREATE TABLE core_users.email_change_requests (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES core_users.users(id),
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id),
current_email VARCHAR(255) NOT NULL,
new_email VARCHAR(255) NOT NULL,
token_hash VARCHAR(255) NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_pending_email_change UNIQUE (user_id, completed_at)
WHERE completed_at IS NULL
);
CREATE INDEX idx_email_change_user ON core_users.email_change_requests(user_id);
CREATE INDEX idx_email_change_token ON core_users.email_change_requests(token_hash);
Definicion de Done
Dependencias
| ID |
Descripcion |
| RF-USER-001 |
CRUD Usuarios (tabla users) |
| RF-AUTH-001 |
Login para autenticacion |
| RF-AUTH-004 |
Logout para invalidar sesiones |
| EmailService |
Para enviar verificacion |
Estimacion
| Tarea |
Story Points |
| Database: Tabla email_change_requests |
1 |
| Backend: Endpoint request-change |
1.5 |
| Backend: Endpoint verify-change |
1.5 |
| Backend: Tests |
1 |
| Frontend: ChangeEmailForm |
0.5 |
| Frontend: Pagina verificacion |
0.5 |
| Total |
6 |
Reglas de Negocio
| ID |
Regla |
Validacion |
| RN-001 |
Requiere password actual |
Verificacion bcrypt |
| RN-002 |
Nuevo email unico en tenant |
UNIQUE constraint |
| RN-003 |
Token expira en 24 horas |
expires_at check |
| RN-004 |
Una solicitud activa a la vez |
Invalidar anteriores |
| RN-005 |
Notificar email anterior |
Email de seguridad |
| RN-006 |
Logout-all post-cambio |
Revocar tokens |
| RN-007 |
Formato email valido |
Regex validation |
Historial
| Version |
Fecha |
Autor |
Cambios |
| 1.0 |
2025-12-06 |
System |
Creacion inicial |