From c86f5463b4a41d7e81a0fbcf540063e1cba18a77 Mon Sep 17 00:00:00 2001 From: Florent Chehab Date: Sat, 6 Apr 2019 11:09:17 +0200 Subject: [PATCH] fix(composable permissions): no more double level `OR` * POC to demonstrate a quick fix to prevent the double level `OR` permission check --- rest_framework/permissions.py | 7 +++++-- tests/test_permissions.py | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 5d75f54ba..4f99dde7b 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -80,9 +80,12 @@ class OR: ) def has_object_permission(self, request, view, obj): + # We enforce a "block" `OR`, so we need the result of `has_permission` too. + op1_hp_res = self.op1.has_permission(request, view) + op2_hp_res = self.op2.has_permission(request, view) return ( - self.op1.has_object_permission(request, view, obj) or - self.op2.has_object_permission(request, view, obj) + (op1_hp_res and self.op1.has_object_permission(request, view, obj)) or + (op2_hp_res and self.op2.has_object_permission(request, view, obj)) ) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 2fabdfa05..f0a00ae0f 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -580,6 +580,13 @@ class PermissionsCompositionTests(TestCase): composed_perm = permissions.IsAuthenticated | permissions.AllowAny assert composed_perm().has_permission(request, None) is True + def test_or_as_block(self): + request = factory.get('/1', format='json') + request.user = AnonymousUser() + composed_perm = BasicObjectPerm | permissions.IsAuthenticated + assert composed_perm().has_permission(request, None) is True + assert composed_perm().has_object_permission(request, None, None) is False + def test_not_false(self): request = factory.get('/1', format='json') request.user = AnonymousUser()