tldr: I want to make a permission, that allows 'retrieve' action but not 'list'.
I'm writing REST API using Django Rest Framework and met a problem creating custom permission (for View from viewsets.ModelViewSet)
Got stuck creating an endpoint that should return site users:
-Admin should have permission to access every method
-Regular user should only be able to 'retrieve' and 'patch' his own account
I can't find a way to differ GET request 'list' from 'retrieve'.
Checking for request.method == GET
allows both of them, but I don't want user to be able to list all other users.
from rest_framework.permissions import BasePermission
```
def is_superuser(request):
return request.user.is_superuser
```
class IsAdminOrReadOnlyOwner(BasePermission):
def has_permission(self, request, view):
if is_superuser(request):
return True
else:
return request.method in ['GET', 'PATCH']
def has_object_permission(self, request, view, obj):
is_owner_and_safe = int(request.user.id) == obj.id and request.method in ['GET', 'PATCH']
return is_owner_and_safe or is_superuser(request)
Is there a way to do this, still using ModelViewSet?
When checking permissions, Django Rest passes the view to the permission class methods, and from the view you can determine the action. You can see an example for has_object_permission
and RetrieveAPIView
in the source code here.
You can use view.action
to identify the action from your permission class methods, for example:
def has_permission(self, request, view):
if is_superuser(request):
return True
else:
return view.action in ['retrieve', 'update']
You can check for view.action
in has_object_permission
to achieve what you want.