Skip to content

Commit 7457421

Browse files
committed
Fix composable permissions
In some cases we end with an operation between two `OperandHolder`. This didn't work as it didn't knew how to deal with | or & This fixes by adding those operations.
1 parent 0f5dfe8 commit 7457421

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

rest_framework/permissions.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,21 @@
1111
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
1212

1313

14-
class OperandHolder:
14+
class OperationHolderMixin:
15+
def __and__(self, other):
16+
return OperandHolder(AND, self, other)
17+
18+
def __or__(self, other):
19+
return OperandHolder(OR, self, other)
20+
21+
def __rand__(self, other):
22+
return OperandHolder(AND, other, self)
23+
24+
def __ror__(self, other):
25+
return OperandHolder(OR, other, self)
26+
27+
28+
class OperandHolder(OperationHolderMixin):
1529
def __init__(self, operator_class, op1_class, op2_class):
1630
self.operator_class = operator_class
1731
self.op1_class = op1_class
@@ -59,18 +73,8 @@ def has_object_permission(self, request, view, obj):
5973
)
6074

6175

62-
class BasePermissionMetaclass(type):
63-
def __and__(cls, other):
64-
return OperandHolder(AND, cls, other)
65-
66-
def __or__(cls, other):
67-
return OperandHolder(OR, cls, other)
68-
69-
def __rand__(cls, other):
70-
return OperandHolder(AND, other, cls)
71-
72-
def __ror__(cls, other):
73-
return OperandHolder(OR, other, cls)
76+
class BasePermissionMetaclass(OperationHolderMixin, type):
77+
pass
7478

7579

7680
@six.add_metaclass(BasePermissionMetaclass)

tests/test_permissions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,3 +589,14 @@ def test_several_levels(self):
589589
permissions.IsAuthenticated
590590
)
591591
assert composed_perm().has_permission(request, None) is True
592+
593+
def test_several_levels_and_precedence(self):
594+
request = factory.get('/1', format='json')
595+
request.user = self.user
596+
composed_perm = (
597+
permissions.IsAuthenticated &
598+
permissions.IsAuthenticated |
599+
permissions.IsAuthenticated &
600+
permissions.IsAuthenticated
601+
)
602+
assert composed_perm().has_permission(request, None) is True

0 commit comments

Comments
 (0)