Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django rest framework - object permission does not trigger

I have the following setup:

permission.py

def get_permission_level(request, obj):
    try:
        level = PasswordListACL.objects.get(list=obj, user=request.user)
    except PasswordListACL.DoesNotExist:
        level = None
    return level


class IsPasswordListOwner(permissions.DjangoObjectPermissions):

    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        print(get_permission_level(request, obj))
        if get_permission_level(request, obj) == None:
            print('false')
            return False
        else:
            level = AccessLevel.objects.get(pk=get_permission_level(request, obj).level_id).name
            if level == 'Owner':
                return True
            else:
                return False

I can confirm through my print('false') that the permission is being acted on and it is returning the correct value (I'm expecting False) however the view is still returning the data instead of a 403.

views.py

class PasswordListViewSet(viewsets.ModelViewSet):
    queryset = PasswordList.objects.all()
    serializer_class = PasswordListSerializer
    permission_classes = (IsPasswordListOwner,)

    def list(self, request):
        self.permission_classes = [IsPasswordListOwner, ]
        queryset = self.get_queryset().filter(passwordlistacl__user=request.user)
        serializer = PasswordListSerializer(queryset, many=True, context={'request': request})
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        self.permission_classes = [IsPasswordListOwner, ]
        queryset = self.get_queryset()
        if get_object_or_404(queryset, pk=pk):
            password = get_object_or_404(queryset, pk=pk)
        else:
            pass
        serializer = PasswordListSerializer(password, context={'request': request})
        return Response(serializer.data)

edit - changing the return on has_permission confirms the permission there is overriding my has_object_permission?

Doing this gives me a 403 (correct):

def has_permission(self, request, view):
    return False
like image 557
whoisearth Avatar asked Jul 27 '26 07:07

whoisearth


1 Answers

The documentation states:

If you're writing your own views and want to enforce object level permissions, or if you override the get_object method on a generic view, then you'll need to explicitly call the .check_object_permissions(request, obj) method on the view at the point at which you've retrieved the object.

So since you're not calling get_object() you need to be calling self.check_object_permissions(self.request, obj) at some point.

like image 132
Linovia Avatar answered Jul 30 '26 05:07

Linovia