# RF-ROLE-003: Asignacion de Roles a Usuarios

## Identificacion

| Campo | Valor |
|-------|-------|
| **ID** | RF-ROLE-003 |
| **Modulo** | MGN-003 Roles/RBAC |
| **Prioridad** | P0 - Critica |
| **Estado** | Ready |
| **Fecha** | 2025-12-05 |

---

## Descripcion

El sistema debe permitir asignar uno o mas roles a cada usuario. Los permisos efectivos de un usuario son la union de todos los permisos de sus roles asignados. La asignacion puede realizarse desde la gestion de usuarios o desde la gestion de roles.

---

## Actores

| Actor | Descripcion |
|-------|-------------|
| Super Admin | Puede asignar cualquier rol a cualquier usuario |
| Admin | Puede asignar roles (excepto super_admin) a usuarios del tenant |

---

## Precondiciones

1. Usuario autenticado con permiso `roles:assign`
2. Usuario destino existente y activo
3. Rol existente y activo

---

## Flujo Principal

### Asignar Rol desde Usuario

```
1. Admin accede a Usuarios > Detalle de usuario
2. Click en "Gestionar Roles"
3. Sistema muestra:
   - Roles actuales del usuario
   - Roles disponibles para asignar
4. Admin selecciona roles a asignar
5. Admin deselecciona roles a quitar
6. Click en "Guardar Cambios"
7. Sistema actualiza asignaciones
8. Sistema recalcula permisos del usuario
9. Sistema muestra confirmacion
```

### Asignar Usuarios desde Rol

```
1. Admin accede a Roles > Detalle de rol
2. Click en pestaña "Usuarios"
3. Sistema muestra usuarios con este rol
4. Click en "Agregar Usuarios"
5. Sistema muestra lista de usuarios sin este rol
6. Admin selecciona usuarios
7. Click en "Asignar"
8. Sistema asigna rol a usuarios seleccionados
```

### Asignacion Masiva

```
1. Admin accede a Usuarios
2. Selecciona multiples usuarios (checkbox)
3. Click en "Acciones > Asignar Rol"
4. Sistema muestra selector de rol
5. Admin selecciona rol
6. Sistema asigna rol a todos los usuarios seleccionados
```

---

## Flujos Alternativos

### FA1: Usuario ya tiene el rol

```
1. Admin intenta asignar rol que usuario ya tiene
2. Sistema ignora la asignacion duplicada
3. Continua sin error
```

### FA2: Quitar ultimo rol

```
1. Admin intenta quitar el unico rol del usuario
2. Sistema muestra advertencia
3. Admin confirma o cancela
4. Si confirma: usuario queda sin roles (acceso minimo)
```

### FA3: Admin intenta asignar super_admin

```
1. Admin (no super_admin) intenta asignar rol super_admin
2. Sistema muestra error "Solo Super Admin puede asignar este rol"
3. Operacion cancelada
```

---

## Reglas de Negocio

| ID | Regla |
|----|-------|
| RN-001 | Usuario puede tener multiples roles |
| RN-002 | Permisos efectivos = union de permisos de todos los roles |
| RN-003 | Solo super_admin puede asignar rol super_admin |
| RN-004 | No se puede quitar rol super_admin del ultimo super_admin |
| RN-005 | Cambios de roles toman efecto inmediato |
| RN-006 | Se registra en auditoria cada cambio de asignacion |
| RN-007 | Usuario sin roles tiene acceso minimo (solo perfil propio) |

---

## Criterios de Aceptacion

### Escenario 1: Asignar rol a usuario

```gherkin
Given un usuario "juan@empresa.com" con rol "user"
  And un rol "vendedor" disponible
When el admin asigna rol "vendedor" al usuario
Then el usuario tiene roles ["user", "vendedor"]
  And el usuario tiene permisos de ambos roles combinados
  And se registra en auditoria
```

### Escenario 2: Quitar rol de usuario

```gherkin
Given un usuario con roles ["admin", "manager"]
When el admin quita el rol "manager"
Then el usuario solo tiene rol ["admin"]
  And pierde los permisos exclusivos de "manager"
```

### Escenario 3: Asignacion masiva

```gherkin
Given 10 usuarios seleccionados
  And rol "vendedor" disponible
When el admin asigna "vendedor" a todos
Then los 10 usuarios tienen rol "vendedor" agregado
  And responde con resumen: { success: 10, failed: 0 }
```

### Escenario 4: Proteccion de super_admin

```gherkin
Given un admin autenticado (no super_admin)
When intenta asignar rol "super_admin" a un usuario
Then el sistema responde con status 403
  And el mensaje es "Solo Super Admin puede asignar este rol"
```

### Escenario 5: No quitar ultimo super_admin

```gherkin
Given solo 1 usuario con rol "super_admin"
When se intenta quitar el rol
Then el sistema responde con status 400
  And el mensaje es "Debe existir al menos un Super Admin"
```

---

## Mockup / Wireframe

