From 997c8b3932c9a6bbbc6d89b3879ed14f1be3a982 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 14 Jan 2016 00:46:01 +0100 Subject: [PATCH] provision users on role parenting changes (fixes #9643) --- hobo/agent/authentic2/apps.py | 18 +++++++++++++- tests_authentic/test_provisionning.py | 45 ++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/hobo/agent/authentic2/apps.py b/hobo/agent/authentic2/apps.py index 51601e2..419d6e8 100644 --- a/hobo/agent/authentic2/apps.py +++ b/hobo/agent/authentic2/apps.py @@ -22,9 +22,10 @@ from django.db.models.signals import post_save, post_delete, m2m_changed from django.conf import settings from django.contrib.auth import get_user_model from django.db import connection +from django.db.models import Q from django.core.urlresolvers import reverse -from django_rbac.utils import get_role_model +from django_rbac.utils import get_role_model, get_role_parenting_model from hobo.agent.common import notify_agents from authentic2.models import AttributeValue @@ -198,6 +199,18 @@ def provision_user_on_attribute_value_delete(sender, instance, **kwargs): return provision_user(User, instance.owner) +def on_save_role_parenting(sender, instance, created, **kwargs): + if not created: + return + User = get_user_model() + for user in instance.child.all_members(): + provision_user(User, user) + +def on_delete_role_parenting(sender, instance, **kwargs): + User = get_user_model() + for user in instance.child.all_members(): + provision_user(User, user) + class Authentic2AgentConfig(AppConfig): name = 'hobo.agent.authentic2' @@ -206,12 +219,15 @@ class Authentic2AgentConfig(AppConfig): def ready(self): Role = get_role_model() + RoleParenting = get_role_parenting_model() post_save.connect(notify_roles, sender=Role) post_delete.connect(notify_roles, sender=Role) post_save.connect(notify_roles, Role) post_delete.connect(notify_roles, Role) post_save.connect(notify_roles, Role.members.through) post_delete.connect(notify_roles, Role.members.through) + post_save.connect(on_save_role_parenting, sender=RoleParenting) + post_delete.connect(on_delete_role_parenting, sender=RoleParenting) User = get_user_model() post_save.connect(provision_user) post_delete.connect(deprovision_user) diff --git a/tests_authentic/test_provisionning.py b/tests_authentic/test_provisionning.py index 422e69d..c48f37f 100644 --- a/tests_authentic/test_provisionning.py +++ b/tests_authentic/test_provisionning.py @@ -13,7 +13,6 @@ from authentic2.models import Attribute, AttributeValue pytestmark = pytest.mark.django_db - def test_provision_role(tenant): with patch('hobo.agent.authentic2.apps.notify_agents') as notify_agents: with tenant_context(tenant): @@ -58,6 +57,7 @@ def test_provision_user(tenant): service = LibertyProvider.objects.create(ou=get_default_ou(), name='provider', entity_id='http://provider.com', protocol_conformance=lasso.PROTOCOL_SAML_2_0) + parent = Role.objects.create(name='parent', service=service, ou=get_default_ou()) role = Role.objects.create(name='coin', service=service, ou=get_default_ou()) role.attributes.create(kind='string', name='is_superuser', value='true') notify_agents.reset_mock() @@ -208,6 +208,49 @@ def test_provision_user(tenant): assert o['is_superuser'] is True notify_agents.reset_mock() + role.add_parent(parent) + + assert notify_agents.call_count == 1 + arg = notify_agents.call_args + assert arg == call(ANY) + arg = arg[0][0] + assert isinstance(arg, dict) + assert set(arg.keys()) == set([ + 'issuer', 'audience', '@type', 'objects', 'full']) + assert arg['issuer'] == \ + 'http://%s/idp/saml2/metadata' % tenant.domain_url + assert arg['audience'] == ['http://provider.com'] + assert arg['@type'] == 'provision' + assert arg['full'] is False + objects = arg['objects'] + assert isinstance(objects, dict) + assert set(objects.keys()) == set(['data', '@type']) + assert objects['@type'] == 'user' + data = objects['data'] + assert isinstance(data, list) + assert len(data) == 1 + order_by_uuid = lambda l: sorted(l, key=lambda x: x['uuid']) + for o in data: + assert set(o.keys()) == set(['uuid', 'username', 'first_name', + 'is_superuser', 'last_name', 'email', 'roles']) + assert o['uuid'] == user.uuid + assert o['username'] == user.username + assert o['first_name'] == user.first_name + assert o['last_name'] == user.last_name + assert o['email'] == user.email + assert order_by_uuid(o['roles']) == order_by_uuid([{ + 'uuid': role.uuid, + 'name': role.name, + 'slug': role.slug + }, + { + 'uuid': parent.uuid, + 'name': parent.name, + 'slug': parent.slug + }]) + assert o['is_superuser'] is True + + notify_agents.reset_mock() user.roles.remove(role) assert notify_agents.call_count == 1 -- 2.1.4