diff --git a/backend/api/v1/requests_app/permissions.py b/backend/api/v1/requests_app/permissions.py index a53a6d55..4dd928a4 100644 --- a/backend/api/v1/requests_app/permissions.py +++ b/backend/api/v1/requests_app/permissions.py @@ -37,6 +37,43 @@ class IsRecipientOfRequest(BasePermission): return obj.recipients.filter(id=user.id).exists() +class CanViewRequest(BasePermission): + """Проверяет, может ли пользователь просматривать заявку. + + Доступ разрешается если пользователь: + - staff/superuser + - автор заявки (employee) + - получатель заявки (recipients) + - в копии заявки (cc_users) + """ + + message = "У вас нет доступа к этой заявке." + + def has_permission(self, request: Request, view: Any) -> bool: + return bool(getattr(request.user, "is_authenticated", False)) + + def has_object_permission(self, request: Request, view: Any, obj: Any) -> bool: + user = request.user + + # Staff/superuser могут просматривать любые заявки + if getattr(user, "is_staff", False) or getattr(user, "is_superuser", False): + return True + + # Автор заявки + if getattr(obj, "employee_id", None) == user.id: + return True + + # Получатель заявки (recipients) + if obj.recipients.filter(id=user.id).exists(): + return True + + # В копии заявки (cc_users) + if obj.cc_users.filter(id=user.id).exists(): + return True + + return False + + class CommentsPermission(BasePermission): """Комментарии: модельные права, staff, head. diff --git a/backend/api/v1/requests_app/views.py b/backend/api/v1/requests_app/views.py index 6d97fdc5..7458791f 100644 --- a/backend/api/v1/requests_app/views.py +++ b/backend/api/v1/requests_app/views.py @@ -27,6 +27,7 @@ from rest_framework.serializers import ( from ..permissions import AdminOrActionOrModelPerms, AdminOrDeptAllowed, IsSelfOrStaff from .permissions import ( + CanViewRequest, CommentsPermission, DeptCanProcess, DeptChangeRequest, @@ -96,7 +97,14 @@ class RequestViewSet(viewsets.ModelViewSet): if self.action == "cancel": return [IsSelfOrStaff()] if self.action == "retrieve": - return [(IsSelfOrStaff | DeptViewRequest | AdminOrActionOrModelPerms)()] + # Автор, получатель, в копии, по отделу, staff/admin + return [ + ( + CanViewRequest + | DeptViewRequest + | AdminOrActionOrModelPerms + )() + ] if self.action == "destroy": return [ (IsSelfOrStaff | AdminOrActionOrModelPerms | DeptChangeRequest)(),