mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-04 20:40:14 +03:00
Merge 2d762fe3f4
into 003c304115
This commit is contained in:
commit
c6fbc4e107
|
@ -4,6 +4,7 @@ Provides a set of pluggable permission policies.
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import Http404
|
||||
from django.utils import six
|
||||
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.compat import is_authenticated
|
||||
|
@ -11,6 +12,49 @@ from rest_framework.compat import is_authenticated
|
|||
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
|
||||
|
||||
|
||||
class BasePermissionMetaClass(type):
|
||||
"""
|
||||
Metaclass for the base permission class.
|
||||
"""
|
||||
|
||||
def __init__(cls, name, bases, dct):
|
||||
super(BasePermissionMetaClass, cls).__init__(name, bases, dct)
|
||||
|
||||
def __or__(klass, perm_class):
|
||||
"""
|
||||
Returns a new permission class performing a logical OR between two
|
||||
different permission classes.
|
||||
"""
|
||||
assert issubclass(perm_class, BasePermission), (
|
||||
"%s is not a subclass of BasePermission" % perm_class
|
||||
)
|
||||
|
||||
def has_permission(self, request, view):
|
||||
perm = klass.has_permission(self, request, view)
|
||||
otherwise = perm_class().has_permission(request, view)
|
||||
|
||||
return perm or otherwise
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
perm = klass.has_object_permission(self, request, view, obj)
|
||||
otherwise = perm_class().has_object_permission(request, view, obj)
|
||||
|
||||
return perm or otherwise
|
||||
|
||||
t = type(
|
||||
str('{0}Or{1}').format(klass.__name__, perm_class.__name__),
|
||||
(klass,),
|
||||
{}
|
||||
)
|
||||
|
||||
t.has_permission = has_permission
|
||||
t.has_object_permission = has_object_permission
|
||||
|
||||
return t
|
||||
|
||||
|
||||
# Needed for performing logical operations between permission classes.
|
||||
@six.add_metaclass(BasePermissionMetaClass)
|
||||
class BasePermission(object):
|
||||
"""
|
||||
A base class from which all permission classes should inherit.
|
||||
|
|
|
@ -483,3 +483,36 @@ class CustomPermissionsTests(TestCase):
|
|||
detail = response.data.get('detail')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(detail, self.custom_message)
|
||||
|
||||
|
||||
class AllowPermission(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
return True
|
||||
|
||||
|
||||
class DenyPermission(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
return False
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
return False
|
||||
|
||||
|
||||
class PermissionOperatorTests(TestCase):
|
||||
def test_permission_logical_or(self):
|
||||
# We evaluate all possible combinations.
|
||||
|
||||
# We pass None to the has_permission function, request and view aren't
|
||||
# relevant to these classes.
|
||||
self.assertFalse((DenyPermission | DenyPermission)().has_permission(None, None))
|
||||
self.assertTrue((AllowPermission | DenyPermission)().has_permission(None, None))
|
||||
self.assertTrue((DenyPermission | AllowPermission)().has_permission(None, None))
|
||||
self.assertTrue((AllowPermission | AllowPermission)().has_permission(None, None))
|
||||
|
||||
self.assertFalse((DenyPermission | DenyPermission)().has_object_permission(None, None, None))
|
||||
self.assertTrue((AllowPermission | DenyPermission)().has_object_permission(None, None, None))
|
||||
self.assertTrue((DenyPermission | AllowPermission)().has_object_permission(None, None, None))
|
||||
self.assertTrue((AllowPermission | AllowPermission)().has_object_permission(None, None, None))
|
||||
|
|
Loading…
Reference in New Issue
Block a user