How to check object level permission efficiently in DRF?

Viewed 439

Scenario: In DRF I had to write following lines of code to check permission for the user

class RetrieveCampaignListView(APIView) :

authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]


def get(self, request , *args, **kwargs):

    if request.user.has_perm('campaign.view_campaign'):

        try:
            #some view code
        
        except:

            return Response({"status":False}, status=status.HTTP_404_NOT_FOUND)
    else:
        return Response({"status":"Sorry User is not permitted"})

But I want to shorten the

request.user.has_perm('campaign.view_camapign') and it's else condition

into something like this.

@check_permission('campaign.view_campaign') 

Any Help Would be highly appericiated.

1 Answers

You can use DRF custom permissions:

from rest_framework import permissions


class ViewCampaignPermission(permissions.BasePermission):
    message = 'Sorry User is not permitted'

    def has_permission(self, request, view):
        return request.user.has_perm('campaign.view_campaign'):

class RetrieveCampaignListView(APIView) :
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated, ViewCampaignPermission]
    ...

See: https://www.django-rest-framework.org/api-guide/permissions/#custom-permissions

or if you really want a decorator, you can use something like:

from functools import wraps
from rest_framework.views import APIView

def has_permission(permission):
    def has_permission_decorator(func):
        @wraps(func)
        def has_permission_wrapper(*args, **kwargs):
            request = args[0].request
            if not request.user.has_perm(permission):
                return Response(status='Sorry User is not permitted'})
            return func(*args, **kwargs)
        return has_permission_wrapper
    return has_permission_decorator


class RetrieveCampaignListView(APIView):
    @has_permission('campaign.view_campaign')
    def get(self, request, *args, **kwargs):
        pass

But this will only work for one permission string.

Related