Gestión de Permisos
El sistema de permisos permite controlar de forma granular qué puede ver y hacer cada usuario en la aplicación. Los permisos se asignan a nivel de rol y pueden ser sobreescritos a nivel de usuario individual, sin necesidad de cambios en el código.
Conceptos Clave
Permiso
Un permiso es un derecho de acceso nombrado que protege un recurso específico del sistema. Cada permiso tiene:
- Nombre — Identificador único (ej:
page:users,api:import:pagos) - Categoría —
page(sección de la UI) oapi(endpoint del servidor) - Etiqueta — Nombre legible para humanos (ej: "Usuarios", "Importar Pagos")
Asociación Rol-Permiso
Define qué permisos tiene cada rol por defecto. Todos los usuarios con ese rol heredan esos permisos automáticamente.
Override por Usuario
Permite otorgar o revocar permisos a un usuario específico, independientemente de lo que su rol defina:
- Grant (Otorgar) — Da un permiso que el rol no incluye
- Revoke (Revocar) — Quita un permiso que el rol normalmente otorga
Resolución de Permisos Efectivos
Los permisos efectivos de un usuario se calculan con esta fórmula:
permisos_efectivos = permisos_del_rol + overrides_grant − overrides_revoke
:::info Ejemplo
Si un Ejecutivo tiene por rol los permisos page:dashboard y page:integrantes, pero un Admin le agrega un override de tipo "grant" para page:gestiones:export, su resultado efectivo será:
page:dashboard✅ (del rol)page:integrantes✅ (del rol)page:gestiones:export✅ (override grant) :::
Administración de Permisos
Acceso
- Ruta:
Configuraciones → Permisos(/roles/permissions) - Permiso requerido:
page:roles - Roles por defecto: Solo Admin
Permisos por Rol
La pestaña "Permisos por Rol" muestra una matriz interactiva:
- Filas: Todos los permisos del sistema, agrupados por categoría (Páginas, API)
- Columnas: Los tres roles (Admin, Supervisor, Ejecutivo)
- Celdas: Checkbox que indica si el rol tiene ese permiso
Para modificar permisos de un rol:
- Activar o desactivar los checkboxes deseados
- Hacer clic en "Guardar"
- Los cambios se persisten inmediatamente en la base de datos
Los cambios toman efecto en el próximo inicio de sesión de los usuarios afectados. Las sesiones activas mantienen los permisos anteriores hasta que el usuario vuelva a iniciar sesión.
Permisos por Usuario
La pestaña "Permisos por Usuario" permite gestionar overrides individuales:
- Buscar al usuario por nombre, usuario o email
- Seleccionar al usuario de los resultados
- Visualizar sus permisos efectivos con indicador de fuente:
- Rol — Viene del rol asignado (no editable desde aquí)
- +Grant — Override que otorga un permiso adicional
- −Revoke — Override que revoca un permiso del rol
- Modificar permisos individuales:
- Activar un permiso que el rol no tiene → crea override "grant"
- Desactivar un permiso que el rol tiene → crea override "revoke"
- Click en "Quitar override" → revierte al comportamiento del rol
- Guardar los cambios
Puntos de Enforcement
Los permisos se evalúan en tres capas del sistema:
| Capa | Qué protege | Comportamiento si no tiene permiso |
|---|---|---|
| Proxy (Edge) | Acceso a páginas por URL | Redirige a /dashboard |
| Sidebar | Visibilidad de ítems de navegación | El ítem no aparece en el menú |
| API Routes | Acceso a endpoints del servidor | Retorna HTTP 403 Forbidden |
Esto significa que aunque un usuario conozca la URL directa de una página, no podrá acceder si no tiene el permiso correspondiente.
Catálogo Completo de Permisos
Permisos de Página (17)
Controlan el acceso a las secciones de la interfaz de usuario:
| Permiso | Recurso (Ruta) | Admin | Supervisor | Ejecutivo |
|---|---|---|---|---|
page:dashboard | /dashboard | ✅ | ✅ | ✅ |
page:users | /users | ✅ | ❌ | ❌ |
page:customers | /customers | ✅ | ❌ | ❌ |
page:asignaciones:campos | /asignaciones/campos | ✅ | ❌ | ❌ |
page:asignaciones:plantillas | /asignaciones/plantillas | ✅ | ✅ | ❌ |
page:asignaciones:importar | /asignaciones/importar | ✅ | ✅ | ❌ |
page:accounts:import | /accounts/import | ✅ | ✅ | ❌ |
page:integrantes | /integrantes | ✅ | ✅ | ✅ |
page:gestiones:import | /gestiones/import | ✅ | ✅ | ❌ |
page:gestiones:export | /gestiones/export | ✅ | ❌ | ❌ |
page:gestiones:promesas | /gestiones/promesas | ✅ | ✅ | ✅ |
page:gestiones:pagos | /gestiones/pagos | ✅ | ✅ | ✅ |
page:gestiones:carga-pagos | /gestiones/carga-pagos | ✅ | ❌ | ❌ |
page:admin:goals | /admin/goals | ✅ | ✅ | ❌ |
page:actions | /actions | ✅ | ❌ | ❌ |
page:results | /results | ✅ | ❌ | ❌ |
page:roles | /roles | ✅ | ❌ | ❌ |
Permisos de API (25)
Controlan el acceso a los endpoints del servidor:
| Permiso | Recurso (API) | Admin | Supervisor | Ejecutivo |
|---|---|---|---|---|
api:users:manage | /api/users/[id] (GET/PUT) | ✅ | ✅ | ❌ |
api:users:goals | /api/users/[id]/goals | ✅ | ✅ | ❌ |
api:customers:manage | /api/customers/[id] (PUT/DELETE) | ✅ | ❌ | ❌ |
api:accounts:import | /api/accounts/import | ✅ | ✅ | ❌ |
api:import:analyze | /api/import/analyze | ✅ | ✅ | ❌ |
api:import:suggest-mappings | /api/import/suggest-mappings | ✅ | ✅ | ❌ |
api:import:validate-mappings | /api/import/validate-mappings | ✅ | ✅ | ❌ |
api:import:integrantes | /api/import/integrantes | ✅ | ✅ | ❌ |
api:import:gestiones | /api/import/gestiones | ✅ | ✅ | ❌ |
api:import:pagos | /api/import/pagos | ✅ | ❌ | ❌ |
api:import:pagos:history | /api/import/pagos/history | ✅ | ❌ | ❌ |
api:import:pagos:rollback | /api/import/pagos/jobs/[jobId]/rollback | ✅ | ❌ | ❌ |
api:templates:manage | /api/templates (CRUD) | ✅ | ✅ | ❌ |
api:gestiones:export | /api/gestiones/export | ✅ | ✅ | ✅ |
api:export-jobs:manage | /api/export-jobs | ✅ | ✅ | ✅ |
api:export-config:manage | /api/export-config/[customerId] (PUT) | ✅ | ❌ | ❌ |
api:global-goals:manage | /api/global-goals | ✅ | ✅ | ❌ |
api:pagos:list | /api/pagos/list | ✅ | ✅ | ✅ |
api:pagos:assign | /api/pagos/assign | ✅ | ✅ | ✅ |
api:pagos:search-integrante | /api/pagos/search-integrante | ✅ | ✅ | ✅ |
api:asignaciones:campos | /api/asignaciones/campos (CRUD) | ✅ | ❌ | ❌ |
api:asignaciones:campos:export | /api/asignaciones/campos/export | ✅ | ❌ | ❌ |
api:asignaciones:campos:bulk-import | /api/asignaciones/campos/bulk-import | ✅ | ❌ | ❌ |
api:worker:wake | /api/worker/wake | ✅ | ✅ | ❌ |
api:worker:check-stale | /api/worker/check-stale | ✅ | ✅ | ❌ |
Resumen por Rol
| Rol | Permisos de Página | Permisos de API | Total |
|---|---|---|---|
| Admin | 17 | 25 | 42 |
| Supervisor | 10 | 16 | 26 |
| Ejecutivo | 4 | 5 | 9 |
Notas Importantes
Control de Acceso a Datos (Enrollment)
Además del sistema de permisos, existe un control de acceso a nivel de datos basado en enrollment (inscripción a cliente). Un Supervisor o Ejecutivo solo ve las cuentas de los clientes a los que está inscrito, independientemente de sus permisos de página/API.
El enrollment opera como una capa adicional por encima de los permisos:
- Tener el permiso
page:integrantespermite acceder a la página - Pero solo se muestran las cuentas del cliente al que el usuario está inscrito
El Admin ve todas las cuentas independientemente del enrollment.
Cuándo Toman Efecto los Cambios
- Los permisos se almacenan en el token JWT al momento del login
- Cualquier cambio en permisos (rol o override) toma efecto en el próximo inicio de sesión del usuario afectado
- Las sesiones activas no se ven afectadas hasta que expiren o el usuario cierre sesión
Sesiones Legacy
Si un usuario tiene una sesión creada antes de la activación del sistema de permisos (sin el campo permissions en el token), la sesión se invalida automáticamente y el usuario debe re-loguearse.