import uuid from django.conf import settings from django.db import models class RolePermission(models.Model): """Catálogo global de permisos de la aplicación. Se define una vez y es compartido por todas las orgs.""" codename = models.CharField(max_length=100, unique=True) descripcion = models.CharField(max_length=255) modulo = models.CharField(max_length=50) def __str__(self): return self.codename class Meta: db_table = 'rbac_role_permission' ordering = ['modulo', 'codename'] verbose_name = 'Permiso' verbose_name_plural = 'Permisos' class OrganizationRole(models.Model): """Rol de una organización. Cada org tiene su propio conjunto de roles con sus permisos.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) organizacion = models.ForeignKey( 'organization.Organizacion', on_delete=models.CASCADE, related_name='roles', ) nombre = models.CharField(max_length=100) descripcion = models.CharField(max_length=255, blank=True) # El rol admin maestro no puede ser removido del owner de la org is_admin_role = models.BooleanField(default=False) permissions = models.ManyToManyField( RolePermission, blank=True, related_name='roles', ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f'{self.nombre} ({self.organizacion})' class Meta: db_table = 'rbac_organization_role' ordering = ['nombre'] verbose_name = 'Rol de Organización' verbose_name_plural = 'Roles de Organización' constraints = [ models.UniqueConstraint(fields=['organizacion', 'nombre'], name='unique_role_per_org'), ] class UserRole(models.Model): """Asignación de un rol a un usuario dentro de su organización.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='user_roles', ) role = models.ForeignKey( OrganizationRole, on_delete=models.CASCADE, related_name='user_roles', ) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f'{self.user} → {self.role.nombre}' class Meta: db_table = 'rbac_user_role' verbose_name = 'Rol de Usuario' verbose_name_plural = 'Roles de Usuario' constraints = [ models.UniqueConstraint(fields=['user', 'role'], name='unique_user_role'), ] class UserPermission(models.Model): """Permiso singular asignado directamente a un usuario, sin necesidad de rol. granted=True otorga, granted=False deniega explícitamente (override sobre roles).""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='rbac_permissions', ) permission = models.ForeignKey( RolePermission, on_delete=models.CASCADE, related_name='user_overrides', ) granted = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): estado = 'GRANT' if self.granted else 'DENY' return f'{estado}: {self.user} → {self.permission.codename}' class Meta: db_table = 'rbac_user_permission' verbose_name = 'Permiso Singular' verbose_name_plural = 'Permisos Singulares' constraints = [ models.UniqueConstraint(fields=['user', 'permission'], name='unique_user_permission'), ]