Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize Error Message When Permission Check Fails

The DRF documentation provides clear instructions on how to create a custom permission, offering the following code sample:

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

By default this gives the following response when the permission check function return False.

HTTP 403 FORBIDDEN
Content-Type: application/json
Vary: Accept
Allow: GET, POST, HEAD, OPTIONS

{ "detail": "You do not have permission to perform this action." }

I would like to change the "detail" section above, offering a more developer-friendly error message. How could I do this, ensuring the message is presented each time the permission check fails?

like image 929
inperspective Avatar asked Feb 09 '15 16:02

inperspective


2 Answers

Class APIView checks permissions via

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)

And here's permission_denied

def permission_denied(self, request):
    """
    If request is not permitted, determine what kind of exception to raise.
    """
    if not request.successful_authenticator:
        raise exceptions.NotAuthenticated()
    raise exceptions.PermissionDenied()

So it seems entirely reasonable to subclass exceptions.PermissionDenied and raise it directly in your custom Permission class, eg

class CustomForbidden(APIException):
    status_code = status.HTTP_403_FORBIDDEN
    default_detail = "Add your custom error message here"


class CustomPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        if not_allowed:
            raise CustomForbidden
like image 79
cerberos Avatar answered Oct 19 '22 23:10

cerberos


For anybody from Google. There is now easier way to provide custom message. Just add attribute message to your custom permission class. Docs

class CustomPermission(BasePermission):
    message = 'My custom message'
like image 35
Mikhail Pyrev Avatar answered Oct 20 '22 00:10

Mikhail Pyrev