I want to have easy way to check if somebody is owner or admin of post
, proposal
and so on he's trying to edit \ delete.
So, every time I use IsAuthenticated
permission and in the method of ModelViewSet
I get instance and check if instance.author
or sometimes instance.owner
is the user who requested it (request.user == instance.owner
on some objects it's request.user == instance.author
).
Question
The main question is: how can I create permission class that can check this kind of ownership with dynamic user attribute name on instance?
One of mine solutions (not the best, i think)
I've created function that take user attribute instance name returns permission class:
def is_owner_or_admin_permission_factory(owner_prop_name):
class IsOwnerOrAdmin(BasePermission):
def has_permission(self, request, view, *args, **kwargs):
instance = view.get_object()
try:
owner = getattr(instance, owner_prop_name)
except AttributeError:
return False
return (
request.user and request.user.id and (owner == request.user or request.user.is_staff)
)
return IsOwnerOrAdmin
I have also been frustrated over the same exact problem for days, and I've managed to find a suitable work-around (at least for me, of course), when dealing with multiple models with different lookup names for user attributes.
The work-around was something like this, in the ModelViewSet
defined a separate attribute user_lookup_kwarg
in the view, which could be used for checking the appropriate permissions.
Eg,
class YourViewSet(viewsets.ModelViewSet):
queryset = YourModel.objects.all()
serializer_class = YourSerializer
user_lookup_kwarg = 'user' #or 'account/created_by' whatever.
Now, your permission_class
would be somewhat like this,
class CustomPermission(BasePermission):
def has_object_permission(self, request, view, obj):
try:
return request.user.is_superuser or getattr(obj, view.user_lookup_kwarg) == request.user
except:
return False
return request.user.is_superuser
You only just need to override has_object_permission()
method to check instance level permissions.