phone-authn: on registration, inform user of existing duplicate (#88163)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Paul Marillonnet 2024-03-26 09:55:10 +01:00
parent 4dc8f6aab7
commit 448d3f16e6
2 changed files with 103 additions and 0 deletions

View File

@ -1910,6 +1910,18 @@ class RegistrationCompletionView(CreateView):
or self.phone_is_unique
and self.token.get('phone', None)
):
if self.ou and not (
app_settings.A2_PHONE_IS_UNIQUE or app_settings.A2_REGISTRATION_PHONE_IS_UNIQUE
):
# no creation because of ou identifier uniqueness
message = _(
"You've been logged in with your account already existing within ou {ou} for this identifier."
).format(ou=self.ou.name or self.ou.slug)
else:
# no creation because of global uniqueness
message = _("You've been logged in with your already-existing account for this identifier.")
messages.info(request, message)
# Found one user whose identifier is unique, log her in
utils_misc.simulate_authentication(request, self.users[0], method=self.authentication_method)
return utils_misc.redirect(request, self.get_success_url())

View File

@ -19,9 +19,11 @@ from datetime import date, timedelta
from unittest import mock
from urllib.parse import quote, urlparse
import pytest
import requests
import responses
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from authentic2 import models
@ -1432,3 +1434,92 @@ def test_already_logged(db, app, simple_user):
# then we can register.
resp = resp.follow()
assert resp.form['email']
@responses.activate
def test_phone_registration_existing_identifier_number(app, db, settings, phone_activated_authn):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
random_user = User.objects.create(
first_name='foo',
last_name='bar',
email='foobar@example.com',
username='foobar',
)
random_user.attributes.phone = '+33612345678'
random_user.save()
resp = app.get(reverse('registration_register'))
resp.form.set('phone_1', '612345678')
resp = resp.form.submit().follow()
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()
user = User.objects.get(first_name='John', last_name='Doe')
assert user.attributes.phone == '+33612345678'
assert user.phone_verified_on
assert not user.email_verified
assert user.id != random_user.id
@responses.activate
@pytest.mark.parametrize('global_uniqueness', [False, True])
def test_phone_registration_existing_identifier_number_ou_phone_is_unique(
app, db, settings, phone_activated_authn, global_uniqueness
):
settings.SMS_URL = 'https://foo.whatever.none/'
settings.A2_PHONE_IS_UNIQUE = global_uniqueness
responses.post('https://foo.whatever.none/', status=200)
random_user = User.objects.create(
first_name='foo',
last_name='bar',
email='foobar@example.com',
username='foobar',
)
ou = get_default_ou()
ou.phone_is_unique = True
ou.save()
random_user.attributes.phone = '+33612345678'
random_user.ou = ou
random_user.save()
resp = app.get(reverse('registration_register'))
resp.form.set('phone_1', '612345678')
resp = resp.form.submit().follow()
code = SMSCode.objects.get()
resp.form.set('sms_code', code.value)
resp = resp.form.submit().follow()
assert resp.location == '/'
resp = resp.follow()
if not global_uniqueness:
assert resp.pyquery('.messages .info')[0].text_content() == (
"You've been logged in with your account already existing within ou "
'Default organizational unit for this identifier.'
)
else:
assert resp.pyquery('.messages .info')[0].text_content() == (
"You've been logged in with your already-existing account " 'for this identifier.'
)
assert resp.pyquery('.ui-name')[0].text_content() == 'foo bar'
assert (
AttributeValue.objects.filter(
content='+33612345678', content_type=ContentType.objects.get_for_model(User)
)
.order_by('object_id')
.distinct('object_id')
.count()
== 1
)