Projet

Général

Profil

0001-auth_saml-remove-rename-attribute-action-68383.patch

Valentin Deniaud, 24 août 2022 17:41

Télécharger (14,2 ko)

Voir les différences:

Subject: [PATCH] auth_saml: remove rename attribute action (#68383)

 src/authentic2_auth_saml/adapters.py          |  6 ---
 .../0010_statically_rename_attributes.py      | 33 ++++++++++++
 .../0011_delete_renameattributeaction.py      | 16 ++++++
 src/authentic2_auth_saml/models.py            | 12 -----
 src/authentic2_auth_saml/views.py             | 10 +---
 tests/test_auth_saml.py                       | 54 +++++++++++++++----
 tests/test_manager_authenticators.py          | 11 ----
 tests/test_manager_journal.py                 | 12 ++---
 8 files changed, 102 insertions(+), 52 deletions(-)
 create mode 100644 src/authentic2_auth_saml/migrations/0010_statically_rename_attributes.py
 create mode 100644 src/authentic2_auth_saml/migrations/0011_delete_renameattributeaction.py
src/authentic2_auth_saml/adapters.py
111 111
    def provision_a2_attributes(self, user, idp, saml_attributes):
112 112
        saml_attributes = saml_attributes.copy()
113 113

  
114
        self.rename_attributes(idp, saml_attributes)
115 114
        self.set_attributes(user, idp, saml_attributes)
116 115
        self.action_add_role(user, idp, saml_attributes)
117 116

  
118
    def rename_attributes(self, idp, saml_attributes):
119
        for action in idp['authenticator'].rename_attribute_actions.all():
120
            if action.from_name in saml_attributes:
121
                saml_attributes[action.to_name] = saml_attributes[action.from_name]
122

  
123 117
    def set_attributes(self, user, idp, saml_attributes):
124 118
        user_modified = False
125 119
        for action in idp['authenticator'].set_attribute_actions.all():
src/authentic2_auth_saml/migrations/0010_statically_rename_attributes.py
1
# Generated by Django 2.2.26 on 2022-08-24 14:55
2

  
3
import logging
4

  
5
from django.db import migrations
6

  
7
logger = logging.getLogger('authentic2.auth_saml')
8

  
9

  
10
def rename_attributes(apps, schema_editor):
11
    SAMLAuthenticator = apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
12

  
13
    for authenticator in SAMLAuthenticator.objects.all():
14
        rename_map = {x.to_name: x.from_name for x in authenticator.rename_attribute_actions.all()}
15

  
16
        for action in authenticator.set_attribute_actions.all():
17
            action.saml_attribute = rename_map.get(action.saml_attribute, action.saml_attribute)
18
            action.save()
19

  
20
        for lookup in authenticator.attribute_lookups.all():
21
            lookup.saml_attribute = rename_map.get(lookup.saml_attribute, lookup.saml_attribute)
22
            lookup.save()
23

  
24

  
25
class Migration(migrations.Migration):
26

  
27
    dependencies = [
28
        ('authentic2_auth_saml', '0009_rename_attribute_field'),
29
    ]
30

  
31
    operations = [
32
        migrations.RunPython(rename_attributes, reverse_code=migrations.RunPython.noop),
33
    ]
src/authentic2_auth_saml/migrations/0011_delete_renameattributeaction.py
1
# Generated by Django 2.2.26 on 2022-08-24 15:07
2

  
3
from django.db import migrations
4

  
5

  
6
class Migration(migrations.Migration):
7

  
8
    dependencies = [
9
        ('authentic2_auth_saml', '0010_statically_rename_attributes'),
10
    ]
11

  
12
    operations = [
13
        migrations.DeleteModel(
14
            name='RenameAttributeAction',
15
        ),
16
    ]
src/authentic2_auth_saml/models.py
221 221
        return SelectAttributeWidget.get_options().get(self.user_field, self.user_field)
222 222

  
223 223

  
224
class RenameAttributeAction(SAMLRelatedObjectBase):
225
    from_name = models.CharField(_('From'), max_length=1024)
226
    to_name = models.CharField(_('To'), max_length=64)
227

  
228
    class Meta:
229
        default_related_name = 'rename_attribute_actions'
230
        verbose_name = _('Rename an attribute')
231

  
232
    def __str__(self):
233
        return '%s → %s' % (self.from_name, self.to_name)
234

  
235

  
236 224
class SAMLAttributeLookup(SAMLRelatedObjectBase):
237 225
    user_field = models.CharField(_('User field'), max_length=256)
238 226
    saml_attribute = models.CharField(_('SAML attribute'), max_length=1024)
src/authentic2_auth_saml/views.py
11 11
from authentic2.utils.misc import redirect_to_login
12 12

  
13 13
from .forms import RoleChoiceField, SelectAttributeWidget
14
from .models import (
15
    AddRoleAction,
16
    RenameAttributeAction,
17
    SAMLAttributeLookup,
18
    SAMLAuthenticator,
19
    SetAttributeAction,
20
)
14
from .models import AddRoleAction, SAMLAttributeLookup, SAMLAuthenticator, SetAttributeAction
21 15

  
22 16

  
23 17
def login(request, authenticator, *args, **kwargs):
......
52 46

  
53 47

  
54 48
class SAMLAuthenticatorMixin(MediaMixin, TitleMixin):
55
    allowed_models = (SAMLAttributeLookup, RenameAttributeAction, SetAttributeAction, AddRoleAction)
49
    allowed_models = (SAMLAttributeLookup, SetAttributeAction, AddRoleAction)
56 50

  
57 51
    def dispatch(self, request, *args, **kwargs):
58 52
        self.authenticator = get_object_or_404(SAMLAuthenticator, pk=kwargs.get('authenticator_pk'))
tests/test_auth_saml.py
30 30
from authentic2_auth_saml.adapters import AuthenticAdapter, MappingError
31 31
from authentic2_auth_saml.models import (
32 32
    AddRoleAction,
33
    RenameAttributeAction,
34 33
    SAMLAttributeLookup,
35 34
    SAMLAuthenticator,
36 35
    SetAttributeAction,
......
101 100
        user_field='first_name',
102 101
        saml_attribute='first_name',
103 102
    )
104
    RenameAttributeAction.objects.create(
105
        authenticator=authenticator,
106
        from_name='http://nice/attribute/givenName',
107
        to_name='first_name',
108
    )
109 103
    return authenticator.settings
110 104

  
111 105

  
......
122 116
        'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
123 117
        'mail': ['john.doe@example.com'],
124 118
        'title': ['Mr.'],
125
        'http://nice/attribute/givenName': ['John'],
119
        'first_name': ['John'],
126 120
    }