```
Modal: Gestionar Roles de Usuario
┌──────────────────────────────────────────────────────────────────┐
│  ROLES DE: Juan Perez (juan@empresa.com)                         │
├──────────────────────────────────────────────────────────────────┤
│                                                                   │
│  Roles Asignados:                                                │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ ☑ Admin          Gestion completa del tenant         [x]   │ │
│  │ ☑ Manager        Supervision operativa               [x]   │ │
│  │ ☐ User           Acceso basico                             │ │
│  │ ☐ Vendedor       Equipo de ventas                          │ │
│  │ ☐ Contador       Area contable                             │ │
│  │ ☐ Almacenista    Gestion de inventario                     │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                   │
│  Permisos Efectivos: 45 permisos (de 2 roles)                   │
│  [Ver detalle de permisos]                                       │
│                                                                   │
│  [  Cancelar  ]                        [ Guardar Cambios ]       │
└──────────────────────────────────────────────────────────────────┘

Vista: Usuarios de un Rol
┌──────────────────────────────────────────────────────────────────┐
│  ROL: Vendedor                                 [+ Agregar Usuarios]│
├──────────────────────────────────────────────────────────────────┤
│  Usuarios con este rol (8):                                      │
│                                                                   │
│  | Avatar | Nombre         | Email              | Desde      | ⚙ |
│  |--------|----------------|--------------------|-----------|----|
│  | 👤     | Carlos Lopez   | carlos@empresa.com | 01/12/2025 | 🗑|
│  | 👤     | Maria Garcia   | maria@empresa.com  | 15/11/2025 | 🗑|
│  | 👤     | Pedro Martinez | pedro@empresa.com  | 10/11/2025 | 🗑|
│  | ...    | ...            | ...                | ...        | ...|
│                                                                   │
│  Mostrando 1-8 de 8                                              │
└──────────────────────────────────────────────────────────────────┘
```

---

## Notas Tecnicas

### API Endpoints

```typescript
// Asignar roles a usuario
PUT /api/v1/users/:userId/roles
{
  "roleIds": ["role-uuid-1", "role-uuid-2"]
}

// Response 200
{
  "userId": "user-uuid",
  "roles": [
    { "id": "role-uuid-1", "name": "Admin", "assignedAt": "..." },
    { "id": "role-uuid-2", "name": "Manager", "assignedAt": "..." }
  ],
  "effectivePermissions": ["users:*", "reports:read", ...]
}

// Agregar rol a usuario (sin quitar existentes)
POST /api/v1/users/:userId/roles
{
  "roleId": "role-uuid"
}

// Quitar rol de usuario
DELETE /api/v1/users/:userId/roles/:roleId

// Asignar rol a multiples usuarios
POST /api/v1/roles/:roleId/users
{
  "userIds": ["user-1", "user-2", "user-3"]
}

// Response 200
{
  "roleId": "role-uuid",
  "results": {
    "success": ["user-1", "user-2"],
    "failed": [{ "userId": "user-3", "reason": "Ya tiene el rol" }]
  }
}

// Listar usuarios de un rol
GET /api/v1/roles/:roleId/users?page=1&limit=20

// Obtener permisos efectivos de usuario
GET /api/v1/users/:userId/permissions

// Response 200
{
  "roles": ["admin", "manager"],
  "permissions": {
    "direct": [...],      // Permisos de roles asignados
    "inherited": [...],   // Via wildcards
    "all": [...]          // Union de todos
  }
}
```

### Calculo de Permisos Efectivos

```typescript
function calculateEffectivePermissions(userId: string): string[] {
  // 1. Obtener roles del usuario
  const userRoles = await getUserRoles(userId);

  // 2. Obtener permisos de cada rol
  const allPermissions = new Set<string>();

  for (const role of userRoles) {
    const rolePermissions = await getRolePermissions(role.id);
    rolePermissions.forEach(p => allPermissions.add(p));
  }

  // 3. Expandir wildcards
  const expanded = expandWildcards(allPermissions);

  return Array.from(expanded);
}

function expandWildcards(permissions: Set<string>): Set<string> {
  const result = new Set(permissions);

  for (const perm of permissions) {
    if (perm.endsWith(':*')) {
      // users:* -> agregar users:read, users:create, etc.
      const module = perm.replace(':*', '');
      const modulePerms = getModulePermissions(module);
      modulePerms.forEach(p => result.add(p));
    }
  }

  return result;
}
```

---

## Dependencias

| ID | Descripcion |
|----|-------------|
| RF-ROLE-001 | Roles existentes para asignar |
| RF-ROLE-002 | Permisos para calcular efectivos |
| RF-USER-001 | Usuarios existentes |

---

## Estimacion

| Tarea | Puntos |
|-------|--------|
| Backend: Endpoints asignacion | 3 |
| Backend: Calculo permisos efectivos | 3 |
| Backend: Validaciones y reglas | 2 |
| Backend: Tests | 2 |
| Frontend: RoleAssignment modal | 3 |
| Frontend: BulkAssignment | 2 |
| Frontend: Tests | 2 |
| **Total** | **17 SP** |

---

## Historial

| Version | Fecha | Autor | Cambios |
|---------|-------|-------|---------|
| 1.0 | 2025-12-05 | System | Creacion inicial |
