fix: aligned ProcurementItem permissions with ProcurementRequest logic
- Added comprehensive permission checks in perform_create() - Created _check_item_edit_permission() helper method - Updated perform_update() and perform_destroy() to use helper - Permission logic now matches CanManageProcurementRequest: * Admins/Staff can edit items in DRAFT requests * Users with change_procurementrequest permission * Request author can edit their own requests * Department head can edit requests from their department - Fixes 403 Forbidden error when creating/editing/deleting items
This commit is contained in:
parent
2e92c4d7a0
commit
978ed9a819
@ -688,57 +688,100 @@ class ProcurementItemViewSet(viewsets.ModelViewSet):
|
||||
return [permission() for permission in permission_classes]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
"""Проверяем права при создании позиции."""
|
||||
"""Проверяем права при создании позиции.
|
||||
|
||||
Логика соответствует CanManageProcurementRequest:
|
||||
- Админы/Staff могут добавлять в любые заявки в DRAFT
|
||||
- Модельные права (change_procurementrequest) → любые заявки в DRAFT
|
||||
- Автор заявки → свои заявки в DRAFT
|
||||
- Начальник отдела → заявки своего отдела в DRAFT
|
||||
"""
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
procurement_request = serializer.validated_data.get('request')
|
||||
user = self.request.user
|
||||
|
||||
# Проверяем, что пользователь - создатель заявки
|
||||
if procurement_request.requestor != self.request.user:
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
raise PermissionDenied(
|
||||
"Вы можете добавлять позиции только в свои заявки"
|
||||
)
|
||||
|
||||
# Проверяем, что заявка редактируема
|
||||
# Проверяем, что заявка в DRAFT
|
||||
if not procurement_request.is_editable:
|
||||
from rest_framework.exceptions import ValidationError
|
||||
raise ValidationError(
|
||||
"Нельзя добавлять позиции в заявку не в статусе черновика"
|
||||
raise PermissionDenied(
|
||||
"Нельзя добавлять позиции в заявку со статусом '{}'".format(
|
||||
procurement_request.get_status_display()
|
||||
)
|
||||
)
|
||||
|
||||
serializer.save()
|
||||
# Админы могут редактировать
|
||||
if user.is_superuser or user.is_staff:
|
||||
serializer.save()
|
||||
return
|
||||
|
||||
# Модельные права
|
||||
if user.has_perm('procurement.change_procurementrequest'):
|
||||
serializer.save()
|
||||
return
|
||||
|
||||
# Автор заявки
|
||||
if procurement_request.requestor == user:
|
||||
serializer.save()
|
||||
return
|
||||
|
||||
# Начальник отдела
|
||||
if procurement_request.department.head == user:
|
||||
serializer.save()
|
||||
return
|
||||
|
||||
# Нет прав
|
||||
raise PermissionDenied(
|
||||
"Вы не можете добавлять позиции в эту заявку"
|
||||
)
|
||||
|
||||
def _check_item_edit_permission(self, item):
|
||||
"""Проверка прав на редактирование позиции.
|
||||
|
||||
Вынесена в отдельный метод для переиспользования.
|
||||
"""
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
user = self.request.user
|
||||
procurement_request = item.request
|
||||
|
||||
# Проверяем, что заявка в DRAFT
|
||||
if not procurement_request.is_editable:
|
||||
raise PermissionDenied(
|
||||
"Нельзя изменять позиции в заявке со статусом '{}'".format(
|
||||
procurement_request.get_status_display()
|
||||
)
|
||||
)
|
||||
|
||||
# Админы могут редактировать
|
||||
if user.is_superuser or user.is_staff:
|
||||
return True
|
||||
|
||||
# Модельные права
|
||||
if user.has_perm('procurement.change_procurementrequest'):
|
||||
return True
|
||||
|
||||
# Автор заявки
|
||||
if procurement_request.requestor == user:
|
||||
return True
|
||||
|
||||
# Начальник отдела
|
||||
if procurement_request.department.head == user:
|
||||
return True
|
||||
|
||||
# Нет прав
|
||||
raise PermissionDenied(
|
||||
"Вы не можете изменять позиции в этой заявке"
|
||||
)
|
||||
|
||||
def perform_update(self, serializer):
|
||||
"""Проверяем права при обновлении позиции."""
|
||||
item = self.get_object()
|
||||
|
||||
if item.request.requestor != self.request.user:
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
raise PermissionDenied(
|
||||
"Вы можете изменять только позиции своих заявок"
|
||||
)
|
||||
|
||||
if not item.request.is_editable:
|
||||
from rest_framework.exceptions import ValidationError
|
||||
raise ValidationError(
|
||||
"Нельзя изменять позиции в заявке не в статусе черновика"
|
||||
)
|
||||
|
||||
self._check_item_edit_permission(item)
|
||||
serializer.save()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
"""Проверяем права при удалении позиции."""
|
||||
if instance.request.requestor != self.request.user:
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
raise PermissionDenied(
|
||||
"Вы можете удалять только позиции своих заявок"
|
||||
)
|
||||
|
||||
if not instance.request.is_editable:
|
||||
from rest_framework.exceptions import ValidationError
|
||||
raise ValidationError(
|
||||
"Нельзя удалять позиции из заявки не в статусе черновика"
|
||||
)
|
||||
|
||||
self._check_item_edit_permission(instance)
|
||||
instance.delete()
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
|
||||
@ -93,6 +93,15 @@ def request_detail(request, pk):
|
||||
"""Детальная страница заявки.
|
||||
|
||||
Загружает данные из БД и передаёт в шаблон.
|
||||
|
||||
Права на редактирование (can_edit):
|
||||
- Админы/Staff → любая заявка в DRAFT
|
||||
- Модельные права (change_procurementrequest) → любая заявка в DRAFT
|
||||
- Автор заявки → своя заявка в DRAFT
|
||||
- Начальник отдела → заявки своего отдела в DRAFT
|
||||
|
||||
Права на согласование (can_approve):
|
||||
- Пользователи с активным approval для этой заявки
|
||||
"""
|
||||
from django.shortcuts import get_object_or_404
|
||||
from procurement.models import ProcurementRequest
|
||||
@ -106,11 +115,21 @@ def request_detail(request, pk):
|
||||
|
||||
user = request.user
|
||||
|
||||
# Проверяем права на редактирование
|
||||
can_edit = (
|
||||
request_obj.requestor == user and
|
||||
request_obj.status == 'draft'
|
||||
)
|
||||
# Проверяем права на редактирование (синхронизировано с API)
|
||||
can_edit = False
|
||||
if request_obj.is_editable: # Только DRAFT
|
||||
# Админы могут редактировать
|
||||
if user.is_superuser or user.is_staff:
|
||||
can_edit = True
|
||||
# Модельные права
|
||||
elif user.has_perm('procurement.change_procurementrequest'):
|
||||
can_edit = True
|
||||
# Автор заявки
|
||||
elif request_obj.requestor == user:
|
||||
can_edit = True
|
||||
# Начальник отдела
|
||||
elif request_obj.department.head == user:
|
||||
can_edit = True
|
||||
|
||||
# Проверяем права на согласование
|
||||
can_approve = (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user