127 121

  
128 122

  
......
155 149
    caplog, adapter, idp, saml_attributes, title_attribute, user
156 150
):
157 151
    caplog.set_level('WARNING')
158
    saml_attributes['http://nice/attribute/givenName'] = []
152
    saml_attributes['first_name'] = []
159 153
    adapter.provision_a2_attributes(user, idp, saml_attributes)
160 154
    assert re.match('.*no value.*first_name', caplog.records[-1].message)
161 155

  
......
163 157
def test_apply_attribute_mapping_missing_attribute_exception(
164 158
    adapter, idp, saml_attributes, title_attribute, user, rf
165 159
):
166
    saml_attributes['http://nice/attribute/givenName'] = []
160
    saml_attributes['first_name'] = []
167 161
    SetAttributeAction.objects.filter(user_field='first_name').update(mandatory=True)
168 162
    with pytest.raises(MappingError, match='no value'):
169 163
        adapter.provision_a2_attributes(user, idp, saml_attributes)
......
679 673
        'lookup by attributes for SAMLAuthenticator object (%s): [{"user_field": "email", "saml_attribute": "email"}]'
680 674
        % authenticator.pk,
681 675
    ]
676

  
677

  
678
def test_saml_authenticator_data_migration_rename_attributes(migration, settings):
679
    migrate_from = [('authentic2_auth_saml', '0009_rename_attribute_field')]
680
    migrate_to = [('authentic2_auth_saml', '0010_statically_rename_attributes')]
681

  
682
    old_apps = migration.before(migrate_from)
683
    SAMLAuthenticator = old_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
684
    RenameAttributeAction = old_apps.get_model('authentic2_auth_saml', 'RenameAttributeAction')
685
    SetAttributeAction = old_apps.get_model('authentic2_auth_saml', 'SetAttributeAction')
686
    SAMLAttributeLookup = old_apps.get_model('authentic2_auth_saml', 'SAMLAttributeLookup')
687

  
688
    authenticator = SAMLAuthenticator.objects.create(slug='idp1')
689
    RenameAttributeAction.objects.create(
690
        authenticator=authenticator, from_name='http://nice/attribute/givenName', to_name='first_name'
691
    )
692
    SAMLAttributeLookup.objects.create(
693
        authenticator=authenticator, user_field='first_name', saml_attribute='first_name'
694
    )
695
    SAMLAttributeLookup.objects.create(
696
        authenticator=authenticator, user_field='title', saml_attribute='title'
697
    )
698
    SetAttributeAction.objects.create(
699
        authenticator=authenticator, user_field='first_name', saml_attribute='first_name'
700
    )
