Projet

Général

Profil

0001-misc-unserialize-attribute-in-registration-view-4571.patch

Benjamin Dauvergne, 13 août 2020 17:33

Télécharger (8,67 ko)

Voir les différences:

Subject: [PATCH] misc: unserialize attribute in registration view (#45710)

Registration view pass attribute values in JSON tokens, so we need to
get a JSON compatible serialization of attribute values for the token
using their serialization function.
 src/authentic2/attribute_kinds.py    |  8 +++--
 src/authentic2/custom_user/models.py |  6 ++++
 src/authentic2/views.py              | 17 ++++++----
 tests/test_registration.py           | 46 +++++++++++++++++++++++-----
 4 files changed, 61 insertions(+), 16 deletions(-)
src/authentic2/attribute_kinds.py
355 355
    return defn['field_class'](**kwargs)
356 356

  
357 357

  
358
def identity(x):
359
    return x
360

  
361

  
358 362
def get_kind(kind):
359 363
    d = get_attribute_kinds()[kind]
360 364
    d.setdefault('default', None)
361
    d.setdefault('serialize', lambda x: x)
362
    d.setdefault('deserialize', lambda x: x)
365
    d.setdefault('serialize', identity)
366
    d.setdefault('deserialize', identity)
363 367
    rest_field_kwargs = d.setdefault('rest_framework_field_kwargs', {})
364 368
    if 'rest_framework_field_class' not in d:
365 369
        d['rest_framework_field_class'] = serializers.CharField
src/authentic2/custom_user/models.py
53 53
    return mapping
54 54

  
55 55

  
56
def iter_attributes():
57
    for key, value in get_attributes_map().items():
58
        if isinstance(key, str):
59
            yield value
60

  
61

  
56 62
class Attributes(object):
57 63
    def __init__(self, owner, verified=None):
58 64
        self.__dict__['owner'] = owner
src/authentic2/views.py
17 17
import collections
18 18
from email.utils import parseaddr
19 19
import logging
20
import random
21 20
import re
22 21

  
23 22
from ratelimit.utils import is_ratelimited
......
28 27
from django.views.generic.edit import UpdateView, FormView
29 28
from django.views.generic import TemplateView
30 29
from django.views.generic.base import View
31
from django.contrib.auth import SESSION_KEY
32
from django import http, shortcuts
30
from django import shortcuts
33 31
from django.core import signing
34 32
from django.core.exceptions import ValidationError
35 33
from django.contrib import messages
......
42 40
from django.http import (HttpResponseRedirect, HttpResponseForbidden, HttpResponse)
43 41
from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
44 42
from django.views.decorators.cache import never_cache
45
from django.views.decorators.debug import sensitive_post_parameters
46 43
from django.contrib.auth.decorators import login_required
47 44
from django.db.models.fields import FieldDoesNotExist
48 45
from django.db.models.query import Q
......
54 51
from django.http import HttpResponseBadRequest
55 52
from django.template import loader
56 53

  
54
from authentic2.custom_user.models import iter_attributes
57 55
from authentic2.compat.misc import default_token_generator
58 56
from . import (utils, app_settings, decorators, constants,
59
               models, cbv, hooks, validators)
57
               models, cbv, hooks, validators, attribute_kinds)
60 58
from .utils import switch_user
61 59
from .a2_rbac.utils import get_default_ou
62 60
from .a2_rbac.models import OrganizationalUnit as OU
......
1082 1080
                and ('email' not in self.token or self.request.POST['email'] != self.token['email'])
1083 1081
                and not self.token.get('skip_email_check')):
1084 1082
            # If an email is submitted it must be validated or be the same as in the token
1085
            data = form.cleaned_data
1083
            data = form.cleaned_data.copy()
1084
            # handle complex attributes
1085
            for attribute in iter_attributes():
1086
                kind = attribute.get_kind()
1087
                if kind['serialize'] == attribute_kinds.identity:
1088
                    continue
