0001-misc-unserialize-attribute-in-registration-view-4571.patch
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 |
|
712 |
import pdb |
|
713 |
pdb.set_trace() |
|
682 |
- |