From 74855ff3836bbcdde325ca381fdb656d1af2bf42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Pierobon?= Date: Fri, 21 Jun 2019 11:54:18 -0300 Subject: [PATCH 1/5] Let AND and OR operators have multiple members resolve permission AND(OR(a,b,c), d, e) with logic (a v b v c) ^ d ^ e --- rest_framework/permissions.py | 90 +++++++++++++++++------------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 3a8c580646..6f61709e53 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -47,73 +47,71 @@ def __call__(self, *args, **kwargs): return self.operator_class(op1, op2) -class AND: - def __init__(self, op1, op2): - self.op1 = op1 - self.op2 = op2 +class BasePermissionMetaclass(OperationHolderMixin, type): + pass + + +class BasePermission(metaclass=BasePermissionMetaclass): + """ + A base class from which all permission classes should inherit. + """ def has_permission(self, request, view): - return ( - self.op1.has_permission(request, view) and - self.op2.has_permission(request, view) - ) + """ + Return `True` if permission is granted, `False` otherwise. + """ + return True def has_object_permission(self, request, view, obj): - return ( - self.op1.has_object_permission(request, view, obj) and - self.op2.has_object_permission(request, view, obj) - ) - + """ + Return `True` if permission is granted, `False` otherwise. + """ + return True -class OR: - def __init__(self, op1, op2): - self.op1 = op1 - self.op2 = op2 +class AND(BasePermission): + def __init__(self, *args): + self.permissions = args def has_permission(self, request, view): - return ( - self.op1.has_permission(request, view) or - self.op2.has_permission(request, view) - ) + for permission in self.permissions: + if not permissions.has_permission(request, view): + return False + return True def has_object_permission(self, request, view, obj): - return ( - self.op1.has_object_permission(request, view, obj) or - self.op2.has_object_permission(request, view, obj) - ) + for permission in self.permissions: + if not permissions.has_object_permission(request, view, obj): + return False + return True -class NOT: - def __init__(self, op1): - self.op1 = op1 +class OR(BasePermission): + def __init__(self, *args): + self.permissions = op1 def has_permission(self, request, view): - return not self.op1.has_permission(request, view) + for permission in self.permissions: + if permission.has_permission(request, view): + return True + return False def has_object_permission(self, request, view, obj): - return not self.op1.has_object_permission(request, view, obj) + for permission in self.permissions: + if permission.has_object_permission(request, view, obj): + return True + return False -class BasePermissionMetaclass(OperationHolderMixin, type): - pass - - -class BasePermission(metaclass=BasePermissionMetaclass): - """ - A base class from which all permission classes should inherit. - """ +class NOT(BasePermission): + def __init__(self, op1): + self.op1 = op1 def has_permission(self, request, view): - """ - Return `True` if permission is granted, `False` otherwise. - """ - return True + return not self.op1.has_permission(request, view) def has_object_permission(self, request, view, obj): - """ - Return `True` if permission is granted, `False` otherwise. - """ - return True + return not self.op1.has_object_permission(request, view, obj) + class AllowAny(BasePermission): From db16bb3799cf500caa5dba30bca622fbfd1aee52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Pierobon?= Date: Fri, 21 Jun 2019 12:03:28 -0300 Subject: [PATCH 2/5] Fix typo at OR constructor OR members should be the constructors arguments --- rest_framework/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 6f61709e53..a5dfe4a2ed 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -87,7 +87,7 @@ def has_object_permission(self, request, view, obj): class OR(BasePermission): def __init__(self, *args): - self.permissions = op1 + self.permissions = args def has_permission(self, request, view): for permission in self.permissions: From 88b6200b4b78a24368f971ef9c57d82eb54ad7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Pierobon?= Date: Fri, 21 Jun 2019 12:19:06 -0300 Subject: [PATCH 3/5] Fix NameError --- rest_framework/permissions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index a5dfe4a2ed..66013009fe 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -74,13 +74,13 @@ def __init__(self, *args): def has_permission(self, request, view): for permission in self.permissions: - if not permissions.has_permission(request, view): + if not permission.has_permission(request, view): return False return True def has_object_permission(self, request, view, obj): for permission in self.permissions: - if not permissions.has_object_permission(request, view, obj): + if not permission.has_object_permission(request, view, obj): return False return True From 9c3ea305656dfab56920cf22f7950661ffc89da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Pierobon?= Date: Fri, 21 Jun 2019 12:31:10 -0300 Subject: [PATCH 4/5] Fix tox E302 and E303 --- rest_framework/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 66013009fe..24b3e4ec93 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -68,6 +68,7 @@ def has_object_permission(self, request, view, obj): """ return True + class AND(BasePermission): def __init__(self, *args): self.permissions = args @@ -113,7 +114,6 @@ def has_object_permission(self, request, view, obj): return not self.op1.has_object_permission(request, view, obj) - class AllowAny(BasePermission): """ Allow any access. From e709378ddbf4caa75fb7bf246fe078eb2533f624 Mon Sep 17 00:00:00 2001 From: Kevin Brown Date: Wed, 13 Nov 2019 22:06:47 -0500 Subject: [PATCH 5/5] Do not extend AND/OR/NOT from BasePermission This can be done in a separate pull request, but it was reverted out of this one because it made it more difficult to review and increased its chances of not being accepted. --- rest_framework/permissions.py | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 24b3e4ec93..f880fcc254 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -47,29 +47,7 @@ def __call__(self, *args, **kwargs): return self.operator_class(op1, op2) -class BasePermissionMetaclass(OperationHolderMixin, type): - pass - - -class BasePermission(metaclass=BasePermissionMetaclass): - """ - A base class from which all permission classes should inherit. - """ - - def has_permission(self, request, view): - """ - Return `True` if permission is granted, `False` otherwise. - """ - return True - - def has_object_permission(self, request, view, obj): - """ - Return `True` if permission is granted, `False` otherwise. - """ - return True - - -class AND(BasePermission): +class AND: def __init__(self, *args): self.permissions = args @@ -86,7 +64,7 @@ def has_object_permission(self, request, view, obj): return True -class OR(BasePermission): +class OR: def __init__(self, *args): self.permissions = args @@ -103,7 +81,7 @@ def has_object_permission(self, request, view, obj): return False -class NOT(BasePermission): +class NOT: def __init__(self, op1): self.op1 = op1 @@ -114,6 +92,28 @@ def has_object_permission(self, request, view, obj): return not self.op1.has_object_permission(request, view, obj) +class BasePermissionMetaclass(OperationHolderMixin, type): + pass + + +class BasePermission(metaclass=BasePermissionMetaclass): + """ + A base class from which all permission classes should inherit. + """ + + def has_permission(self, request, view): + """ + Return `True` if permission is granted, `False` otherwise. + """ + return True + + def has_object_permission(self, request, view, obj): + """ + Return `True` if permission is granted, `False` otherwise. + """ + return True + + class AllowAny(BasePermission): """ Allow any access.