Skip to main content

Sistema de roles

El sistema implementa control de acceso basado en roles (RBAC). Cada usuario tiene asignado un rol que determina qué acciones puede realizar.
Los roles están definidos en backend/usuarios/roles.py y se aplican mediante el decorador @permiso_requerido.

Roles disponibles

Existen cuatro roles con permisos progresivos:

Sys Admin

Permisos completos sobre todo el sistema:
  • ver_activos: Ver listado de activos
  • ver_historial: Consultar historial de cambios
  • ver_eliminados: Acceder a registro de activos eliminados
  • generar_informes: Generar reportes PDF/Excel
  • crear_anotaciones: Crear anotaciones sobre activos
  • crear_activos: Crear nuevos activos
  • crud_activos: Crear, leer, actualizar y eliminar activos
  • subir_excel: Cargar activos masivamente desde Excel
Uso típico: Administradores del sistema, gerentes de IT

Auxiliar

Permisos operativos sin capacidad de eliminación:
  • ver_activos
  • ver_eliminados
  • generar_informes
  • crear_anotaciones
  • crear_activos
NO puede:
  • Eliminar activos (crud_activos)
  • Cargar archivos Excel (subir_excel)
  • Ver historial completo de cambios (ver_historial)
Uso típico: Personal operativo, encargados de inventario

Administrativo

Permisos de solo lectura y reportes:
  • ver_activos
  • ver_eliminados
  • generar_informes
NO puede:
  • Crear o modificar activos
  • Crear anotaciones
  • Ver historial detallado
Uso típico: Personal administrativo, contadores, auditores externos

Invitado

Permisos mínimos:
  • ver_activos (solo lectura)
NO puede:
  • Modificar nada
  • Generar reportes
  • Ver eliminados
  • Crear anotaciones
Uso típico: Consultores, personal temporal, visitantes

Definición en código

Los roles están definidos en usuarios/roles.py:
ROLES = (
    ('sys_admin', 'Sys Admin'),
    ('auxiliar', 'Auxiliar'),
    ('administracion', 'Administración'),
    ('invitado', 'Invitado'),
)

ROLE_PERMISSIONS = {
    'sys_admin': [
        'ver_activos', 
        'ver_historial', 
        'ver_eliminados', 
        'generar_informes', 
        'crear_anotaciones', 
        'crear_activos',
        'crud_activos', 
        'subir_excel'
    ],
    'auxiliar': [
        'ver_activos', 
        'ver_eliminados', 
        'generar_informes', 
        'crear_anotaciones', 
        'crear_activos'
    ],
    'administracion': [
        'ver_activos', 
        'ver_eliminados', 
        'generar_informes'
    ],
    'invitado': [
        'ver_activos'
    ],
}

Asignar roles a usuarios

Al crear un usuario

Los usuarios pueden crearse de tres formas:

1. Mediante el admin de Django

Acceda a http://localhost:8000/admin/ y cree un usuario especificando el rol: Admin Django

2. Mediante manage.py (superusuarios)

python manage.py createsuperuser
Los superusuarios se crean automáticamente con rol sys_admin.

3. Mediante registro con código de administrador

Los usuarios pueden registrarse mediante el endpoint /api/usuarios/registro/ con un código de administrador. El rol se asigna en el proceso de validación.

Cambiar el rol de un usuario existente

Desde el admin de Django

  1. Acceda a http://localhost:8000/admin/auth/user/
  2. Seleccione el usuario
  3. Cambie el campo Rol
  4. Guarde

Desde la base de datos

UPDATE "user" SET rol = 'auxiliar' WHERE email = '[email protected]';

Mediante API (requiere permisos de administrador)

Si implementa un endpoint de gestión de usuarios, puede actualizar el rol:
@api_view(['PATCH'])
@permission_classes([permissions.IsAuthenticated])
@permiso_requerido('crud_activos')  # Solo sys_admin
def actualizar_rol_usuario(request, user_id):
    user = User.objects.get(id=user_id)
    nuevo_rol = request.data.get('rol')
    
    if nuevo_rol not in dict(ROLES):
        return Response(
            {'error': 'Rol inválido'}, 
            status=400
        )
    
    user.rol = nuevo_rol
    user.save()
    
    return Response({'message': 'Rol actualizado'})

Validar permisos en el backend

Decorador permiso_requerido

El sistema usa el decorador @permiso_requerido para proteger endpoints:
from usuarios.decorators import permiso_requerido
from rest_framework.decorators import api_view, permission_classes
from rest_framework import permissions

