migrate A2_ACCEPT_*_AUTHENTICATION to models (#78046)
This commit is contained in:
parent
a1169d83ff
commit
eef2e168a7
|
@ -142,7 +142,6 @@ def extract_settings_from_environ():
|
|||
'SHOW_DISCO_IN_MD',
|
||||
'SSLAUTH_CREATE_USER',
|
||||
'PUSH_PROFILE_UPDATES',
|
||||
'A2_ACCEPT_EMAIL_AUTHENTICATION',
|
||||
'A2_CAN_RESET_PASSWORD',
|
||||
'A2_REGISTRATION_CAN_DELETE_ACCOUNT',
|
||||
'A2_REGISTRATION_EMAIL_IS_UNIQUE',
|
||||
|
|
|
@ -283,8 +283,6 @@ default_settings = dict(
|
|||
),
|
||||
A2_ACCOUNTS_URL=Setting(default=None, definition='IdP has no account page, redirect to this one.'),
|
||||
A2_CACHE_ENABLED=Setting(default=True, definition='Disable all cache decorators for testing purpose.'),
|
||||
A2_ACCEPT_EMAIL_AUTHENTICATION=Setting(default=True, definition='Enable authentication by email'),
|
||||
A2_ACCEPT_PHONE_AUTHENTICATION=Setting(default=False, definition='Enable authentication by phone'),
|
||||
A2_USER_DELETED_KEEP_DATA=Setting(
|
||||
default=['email', 'uuid', 'phone'], definition='User data to keep after deletion'
|
||||
),
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 3.2.18 on 2023-06-01 15:44
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def migrate_a2_accept_authentication_settings(apps, schema_editor):
|
||||
LoginPasswordAuthenticator = apps.get_model('authenticators', 'LoginPasswordAuthenticator')
|
||||
authenticator, _ = LoginPasswordAuthenticator.objects.get_or_create(
|
||||
slug='password-authenticator',
|
||||
defaults={'enabled': True},
|
||||
)
|
||||
authenticator.accept_email_authentication = getattr(settings, 'A2_ACCEPT_EMAIL_AUTHENTICATION', True)
|
||||
authenticator.accept_phone_authentication = getattr(settings, 'A2_ACCEPT_PHONE_AUTHENTICATION', False)
|
||||
authenticator.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authenticators', '0010_auto_20230614_1017'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
migrate_a2_accept_authentication_settings, reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
|
@ -46,7 +46,6 @@ from ldap.dn import escape_dn_chars
|
|||
from ldap.filter import filter_format
|
||||
from ldap.ldapobject import ReconnectLDAPObject as NativeLDAPObject
|
||||
|
||||
from authentic2 import app_settings
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.backends import is_user_authenticable
|
||||
|
@ -56,7 +55,7 @@ from authentic2.middleware import StoreRequestMiddleware
|
|||
from authentic2.models import Lock, UserExternalId
|
||||
from authentic2.user_login_failure import user_login_failure, user_login_success
|
||||
from authentic2.utils import crypto
|
||||
from authentic2.utils.misc import PasswordChangeError, to_list
|
||||
from authentic2.utils.misc import PasswordChangeError, get_password_authenticator, to_list
|
||||
|
||||
# code originaly copied from by now merely inspired by
|
||||
# http://www.amherst.k12.oh.us/django-ldap.html
|
||||
|
@ -450,7 +449,6 @@ class LDAPBackend:
|
|||
'bindsasl': (),
|
||||
'user_dn_template': '',
|
||||
'user_filter': 'uid=%s', # will be '(|(mail=%s)(uid=%s))' if
|
||||
# A2_ACCEPT_EMAIL_AUTHENTICATION is set (see update_default)
|
||||
'sync_ldap_users_filter': '',
|
||||
'user_basedn': '',
|
||||
'group_basedn': '',
|
||||
|
@ -1955,10 +1953,11 @@ class LDAPBackend:
|
|||
if i in block and isinstance(block[i], str):
|
||||
block[i] = (block[i],)
|
||||
|
||||
email_authn = get_password_authenticator().accept_email_authentication
|
||||
for d, value in cls._DEFAULTS.items():
|
||||
if d not in block:
|
||||
block[d] = value
|
||||
if d == 'user_filter' and app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
|
||||
if d == 'user_filter' and email_authn:
|
||||
block[d] = '(|(mail=%s)(uid=%s))'
|
||||
else:
|
||||
if isinstance(value, str):
|
||||
|
|
|
@ -24,7 +24,7 @@ from phonenumbers import PhoneNumberFormat, format_number, is_valid_number
|
|||
|
||||
from authentic2.backends import get_user_queryset
|
||||
from authentic2.user_login_failure import user_login_failure, user_login_success
|
||||
from authentic2.utils.misc import parse_phone_number
|
||||
from authentic2.utils.misc import get_password_authenticator, parse_phone_number
|
||||
|
||||
from .. import app_settings
|
||||
|
||||
|
@ -45,9 +45,10 @@ class ModelBackend(BaseModelBackend):
|
|||
def get_query(self, username, realm=None, ou=None):
|
||||
username_field = 'username'
|
||||
queries = []
|
||||
if app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
|
||||
password_authenticator = get_password_authenticator()
|
||||
if password_authenticator.accept_email_authentication:
|
||||
queries.append(models.Q(**{'email__iexact': username}))
|
||||
if app_settings.A2_ACCEPT_PHONE_AUTHENTICATION:
|
||||
if password_authenticator.is_phone_authn_active:
|
||||
# try with the phone number as user identifier
|
||||
if (pn := parse_phone_number(username)) and is_valid_number(pn):
|
||||
query = {'phone': format_number(pn, PhoneNumberFormat.E164)}
|
||||
|
|
|
@ -61,7 +61,7 @@ class PasswordResetForm(HoneypotForm):
|
|||
label=_('Email or username'), max_length=254, required=False
|
||||
)
|
||||
|
||||
if not app_settings.A2_ACCEPT_PHONE_AUTHENTICATION or not get_user_model()._meta.get_field('phone'):
|
||||
if not self.authenticator.is_phone_authn_active:
|
||||
del self.fields['phone']
|
||||
if 'email' in self.fields:
|
||||
self.fields['email'].required = True
|
||||
|
@ -95,7 +95,7 @@ class PasswordResetForm(HoneypotForm):
|
|||
return phone
|
||||
|
||||
def clean(self):
|
||||
if app_settings.A2_ACCEPT_PHONE_AUTHENTICATION and get_user_model()._meta.get_field('phone'):
|
||||
if self.authenticator.is_phone_authn_active:
|
||||
if (
|
||||
not self.cleaned_data['email']
|
||||
and not self.cleaned_data.get('email_or_username')
|
||||
|
|
|
@ -30,6 +30,7 @@ from authentic2.forms.fields import CharField, CheckPasswordField, NewPasswordFi
|
|||
from authentic2.passwords import get_min_password_strength
|
||||
|
||||
from .. import app_settings, models
|
||||
from ..utils import misc as utils_misc
|
||||
from . import profile as profile_forms
|
||||
from .fields import PhoneField, ValidatedEmailField
|
||||
from .honeypot import HoneypotForm
|
||||
|
@ -58,7 +59,7 @@ class RegistrationForm(HoneypotForm):
|
|||
super().__init__(*args, **kwargs)
|
||||
attributes = {a.name: a for a in models.Attribute.objects.all()}
|
||||
|
||||
if not app_settings.A2_ACCEPT_PHONE_AUTHENTICATION or not get_user_model()._meta.get_field('phone'):
|
||||
if not utils_misc.get_password_authenticator().is_phone_authn_active:
|
||||
del self.fields['phone']
|
||||
self.fields['email'].required = True
|
||||
|
||||
|
@ -81,7 +82,7 @@ class RegistrationForm(HoneypotForm):
|
|||
return email
|
||||
|
||||
def clean(self):
|
||||
if app_settings.A2_ACCEPT_PHONE_AUTHENTICATION and get_user_model()._meta.get_field('phone'):
|
||||
if utils_misc.get_password_authenticator().is_phone_authn_active:
|
||||
if not self.cleaned_data.get('email') and not self.cleaned_data.get('phone'):
|
||||
raise ValidationError(gettext('Please provide an email address or a mobile phone number.'))
|
||||
|
||||
|
|
|
@ -748,11 +748,11 @@ def login_password_login(request, authenticator, *args, **kwargs):
|
|||
if request.user.is_authenticated and request.login_token.get('action'):
|
||||
form.initial['username'] = request.user.username or request.user.email
|
||||
form.fields['username'].widget.attrs['readonly'] = True
|
||||
if app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
|
||||
if authenticator.accept_email_authentication:
|
||||
form.fields['username'].label = _('Username or email')
|
||||
if app_settings.A2_ACCEPT_PHONE_AUTHENTICATION:
|
||||
if authenticator.is_phone_authn_active:
|
||||
form.fields['username'].label = _('Username, email or phone number')
|
||||
elif app_settings.A2_ACCEPT_PHONE_AUTHENTICATION:
|
||||
elif authenticator.is_phone_authn_active:
|
||||
form.fields['username'].label = _('Username or phone number')
|
||||
if app_settings.A2_USERNAME_LABEL:
|
||||
form.fields['username'].label = app_settings.A2_USERNAME_LABEL
|
||||
|
@ -858,7 +858,9 @@ class PasswordResetView(FormView):
|
|||
return super().dispatch(*args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
if not app_settings.A2_ACCEPT_PHONE_AUTHENTICATION or not self.code: # user input is email
|
||||
if (
|
||||
not utils_misc.get_password_authenticator().is_phone_authn_active or not self.code
|
||||
): # user input is email
|
||||
return reverse('password_reset_instructions')
|
||||
else: # user input is phone number
|
||||
params = {}
|
||||
|
@ -1168,7 +1170,7 @@ class BaseRegistrationView(HomeURLMixin, FormView):
|
|||
if email:
|
||||
return self.perform_email_registration(form, email)
|
||||
|
||||
if app_settings.A2_ACCEPT_PHONE_AUTHENTICATION:
|
||||
if self.authenticator.is_phone_authn_active:
|
||||
phone = form.cleaned_data.pop('phone')
|
||||
return self.perform_phone_registration(form, phone)
|
||||
|
||||
|
|
|
@ -3206,10 +3206,7 @@ def test_check_api_client_role_inheritance(app, superuser):
|
|||
assert set(resp.json['data']['roles']) == {role1.uuid, role2.uuid, role3.uuid}
|
||||
|
||||
|
||||
def test_api_basic_authz_user_phone_number(app, settings, superuser):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
Attribute.objects.get_or_create(name='phone', kind='phone_number')
|
||||
|
||||
def test_api_basic_authz_user_phone_number(app, settings, superuser, phone_activated_authn):
|
||||
headers = {'Authorization': 'Basic abc'}
|
||||
app.get('/api/users/', headers=headers, status=401)
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ from django.db.migrations.executor import MigrationExecutor
|
|||
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.authenticators.models import LoginPasswordAuthenticator
|
||||
from authentic2.authentication import OIDCUser
|
||||
from authentic2.manager.utils import get_ou_count
|
||||
from authentic2.models import Attribute, Service
|
||||
|
@ -329,6 +330,20 @@ def api_user(
|
|||
return locals().get(request.param)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def phone_activated_authn(db):
|
||||
phone, dummy = Attribute.objects.get_or_create(
|
||||
name='phone',
|
||||
kind='phone_number',
|
||||
defaults={'label': 'Phone'},
|
||||
)
|
||||
LoginPasswordAuthenticator.objects.update(
|
||||
accept_phone_authentication=True,
|
||||
phone_identifier_field=phone,
|
||||
)
|
||||
return LoginPasswordAuthenticator.objects.get()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clear_cache():
|
||||
cache.clear()
|
||||
|
|
|
@ -40,16 +40,20 @@ def test_user_filters(settings, db, simple_user, user_ou1, ou1):
|
|||
assert not is_user_authenticable(user_ou1)
|
||||
|
||||
|
||||
def test_model_backend_phone_number(settings, db, simple_user, nomail_user, ou1):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_model_backend_phone_number(settings, db, simple_user, nomail_user, ou1, phone_activated_authn):
|
||||
nomail_user.attributes.phone = '+33123456789'
|
||||
nomail_user.save()
|
||||
simple_user.attributes.phone = '+33123456789'
|
||||
simple_user.save()
|
||||
assert authenticate(username=simple_user.phone, password=simple_user.username)
|
||||
assert is_user_authenticable(simple_user)
|
||||
assert authenticate(username=nomail_user.phone, password=nomail_user.username)
|
||||
assert is_user_authenticable(nomail_user)
|
||||
|
||||
|
||||
def test_model_backend_phone_number_email(settings, db, simple_user):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_model_backend_phone_number_email(settings, db, simple_user, phone_activated_authn):
|
||||
simple_user.attributes.phone = '+33123456789'
|
||||
simple_user.save()
|
||||
# user with both phone number and username can authenticate in two different ways
|
||||
assert authenticate(username=simple_user.username, password=simple_user.username)
|
||||
assert authenticate(username=simple_user.phone, password=simple_user.username)
|
||||
|
|
|
@ -2119,7 +2119,7 @@ def test_get_extra_attributes(slapd, settings, client):
|
|||
assert {'id': EE_O, 'street': EE_STREET, 'city': EE_CITY, 'postal_code': EE_POSTALCODE} in orgas
|
||||
|
||||
|
||||
def test_config_to_lowercase():
|
||||
def test_config_to_lowercase(db):
|
||||
config = {
|
||||
'fname_field': 'givenName',
|
||||
'lname_field': 'surName',
|
||||
|
|
|
@ -36,8 +36,7 @@ def test_success(db, app, simple_user):
|
|||
assert_event('user.logout', user=simple_user, session=session)
|
||||
|
||||
|
||||
def test_success_email_with_phone_authn_activated(db, app, simple_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_success_email_with_phone_authn_activated(db, app, simple_user, settings, phone_activated_authn):
|
||||
login(app, simple_user)
|
||||
assert_event('user.login', user=simple_user, session=app.session, how='password-on-https')
|
||||
session = app.session
|
||||
|
@ -45,8 +44,9 @@ def test_success_email_with_phone_authn_activated(db, app, simple_user, settings
|
|||
assert_event('user.logout', user=simple_user, session=session)
|
||||
|
||||
|
||||
def test_success_phone_authn_nomail_user(db, app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_success_phone_authn_nomail_user(db, app, nomail_user, settings, phone_activated_authn):
|
||||
nomail_user.attributes.phone = '+33123456789'
|
||||
nomail_user.save()
|
||||
login(app, nomail_user, login='123456789', phone_authn=True)
|
||||
assert_event('user.login', user=nomail_user, session=app.session, how='password-on-https')
|
||||
session = app.session
|
||||
|
@ -54,9 +54,9 @@ def test_success_phone_authn_nomail_user(db, app, nomail_user, settings):
|
|||
assert_event('user.logout', user=nomail_user, session=session)
|
||||
|
||||
|
||||
def test_success_phone_authn_simple_user(db, app, simple_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
|
||||
def test_success_phone_authn_simple_user(db, app, simple_user, settings, phone_activated_authn):
|
||||
simple_user.attributes.phone = '+33123456789'
|
||||
simple_user.save()
|
||||
login(app, simple_user, login='123456789', phone_authn=True)
|
||||
assert_event('user.login', user=simple_user, session=app.session, how='password-on-https')
|
||||
session = app.session
|
||||
|
@ -72,8 +72,7 @@ def test_failure(db, app, simple_user):
|
|||
assert_event('user.login.failure', username='noone')
|
||||
|
||||
|
||||
def test_failure_no_means_of_authentication(db, app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_failure_no_means_of_authentication(db, app, nomail_user, settings, phone_activated_authn):
|
||||
nomail_user.username = None
|
||||
nomail_user.phone = None
|
||||
nomail_user.save()
|
||||
|
@ -92,17 +91,25 @@ def test_required_username_identifier(db, app, settings, caplog):
|
|||
assert not response.pyquery('span.optional')
|
||||
assert response.pyquery('label[for="id_username"]').text() == 'Username or email:'
|
||||
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
phone, dummy = models.Attribute.objects.get_or_create(
|
||||
name='phone',
|
||||
kind='phone_number',
|
||||
defaults={'label': 'Phone'},
|
||||
)
|
||||
LoginPasswordAuthenticator.objects.update(
|
||||
accept_phone_authentication=True,
|
||||
phone_identifier_field=phone,
|
||||
)
|
||||
response = app.get('/login/')
|
||||
assert not response.pyquery('span.optional')
|
||||
assert response.pyquery('label[for="id_username"]').text() == 'Username, email or phone number:'
|
||||
|
||||
settings.A2_ACCEPT_EMAIL_AUTHENTICATION = False
|
||||
LoginPasswordAuthenticator.objects.update(accept_email_authentication=False)
|
||||
response = app.get('/login/')
|
||||
assert not response.pyquery('span.optional')
|
||||
assert response.pyquery('label[for="id_username"]').text() == 'Username or phone number:'
|
||||
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = False
|
||||
LoginPasswordAuthenticator.objects.update(accept_phone_authentication=False)
|
||||
response = app.get('/login/')
|
||||
assert not response.pyquery('span.optional')
|
||||
assert response.pyquery('label[for="id_username"]').text() == 'Username:'
|
||||
|
@ -117,7 +124,7 @@ def test_login_form_fields_order(db, app, settings, ou1, ou2):
|
|||
'login-password-submit',
|
||||
]
|
||||
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
LoginPasswordAuthenticator.objects.update(accept_phone_authentication=True)
|
||||
|
||||
response = app.get('/login/')
|
||||
assert list(response.form.fields.keys()) == [
|
||||
|
@ -572,3 +579,22 @@ def test_password_authenticator_data_migration_new_settings_invalid(migration, s
|
|||
assert authenticator.login_exponential_retry_timeout_max_duration == 10
|
||||
assert authenticator.emails_ip_ratelimit == '10/h'
|
||||
assert authenticator.sms_ip_ratelimit == '10/h'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('email,phone', [(True, True), (True, False), (False, True)])
|
||||
def test_password_authenticator_migration_accept_authentication_settings(migration, settings, email, phone):
|
||||
app = 'authenticators'
|
||||
migrate_from = [(app, '0010_auto_20230614_1017')]
|
||||
migrate_to = [(app, '0011_migrate_a2_accept_authentication_settings')]
|
||||
|
||||
migration.before(migrate_from)
|
||||
|
||||
settings.A2_ACCEPT_EMAIL_AUTHENTICATION = email
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = phone
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
|
||||
assert authenticator.accept_email_authentication == email
|
||||
assert authenticator.accept_phone_authentication == phone
|
||||
|
|
|
@ -80,6 +80,9 @@ def test_authenticators_password(app, superuser_or_admin):
|
|||
'show_condition',
|
||||
'button_description',
|
||||
'registration_open',
|
||||
'accept_email_authentication',
|
||||
'accept_phone_authentication',
|
||||
'phone_identifier_field',
|
||||
'password_min_length',
|
||||
'remember_me',
|
||||
'include_ou_selector',
|
||||
|
@ -170,6 +173,8 @@ def test_authenticators_password_export(app, superuser):
|
|||
'sms_number_ratelimit': '10/h',
|
||||
'ou': None,
|
||||
'related_objects': [],
|
||||
'accept_email_authentication': True,
|
||||
'accept_phone_authentication': False,
|
||||
}
|
||||
|
||||
resp = app.get('/manage/authenticators/')
|
||||
|
|
|
@ -60,8 +60,11 @@ def test_send_password_reset_email(app, simple_user, mailoutbox):
|
|||
utils.assert_event('user.password.reset', user=simple_user, session=app.session)
|
||||
|
||||
|
||||
def test_send_password_reset_by_sms_code_improperly_configured(app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_send_password_reset_by_sms_code_improperly_configured(
|
||||
app, nomail_user, settings, phone_activated_authn
|
||||
):
|
||||
nomail_user.attributes.phone = nomail_user.phone
|
||||
nomail_user.save()
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
assert not SMSCode.objects.count()
|
||||
|
@ -74,8 +77,9 @@ def test_send_password_reset_by_sms_code_improperly_configured(app, nomail_user,
|
|||
assert 'Something went wrong while trying to send' in resp.pyquery('li.error').text()
|
||||
|
||||
|
||||
def test_send_password_reset_by_sms_code(app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_send_password_reset_by_sms_code(app, nomail_user, settings, phone_activated_authn):
|
||||
nomail_user.attributes.phone = '+33123456789'
|
||||
nomail_user.save()
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
code_length = settings.SMS_CODE_LENGTH
|
||||
|
@ -111,8 +115,9 @@ def test_send_password_reset_by_sms_code(app, nomail_user, settings):
|
|||
app.get(url, status=404)
|
||||
|
||||
|
||||
def test_send_password_reset_by_sms_code_next_url(app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_send_password_reset_by_sms_code_next_url(app, nomail_user, settings, phone_activated_authn):
|
||||
nomail_user.attributes.phone = '+33123456789'
|
||||
nomail_user.save()
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get('/accounts/consents/').follow()
|
||||
|
@ -134,8 +139,7 @@ def test_send_password_reset_by_sms_code_next_url(app, nomail_user, settings):
|
|||
assert "Consent Management" in resp
|
||||
|
||||
|
||||
def test_password_reset_empty_form(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_password_reset_empty_form(app, db, settings, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
url = reverse('password_reset')
|
||||
|
@ -147,8 +151,11 @@ def test_password_reset_empty_form(app, db, settings):
|
|||
)
|
||||
|
||||
|
||||
def test_password_reset_both_fields_filled_email_precedence(app, simple_user, settings, mailoutbox):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_password_reset_both_fields_filled_email_precedence(
|
||||
app, simple_user, settings, mailoutbox, phone_activated_authn
|
||||
):
|
||||
simple_user.attributes.phone = '+33123456789'
|
||||
simple_user.save()
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
url = reverse('password_reset')
|
||||
|
@ -163,8 +170,9 @@ def test_password_reset_both_fields_filled_email_precedence(app, simple_user, se
|
|||
assert not SMSCode.objects.count()
|
||||
|
||||
|
||||
def test_send_password_reset_by_sms_code_erroneous_phone_number(app, nomail_user, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_send_password_reset_by_sms_code_erroneous_phone_number(
|
||||
app, nomail_user, settings, phone_activated_authn
|
||||
):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
assert not SMSCode.objects.count()
|
||||
|
|
|
@ -951,15 +951,13 @@ def test_registration_completion(db, app, mailoutbox):
|
|||
assert 'This password is not strong enough' in resp.text
|
||||
|
||||
|
||||
def test_registration_no_identifier(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_registration_no_identifier(app, db, settings, phone_activated_authn):
|
||||
resp = app.get(reverse('registration_register'))
|
||||
resp = resp.form.submit()
|
||||
assert 'Please provide an email address or a mobile' in resp.text
|
||||
|
||||
|
||||
def test_registration_erroneous_phone_identifier(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_registration_erroneous_phone_identifier(app, db, settings, phone_activated_authn):
|
||||
resp = app.get(reverse('registration_register'))
|
||||
resp.form.set('phone_1', 'thatsnotquiteit')
|
||||
resp = resp.form.submit()
|
||||
|
@ -981,8 +979,7 @@ def sms_service_mock(url, request):
|
|||
}
|
||||
|
||||
|
||||
def test_phone_registration_wrong_code(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_wrong_code(app, db, settings, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get(reverse('registration_register'))
|
||||
|
@ -995,8 +992,7 @@ def test_phone_registration_wrong_code(app, db, settings):
|
|||
assert resp.pyquery('li')[0].text_content() == 'Wrong SMS code.'
|
||||
|
||||
|
||||
def test_phone_registration_expired_code(app, db, settings, freezer):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_expired_code(app, db, settings, freezer, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get(reverse('registration_register'))
|
||||
|
@ -1011,8 +1007,7 @@ def test_phone_registration_expired_code(app, db, settings, freezer):
|
|||
assert resp.pyquery('li')[0].text_content() == 'The code has expired.'
|
||||
|
||||
|
||||
def test_phone_registration_cancel(app, db, settings, freezer):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_cancel(app, db, settings, freezer, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get(reverse('registration_register'))
|
||||
|
@ -1026,8 +1021,7 @@ def test_phone_registration_cancel(app, db, settings, freezer):
|
|||
assert not SMSCode.objects.count()
|
||||
|
||||
|
||||
def test_phone_registration_improperly_configured(app, db, settings, freezer, caplog):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_improperly_configured(app, db, settings, freezer, caplog, phone_activated_authn):
|
||||
settings.SMS_URL = ''
|
||||
|
||||
resp = app.get(reverse('registration_register'))
|
||||
|
@ -1043,8 +1037,7 @@ def test_phone_registration_improperly_configured(app, db, settings, freezer, ca
|
|||
assert caplog.records[0].message == 'settings.SMS_URL is not set'
|
||||
|
||||
|
||||
def test_phone_registration_connection_error(app, db, settings, freezer, caplog):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_connection_error(app, db, settings, freezer, caplog, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
def mocked_requests_connection_error(*args, **kwargs):
|
||||
|
@ -1067,8 +1060,7 @@ def test_phone_registration_connection_error(app, db, settings, freezer, caplog)
|
|||
)
|
||||
|
||||
|
||||
def test_phone_registration(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration(app, db, settings, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
code_length = settings.SMS_CODE_LENGTH
|
||||
|
||||
|
@ -1099,8 +1091,7 @@ def test_phone_registration(app, db, settings):
|
|||
assert user.phone == '+33612345678'
|
||||
|
||||
|
||||
def test_phone_registration_redirect_url(app, db, settings):
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
def test_phone_registration_redirect_url(app, db, settings, phone_activated_authn):
|
||||
settings.SMS_URL = 'https://foo.whatever.none/'
|
||||
|
||||
resp = app.get('/accounts/consents/').follow()
|
||||
|
|
|
@ -321,10 +321,9 @@ def test_custom_account(settings, app, simple_user):
|
|||
|
||||
|
||||
@pytest.mark.parametrize('view_name', ['registration_register']) # password_lost to be added with #69890
|
||||
def test_views_sms_ratelimit(app, db, simple_user, settings, freezer, view_name):
|
||||
def test_views_sms_ratelimit(app, db, simple_user, settings, freezer, view_name, phone_activated_authn):
|
||||
freezer.move_to('2020-01-01')
|
||||
LoginPasswordAuthenticator.objects.update(sms_ip_ratelimit='10/h', sms_number_ratelimit='3/d')
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = True
|
||||
settings.SMS_SENDER = 'EO'
|
||||
settings.SMS_URL = 'https://www.example.com/send'
|
||||
|
||||
|
|
Loading…
Reference in New Issue