feature/rbac permisos y roles implementados

This commit is contained in:
2026-05-21 07:54:59 -06:00
parent 9bbed42cf3
commit a318b70324
38 changed files with 2596 additions and 901 deletions

View File

@@ -4,31 +4,43 @@ from django.dispatch import receiver
from api.notificaciones.models import Notificacion
from api.record.models import Document
@receiver(post_save, sender=Document)
def trigger_notificacion(sender, instance, created, **kwargs):
if created:
from api.cuser.models import CustomUser
from api.customs.models import Pedimento
from api.notificaciones.models import TipoNotificacion
if not created:
return
# Obtener el tipo de notificación (puedes ajustar el nombre si tienes tipos definidos)
tipo_info, _ = TipoNotificacion.objects.get_or_create(tipo="info", defaults={"descripcion": "Notificación informativa"})
from api.cuser.models import CustomUser
from api.notificaciones.models import TipoNotificacion
from core.permissions import user_has_permission
# Notificar a todos los usuarios de la organización
usuarios_org = CustomUser.objects.filter(organizacion=instance.organizacion)
for usuario in usuarios_org:
# Notificar solo a importadores cuyo RFC coincide
if (usuario.is_importador or usuario.groups.filter(name='Importador').exists()):
if instance.pedimento.contribuyente in usuario.rfc.all():
Notificacion.objects.create(
tipo=tipo_info,
dirigido=usuario,
mensaje=f"Se agregó el documento {instance.archivo} al pedimento {instance.pedimento.pedimento} \n {instance.document_type.nombre}",
)
# Notificar a otros roles (no importadores)
elif (usuario.is_superuser or usuario.groups.filter(name='Agente Aduanal').exists() or usuario.groups.filter(name='admin').exists()):
Notificacion.objects.create(
tipo=tipo_info,
dirigido=usuario,
mensaje=f"Se agregó el documento {instance.archivo} al pedimento {instance.pedimento.pedimento} \n {instance.document_type.nombre}",
)
tipo_info, _ = TipoNotificacion.objects.get_or_create(
tipo='info',
defaults={'descripcion': 'Notificación informativa'},
)
mensaje = (
f"Se agregó el documento {instance.archivo} "
f"al pedimento {instance.pedimento.pedimento}\n"
f"{instance.document_type.nombre}"
)
usuarios_org = CustomUser.objects.filter(
organizacion=instance.organizacion,
is_active=True,
).prefetch_related('rfc')
for usuario in usuarios_org:
if not user_has_permission(usuario, 'notificaciones.receive'):
continue
# Importadores: solo si el pedimento corresponde a uno de sus RFC
if usuario.is_importador:
if instance.pedimento.contribuyente not in usuario.rfc.all():
continue
Notificacion.objects.create(
tipo=tipo_info,
dirigido=usuario,
mensaje=mensaje,
)

View File

@@ -1,39 +1,36 @@
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.exceptions import PermissionDenied
from .models import Notificacion, TipoNotificacion
from .serializers import NotificacionSerializer, TipoNotificacionSerializer
from core.permissions import (
IsSameOrganization,
IsSameOrganizationDeveloper,
IsSameOrganizationAndAdmin,
IsSuperUser
)
# Create your views here.
from core.permissions import require_permission
class TipoNotificacionViewSet(viewsets.ModelViewSet):
queryset = TipoNotificacion.objects.all()
serializer_class = TipoNotificacionSerializer
http_method_names = ['get']
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
permission_classes = [IsAuthenticated]
my_tags = ['Notificaciones']
def get_queryset(self):
return self.queryset.order_by('tipo')
class NotificacionViewSet(viewsets.ModelViewSet):
queryset = Notificacion.objects.all()
serializer_class = NotificacionSerializer
http_method_names = ['get', 'post', 'put', 'patch', 'delete']
filterset_fields = ['visto']
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
my_tags = ['Notificaciones']
def get_permissions(self):
if self.action in ('list', 'retrieve'):
return [IsAuthenticated(), require_permission('notificaciones.view')()]
return [IsAuthenticated()]
def get_queryset(self):
# Evita error en generación de esquema Swagger
if getattr(self, 'swagger_fake_view', False):
return Notificacion.objects.none()
user = self.request.user
@@ -45,6 +42,6 @@ class NotificacionViewSet(viewsets.ModelViewSet):
if not self.request.user.is_authenticated:
raise PermissionDenied("Usuario no autenticado")
if self.request.user.is_superuser:
# Allow superusers and admins to create notifications for any user
serializer.save()
raise PermissionDenied("No tienes permiso para crear notificaciones para otros usuarios")
return
raise PermissionDenied("No tienes permiso para crear notificaciones para otros usuarios")