@api_view(['DELETE'])
@permission_classes([permissions.IsAuthenticated])
@permiso_requerido('crud_activos')
def eliminar_activos(request):
    # Solo ejecutable por usuarios con permiso 'crud_activos'
    # (sys_admin en este caso)
    placas = request.data.get('placas', [])
    # ... lógica de eliminación

Implementación del decorador

El decorador se define en usuarios/decorators.py:
from functools import wraps
from rest_framework.response import Response
from rest_framework import status

def permiso_requerido(*permisos_necesarios):
    def decorador(view_func):
        @wraps(view_func)
        def wrapper(request, *args, **kwargs):
            user = request.user
            permisos_usuario = user.get_permisos()
            
            # Verificar si el usuario tiene todos los permisos necesarios
            if not all(permiso in permisos_usuario for permiso in permisos_necesarios):
                return Response(
                    {'detail': 'No tiene permiso para realizar esta acción'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            return view_func(request, *args, **kwargs)
        return wrapper
    return decorador

Validar permisos en el frontend

Obtener rol del usuario autenticado

El rol del usuario se devuelve en la respuesta del endpoint de login:
{
  "access": "...",
  "refresh": "...",
  "user": {
    "id": 5,
    "email": "[email protected]",
    "nombre": "Juan Pérez",
    "rol": "auxiliar"  // <-- Rol del usuario
  }
}

Ocultar funcionalidades en Angular

En su aplicación Angular, puede ocultar elementos UI basados en el rol:
// auth.service.ts
export class AuthService {
  getUser() {
    const user = localStorage.getItem('user');
    return user ? JSON.parse(user) : null;
  }
  
  hasRole(role: string): boolean {
    const user = this.getUser();
    return user && user.rol === role;
  }
  
  hasPermission(permission: string): boolean {
    const user = this.getUser();
    if (!user) return false;
    
    const rolePermissions = {
      'sys_admin': ['ver_activos', 'ver_historial', 'ver_eliminados', 'generar_informes', 'crear_anotaciones', 'crear_activos', 'crud_activos', 'subir_excel'],
      'auxiliar': ['ver_activos', 'ver_eliminados', 'generar_informes', 'crear_anotaciones', 'crear_activos'],
      'administracion': ['ver_activos', 'ver_eliminados', 'generar_informes'],
      'invitado': ['ver_activos']
    };
    
    return rolePermissions[user.rol]?.includes(permission) || false;
  }
}
En templates:
<!-- Solo mostrar botón de eliminar a sys_admin -->
<button 
  *ngIf="authService.hasPermission('crud_activos')"
  (click)="eliminarActivo()">
  Eliminar
</button>

<!-- Solo mostrar subida de Excel a sys_admin -->
<div *ngIf="authService.hasPermission('subir_excel')">
  <app-upload-excel></app-upload-excel>
</div>
Importante: Ocultar elementos UI no es suficiente para seguridad. Siempre valide permisos en el backend. Los usuarios pueden manipular el frontend.

Matriz de permisos

AcciónSys AdminAuxiliarAdministrativoInvitado
Ver activos
Crear activos
Editar activos
Eliminar activos
Ver historial
Ver eliminados
Generar informes
Crear anotaciones
Cargar Excel

Mejores prácticas

1

Principio de menor privilegio

Asigne a los usuarios el rol más restrictivo que les permita realizar su trabajo.
2

Revisión periódica

Revise regularmente los roles asignados y ajuste según cambios en responsabilidades.
3

Documentación interna

Documente qué roles se asignan a qué posiciones en su organización.
4

Auditoría

Registre cambios de roles en un log de auditoría para cumplimiento normativo.

Agregar nuevos permisos

Si necesita agregar nuevos permisos:
  1. Agregue el permiso a ROLE_PERMISSIONS en usuarios/roles.py:
ROLE_PERMISSIONS = {
    'sys_admin': [
        # ... permisos existentes
        'nuevo_permiso',  # <-- Agregar aquí
    ],
    # ...
}
  1. Use el decorador en las vistas correspondientes:
@permiso_requerido('nuevo_permiso')
def nueva_vista(request):
    # ...
  1. Actualice la lógica del frontend para reflejar el nuevo permiso.

Recursos adicionales

Autenticación

Cómo funcionan los tokens JWT

Gestionar usuarios

API para crear y gestionar usuarios

Build docs developers (and LLMs) love