Projet

Général

Profil

0001-auth_saml-prefer-metadata-file-upload-over-metadata-.patch

Valentin Deniaud, 24 août 2022 15:47

Télécharger (7,38 ko)

Voir les différences:

Subject: [PATCH] auth_saml: prefer metadata file upload over metadata path
 (#67451)

 src/authentic2/apps/authenticators/models.py   | 16 +++++++++++-----
 src/authentic2_auth_saml/forms.py              |  5 +++++
 .../0008_samlauthenticator_metadata_file.py    | 18 ++++++++++++++++++
 src/authentic2_auth_saml/models.py             |  7 ++++++-
 tests/test_manager_authenticators.py           | 16 +++++++++++++---
 5 files changed, 53 insertions(+), 9 deletions(-)
 create mode 100644 src/authentic2_auth_saml/migrations/0008_samlauthenticator_metadata_file.py
src/authentic2/apps/authenticators/models.py
20 20

  
21 21
from django.core.exceptions import ValidationError
22 22
from django.db import models
23
from django.db.models.fields.files import FieldFile
23 24
from django.shortcuts import render, reverse
24 25
from django.utils.formats import date_format
26
from django.utils.html import format_html
27
from django.utils.safestring import mark_safe
25 28
from django.utils.text import capfirst
26 29
from django.utils.translation import pgettext_lazy
27 30
from django.utils.translation import ugettext_lazy as _
......
111 114

  
112 115
            if isinstance(value, datetime.datetime):
113 116
                value = date_format(value, 'DATETIME_FORMAT')
114

  
115
            yield _('%(field)s: %(value)s') % {
116
                'field': capfirst(self._meta.get_field(field).verbose_name),
117
                'value': value,
118
            }
117
            elif isinstance(value, FieldFile):
118
                value = mark_safe(f'<a href={value.url}>{value.name}</a>')
119

  
120
            yield format_html(
121
                _('{field}: {value}'),
122
                field=capfirst(self._meta.get_field(field).verbose_name),
123
                value=value,
124
            )
119 125

  
120 126
    def shown(self, ctx=()):
121 127
        if not self.show_condition:
src/authentic2_auth_saml/forms.py
27 27
        model = SAMLAuthenticator
28 28
        exclude = ('ou',)
29 29

  
30
    def __init__(self, *args, **kwargs):
31
        super().__init__(*args, **kwargs)
32
        if not self.initial.get('metadata_path'):
33
            del self.fields['metadata_path']
34

  
30 35

  
31 36
class RoleChoiceField(forms.ModelChoiceField):
32 37
    def __init__(self, *args, **kwargs):
src/authentic2_auth_saml/migrations/0008_samlauthenticator_metadata_file.py
1
# Generated by Django 2.2.26 on 2022-08-24 13:12
2

  
3
from django.db import migrations, models
4

  
5

  
6
class Migration(migrations.Migration):
7

  
8
    dependencies = [
9
        ('authentic2_auth_saml', '0007_remove_jsonfields'),
10
    ]
11

  
12
    operations = [
13
        migrations.AddField(
14
            model_name='samlauthenticator',
15
            name='metadata_file',
16
            field=models.FileField(blank=True, null=True, upload_to=''),
17
        ),
18
    ]
src/authentic2_auth_saml/models.py
30 30
    metadata_cache_time = models.PositiveSmallIntegerField(_('Metadata cache time'), default=3600)
31 31
    metadata_http_timeout = models.PositiveSmallIntegerField(_('Metadata HTTP timeout'), default=10)
32 32

  
33
    metadata_file = models.FileField(null=True, blank=True)
33 34
    metadata_path = models.CharField(
34 35
        _('Metadata file path'),
35 36
        max_length=300,
......
147 148
    description_fields = [
148 149
        'show_condition',
149 150
        'metadata_url',
151
        'metadata_file',
150 152
        'metadata_path',
151 153
        'metadata',
152 154
        'provision',
......
166 168
            if not settings[setting]:
167 169
                del settings[setting]
168 170

  
171
        if self.metadata_file:
172
            settings['METADATA_PATH'] = self.metadata_file.path
173

  
169 174
        settings['LOOKUP_BY_ATTRIBUTES'] = [lookup.as_dict() for lookup in self.attribute_lookups.all()]
170 175

  
171 176
        settings['authenticator'] = self
......
178 183
        return SAMLAuthenticatorForm
179 184

  
180 185
    def clean(self):
181
        if not (self.metadata or self.metadata_path or self.metadata_url):
186
        if not (self.metadata or self.metadata_path or self.metadata_url or self.metadata_file):
182 187
            raise ValidationError(_('One of the metadata fields must be filled.'))
183 188

  
184 189
    def autorun(self, request, block_id):
tests/test_manager_authenticators.py
17 17
import pytest
18 18
from django import VERSION as DJ_VERSION
19 19
from django.utils.html import escape
20
from webtest import Upload
20 21

  
21 22
from authentic2.a2_rbac.utils import get_default_ou
22 23
from authentic2.apps.authenticators.models import BaseAuthenticator, LoginPasswordAuthenticator
......
256 257
    resp = app.get(authenticator.get_absolute_url())
257 258
    assert 'Username template: {attributes[name_id_content]}@{realm}' in resp.text
258 259
    assert 'Provision: True' in resp.text
259
    assert 'Metadata file path' not in resp.text
260
    assert 'Metadata file' not in resp.text
260 261

  
261 262
    assert 'Enable' not in resp.text
262 263
    assert 'configuration is not complete' in resp.text
263 264

  
264 265
    resp = resp.click('Edit')
266
    assert 'metadata_path' not in resp.form.fields
267

  
265 268
    resp = resp.form.submit()
266 269
    assert 'One of the metadata fields must be filled.' in resp.text
267 270

  
268
    resp.form['metadata_path'] = '/var/lib/authentic2/metadata.xml'
271
    resp.form['metadata_file'] = Upload('metadata.xml', b'<xml>some-xml</xml>', 'text/xml')
269 272
    resp.form['attribute_mapping'] = '[{"attribute": "email", "saml_attribute": "mail", "mandatory": false}]'
270 273
    resp = resp.form.submit().follow()
271 274

  
272
    assert 'Metadata file path: /var/lib/authentic2/metadata.xml' in resp.text
275
    assert 'Metadata file: <a href=/media/metadata.xml>metadata.xml</a>' in resp.text
273 276

  
274 277
    authenticator.refresh_from_db()
275 278
    assert authenticator.attribute_mapping == [
......
279 282
    resp = resp.click('Enable').follow()
280 283
    assert 'Authenticator has been enabled.' in resp.text
281 284

  
285
    authenticator.metadata_file = None
286
    authenticator.metadata_path = '/var/lib/authentic2/metadata.xml'
287
    authenticator.save()
288

  
289
    resp = resp.click('Edit')
290
    assert 'metadata_path' in resp.form.fields
291

  
282 292

  
283 293
def test_authenticators_saml_attribute_lookup(app, superuser):
284 294
    authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
285
-