701
    SetAttributeAction.objects.create(authenticator=authenticator, user_field='title', saml_attribute='title')
702

  
703
    new_apps = migration.apply(migrate_to)
704
    SAMLAuthenticator = new_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
705
    authenticator = SAMLAuthenticator.objects.get()
706

  
707
    attribute_lookup1, attribute_lookup2 = authenticator.attribute_lookups.all().order_by('pk')
708
    assert attribute_lookup1.saml_attribute == 'http://nice/attribute/givenName'
709
    assert attribute_lookup1.user_field == 'first_name'
710
    assert attribute_lookup2.saml_attribute == 'title'
711
    assert attribute_lookup2.user_field == 'title'
712

  
713
    set_attribute1, set_attribute2 = authenticator.set_attribute_actions.all().order_by('pk')
714
    assert set_attribute1.saml_attribute == 'http://nice/attribute/givenName'
715
    assert set_attribute1.user_field == 'first_name'
716
    assert set_attribute2.saml_attribute == 'title'
717
    assert set_attribute2.user_field == 'title'
tests/test_manager_authenticators.py
323 323
    assert_event('authenticator.saml.related_object.deletion', user=superuser, session=app.session)
324 324

  
325 325

  
326
def test_authenticators_saml_rename_attribute(app, superuser):
327
    authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
328
    resp = login(app, superuser, path=authenticator.get_absolute_url())
329

  
330
    resp = resp.click('Add', href='renameattributeaction')
331
    resp.form['from_name'] = 'a'
332
    resp.form['to_name'] = 'b'
333
    resp = resp.form.submit().follow()
334
    assert 'a → b' in resp.text
335

  
336

  
337 326
def test_authenticators_saml_set_attribute(app, superuser):
338 327
    authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
339 328
    resp = login(app, superuser, path=authenticator.get_absolute_url())
tests/test_manager_journal.py
28 28
from authentic2.custom_user.models import Profile, ProfileType, User
29 29
from authentic2.journal import journal
30 30
from authentic2.models import Service
31
from authentic2_auth_saml.models import RenameAttributeAction, SAMLAuthenticator
31
from authentic2_auth_saml.models import SAMLAuthenticator, SetAttributeAction
32 32

  
33 33
from .utils import login, logout, text_content
34 34

  
......
60 60
    service = Service.objects.create(name="service")
61 61
    authenticator = LoginPasswordAuthenticator.objects.create(slug='test')
62 62
    saml_authenticator = SAMLAuthenticator.objects.create(slug='saml')
63
    rename_attribute_action = RenameAttributeAction.objects.create(authenticator=saml_authenticator)
63
    rename_attribute_action = SetAttributeAction.objects.create(authenticator=saml_authenticator)
64 64

  
65 65
    class EventFactory:
66 66
        date = make_aware(datetime.datetime(2020, 1, 1))
......
358 358

  
359 359
def test_global_journal(app, superuser, events):
360 360
    response = login(app, user=superuser, path="/manage/")
361
    rename_attribute_action = RenameAttributeAction.objects.get()
361
    rename_attribute_action = SetAttributeAction.objects.get()
362 362

  
363 363
    # remove event about admin login
364 364
    Event.objects.filter(user=superuser).delete()
......
715 715
            'user': 'agent',
716 716
        },
717 717
        {
718
            'message': 'creation of RenameAttributeAction (%s) in authenticator "SAML"'
718
            'message': 'creation of SetAttributeAction (%s) in authenticator "SAML"'
719 719
            % rename_attribute_action.pk,
720 720
            'timestamp': 'Jan. 3, 2020, 8 a.m.',
721 721
            'type': 'authenticator.saml.related_object.creation',
722 722
            'user': 'agent',
723 723
        },
724 724
        {
725
            'message': 'edit RenameAttributeAction (%s) in authenticator "SAML" (from_name)'
725
            'message': 'edit SetAttributeAction (%s) in authenticator "SAML" (from_name)'
726 726
            % rename_attribute_action.pk,
727 727
            'timestamp': 'Jan. 3, 2020, 9 a.m.',
728 728
            'type': 'authenticator.saml.related_object.edit',
729 729
            'user': 'agent',
730 730
        },
731 731
        {
732
            'message': 'deletion of RenameAttributeAction (%s) in authenticator "SAML"'
732
            'message': 'deletion of SetAttributeAction (%s) in authenticator "SAML"'
733 733
            % rename_attribute_action.pk,
734 734
            'timestamp': 'Jan. 3, 2020, 10 a.m.',
735 735
            'type': 'authenticator.saml.related_object.deletion',
736
-