From 4d74941790e83cb622c30313429ac7ffe223d8e5 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 | 10 +++++- .../migrations/0018_auto_20170524_0842.py | 2 +- src/authentic2/models.py | 4 +-- tests/test_api.py | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index 1292237c..3b8fc137 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -27,7 +27,7 @@ from django_filters.rest_framework import FilterSet from .custom_user.models import User from . import utils, decorators, attribute_kinds, app_settings, hooks -from .models import Attribute, PasswordReset +from .models import Attribute, PasswordReset, Service from .a2_rbac.utils import get_default_ou @@ -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'] + service = Service.objects.filter(slug=service_slug, ou__slug=service_ou).prefetch_related('authorized_roles').first() + if service and service.authorized_roles.all(): + qs = qs.filter(roles__in=service.authorized_roles.children()) + 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 23e4efff..43cb678d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -141,6 +141,39 @@ 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] + + service1 = Service.objects.create(ou=get_default_ou(), name='service1', slug='service1') + service1.add_authorized_role(role1) + + service2 = Service.objects.create(ou=get_default_ou(), name='service2', slug='service2') + + resp = app.get('/api/users/') + assert len(resp.json['results']) == 4 + + resp = app.get('/api/users/?service-ou=default&service-slug=service1') + assert len(resp.json['results']) == 2 + assert set(user['username'] for user in resp.json['results']) == set(['user1', 'user2']) + + resp = app.get('/api/users/?service-ou=default&service-slug=service2') + assert len(resp.json['results']) == 4 + + def test_api_users_create(settings, app, api_user): from django.contrib.auth import get_user_model from authentic2.models import Attribute, AttributeValue -- 2.18.0