mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-29 13:04:03 +03:00
Add negation ~ operator to permissions composition (#6361)
This commit is contained in:
parent
739b0a272a
commit
2daf6f1341
|
@ -134,7 +134,7 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi
|
||||||
}
|
}
|
||||||
return Response(content)
|
return Response(content)
|
||||||
|
|
||||||
__Note:__ it only supports & -and- and | -or-.
|
__Note:__ it supports & (and), | (or) and ~ (not).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,19 @@ class OperationHolderMixin:
|
||||||
def __ror__(self, other):
|
def __ror__(self, other):
|
||||||
return OperandHolder(OR, other, self)
|
return OperandHolder(OR, other, self)
|
||||||
|
|
||||||
|
def __invert__(self):
|
||||||
|
return SingleOperandHolder(NOT, self)
|
||||||
|
|
||||||
|
|
||||||
|
class SingleOperandHolder(OperationHolderMixin):
|
||||||
|
def __init__(self, operator_class, op1_class):
|
||||||
|
self.operator_class = operator_class
|
||||||
|
self.op1_class = op1_class
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
op1 = self.op1_class(*args, **kwargs)
|
||||||
|
return self.operator_class(op1)
|
||||||
|
|
||||||
|
|
||||||
class OperandHolder(OperationHolderMixin):
|
class OperandHolder(OperationHolderMixin):
|
||||||
def __init__(self, operator_class, op1_class, op2_class):
|
def __init__(self, operator_class, op1_class, op2_class):
|
||||||
|
@ -73,6 +86,17 @@ class OR:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NOT:
|
||||||
|
def __init__(self, op1):
|
||||||
|
self.op1 = op1
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return not self.op1.has_permission(request, view)
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
return not self.op1.has_object_permission(request, view, obj)
|
||||||
|
|
||||||
|
|
||||||
class BasePermissionMetaclass(OperationHolderMixin, type):
|
class BasePermissionMetaclass(OperationHolderMixin, type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -580,7 +580,19 @@ class PermissionsCompositionTests(TestCase):
|
||||||
composed_perm = permissions.IsAuthenticated | permissions.AllowAny
|
composed_perm = permissions.IsAuthenticated | permissions.AllowAny
|
||||||
assert composed_perm().has_permission(request, None) is True
|
assert composed_perm().has_permission(request, None) is True
|
||||||
|
|
||||||
def test_several_levels(self):
|
def test_not_false(self):
|
||||||
|
request = factory.get('/1', format='json')
|
||||||
|
request.user = AnonymousUser()
|
||||||
|
composed_perm = ~permissions.IsAuthenticated
|
||||||
|
assert composed_perm().has_permission(request, None) is True
|
||||||
|
|
||||||
|
def test_not_true(self):
|
||||||
|
request = factory.get('/1', format='json')
|
||||||
|
request.user = self.user
|
||||||
|
composed_perm = ~permissions.AllowAny
|
||||||
|
assert composed_perm().has_permission(request, None) is False
|
||||||
|
|
||||||
|
def test_several_levels_without_negation(self):
|
||||||
request = factory.get('/1', format='json')
|
request = factory.get('/1', format='json')
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
composed_perm = (
|
composed_perm = (
|
||||||
|
@ -591,6 +603,17 @@ class PermissionsCompositionTests(TestCase):
|
||||||
)
|
)
|
||||||
assert composed_perm().has_permission(request, None) is True
|
assert composed_perm().has_permission(request, None) is True
|
||||||
|
|
||||||
|
def test_several_levels_and_precedence_with_negation(self):
|
||||||
|
request = factory.get('/1', format='json')
|
||||||
|
request.user = self.user
|
||||||
|
composed_perm = (
|
||||||
|
permissions.IsAuthenticated &
|
||||||
|
~ permissions.IsAdminUser &
|
||||||
|
permissions.IsAuthenticated &
|
||||||
|
~(permissions.IsAdminUser & permissions.IsAdminUser)
|
||||||
|
)
|
||||||
|
assert composed_perm().has_permission(request, None) is True
|
||||||
|
|
||||||
def test_several_levels_and_precedence(self):
|
def test_several_levels_and_precedence(self):
|
||||||
request = factory.get('/1', format='json')
|
request = factory.get('/1', format='json')
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
|
|
Loading…
Reference in New Issue
Block a user