From 3912f2648c98bafd493cd788b2cf3f57b3f37a4d Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Mon, 23 May 2022 15:06:23 +0200 Subject: [PATCH] authentic2_auth_oidc: attach claims and accounts to new authenticator (#65504) --- ...0009_oidcprovider_baseauthenticator_ptr.py | 10 ++++++ .../migrations/0010_auto_20220413_1622.py | 15 ++++++++ .../migrations/0012_auto_20220524_1147.py | 34 +++++++++++++++++++ tests/test_auth_oidc.py | 33 +++++++++++++++--- 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 src/authentic2_auth_oidc/migrations/0012_auto_20220524_1147.py diff --git a/src/authentic2_auth_oidc/migrations/0009_oidcprovider_baseauthenticator_ptr.py b/src/authentic2_auth_oidc/migrations/0009_oidcprovider_baseauthenticator_ptr.py index 1773f589f..cb1360319 100644 --- a/src/authentic2_auth_oidc/migrations/0009_oidcprovider_baseauthenticator_ptr.py +++ b/src/authentic2_auth_oidc/migrations/0009_oidcprovider_baseauthenticator_ptr.py @@ -16,4 +16,14 @@ class Migration(migrations.Migration): field=models.IntegerField(default=0), preserve_default=False, ), + migrations.AlterField( + model_name='oidcaccount', + name='provider', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='oidcclaimmapping', + name='provider', + field=models.IntegerField(), + ), ] diff --git a/src/authentic2_auth_oidc/migrations/0010_auto_20220413_1622.py b/src/authentic2_auth_oidc/migrations/0010_auto_20220413_1622.py index 9e382d49a..1a72f60e2 100644 --- a/src/authentic2_auth_oidc/migrations/0010_auto_20220413_1622.py +++ b/src/authentic2_auth_oidc/migrations/0010_auto_20220413_1622.py @@ -14,7 +14,10 @@ def add_base_authenticators(apps, schema_editor): BaseAuthenticator = apps.get_model('authenticators', 'BaseAuthenticator') OIDCProvider = apps.get_model('authentic2_auth_oidc', 'OIDCProvider') + OIDCClaimMapping = apps.get_model('authentic2_auth_oidc', 'OIDCClaimMapping') + OIDCAccount = apps.get_model('authentic2_auth_oidc', 'OIDCAccount') + remap_provider_ids = [] for provider in OIDCProvider.objects.all(): if isinstance(show_condition, dict): show_condition_authenticator = show_condition.get(provider.slug) or '' @@ -32,6 +35,18 @@ def add_base_authenticators(apps, schema_editor): provider.baseauthenticator_ptr = base_authenticator.pk provider.save() + remap_provider_ids.append( + ( + list(OIDCClaimMapping.objects.filter(provider=provider.pk).values_list('pk', flat=True)), + list(OIDCAccount.objects.filter(provider=provider.pk).values_list('pk', flat=True)), + base_authenticator.pk, + ) + ) + + for mapping_ids, account_ids, to_provider_id in remap_provider_ids: + OIDCClaimMapping.objects.filter(id__in=mapping_ids).update(provider=to_provider_id) + OIDCAccount.objects.filter(id__in=account_ids).update(provider=to_provider_id) + class Migration(migrations.Migration): diff --git a/src/authentic2_auth_oidc/migrations/0012_auto_20220524_1147.py b/src/authentic2_auth_oidc/migrations/0012_auto_20220524_1147.py new file mode 100644 index 000000000..2245277c8 --- /dev/null +++ b/src/authentic2_auth_oidc/migrations/0012_auto_20220524_1147.py @@ -0,0 +1,34 @@ +# Generated by Django 2.2.28 on 2022-05-24 09:47 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentic2_auth_oidc', '0011_auto_20220413_1632'), + ] + + operations = [ + migrations.AlterField( + model_name='oidcaccount', + name='provider', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='accounts', + to='authentic2_auth_oidc.OIDCProvider', + verbose_name='provider', + ), + ), + migrations.AlterField( + model_name='oidcclaimmapping', + name='provider', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='claim_mappings', + to='authentic2_auth_oidc.OIDCProvider', + verbose_name='provider', + ), + ), + ] diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index 44ed7f331..a6e8e4085 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -1083,14 +1083,17 @@ def test_oidc_provider_authenticator_data_migration(auth_frontend_kwargs, migrat app = 'authentic2_auth_oidc' migrate_from = [(app, '0008_auto_20201102_1142')] - migrate_to = [(app, '0011_auto_20220413_1632')] + migrate_to = [(app, '0012_auto_20220524_1147')] old_apps = migration.before(migrate_from) OIDCProvider = old_apps.get_model(app, 'OIDCProvider') + OIDCClaimMapping = old_apps.get_model(app, 'OIDCClaimMapping') + OIDCAccount = old_apps.get_model(app, 'OIDCAccount') OrganizationalUnit = old_apps.get_model('a2_rbac', 'OrganizationalUnit') + User = old_apps.get_model('custom_user', 'User') ou1 = OrganizationalUnit.objects.create(name='OU1', slug='ou1') issuer = 'https://baz.example.com' - OIDCProvider.objects.create( + first_provider = OIDCProvider.objects.create( name='Baz', slug='baz', ou=ou1, @@ -1102,19 +1105,39 @@ def test_oidc_provider_authenticator_data_migration(auth_frontend_kwargs, migrat userinfo_endpoint='%s/user_info' % issuer, token_revocation_endpoint='%s/revoke' % issuer, ) + second_provider = OIDCProvider.objects.create(name='Second', slug='second', ou=ou1) + second_provider_claim_mapping = OIDCClaimMapping.objects.create( + provider=second_provider, claim='second_provider', attribute='username' + ) + user1 = User.objects.create() + second_provider_account = OIDCAccount.objects.create( + user=user1, provider=second_provider, sub='second_provider' + ) + first_provider_claim_mapping = OIDCClaimMapping.objects.create( + provider=first_provider, claim='first_provider', attribute='username' + ) new_apps = migration.apply(migrate_to) OIDCProvider = new_apps.get_model(app, 'OIDCProvider') BaseAuthenticator = new_apps.get_model('authenticators', 'BaseAuthenticator') - authenticator = OIDCProvider.objects.get() + authenticator = OIDCProvider.objects.get(slug='baz') assert authenticator.name == 'Baz' - assert authenticator.slug == 'baz' assert authenticator.ou.pk == ou1.pk assert authenticator.enabled is True assert authenticator.order == auth_frontend_kwargs['oidc'].get('priority', 2) assert authenticator.show_condition == '"backoffice" not in login_hint' assert authenticator.authorization_endpoint == '%s/authorize' % issuer + assert authenticator.claim_mappings.count() == 1 + assert authenticator.claim_mappings.get().pk == first_provider_claim_mapping.pk + assert not authenticator.accounts.exists() - base_authenticator = BaseAuthenticator.objects.get() + base_authenticator = BaseAuthenticator.objects.get(slug='baz') assert authenticator.uuid == base_authenticator.uuid + + second_authenticator = OIDCProvider.objects.get(slug='second') + assert second_authenticator.name == 'Second' + assert second_authenticator.claim_mappings.count() == 1 + assert second_authenticator.claim_mappings.get().pk == second_provider_claim_mapping.pk + assert second_authenticator.accounts.count() == 1 + assert second_authenticator.accounts.get().pk == second_provider_account.pk -- 2.30.2