Skip to content
Snippets Groups Projects
Verified Commit dfb4f5f6 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

See #230: can now use "or" operator to check permissions

parent ed6c1a9a
Branches
Tags
No related merge requests found
...@@ -72,9 +72,12 @@ class User(AbstractUser): ...@@ -72,9 +72,12 @@ class User(AbstractUser):
perms[p] = v perms[p] = v
return perms return perms
def has_permissions(self, *perms): def has_permissions(self, *perms, operator='and'):
if operator not in ['and', 'or']:
raise ValueError('Invalid operator {}'.format(operator))
permissions = self.get_permissions() permissions = self.get_permissions()
return all([permissions[p] for p in perms]) checker = all if operator == 'and' else any
return checker([permissions[p] for p in perms])
def get_absolute_url(self): def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username}) return reverse('users:detail', kwargs={'username': self.username})
......
...@@ -16,4 +16,6 @@ class HasUserPermission(BasePermission): ...@@ -16,4 +16,6 @@ class HasUserPermission(BasePermission):
return False return False
if request.user.is_anonymous: if request.user.is_anonymous:
return False return False
return request.user.has_permissions(*view.required_permissions) operator = getattr(view, 'permission_operator', 'and')
return request.user.has_permissions(
*view.required_permissions, operator=operator)
...@@ -231,8 +231,9 @@ def authenticated_actor(factories, mocker): ...@@ -231,8 +231,9 @@ def authenticated_actor(factories, mocker):
@pytest.fixture @pytest.fixture
def assert_user_permission(): def assert_user_permission():
def inner(view, permissions): def inner(view, permissions, operator='and'):
assert HasUserPermission in view.permission_classes assert HasUserPermission in view.permission_classes
assert getattr(view, 'permission_operator', 'and') == operator
assert set(view.required_permissions) == set(permissions) assert set(view.required_permissions) == set(permissions)
return inner return inner
......
...@@ -47,6 +47,17 @@ def test_get_permissions_regular(factories): ...@@ -47,6 +47,17 @@ def test_get_permissions_regular(factories):
({'permission_library': True}, ['library'], True), ({'permission_library': True}, ['library'], True),
({'permission_library': True}, ['library', 'federation'], False), ({'permission_library': True}, ['library', 'federation'], False),
]) ])
def test_has_permissions(args, perms, expected, factories): def test_has_permissions_and(args, perms, expected, factories):
user = factories['users.User'](**args) user = factories['users.User'](**args)
assert user.has_permissions(*perms) is expected assert user.has_permissions(*perms, operator='and') is expected
@pytest.mark.parametrize('args,perms,expected', [
({'is_superuser': True}, ['federation', 'library'], True),
({'is_superuser': False}, ['federation'], False),
({'permission_library': True}, ['library', 'federation'], True),
({'permission_library': True}, ['federation'], False),
])
def test_has_permissions_or(args, perms, expected, factories):
user = factories['users.User'](**args)
assert user.has_permissions(*perms, operator='or') is expected
...@@ -39,7 +39,7 @@ def test_has_user_permission_logged_in_single(value, factories, api_request): ...@@ -39,7 +39,7 @@ def test_has_user_permission_logged_in_single(value, factories, api_request):
(False, False, False), (False, False, False),
(True, True, True), (True, True, True),
]) ])
def test_has_user_permission_logged_in_single( def test_has_user_permission_logged_in_multiple_and(
federation, library, expected, factories, api_request): federation, library, expected, factories, api_request):
user = factories['users.User']( user = factories['users.User'](
permission_federation=federation, permission_federation=federation,
...@@ -48,9 +48,35 @@ def test_has_user_permission_logged_in_single( ...@@ -48,9 +48,35 @@ def test_has_user_permission_logged_in_single(
class View(APIView): class View(APIView):
required_permissions = ['federation', 'library'] required_permissions = ['federation', 'library']
permission_operator = 'and'
view = View() view = View()
permission = permissions.HasUserPermission() permission = permissions.HasUserPermission()
request = api_request.get('/') request = api_request.get('/')
setattr(request, 'user', user) setattr(request, 'user', user)
result = permission.has_permission(request, view) result = permission.has_permission(request, view)
assert result == user.has_permissions('federation', 'library') == expected assert result == user.has_permissions('federation', 'library') == expected
@pytest.mark.parametrize('federation,library,expected', [
(True, False, True),
(False, True, True),
(False, False, False),
(True, True, True),
])
def test_has_user_permission_logged_in_multiple_or(
federation, library, expected, factories, api_request):
user = factories['users.User'](
permission_federation=federation,
permission_library=library,
)
class View(APIView):
required_permissions = ['federation', 'library']
permission_operator = 'or'
view = View()
permission = permissions.HasUserPermission()
request = api_request.get('/')
setattr(request, 'user', user)
result = permission.has_permission(request, view)
assert result == user.has_permissions(
'federation', 'library', operator='or') == expected
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment