rest_condition
rest_condition copied to clipboard
has_object_permission doesn't get called
In my viewset I have the following:
permission_classes = [ Or(And(IsReadOnlyRequest, IsAuthenticated), And(IsPutRequest, IsObjectUser)) ]
Where IsObjectUser has:
def has_object_permission(self, request, view, obj): return obj.user == request.user
The has_object_permission method is never invoked when wrapped inside the conditional statement. However, If I use the IsObjectUser as a plain permission class in permission_classes list, it works fine. This isn't suitable for me because I need them for each method, not for the whole viewset, always.
If this is bug, I would love to see it fixed. Any suggestions or workarounds are appreciated.
You will find that the outer Or
is evaluating to True and short circuiting (not evaluating the second argument) because And(IsReadOnlyRequest, IsAuthenticated).has_object_permission
returns True
.
This is because IsReadOnlyRequest
and IsAuthenticated
both inherit from BasePermission
which just returns True
for has_object_permission
. This is a gotcha when combining permissions with an or
, which doesn't normally happen with the default DRF behavior.
To get your desired behavior, you will need to subclass IsReadOnlyRequest
and IsAuthenticated
so that their has_object_permission
returns a meaningful result. I normally just do this:
class IsAuthenticated(permissions.IsAuthenticated):
def has_object_permission(self, request, view, obj):
return self.has_permission(request, view)