334 lines
13 KiB
Markdown
334 lines
13 KiB
Markdown
# RF-USER-001: CRUD de Usuarios
|
|
|
|
## Identificacion
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | RF-USER-001 |
|
|
| **Modulo** | MGN-002 |
|
|
| **Nombre Modulo** | Users - Gestion de Usuarios |
|
|
| **Prioridad** | P0 |
|
|
| **Complejidad** | Media |
|
|
| **Estado** | Aprobado |
|
|
| **Autor** | System |
|
|
| **Fecha** | 2025-12-05 |
|
|
|
|
---
|
|
|
|
## Descripcion
|
|
|
|
El sistema debe permitir la gestion completa del ciclo de vida de usuarios, incluyendo crear, leer, actualizar y eliminar (soft delete) usuarios dentro de un tenant. Solo usuarios con permisos administrativos pueden gestionar otros usuarios.
|
|
|
|
### Contexto de Negocio
|
|
|
|
La gestion de usuarios es fundamental para:
|
|
- Controlar quien accede al sistema
|
|
- Asignar roles y permisos apropiados
|
|
- Mantener registro de empleados/usuarios del tenant
|
|
- Cumplir con politicas de seguridad y auditoria
|
|
|
|
---
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
- [x] **CA-001:** El sistema debe permitir crear usuarios con datos basicos (email, nombre, apellido)
|
|
- [x] **CA-002:** El sistema debe generar password temporal o enviar invitacion por email
|
|
- [x] **CA-003:** El sistema debe validar unicidad de email dentro del tenant
|
|
- [x] **CA-004:** El sistema debe permitir listar usuarios con paginacion y filtros
|
|
- [x] **CA-005:** El sistema debe permitir buscar usuarios por nombre, email o rol
|
|
- [x] **CA-006:** El sistema debe permitir actualizar datos de usuario
|
|
- [x] **CA-007:** El sistema debe implementar soft delete (no eliminar fisicamente)
|
|
- [x] **CA-008:** El sistema debe permitir activar/desactivar usuarios
|
|
- [x] **CA-009:** El sistema debe registrar quien creo/modifico cada usuario (auditoria)
|
|
- [x] **CA-010:** Solo admins pueden crear/modificar/eliminar usuarios
|
|
|
|
### Ejemplos de Verificacion
|
|
|
|
```gherkin
|
|
Scenario: Crear usuario exitosamente
|
|
Given un administrador autenticado
|
|
When crea un nuevo usuario con email "nuevo@empresa.com"
|
|
And nombre "Juan" y apellido "Perez"
|
|
Then el sistema crea el usuario con estado "pending_activation"
|
|
And envia email de invitacion al usuario
|
|
And registra created_by con el ID del admin
|
|
And responde con status 201
|
|
|
|
Scenario: Crear usuario con email duplicado
|
|
Given un usuario existente con email "existente@empresa.com"
|
|
When un admin intenta crear otro usuario con el mismo email
|
|
Then el sistema responde con status 409
|
|
And el mensaje es "El email ya esta registrado"
|
|
|
|
Scenario: Listar usuarios con filtros
|
|
Given 50 usuarios en el sistema
|
|
When un admin solicita GET /api/v1/users?page=1&limit=10&role=admin
|
|
Then el sistema retorna los primeros 10 usuarios con rol admin
|
|
And incluye metadata de paginacion (total, pages, hasNext)
|
|
|
|
Scenario: Soft delete de usuario
|
|
Given un usuario activo con ID "user-123"
|
|
When un admin elimina el usuario
|
|
Then el campo deleted_at se establece con la fecha actual
|
|
And el campo deleted_by se establece con el ID del admin
|
|
And el usuario ya no aparece en listados normales
|
|
And el usuario no puede hacer login
|
|
```
|
|
|
|
---
|
|
|
|
## Reglas de Negocio
|
|
|
|
| ID | Regla | Validacion |
|
|
|----|-------|------------|
|
|
| RN-001 | Email unico por tenant | UNIQUE(tenant_id, email) |
|
|
| RN-002 | Email en formato valido | Regex validation |
|
|
| RN-003 | Nombre y apellido requeridos | NOT NULL, min 2 chars |
|
|
| RN-004 | Soft delete en lugar de hard delete | deleted_at NOT NULL |
|
|
| RN-005 | Solo admins gestionan usuarios | RBAC permission check |
|
|
| RN-006 | Usuario no puede eliminarse a si mismo | Validacion en backend |
|
|
| RN-007 | Password temporal expira en 24 horas | Validacion en activacion |
|
|
| RN-008 | Auditoria de cambios obligatoria | created_by, updated_by |
|
|
|
|
### Estados de Usuario
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ CREATED │
|
|
│ (pending_activ) │
|
|
└────────┬────────┘
|
|
│ Usuario activa cuenta
|
|
▼
|
|
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
|
|
│ LOCKED │◄────►│ ACTIVE │◄────►│ INACTIVE │
|
|
│ (bloqueado) │ │ (activo) │ │ (inactivo) │
|
|
└─────────────┘ └────────┬────────┘ └─────────────┘
|
|
│ Admin elimina
|
|
▼
|
|
┌─────────────────┐
|
|
│ DELETED │
|
|
│ (soft delete) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Impacto en Capas
|
|
|
|
### Database
|
|
|
|
| Elemento | Accion | Descripcion |
|
|
|----------|--------|-------------|
|
|
| Schema | crear | `core_users` |
|
|
| Tabla | crear | `users` - tabla principal |
|
|
| Columna | - | `id` UUID PK |
|
|
| Columna | - | `tenant_id` UUID FK |
|
|
| Columna | - | `email` VARCHAR(255) |
|
|
| Columna | - | `password_hash` VARCHAR(255) |
|
|
| Columna | - | `first_name` VARCHAR(100) |
|
|
| Columna | - | `last_name` VARCHAR(100) |
|
|
| Columna | - | `phone` VARCHAR(20) |
|
|
| Columna | - | `status` ENUM |
|
|
| Columna | - | `is_active` BOOLEAN |
|
|
| Columna | - | `email_verified_at` TIMESTAMPTZ |
|
|
| Columna | - | `last_login_at` TIMESTAMPTZ |
|
|
| Columna | - | `failed_login_attempts` INTEGER |
|
|
| Columna | - | `locked_until` TIMESTAMPTZ |
|
|
| Columna | - | `created_by` UUID FK |
|
|
| Columna | - | `updated_by` UUID FK |
|
|
| Columna | - | `deleted_at` TIMESTAMPTZ |
|
|
| Columna | - | `deleted_by` UUID FK |
|
|
| Indice | crear | `idx_users_tenant_email` UNIQUE |
|
|
| Indice | crear | `idx_users_tenant_status` |
|
|
|
|
### Backend
|
|
|
|
| Elemento | Accion | Descripcion |
|
|
|----------|--------|-------------|
|
|
| Controller | crear | `UsersController` |
|
|
| Service | crear | `UsersService` |
|
|
| Method | crear | `create()` |
|
|
| Method | crear | `findAll()` |
|
|
| Method | crear | `findOne()` |
|
|
| Method | crear | `update()` |
|
|
| Method | crear | `remove()` (soft delete) |
|
|
| Method | crear | `activate()` |
|
|
| Method | crear | `deactivate()` |
|
|
| DTO | crear | `CreateUserDto` |
|
|
| DTO | crear | `UpdateUserDto` |
|
|
| DTO | crear | `UserResponseDto` |
|
|
| DTO | crear | `UserListQueryDto` |
|
|
| Guard | usar | `RolesGuard` |
|
|
| Endpoint | crear | `POST /api/v1/users` |
|
|
| Endpoint | crear | `GET /api/v1/users` |
|
|
| Endpoint | crear | `GET /api/v1/users/:id` |
|
|
| Endpoint | crear | `PATCH /api/v1/users/:id` |
|
|
| Endpoint | crear | `DELETE /api/v1/users/:id` |
|
|
|
|
### Frontend
|
|
|
|
| Elemento | Accion | Descripcion |
|
|
|----------|--------|-------------|
|
|
| Pagina | crear | `UsersListPage` |
|
|
| Pagina | crear | `UserDetailPage` |
|
|
| Pagina | crear | `UserCreatePage` |
|
|
| Pagina | crear | `UserEditPage` |
|
|
| Componente | crear | `UsersTable` |
|
|
| Componente | crear | `UserForm` |
|
|
| Componente | crear | `UserCard` |
|
|
| Service | crear | `usersService` |
|
|
| Store | crear | `usersStore` |
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
### Depende de (Bloqueantes)
|
|
|
|
| ID | Requerimiento | Estado |
|
|
|----|---------------|--------|
|
|
| RF-AUTH-001 | Login | Para autenticacion |
|
|
| RF-AUTH-002 | JWT Tokens | Para autorizacion |
|
|
|
|
### Dependencias Relacionadas
|
|
|
|
| ID | Requerimiento | Relacion |
|
|
|----|---------------|----------|
|
|
| RF-USER-002 | Perfil de usuario | Extiende datos de usuario |
|
|
| RF-ROLE-001 | Asignacion de roles | Usa tabla users |
|
|
|
|
---
|
|
|
|
## Especificaciones Tecnicas
|
|
|
|
### Modelo de Datos Simplificado
|
|
|
|
```typescript
|
|
interface User {
|
|
id: string;
|
|
tenantId: string;
|
|
email: string;
|
|
passwordHash: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
phone?: string;
|
|
avatarUrl?: string;
|
|
status: UserStatus;
|
|
isActive: boolean;
|
|
emailVerifiedAt?: Date;
|
|
lastLoginAt?: Date;
|
|
failedLoginAttempts: number;
|
|
lockedUntil?: Date;
|
|
metadata?: Record<string, any>;
|
|
createdAt: Date;
|
|
createdBy?: string;
|
|
updatedAt: Date;
|
|
updatedBy?: string;
|
|
deletedAt?: Date;
|
|
deletedBy?: string;
|
|
}
|
|
|
|
enum UserStatus {
|
|
PENDING_ACTIVATION = 'pending_activation',
|
|
ACTIVE = 'active',
|
|
INACTIVE = 'inactive',
|
|
LOCKED = 'locked',
|
|
}
|
|
```
|
|
|
|
### Flujo de Creacion de Usuario
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 1. Admin envia POST /api/v1/users │
|
|
│ Body: { email, firstName, lastName, roleIds } │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 2. Validaciones │
|
|
│ - Email formato valido │
|
|
│ - Email no existe en tenant │
|
|
│ - Admin tiene permiso users:create │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 3. Crear usuario │
|
|
│ - status = 'pending_activation' │
|
|
│ - is_active = false │
|
|
│ - created_by = admin.id │
|
|
│ - Generar activation token │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 4. Asignar roles │
|
|
│ - Insertar en user_roles │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 5. Enviar email de invitacion │
|
|
│ - Link: /activate?token={activation_token} │
|
|
│ - Token expira en 24 horas │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 6. Responder con usuario creado │
|
|
│ - Status 201 │
|
|
│ - Body: UserResponseDto (sin password) │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Datos de Prueba
|
|
|
|
| Escenario | Entrada | Resultado |
|
|
|-----------|---------|-----------|
|
|
| Crear usuario valido | email, firstName, lastName | 201, usuario creado |
|
|
| Email duplicado | email existente | 409, "Email ya registrado" |
|
|
| Email invalido | "notanemail" | 400, "Email invalido" |
|
|
| Sin permiso | Usuario no admin | 403, "Permiso denegado" |
|
|
| Listar usuarios | page=1, limit=10 | 200, lista paginada |
|
|
| Buscar por email | search=john@ | 200, usuarios filtrados |
|
|
| Actualizar usuario | PATCH con datos | 200, usuario actualizado |
|
|
| Soft delete | DELETE /users/:id | 200, deleted_at set |
|
|
| Eliminar a si mismo | DELETE propio ID | 400, "No puede eliminarse" |
|
|
|
|
---
|
|
|
|
## Estimacion
|
|
|
|
| Capa | Story Points | Notas |
|
|
|------|--------------|-------|
|
|
| Database | 3 | Schema y tabla users |
|
|
| Backend | 5 | CRUD completo con validaciones |
|
|
| Frontend | 5 | 4 paginas, componentes, store |
|
|
| **Total** | **13** | |
|
|
|
|
---
|
|
|
|
## Notas Adicionales
|
|
|
|
- Implementar soft delete para mantener integridad referencial
|
|
- El email de invitacion debe usar template personalizable
|
|
- Considerar bulk import de usuarios via CSV
|
|
- Implementar export de lista de usuarios
|
|
- Los usuarios eliminados se pueden restaurar (admin)
|
|
|
|
---
|
|
|
|
## 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 | - | - | [ ] |
|