# US-MGN-001-002-002: Asignar Permisos CRUD a Roles por Modelo **RF Asociado:** [RF-MGN-001-002](../../02-modelado/requerimientos-funcionales/mgn-001/RF-MGN-001-002-gestion-roles.md) **Módulo:** MGN-001 - Fundamentos **Epic:** Autenticación y Seguridad **Prioridad:** P0 (MVP) **Story Points:** 5 **Sprint:** Sprint 1 **Estado:** Ready for Development **Fecha:** 2025-11-24 --- ## User Story **Como** administrador del sistema, **Quiero** asignar permisos CRUD (create, read, update, delete) a roles por modelo del sistema, **Para** controlar granularmente qué acciones puede realizar cada rol sobre cada entidad. --- ## Descripción Detallada Esta user story implementa la asignación granular de permisos a roles. El sistema debe: 1. Listar todos los modelos disponibles (sale.order, account.invoice, etc.) 2. Permitir seleccionar un rol y un modelo 3. Permitir marcar/desmarcar permisos individuales: create, read, update, delete 4. Guardar permisos en auth.permissions (role_id, model_id, can_create, can_read, can_update, can_delete) 5. Aplicar cambios inmediatamente (sin logout requerido) Los modelos se registran automáticamente en auth.models al iniciar el sistema (decorador/metadata). --- ## Criterios de Aceptación ### Escenario 1: Asignar permisos completos (CRUD) **Dado que** existe un rol "Contador", **Cuando** asigno permisos CRUD completos sobre modelo "account.invoice", **Entonces** el sistema crea registro en auth.permissions con can_create=true, can_read=true, can_update=true, can_delete=true. ### Escenario 2: Asignar permisos parciales (solo lectura) **Dado que** existe un rol "Auditor", **Cuando** asigno solo permiso de lectura (read) sobre modelo "sale.order", **Entonces** usuarios con rol Auditor pueden ver órdenes de venta pero no crearlas, editarlas ni eliminarlas. ### Escenario 3: Modificar permisos existentes **Dado que** un rol "Vendedor" tiene permisos read/create sobre "sale.order", **Cuando** agrego permiso update, **Entonces** el sistema actualiza el registro de auth.permissions y los vendedores pueden ahora editar órdenes. ### Escenario 4: Revocar todos los permisos de un modelo **Dado que** un rol tiene permisos sobre "account.payment", **Cuando** desmarco todos los checkboxes de permisos, **Entonces** el sistema elimina el registro de auth.permissions para ese rol+modelo. ### Escenario 5: Listar permisos actuales de un rol **Dado que** selecciono un rol "Contador", **Cuando** veo la matriz de permisos, **Entonces** veo todos los modelos del sistema con checkboxes indicando qué permisos tiene (marcados/desmarcados). ### Escenario 6: Herencia de permisos visualizada **Dado que** rol "Vendedor Senior" hereda de rol "Vendedor", **Cuando** veo la matriz de permisos, **Entonces** veo permisos heredados en gris (read-only) y permisos propios editables. --- ## Reglas de Negocio - **RN-1:** Un rol puede tener 0 o más permisos sobre múltiples modelos. - **RN-2:** Permisos son granulares: cada CRUD (create, read, update, delete) es independiente. - **RN-3:** Permisos heredados del rol padre no pueden editarse en el hijo (solo agregar, no quitar). - **RN-4:** Rol Administrator tiene is_admin=true y bypass de validación de permisos. - **RN-5:** Cambios de permisos se aplican inmediatamente sin logout. - **RN-6:** Modelos se registran automáticamente en auth.models al inicio del sistema. - **RN-7:** No se puede asignar permisos sobre modelos inexistentes. --- ## Tareas Técnicas (Checklist de Implementación) ### Backend - [ ] Crear endpoint: `POST /api/v1/auth/roles/:roleId/permissions` - Asignar permisos - [ ] Crear endpoint: `GET /api/v1/auth/roles/:roleId/permissions` - Listar permisos del rol - [ ] Crear endpoint: `PATCH /api/v1/auth/roles/:roleId/permissions/:modelId` - Actualizar permisos - [ ] Crear endpoint: `DELETE /api/v1/auth/roles/:roleId/permissions/:modelId` - Revocar permisos - [ ] Crear endpoint: `GET /api/v1/auth/models` - Listar modelos disponibles - [ ] Implementar método: `PermissionsService.assignPermissions(roleId, modelId, permissions)` - [ ] Implementar método: `PermissionsService.getRolePermissions(roleId)` con herencia - [ ] Implementar método: `PermissionsService.updatePermissions(roleId, modelId, permissions)` - [ ] Implementar método: `ModelsService.registerModel(modelName, description)` (decorador) - [ ] Crear DTO: `AssignPermissionsDto` con validaciones - [ ] Crear DTO: `PermissionsMatrixDto` para respuesta con matriz completa - [ ] Implementar caché de permisos en Redis (invalidar al cambiar) - [ ] Agregar unit tests (10 test cases) - [ ] Agregar integration tests (8 test cases) - [ ] Documentar endpoints en Swagger - [ ] Seed data: registrar modelos del sistema en auth.models ### Frontend - [ ] Crear página: `RolePermissionsPage.tsx` con matriz de permisos - [ ] Crear componente: `PermissionsMatrix.tsx` (tabla modelo x CRUD) - [ ] Crear componente: `ModelSelector.tsx` (dropdown de modelos) - [ ] Implementar checkboxes interactivos para CRUD - [ ] Mostrar permisos heredados en gris (disabled) - [ ] Crear API client: `permissionsApi.assign/get/update/revoke` - [ ] Implementar búsqueda/filtrado de modelos por nombre/módulo - [ ] Agregar feedback visual al guardar (toast notification) - [ ] Implementar "bulk actions": asignar mismo permiso a múltiples modelos - [ ] Agregar component tests (6 test cases) - [ ] Agregar e2e test: "should assign and revoke permissions" ### Database - [ ] Verificar tabla: `auth.permissions` (role_id, model_id, can_create, can_read, can_update, can_delete) - [ ] Verificar tabla: `auth.models` (name, description, module, category) - [ ] Crear índice: `idx_permissions_role_model` (UNIQUE on role_id + model_id) - [ ] Crear índice: `idx_models_name` (UNIQUE) - [ ] Validar foreign keys: role_id → auth.roles, model_id → auth.models - [ ] Crear seed data: registrar modelos del sistema (sale.order, account.invoice, etc.) --- ## Mockups / Wireframes **Página de Permisos de Rol:** - Header: "Permisos del Rol: [Nombre Rol]" - Selector: "Seleccione un rol" (dropdown) - Filtros: búsqueda de modelos, agrupar por módulo (Sales, Accounting, Inventory) - Matriz de permisos (tabla): - Columnas: Modelo | Create | Read | Update | Delete - Filas: un row por modelo (ej: sale.order, account.invoice) - Checkboxes interactivos (disabled si es permiso heredado) - Icono de info: tooltip explicando qué hace cada modelo - Permisos heredados: texto "(Heredado de [Rol Padre])" en gris - Botón "Guardar Cambios" (sticky al hacer scroll) - Botón "Restablecer" (descartar cambios) **Estados:** - **Loading:** Skeleton de tabla con shimmer effect - **Success:** Toast "Permisos actualizados correctamente" - **Error:** Alert rojo con mensaje de error --- ## Casos de Prueba (Test Scenarios) ### Pruebas Funcionales 1. **TC-001: Asignar permisos completos** - **Input:** roleId=Contador, modelId=account.invoice, CRUD all true - **Expected:** Registro creado en permissions 2. **TC-002: Asignar permisos parciales** - **Input:** roleId=Auditor, modelId=sale.order, solo read=true - **Expected:** can_read=true, resto false 3. **TC-003: Actualizar permisos** - **Input:** agregar update=true a permiso existente - **Expected:** Registro actualizado 4. **TC-004: Revocar permisos** - **Input:** desmarcar todos los checkboxes - **Expected:** Registro eliminado de permissions 5. **TC-005: Herencia de permisos** - **Input:** Rol hijo con parent_role_id - **Expected:** getRolePermissions retorna permisos propios + heredados 6. **TC-006: Modelo inexistente** - **Input:** modelId=99999 (no existe) - **Expected:** Error 404 "Model not found" 7. **TC-007: Permisos de Administrator** - **Input:** roleId=Administrator - **Expected:** Bypass (no necesita permisos explícitos) 8. **TC-008: Caché de permisos** - **Input:** actualizar permisos de rol - **Expected:** Caché invalidado, próxima request trae permisos actualizados ### Pruebas No Funcionales 1. **Performance:** - Lista de 50 modelos x 10 roles en < 300ms - Validación de permisos en middleware < 10ms (usando caché) 2. **Usabilidad:** - Checkboxes responden < 100ms - Búsqueda de modelos en tiempo real 3. **Seguridad:** - Solo usuarios con 'auth.permissions.manage' pueden acceder --- ## Dependencias - **User Stories bloqueantes:** - US-MGN-001-002-001 (Crear y Gestionar Roles) - **Módulos requeridos:** Sistema de modelos registrado - **Datos maestros necesarios:** Modelos del sistema registrados en auth.models --- ## Notas de Implementación - Implementar decorador `@RegisterModel('sale.order', 'Sales Order')` en entidades - En startup, escanear entidades decoradas y registrar en auth.models - Caché de permisos en Redis: - Key: `permissions:user:{userId}` - Value: JSON con permisos resueltos (incluyendo herencia) - TTL: 1 hora - Invalidar caché al actualizar permisos de un rol - Middleware de permisos: ```typescript @UseGuards(PermissionsGuard) @RequirePermission('sale.order.create') async createOrder() {} ``` --- ## Estimación Detallada | Tarea | Estimación | |-------|------------| | Backend Development | 3 horas | | Frontend Development | 4 horas | | Testing (Unit + Integration + E2E) | 2 horas | | Code Review | 1 hora | | **TOTAL** | **10 horas** | **Equivalente:** 5 Story Points --- ## Definition of Done (DoD) - [ ] Código backend implementado según ET-BACKEND-MGN-001-002 - [ ] Código frontend implementado según ET-FRONTEND-MGN-001-002 - [ ] Unit tests escritos y pasando (cobertura > 80%) - [ ] Integration tests escritos y pasando - [ ] E2E test "should assign and revoke permissions" pasando - [ ] Code review completado y aprobado - [ ] Documentación Swagger actualizada - [ ] Caché de permisos implementado y testeado - [ ] Seed data de modelos creado - [ ] Merge a branch `develop` completado - [ ] QA manual completado --- ## Referencias - [RF-MGN-001-002: Gestión de Roles y Permisos](../../02-modelado/requerimientos-funcionales/mgn-001/RF-MGN-001-002-gestion-roles.md) - [ET-BACKEND-MGN-001-002](../../02-modelado/especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-002-gestion-roles.md) - [ET-FRONTEND-MGN-001-002](../../02-modelado/especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-002-gestion-roles.md) - [TRACEABILITY-MGN-001.yaml](../../02-modelado/trazabilidad/TRACEABILITY-MGN-001.yaml) - [Auth Schema DDL](../../02-modelado/database-design/schemas/auth-schema-ddl.sql)