Hi I am creating a custom middleware in Django for the DRF.
So that when an user try to access any of the api the middleware will perform some operation and determine if the user is authorized to access the endpoint or not.
My code is like below:
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
if request.path.startswith('/admin/'):
return None
if request.path.startswith('/api/'):
is_allowed = True
if not is_allowed:
return # < -- What needs to return to block the access
return None
My problem is what should I return from the method for disallowing access to api? I can return None, if I want to give access. But I want to disallow access and return some message from the api view so that user knows that he is not allwed.
So in summery:
- What should I return from the middleware to block access?
- How can I return message to user from the view that he is not authorized?
Thanks
CodePudding user response:
Let's say you want to restrict access to your endpoint.
- To achieve this you have two view's methods for that:
check_permissions
- gets to decide whether the request and user are allowed to proceed.check_object_permissions
- gets to decide whether a user is allowed to interact with an object. - To define your custom validation logic you can subclass
BasePermission
class fromrest_framework
:class YourCustomPermission(permissions.BasePermission): # Will be retrieved from the view's methods mentioned above custom_message = 'Your message.' def has_permission(self, request, view): if is_your_custom_request_logic_satisfied(request): return True return False def has_object_permission(self, request, view, obj): if is_your_custom_object_logic_satisfied(request, obj): return True return False
- And finally your view:
class APIView(View): ... permission_classes = [IsAuthenticated, YourCustomPermission] def check_permissions(self, request): for permission in self.get_permissions(): if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'custom_message', None), code=getattr(permission, 'code', None) ) def check_object_permissions(self, request, obj): for permission in self.get_permissions(): if not permission.has_object_permission(request, self, obj): self.permission_denied( request, message=getattr(permission, 'custom_message', None), code=getattr(permission, 'code', None) )
Here is a nice tutorial for you to read.
CodePudding user response:
This is approch I took to get the result I was expecting. This way I do not have to modify api view. Hope it will help others in the future.
from django.http import JsonResponse
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
if request.path.startswith('/admin/'):
return None
if request.path.startswith('/api/'):
is_allowed = True
if not is_allowed:
return JsonResponse(
{"detail": "Subscription Expired or Not Subscribed"},
status=403
)
return None
CodePudding user response:
Youre nearly there, you should raise a
PermissionDenied
Error and this would be handled appropriately.
This error would then be handled like so:
https://docs.djangoproject.com/en/4.1/topics/http/middleware/#process-exception