Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter user related records with permissions in Django Rest Framework

I need to know how to restrict access to Authenticated Users such that User Records can be listed in full for those logged in as Administrator and for those logged in as a User only their records can be listed, updated and created for themslefves.

Currently I am using serializers.ModelSerializer, viewsets.ModelViewSet and permissions.BasePermission but don't seem to be getting anywhere very fast.

like image 712
Stephen Brown Avatar asked Mar 13 '23 04:03

Stephen Brown


1 Answers

There is no out of the box way of handling such permissions with a magic wand. Although there are some libraries out there that can handle object level permissions, check django-guardian as it has nice interface with Django rest Framework.

One good way to handle this is combine django-guardian's capabilities with a custom get_queryset() method as described by @ilse2005's answer. This takes care of your list and retrieve and update and deletion can be delegated to django-guardian.

class View(ModelViewSet):
    ...

    def get_queryset(self):
        if self.request.user.is_superuser:
            return FooModel.objects.all()
        return FooModel.objects.filter(owner=self.request.user)

This can also work with APIViews and other Class Based Views in DRF.

Caution : If your API consumers are relying on HTTP error codes for meaning this approach would throw them 404 not found instead of HTTP403 which is a standard way of saying permission denied. In this case it is advisable to write a custom permissions class. For example the following ip blacklisting permission class is straight from the documentation - http://www.django-rest-framework.org/api-guide/permissions/

from rest_framework import permissions

class BlacklistPermission(permissions.BasePermission):
    """
    Global permission check for blacklisted IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
        return not blacklisted

Use this class in the viewset by setting up class variable

permission_classes = BlackListPermission

like image 104
iankit Avatar answered Apr 20 '23 00:04

iankit