[Fixed]-Django rest framework ignores has_object_permission

27👍

the permission-checks for objects are done by DRF in the method APIView.check_object_permissions.

Since you don’t use the GenericAPIView, you define your own get_object method and you have to call check_object_permissions yourself. Since you are mis-using get_object a bit, you have to check for GET (single), PUT and DELETE

self.check_object_permissions(self.request, obj)

Perhaps have a better look at the DRF Generic Views, since your use-case looks much like them. Normally get_object should only return an object and check the permissions.

0👍

I am going to share my solution for ViewSets.
I want superuser to have permission for all, but for staff, only access to his own details

This is how you can use permissions (for a get single object call)

My setup: Django 4, python 3.11

My API class:

class StaffViewSet(viewsets.ModelViewSet):
    serializer_class = StaffSerializer
    queryset = user.objects.filter(is_staff=True)

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        if self.action in ["list", "create", "delete"]:
            permission_classes = [LoggedInSuperUser]
        else:
            permission_classes = [LoggedInSuperUser|LoggedInStaff]
        return [permission() for permission in permission_classes]

My Permissions class:

class LoggedInStaff(BasePermission):
    def has_permission(self, request, view):
        return all([request.user.is_staff, request.user.is_authenticated])

    def has_object_permission(self, request, view, obj):
        if obj.email == request.user.email:
            return True
        return False


class LoggedInSuperUser(BasePermission):
    def has_permission(self, request, view):
        return all([request.user.is_superuser, request.user.is_authenticated])

    def has_object_permission(self, request, view, obj):
        return all([request.user.is_superuser, request.user.is_authenticated])

Leave a comment