Returning custom message when a permission is denied in DRF

前端 未结 7 1979
盖世英雄少女心
盖世英雄少女心 2021-02-13 01:20

Django REST Framework has an excellent piece of documentation about permissions. I\'ve been able to use pre-made permission classes and also built my own.

However, there

相关标签:
7条回答
  • 2021-02-13 01:58

    By default, it is handled by default exception handler, and it is raising a standard message - https://github.com/tomchristie/django-rest-framework/blob/2eb9107b875972e442ed73eef0e653fd4480d873/rest_framework/views.py#L82

    But, you can set own EXCEPTION_HANDLER in settings of DRF, and handle PermissionDenied exception to return message you want.

    See description at http://www.django-rest-framework.org/api-guide/settings/

    0 讨论(0)
  • 2021-02-13 01:58

    I faced the same problem using DRF 3.9.4. As a workaround I defined just a simple message property in the custom permission class and it works. You can also use getattr with the same result I guess.

    class IPWhitelistPermission(permissions.BasePermission):
    
        def __init__(self):
            super(IPWhitelistPermission, self).__init__()
            self._client_ip = None
    
        def has_permission(self, request, view):
            ip = get_client_ip(request)
            ret = IPWhitelist.is_whitelisted(ip)
    
            if not ret:
                logger = logging.getLogger('access')
                logger.warn("Unauthorized access from IP %s" % ip)
                self._client_ip = ip
            return ret
    
        @property
        def message(self):
            return "This IP is not whitelisted [{}]".format(self._client_ip)
    
    0 讨论(0)
  • 2021-02-13 01:59

    when permission isn't granted, I will raise a exception which custom response. It works on djangorestframewor(3.10.1) and django(2.2.3).

    from rest_framework.permissions import BasePermission
    from rest_framework.exceptions import APIException
    from rest_framework import status
    
    
    class IsLogin(BasePermission):
        """
        Allows access only to authenticated users.
        """
    
        def has_permission(self, request, view):
            if request.email:
                return True
            raise NeedLogin()
    
    
    class NeedLogin(APIException):
        status_code = status.HTTP_403_FORBIDDEN
        default_detail = {'error': True, 'message': 'need login'}
        default_code = 'not_authenticated'
    
    0 讨论(0)
  • 2021-02-13 02:00

    Building on Aysennoussi’s answer:

    from rest_framework import permissions
    From django.utils import timezone
    
    class CustomerAccessPermission(permissions.BasePermission):
        message = 'Adding customers not allowed.'
    
        def has_permission(self, request, view): 
            if request.user.has_expired:
                self.message = “Your account has expired.”
                return False
            elif request.user.has_access:
                return True
            else:
                return False
    
    
    0 讨论(0)
  • 2021-02-13 02:04

    From DRF

    you can simply add message attribute.

    from rest_framework import permissions
    
    class IsSuperUserPermission(permissions.BasePermission):
        message = 'User is not superuser'
    
        def has_permission(self, request, view):
            return self.request.user.is_superuser
    

    It will return a dict with key detail, something like this:

    {
        'detail': 'User is not superuser'
    }
    

    But what if you want for example that the dict key not to be detail but errors for example, it will be the same how return errors DRF.

    We can set message attribute not to string but to dict, something like this:

    class IsSuperUserPermission(permissions.BasePermission):
        message = {'errors': ['User is not a superuser']}
    
        def has_permission(self, request, view):
            self.message['errors'].clear()
            return self.request.user.is_superuser
    

    In this case the error will be:

    {
        'errors': ['User is not a superuser']
    }
    
    0 讨论(0)
  • 2021-02-13 02:14

    You can send more than a single customized message if you want to. You can do it using GenericAPIException.

    Step 1: Create a permissions.py file and write this code.

    class Check_user_permission(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True
        else:
            response ={
                "success": "false",
                'message': "Post request is not allowed for user from admin group",
                "status_code":403,
            }
            raise GenericAPIException(detail=response, status_code=403)
    

    Here, response is the JSON response you want to send.

    Step 2: Go to view.py file and add the class Check_user_permission in the permission_classes list this way:

    class UserList(APIView):
        permission_classes = (IsAuthenticated, Check_user_permission)
        authentication_class = JSONWebTokenAuthentication
        ... 
        ...
    

    Now if you go to the endpoint and send a POST request you'll get this response.

    {
    "success": "false",
    "message": "Post request is not allowed!",
    "status_code": 403
    }
    
    0 讨论(0)
提交回复
热议问题