From 3f991fa21978adc3d534fd9f3445fe4d6a336689 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 25 Aug 2022 15:49:58 +0200 Subject: [PATCH 3/3] auth_oidc: improve claims string representation (#66419) --- src/authentic2_auth_oidc/forms.py | 32 +++++++++++++++++----------- src/authentic2_auth_oidc/models.py | 7 +++++- tests/test_manager_authenticators.py | 8 +++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/authentic2_auth_oidc/forms.py b/src/authentic2_auth_oidc/forms.py index 3231b90e..1f47409d 100644 --- a/src/authentic2_auth_oidc/forms.py +++ b/src/authentic2_auth_oidc/forms.py @@ -14,9 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from collections import OrderedDict - from django import forms +from django.utils.text import capfirst from django.utils.translation import ugettext as _ from authentic2.custom_user.models import User @@ -37,6 +36,23 @@ class OIDCProviderEditForm(forms.ModelForm): self.fields['ou'].empty_label = None +class SelectAttributeWidget(forms.Select): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.choices = [('', '---------')] + list(self.get_options().items()) + + @staticmethod + def get_options(): + choices = {} + for name in ('email', 'username', 'first_name', 'last_name'): + field = User._meta.get_field(name) + choices[name] = '%s (%s)' % (capfirst(field.verbose_name), name) + for attribute in Attribute.objects.exclude(name__in=choices): + choices[attribute.name] = '%s (%s)' % (attribute.label, attribute.name) + choices['ou__slug'] = _('Organizational unit slug (ou__slug)') + return choices + + class OIDCClaimMappingForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -67,17 +83,7 @@ class OIDCClaimMappingForm(forms.ModelForm): claim_widget.name = 'list__oidcclaim-mapping-inline' claim_widget.attrs.update({'list': 'list__oidcclaim-mapping-inline'}) - # Setup the attribute field - choices = OrderedDict([('', '---------')]) - for name in ('email', 'username', 'first_name', 'last_name'): - field = User._meta.get_field(name) - choices[name] = '%s (%s)' % (field.verbose_name.title(), name) - for attribute in Attribute.objects.all(): - if attribute.name in choices: - continue - choices[attribute.name] = '%s (%s)' % (attribute.label, attribute.name) - choices['ou__slug'] = _('Organizational unit slug (ou__slug)') - self.fields['attribute'] = forms.ChoiceField(choices=choices.items()) + self.fields['attribute'].widget = SelectAttributeWidget() class Meta: model = OIDCClaimMapping diff --git a/src/authentic2_auth_oidc/models.py b/src/authentic2_auth_oidc/models.py index d5aeafa1..17684758 100644 --- a/src/authentic2_auth_oidc/models.py +++ b/src/authentic2_auth_oidc/models.py @@ -243,8 +243,13 @@ class OIDCClaimMapping(models.Model): def natural_key(self): return (self.claim, self.attribute, self.verified, self.required) + def get_attribute_display(self): + from .forms import SelectAttributeWidget + + return SelectAttributeWidget.get_options().get(self.attribute, self.attribute) + def __str__(self): - s = f'{self.claim} -> {self.attribute}' + s = '%s → %s' % (self.claim, self.get_attribute_display()) if self.verified: s += ', verified' if self.required: diff --git a/tests/test_manager_authenticators.py b/tests/test_manager_authenticators.py index 43f8c8fa..89ba2b1a 100644 --- a/tests/test_manager_authenticators.py +++ b/tests/test_manager_authenticators.py @@ -199,7 +199,7 @@ def test_authenticators_oidc_claims(app, superuser): resp = resp.click('Add') resp.form['claim'] = 'email' - resp.form['attribute'].select(text='Email Address (email)') + resp.form['attribute'].select(text='Email address (email)') resp.form['verified'].select(text='verified claim') resp.form['required'] = True resp.form['idtoken_claim'] = True @@ -208,12 +208,12 @@ def test_authenticators_oidc_claims(app, superuser): assert '#open:claims' in resp.location resp = resp.follow() - assert escape('email -> email, verified, required, idtoken') in resp.text + assert 'email → Email address (email), verified, required, idtoken' in resp.text resp = resp.click('email') - resp.form['attribute'].select(text='First Name (first_name)') + resp.form['attribute'].select(text='First name (first_name)') resp = resp.form.submit().follow() - assert escape('email -> first_name, verified, required, idtoken') in resp.text + assert 'email → First name (first_name), verified, required, idtoken' in resp.text assert_event('authenticator.oidc.claim.edit', user=superuser, session=app.session) resp = resp.click('Remove') -- 2.30.2