Last active
February 24, 2017 01:45
-
-
Save blapid/359d120bcc73609a42cb to your computer and use it in GitHub Desktop.
django-rest-framework - raise permission denied instead of not found
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def HideNotFoundSubClass(base_class): | |
''' | |
So apparently, django-rest-framework's permission checks aren't quite enough | |
for me. | |
It has 2 steps: | |
1. Check global permissions by calling has_permission for each of the | |
permission classes | |
2. Check object permissions by calling has_object_permission for each | |
of the permission classes | |
Between 1 and 2, it tries to find the object with get_object(). | |
Now, if the object does not exist, we get a 404, which would make sense | |
in most cases. However, if the object does exist but test 2 fails, we get | |
403. That allows authenticated users to know whether a resource | |
exists or not, even though they wouldn't have permissions for it if it did. | |
This is quite a serious problem for me, so I made this function. | |
Basically, this wraps a given class by a subclass that overrides get_object(). | |
The new get_object() function catches the 404 and raises a 403 instead. | |
''' | |
cls = type(base_class.__name__+'_HideNotFoundSubClass', (base_class,), {}) | |
def get_object(self, queryset=None): | |
try: | |
obj = super(cls, self).get_object(queryset) | |
return obj | |
except Http404 as e: | |
raise PermissionDenied() | |
cls.get_object = get_object | |
return cls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment