manager: prevent phone id duplicates at user edition time (#85276)
gitea/authentic/pipeline/head This commit looks good
Details
gitea/authentic/pipeline/head This commit looks good
Details
This commit is contained in:
parent
5a969bf584
commit
5b62273fd1
|
@ -23,6 +23,7 @@ from io import StringIO
|
|||
|
||||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import validate_slug
|
||||
from django.urls import reverse
|
||||
|
@ -43,7 +44,7 @@ from authentic2.forms.fields import (
|
|||
)
|
||||
from authentic2.forms.mixins import SlugMixin
|
||||
from authentic2.forms.profile import BaseUserForm
|
||||
from authentic2.models import APIClient, Attribute, PasswordReset, Service, Setting
|
||||
from authentic2.models import APIClient, Attribute, AttributeValue, PasswordReset, Service, Setting
|
||||
from authentic2.passwords import generate_password, validate_password
|
||||
from authentic2.utils.misc import (
|
||||
RUNTIME_SETTINGS,
|
||||
|
@ -172,6 +173,43 @@ class UserEditForm(LimitQuerysetFormMixin, CssClass, BaseUserForm):
|
|||
self.data[self.add_prefix('ou')] = qs[0].pk
|
||||
self.data._mutable = False
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
authn = get_password_authenticator()
|
||||
if (
|
||||
authn.is_phone_authn_active
|
||||
and (name := authn.phone_identifier_field.name)
|
||||
and self.cleaned_data.get(name, '')
|
||||
):
|
||||
if a2_app_settings.A2_PHONE_IS_UNIQUE:
|
||||
if (
|
||||
AttributeValue.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(get_user_model()),
|
||||
attribute=authn.phone_identifier_field,
|
||||
)
|
||||
.exclude(object_id=self.instance.id)
|
||||
.exists()
|
||||
):
|
||||
raise ValidationError(_('This phone number identifier is already used.'))
|
||||
elif getattr(self.instance.ou, 'phone_is_unique', False):
|
||||
other_owners = (
|
||||
AttributeValue.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(get_user_model()),
|
||||
attribute=authn.phone_identifier_field,
|
||||
)
|
||||
.exclude(object_id=self.instance.id)
|
||||
.values('object_id')
|
||||
)
|
||||
if other_owners and User.objects.filter(
|
||||
pk__in=other_owners,
|
||||
ou=self.instance.ou,
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
'This phone number identifier is already used within organizational unit {ou}.'
|
||||
).format(ou=self.instance.ou)
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
exclude = (
|
||||
|
|
|
@ -180,6 +180,85 @@ def test_create_user_email_is_unique(app, superuser, settings):
|
|||
assert 'This email address is already in use' in response
|
||||
|
||||
|
||||
def test_create_user_phone_is_unique(app, superuser, settings, phone_activated_authn):
|
||||
settings.A2_PHONE_IS_UNIQUE = True
|
||||
Attribute.objects.update(required=False)
|
||||
response = login(app, superuser, '/manage/users/')
|
||||
response = response.click('Add user')
|
||||
assert User.objects.count() == 1
|
||||
response.form.set('username', 'john.doe')
|
||||
response.form.set('phone_0', '33')
|
||||
response.form.set('phone_1', '0622332233')
|
||||
response.form.set('password1', '1234Password')
|
||||
response.form.set('password2', '1234Password')
|
||||
response.form.set('send_password_reset', False)
|
||||
response = response.form.submit(status=302)
|
||||
assert User.objects.count() == 2
|
||||
|
||||
# try again
|
||||
response = app.get('/manage/users/')
|
||||
response = response.click('Add user')
|
||||
response.form.set('username', 'john.doe2')
|
||||
response.form.set('phone_0', '33')
|
||||
response.form.set('phone_1', '0622332233')
|
||||
response.form.set('password1', '1234Password')
|
||||
response.form.set('password2', '1234Password')
|
||||
response.form.set('send_password_reset', False)
|
||||
response = response.form.submit(status=200)
|
||||
assert User.objects.count() == 2
|
||||
assert 'This phone number identifier is already used.' in response
|
||||
|
||||
|
||||
def test_create_user_ou_phone_is_unique(app, superuser, settings, phone_activated_authn, ou1, ou2):
|
||||
settings.A2_PHONE_IS_UNIQUE = False
|
||||
ou2.phone_is_unique = ou1.phone_is_unique = True
|
||||
ou1.save()
|
||||
ou2.save()
|
||||
Attribute.objects.update(required=False)
|
||||
response = login(app, superuser, '/manage/users/')
|
||||
response = response.click('Add user')
|
||||
assert User.objects.count() == 1
|
||||
response.form.set('ou', ou1.id)
|
||||
response = response.form.submit().follow()
|
||||
response.form.set('username', 'john.doe')
|
||||
response.form.set('phone_0', '33')
|
||||
response.form.set('phone_1', '0622332233')
|
||||
response.form.set('password1', '1234Password')
|
||||
response.form.set('password2', '1234Password')
|
||||
response.form.set('send_password_reset', False)
|
||||
response = response.form.submit(status=302)
|
||||
assert User.objects.count() == 2
|
||||
|
||||
# try again, same ou -> failure
|
||||
response = app.get('/manage/users/')
|
||||
response = response.click('Add user')
|
||||
response.form.set('ou', ou1.id)
|
||||
response = response.form.submit().follow()
|
||||
response.form.set('username', 'john.doe2')
|
||||
response.form.set('phone_0', '33')
|
||||
response.form.set('phone_1', '0622332233')
|
||||
response.form.set('password1', '1234Password')
|
||||
response.form.set('password2', '1234Password')
|
||||
response.form.set('send_password_reset', False)
|
||||
response = response.form.submit(status=200)
|
||||
assert User.objects.count() == 2
|
||||
assert 'This phone number identifier is already used within organizational unit OU1.' in response
|
||||
|
||||
# try again, different ou -> ok
|
||||
response = app.get('/manage/users/')
|
||||
response = response.click('Add user')
|
||||
response.form.set('ou', ou2.id)
|
||||
response = response.form.submit().follow()
|
||||
response.form.set('username', 'john.doe2')
|
||||
response.form.set('phone_0', '33')
|
||||
response.form.set('phone_1', '0622332233')
|
||||
response.form.set('password1', '1234Password')
|
||||
response.form.set('password2', '1234Password')
|
||||
response.form.set('send_password_reset', False)
|
||||
response = response.form.submit(status=302)
|
||||
assert User.objects.count() == 3
|
||||
|
||||
|
||||
def test_create_user_no_password(app, superuser):
|
||||
response = login(app, superuser, '/manage/users/')
|
||||
response = response.click('Add user')
|
||||
|
|
Loading…
Reference in New Issue