registration: decide on which phone attribute to use (#78046)
This commit is contained in:
parent
f9b9d9ac88
commit
795f04ea7d
|
@ -27,6 +27,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
|
|||
from django.contrib.auth import logout as auth_logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.views import PasswordChangeView as DjPasswordChangeView
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import FieldDoesNotExist, ValidationError
|
||||
from django.db.models import Count
|
||||
from django.db.models.query import Q
|
||||
|
@ -1439,6 +1440,8 @@ class RegistrationCompletionView(CreateView):
|
|||
@atomic(savepoint=False)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
registration_token = kwargs['registration_token'].replace(' ', '')
|
||||
self.authenticator = utils_misc.get_password_authenticator()
|
||||
user_ct = ContentType.objects.get_for_model(get_user_model())
|
||||
try:
|
||||
token = models.Token.use('registration', registration_token, delete=False)
|
||||
except models.Token.DoesNotExist:
|
||||
|
@ -1463,9 +1466,15 @@ class RegistrationCompletionView(CreateView):
|
|||
self.email = self.token['email']
|
||||
qs_filter = {'email__iexact': self.email}
|
||||
Lock.lock_email(self.email)
|
||||
elif self.token.get('phone', None):
|
||||
elif self.token.get('phone', None) and self.authenticator.is_phone_authn_active:
|
||||
self.phone = self.token['phone']
|
||||
qs_filter = {'phone': self.phone}
|
||||
user_ids = models.AttributeValue.objects.filter(
|
||||
attribute=self.authenticator.phone_identifier_field,
|
||||
content=self.phone,
|
||||
content_type=user_ct,
|
||||
).values_list('object_id', flat=True)
|
||||
|
||||
qs_filter = {'id__in': user_ids}
|
||||
Lock.lock_identifier(self.phone)
|
||||
else:
|
||||
messages.warning(request, _('Activation failed'))
|
||||
|
@ -1574,7 +1583,9 @@ class RegistrationCompletionView(CreateView):
|
|||
kwargs['instance'] = User.objects.get(id=self.token.get('user_id'))
|
||||
else:
|
||||
init_kwargs = {}
|
||||
for key in ('email', 'first_name', 'last_name', 'ou', 'phone'):
|
||||
keys = ['email', 'first_name', 'last_name', 'ou']
|
||||
# phone identifier is a separate attribute and is set post user-creation
|
||||
for key in keys:
|
||||
if key in attributes:
|
||||
init_kwargs[key] = attributes[key]
|
||||
kwargs['instance'] = get_user_model()(**init_kwargs)
|
||||
|
@ -1680,6 +1691,18 @@ class RegistrationCompletionView(CreateView):
|
|||
if count:
|
||||
super().form_valid(form) # user creation happens here
|
||||
user = form.instance
|
||||
if (
|
||||
(phone := getattr(self, 'phone', None))
|
||||
and (authn := utils_misc.get_password_authenticator())
|
||||
and authn.is_phone_authn_active
|
||||
):
|
||||
# phone identifier set post user-creation
|
||||
models.AttributeValue.objects.create(
|
||||
content_type=ContentType.objects.get_for_model(get_user_model()),
|
||||
object_id=user.id,
|
||||
content=phone,
|
||||
attribute=authn.phone_identifier_field,
|
||||
)
|
||||
self.process_registration(self.request, user, form)
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -26,6 +26,7 @@ from httmock import HTTMock, remember_called, urlmatch
|
|||
|
||||
from authentic2 import models
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.authenticators.models import LoginPasswordAuthenticator
|
||||
from authentic2.apps.journal.models import Event
|
||||
from authentic2.forms.profile import modelform_factory
|
||||
from authentic2.forms.registration import RegistrationCompletionForm
|
||||
|
@ -1088,7 +1089,42 @@ def test_phone_registration(app, db, settings, phone_activated_authn):
|
|||
assert "You have just created an account" in resp.text
|
||||
|
||||
user = User.objects.get(first_name='John', last_name='Doe')
|
||||
assert user.phone == '+33612345678'
|
||||
assert user.attributes.phone == '+33612345678'
|
||||
|
||||
|
||||
def test_phone_registration_nondefault_attribute(app, db, settings):
|
||||
phone, dummy = models.Attribute.objects.get_or_create(
|
||||
name='another_phone',
|
||||
kind='phone_number',
|
||||
defaults={'label': 'Another phone'},
|
||||
)
|
||||
LoginPasswordAuthenticator.objects.update(
|
||||
accept_phone_authentication=True,
|
||||
phone_identifier_field=phone,
|
||||
)
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get(reverse('registration_register'))
|
||||
resp.form.set('phone_1', '612345678')
|
||||
with HTTMock(sms_service_mock):
|
||||
resp = resp.form.submit().follow()
|
||||
json.loads(sms_service_mock.call['requests'][0].body)
|
||||
code = SMSCode.objects.get()
|
||||
resp.form.set('sms_code', code.value)
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
resp.form.set('password1', 'Password0')
|
||||
resp.form.set('password2', 'Password0')
|
||||
resp.form.set('first_name', 'John')
|
||||
resp.form.set('last_name', 'Doe')
|
||||
resp = resp.form.submit().follow()
|
||||
assert "You have just created an account" in resp.text
|
||||
|
||||
user = User.objects.get(first_name='John', last_name='Doe')
|
||||
assert user.attributes.another_phone == '+33612345678'
|
||||
# no standard attribute set nor even created
|
||||
assert not getattr(user.attributes, 'phone', None)
|
||||
assert not user.phone
|
||||
|
||||
|
||||
def test_phone_registration_redirect_url(app, db, settings, phone_activated_authn):
|
||||
|
@ -1111,4 +1147,4 @@ def test_phone_registration_redirect_url(app, db, settings, phone_activated_auth
|
|||
assert resp.location == '/accounts/consents/'
|
||||
resp.follow()
|
||||
user = User.objects.get(first_name='John', last_name='Doe')
|
||||
assert user.phone == '+33612345678'
|
||||
assert user.attributes.phone == '+33612345678'
|
||||
|
|
Loading…
Reference in New Issue