From b699dbb46c7baacd7188ad84cdfbefad13193983 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 8 Mar 2018 23:56:29 +0100 Subject: [PATCH] api: add parameters to filter users by allowed services (fixes #22377) --- src/authentic2/api_views.py | 8 ++++++ .../migrations/0018_auto_20170524_0842.py | 2 +- src/authentic2/models.py | 4 +-- tests/test_api.py | 28 +++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index 2b4d498f..0c36292a 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -548,6 +548,14 @@ class UsersAPI(HookMixin, ExceptionHandlerMixin, ModelViewSet): if self.request.method == 'GET': qs = qs.prefetch_related('attribute_values', 'attribute_values__attribute') qs = self.request.user.filter_by_perm(['custom_user.view_user'], qs) + # filter users authorized for a specified service + if 'service-slug' in self.request.GET and 'service-ou' in self.request.GET: + service_slug = self.request.GET['service-slug'] + service_ou = self.request.GET['service-ou'] + qs = (qs.filter(roles__allowed_services__slug=service_slug, roles__allowed_services__ou__slug=service_ou) + | qs.filter(roles__parent_relation__parent__allowed_services__slug=service_slug, + roles__parent_relation__parent__allowed_services__ou__slug=service_ou)) + qs = qs.distinct() new_qs = hooks.call_hooks_first_result('api_modify_queryset', self, qs) if new_qs is not None: return new_qs diff --git a/src/authentic2/migrations/0018_auto_20170524_0842.py b/src/authentic2/migrations/0018_auto_20170524_0842.py index 4859b84a..c444d8ec 100644 --- a/src/authentic2/migrations/0018_auto_20170524_0842.py +++ b/src/authentic2/migrations/0018_auto_20170524_0842.py @@ -33,6 +33,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='service', name='authorized_roles', - field=models.ManyToManyField(related_name='authorized_roles', verbose_name='authorized services', to=settings.RBAC_ROLE_MODEL, through='authentic2.AuthorizedRole', blank=True), + field=models.ManyToManyField(related_name='allowed_services', verbose_name='authorized services', to=settings.RBAC_ROLE_MODEL, through='authentic2.AuthorizedRole', blank=True), ), ] diff --git a/src/authentic2/models.py b/src/authentic2/models.py index 505fe704..60ff655c 100644 --- a/src/authentic2/models.py +++ b/src/authentic2/models.py @@ -335,7 +335,7 @@ class Service(models.Model): authorized_roles = models.ManyToManyField( get_role_model_name(), verbose_name=_('authorized services'), through='AuthorizedRole', through_fields=('service', 'role'), - related_name='authorized_roles', blank=True) + related_name='allowed_services', blank=True) unauthorized_url = models.URLField( verbose_name=_('callback url when unauthorized'), max_length=256, null=True, blank=True) @@ -377,7 +377,7 @@ class Service(models.Model): def authorize(self, user): if not self.authorized_roles.exists(): return True - if user.roles_and_parents().filter(authorized_roles=self).exists(): + if user.roles_and_parents().filter(allowed_services=self).exists(): return True raise ServiceAccessDenied(service=self) diff --git a/tests/test_api.py b/tests/test_api.py index f6d7bf29..16a6fe34 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -141,6 +141,34 @@ def test_api_users_list(app, user): assert resp.json['next'] is None +def test_api_users_list_by_authorized_service(app, superuser): + from authentic2.models import Service + + app.authorization = ('Basic', (superuser.username, superuser.username)) + User = get_user_model() + Role = get_role_model() + + user1 = User.objects.create(username='user1') + user2 = User.objects.create(username='user2') + user3 = User.objects.create(username='user3') + + role1 = Role.objects.create(name='role1') + role2 = Role.objects.create(name='role2') + role1.add_child(role2) + user1.roles = [role1] + user2.roles = [role2] + + service = Service.objects.create(ou=get_default_ou(), name='service', slug='service') + service.add_authorized_role(role1) + + resp = app.get('/api/users/') + assert len(resp.json['results']) == 4 + + resp = app.get('/api/users/?service-ou=default&service-slug=service') + assert len(resp.json['results']) == 2 + assert set(user['username'] for user in resp.json['results']) == set(['user1', 'user2']) + + def test_api_users_create(settings, app, api_user): from django.contrib.auth import get_user_model from authentic2.models import Attribute, AttributeValue -- 2.17.0