1089
                data[attribute.name] = kind['serialize'](data[attribute.name])
1090

  
1086 1091
            data['no_password'] = self.token.get('no_password', False)
1087 1092
            utils.send_registration_mail(
1088 1093
                self.request,
tests/test_registration.py
15 15
# You should have received a copy of the GNU Affero General Public License
16 16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 17

  
18
import re
19

  
20 18
from django.contrib.auth import get_user_model, REDIRECT_FIELD_NAME
21 19
from django.urls import reverse
22 20
from django.utils.http import urlquote
......
28 26
from .utils import get_link_from_mail
29 27

  
30 28

  
29
User = get_user_model()
30

  
31

  
31 32
def test_registration(app, db, settings, mailoutbox, external_redirect):
32 33
    next_url, good_next_url = external_redirect
33 34

  
......
37 38
    # disable existing attributes
38 39
    models.Attribute.objects.update(disabled=True)
39 40

  
40
    User = get_user_model()
41 41
    url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url})
42 42
    response = app.get(url)
43 43
    response.form.set('email', 'testbot@entrouvert.com')
......
109 109
    # disable existing attributes
110 110
    models.Attribute.objects.update(disabled=True)
111 111

  
112
    User = get_user_model()
113 112
    next_url = 'http://relying-party.org/'
114 113
    url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url})
115 114

  
......
494 493
    settings.A2_REGISTRATION_EMAIL_IS_UNIQUE = True
495 494

  
496 495
    # Create two user objects
497
    User = get_user_model()
498 496
    User.objects.create(email='testbot@entrouvert.com')
499 497
    User.objects.create(email='testbot@entrouvert.com')
500 498

  
......
518 516
    settings.A2_REQUIRED_FIELDS = ['username', 'first_name', 'last_name']
519 517

  
520 518
    # Create two user objects
521
    User = get_user_model()
522 519
    User.objects.create(username='testbot', email='testbot1@entrouvert.com')
523 520
    User.objects.create(username='testbot', email='testbot2@entrouvert.com')
524 521

  
......
550 547
    # disable existing attributes
551 548
    models.Attribute.objects.update(disabled=True)
552 549

  
553
    User = get_user_model()
554 550
    url = utils.make_url('registration_register', params={REDIRECT_FIELD_NAME: next_url})
555 551
    response = app.get(url)
556 552
    response.form.set('email', 'testbot@entrouvert.com')
......
674 670
    assert "email_domains_suggestions.js" in response.text
675 671
    assert "field-live-hint" in response.text
676 672

  
677

  
678 673
    settings.A2_SUGGESTED_EMAIL_DOMAINS = []
679 674
    response = app.get(url)
680 675
    assert "email_domains_suggestions.js" not in response.text
681 676
    assert "field-live-hint" not in response.text
677

  
678

  
679
def test_registration_no_email_full_profile_no_password(app, db, rf, mailoutbox):
680
    models.Attribute.objects.create(
681
        kind='birthdate',
682
        name='birthdate',
683
        label='birthdate',
684
        required=True)
685

  
686
    data = {
687
        'email': 'john.doe@example.com',
688
        'first_name': 'John',
689
        'last_name': 'Doe',
690
        'confirm_data': 'required',
691
        'no_password': True,
692
        'valid_email': False,
693
        'franceconnect': True,
694
        'authentication_method': 'france-connect',
695
    }
696

  
697
    activation_url = utils.build_activation_url(
698
        rf.post('/accounts/register/'),
699
        next_url='/',
700
        **data)
701

  
702
    response = app.get(activation_url)
703
    response.form.set('first_name', data['first_name'])
704
    response.form.set('last_name', data['last_name'])
705
    response.form.set('birthdate', '1981-01-01')
706
    response.form.set('email', 'john.doe2@example.com')
707
    response = response.form.submit().follow()
708
    link = get_link_from_mail(mailoutbox[0])
709
    response = app.get(link)
710
    assert response.location == '/'
711
    assert User.objects.count() == 1
682
-