Custom Permission Mixin Django Rest Framework
Я пытаюсь создать пользовательский mixim, который обрабатывает дополнительные проверки разрешений в моих представлениях.
Вот что я пробовал:
class ProfilePermissionsRequiredMixin:
required_permissions = []
def get_required_permissions(self):
return self.required_permissions
def dispatch(self, request, *args, **kwargs):
# Check if the user is authenticated
if not request.user.is_authenticated:
raise PermissionDenied("You must be logged in to access this resource.")
# Get the user's profile
profile = request.user.profile
# Check if the profile has all the required permissions
if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
return super().dispatch(request, *args, **kwargs)
# Return 403 Forbidden if any permission check fails
raise PermissionDenied("You do not have permission to access this resource.")
Проблема в том, что запрос, который я получаю, не аутентифицирован. Я использую пользовательский класс аутентификации, и он, очевидно, не применяется в деспетчере.
Что я могу сделать, чтобы исправить это?
В методе диспетчеризации drf APIView есть две части, связанные с аутентификацией.
def dispatch(self, request, *args, **kwargs):
...
self.args = args
self.kwargs = kwargs
-----------------------------------------------------------
request = self.initialize_request(request, *args, **kwargs)
-----------------------------------------------------------
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
--------------------------------------
self.initial(request, *args, **kwargs)
--------------------------------------
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
Сначала вызывается метод initialize_request, в котором импортируются и создаются классы аутентификации, установленные в View.
Ниже приводится вызов метода initial, который вызывает метод perform_authentication, метод, выполняющий практический процесс аутентификации.
def dispatch(self, request, *args, **kwargs):
# Check if the user is authenticated
if not request.user.is_authenticated:
raise PermissionDenied("You must be logged in to access this resource.")
# Get the user's profile
profile = request.user.profile
# Check if the profile has all the required permissions
if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
return super().dispatch(request, *args, **kwargs)
# Return 403 Forbidden if any permission check fails
raise PermissionDenied("You do not have permission to access this resource.")
В вашем методе dispatch часть, в которой происходит процесс аутентификации, предположительно будет super(). dispatch().
Поэтому я думаю сначала вызвать super().dispatch(), сохранить результаты и вернуть ошибку, если проверка require_permission не удалась.
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
# Check if the user is authenticated
if not request.user.is_authenticated:
raise PermissionDenied("You must be logged in to access this resource.")
# Get the user's profile
profile = request.user.profile
# Check if the profile has all the required permissions
if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
return response
# Return 403 Forbidden if any permission check fails
raise PermissionDenied("You do not have permission to access this resource.")