Django rest framework group based permissions for individual views

jaisimha ramanujapura picture jaisimha ramanujapura · Jul 24, 2017 · Viewed 8.1k times · Source

I am using DRF for writing API's. I would like to give different permissions for each view in my Modelviewsets. I have two groups(customers and staff). I have filtered them as Isstaff and Iscustomer in permissions.py.

class Iscustomer(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.user and request.user.groups.filter(name='customers'):
            return True
        return False


class Isstaff(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.user and request.user.groups.filter(name='staff'):
            return True
        return False

I am trying to overide using get_permissions method. When I put a single group in self.permission_classes, it works fine.

class cityviewset(viewsets.ModelViewSet):
    queryset = city.objects.all()
    serializer_class = citySerializer

    def get_permissions(self):    
        if self.request.method == 'POST' or self.request.method == 'DELETE':
            self.permission_classes = [Isstaff]
        return super(cityviewset, self).get_permissions()

But, when i try to put multiple groups in self.permission_classes, it fails.

def get_permissions(self):
    if self.request.method == 'POST' or self.request.method == 'DELETE':
        self.permission_classes = [Isstaff,Iscustomer,]
    return super(cityviewset, self).get_permissions()

Answer

zaidfazil picture zaidfazil · Jul 24, 2017

The problem is where you are adding multiple permission_classes to your views. The method where your permissions are checked is check_permissions(). If you look at the DRF code,

def check_permissions(self, request):
    """
    Check if the request should be permitted.
    Raises an appropriate exception if the request is not permitted.
    """
    for permission in self.get_permissions():
        if not permission.has_permission(request, self):
            self.permission_denied(
                request, message=getattr(permission, 'message', None)
            )

When you are providing multiple permission_classes, the user must satisfy both the permissions. So, the logged in user must be a Staff and Customer at same time. I think this is why your view fails.