feature/rbac permisos y roles implementados
This commit is contained in:
@@ -26,11 +26,13 @@ from django.utils import timezone
|
||||
from django.db.models import Q
|
||||
from api.utils.storage_service import storage_service
|
||||
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
|
||||
from core.permissions import (
|
||||
IsSameOrganization,
|
||||
IsSameOrganizationDeveloper,
|
||||
IsSameOrganizationAndAdmin,
|
||||
IsSuperUser
|
||||
get_org_context,
|
||||
require_permission,
|
||||
user_has_permission,
|
||||
IsInternalService,
|
||||
)
|
||||
|
||||
import logging
|
||||
@@ -142,21 +144,47 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
"""
|
||||
ViewSet for Document model.
|
||||
"""
|
||||
permission_classes = [IsAuthenticated & (IsSuperUser | IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper )]
|
||||
model = Document
|
||||
|
||||
|
||||
pagination_class = CustomPagination
|
||||
serializer_class = DocumentSerializer
|
||||
# Habilitar filtro por pedimento (UUID) y pedimento_numero (campo pedimento del modelo relacionado)
|
||||
filterset_fields = ['extension', 'size', 'document_type', 'pedimento', 'pedimento__pedimento', 'created_at']
|
||||
# filterset_fields = ['extension', 'size', 'pedimento', 'pedimento__pedimento']
|
||||
|
||||
# Puedes filtrar por pedimento usando: /api/record/documents/?pedimento=<id> o /api/record/documents/?pedimento__pedimento=<numero>
|
||||
# Ejemplo: /api/record/documents/?pedimento_numero=12345678
|
||||
my_tags = ['Documents']
|
||||
|
||||
def get_permissions(self):
|
||||
# Service account (Token + superuser): acceso directo sin RBAC de org
|
||||
if (self.request.user.is_authenticated and self.request.user.is_superuser and
|
||||
isinstance(getattr(self.request, 'successful_authenticator', None), TokenAuthentication)):
|
||||
return [IsAuthenticated(), IsInternalService()]
|
||||
perms = {
|
||||
'list': 'documentos.view',
|
||||
'retrieve': 'documentos.view',
|
||||
'create': 'documentos.upload',
|
||||
'update': 'documentos.upload',
|
||||
'partial_update': 'documentos.upload',
|
||||
'destroy': 'documentos.delete',
|
||||
'vu_documentos_errores': 'documentos.view',
|
||||
'bulk_delete': 'documentos.delete',
|
||||
'bulk_delete_partidas_vu': 'documentos.delete',
|
||||
'bulk_delete_coves_vu': 'documentos.delete',
|
||||
'bulk_delete_edocs_vu': 'documentos.delete',
|
||||
'bulk_upload': 'documentos.upload',
|
||||
'bulk_upload_vu': 'documentos.upload',
|
||||
'create_vu_record': 'documentos.upload',
|
||||
}
|
||||
codename = perms.get(self.action, 'documentos.view')
|
||||
return [IsAuthenticated(), require_permission(codename)()]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.get_queryset_filtrado_por_organizacion()
|
||||
user = self.request.user
|
||||
if user.is_superuser and isinstance(
|
||||
getattr(self.request, 'successful_authenticator', None), TokenAuthentication
|
||||
):
|
||||
queryset = Document.objects.all()
|
||||
else:
|
||||
if not user_has_permission(user, 'documentos.view'):
|
||||
return Document.objects.none()
|
||||
queryset = self.get_queryset_filtrado_por_organizacion()
|
||||
modulo_efc = self.request.query_params.get('modulo')
|
||||
if modulo_efc:
|
||||
if modulo_efc == 'expedientes-detalle-pedimentos':
|
||||
@@ -2017,7 +2045,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
|
||||
|
||||
class ProtectedDocumentDownloadView(APIView, DocumentosFiltradosMixin):
|
||||
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.download')]
|
||||
serializer_class = DocumentSerializer
|
||||
model = Document
|
||||
my_tags = ['Documents']
|
||||
@@ -2030,17 +2058,14 @@ class ProtectedDocumentDownloadView(APIView, DocumentosFiltradosMixin):
|
||||
import os
|
||||
from api.utils.storage_service import storage_service
|
||||
|
||||
if not request.user.is_authenticated or not hasattr(request.user, 'organizacion'):
|
||||
raise Http404("Usuario no autenticado")
|
||||
|
||||
try:
|
||||
doc = Document.objects.get(pk=pk)
|
||||
except Document.DoesNotExist:
|
||||
raise Http404("Documento no encontrado")
|
||||
|
||||
if not request.user.is_superuser:
|
||||
if doc.organizacion != request.user.organizacion:
|
||||
raise Http404("No autorizado")
|
||||
org = get_org_context(request.user)
|
||||
if doc.organizacion != org:
|
||||
raise Http404("No autorizado")
|
||||
|
||||
if not doc.archivo:
|
||||
raise Http404("Documento sin archivo asociado")
|
||||
@@ -2064,7 +2089,7 @@ class ProtectedDocumentDownloadView(APIView, DocumentosFiltradosMixin):
|
||||
return response
|
||||
|
||||
class BulkDownloadZipView(APIView):
|
||||
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.download')]
|
||||
my_tags = ['Documents']
|
||||
|
||||
def post(self, request):
|
||||
@@ -2172,7 +2197,7 @@ class BulkDownloadZipView(APIView):
|
||||
logger.warning(f"No se pudo eliminar archivo temporal {tmp_path}: {e}")
|
||||
|
||||
class GetFuenteView(APIView):
|
||||
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.view')]
|
||||
serializer_class = FuenteSerializer
|
||||
my_tags = ['Fuente Documentos']
|
||||
|
||||
@@ -2187,7 +2212,7 @@ class GetFuenteView(APIView):
|
||||
return Response(serializer.data, status=200)
|
||||
|
||||
class DocumentTypeView(APIView):
|
||||
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.view')]
|
||||
serializer_class = DocumentTypeSerializer
|
||||
my_tags = ['Tipo de Documentos']
|
||||
|
||||
@@ -2204,7 +2229,7 @@ class DocumentTypeView(APIView):
|
||||
return Response(serializer.data, status=200)
|
||||
|
||||
class ExpedienteZipDownloadView(APIView, DocumentosFiltradosMixin):
|
||||
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.download')]
|
||||
my_tags = ['Documents']
|
||||
|
||||
def post(self, request):
|
||||
@@ -2306,7 +2331,7 @@ class ExpedienteZipDownloadView(APIView, DocumentosFiltradosMixin):
|
||||
logger.warning(f"No se pudo eliminar archivo temporal {tmp_path}: {e}")
|
||||
|
||||
class MultiPedimentoZipDownloadView(APIView):
|
||||
permission_classes = [IsAuthenticated & (IsSuperUser | IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper)]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.download')]
|
||||
my_tags = ['Documents']
|
||||
|
||||
def post(self, request):
|
||||
@@ -2375,7 +2400,7 @@ class PedimentoDocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
"""
|
||||
ViewSet for Document model.
|
||||
"""
|
||||
permission_classes = [IsAuthenticated & (IsSuperUser | IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper )]
|
||||
permission_classes = [IsAuthenticated, require_permission('documentos.view')]
|
||||
model = Document
|
||||
|
||||
pagination_class = CustomPagination
|
||||
@@ -2389,6 +2414,8 @@ class PedimentoDocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
my_tags = ['Documents']
|
||||
|
||||
def get_queryset(self):
|
||||
if not user_has_permission(self.request.user, 'documentos.view'):
|
||||
return Document.objects.none()
|
||||
queryset = self.get_queryset_filtrado_por_organizacion()
|
||||
pedimento_id = self.request.query_params.get('pedimento')
|
||||
|
||||
@@ -2435,8 +2462,7 @@ class TriggerPedimentoCompletoView(APIView):
|
||||
en el microservicio FastAPI. Reenvía el payload tal cual y devuelve
|
||||
la respuesta del microservicio (normalmente un `task_id`).
|
||||
"""
|
||||
# permission_classes = [IsAuthenticated]
|
||||
permission_classes = [IsAuthenticated & (IsSuperUser | IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper )]
|
||||
permission_classes = [IsAuthenticated, require_permission('pedimentos.process')]
|
||||
|
||||
my_tags = ['Microservice - Pedimento Completo']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user