auth_fc: add flag to disable link by email (#68360)
This commit is contained in:
parent
e524c5f94d
commit
0848d1cb3b
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.16 on 2022-11-23 13:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentic2_auth_fc', '0007_auto_20220615_1002'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fcauthenticator',
|
||||
name='link_by_email',
|
||||
field=models.BooleanField(default=True, verbose_name='Link by email address'),
|
||||
),
|
||||
]
|
|
@ -66,11 +66,19 @@ class FcAuthenticator(BaseAuthenticator):
|
|||
verbose_name=_('Scopes'),
|
||||
default=get_default_scopes,
|
||||
)
|
||||
link_by_email = models.BooleanField(_('Link by email address'), default=True)
|
||||
|
||||
type = 'fc'
|
||||
how = ['france-connect']
|
||||
unique = True
|
||||
description_fields = ['show_condition', 'platform', 'client_id', 'client_secret', 'scopes']
|
||||
description_fields = [
|
||||
'show_condition',
|
||||
'platform',
|
||||
'client_id',
|
||||
'client_secret',
|
||||
'scopes',
|
||||
'link_by_email',
|
||||
]
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('FranceConnect')
|
||||
|
|
|
@ -60,7 +60,7 @@ logger = logging.getLogger(__name__)
|
|||
User = get_user_model()
|
||||
|
||||
|
||||
class UserOutsideDefaultOu(Exception):
|
||||
class EmailExistsError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -435,9 +435,7 @@ class LoginOrLinkView(View):
|
|||
# try to create or find an user with this email
|
||||
try:
|
||||
user, created = self.get_or_create_user_with_email(email)
|
||||
except UserOutsideDefaultOu:
|
||||
user = None
|
||||
except User.MultipleObjectsReturned:
|
||||
except EmailExistsError:
|
||||
user = None
|
||||
if not user:
|
||||
messages.warning(
|
||||
|
@ -557,11 +555,15 @@ class LoginOrLinkView(View):
|
|||
Lock.lock_email(email)
|
||||
try:
|
||||
user = qs.get_by_email(email)
|
||||
if not self.authenticator.link_by_email:
|
||||
raise EmailExistsError
|
||||
except User.DoesNotExist:
|
||||
return User.objects.create(ou=ou, email=email), True
|
||||
except User.MultipleObjectsReturned:
|
||||
raise EmailExistsError
|
||||
|
||||
if user.ou != ou:
|
||||
raise UserOutsideDefaultOu
|
||||
raise EmailExistsError
|
||||
return user, False
|
||||
|
||||
|
||||
|
|
|
@ -166,8 +166,8 @@ def service(db):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def franceconnect(settings, service, db):
|
||||
FcAuthenticator.objects.create(
|
||||
def authenticator(db):
|
||||
return FcAuthenticator.objects.create(
|
||||
enabled=True,
|
||||
client_id=CLIENT_ID,
|
||||
client_secret=CLIENT_SECRET,
|
||||
|
@ -175,6 +175,9 @@ def franceconnect(settings, service, db):
|
|||
scopes=['profile', 'email'],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def franceconnect(settings, authenticator, service, db):
|
||||
mock_object = FranceConnectMock()
|
||||
with mock_object():
|
||||
yield mock_object
|
||||
|
|
|
@ -200,17 +200,44 @@ def test_create_expired(settings, app, franceconnect, hooks):
|
|||
assert User.objects.count() == 0
|
||||
|
||||
|
||||
def test_login_email_is_unique(settings, app, franceconnect, caplog):
|
||||
settings.A2_EMAIL_IS_UNIQUE = True
|
||||
user = User(email='john.doe@example.com', first_name='John', last_name='Doe', ou=get_default_ou())
|
||||
user.set_password('toto')
|
||||
user.save()
|
||||
franceconnect.user_info['email'] = user.email
|
||||
class TestLinkByEmail:
|
||||
@pytest.fixture
|
||||
def franceconnect(self, franceconnect):
|
||||
franceconnect.callback_params = {'next': '/accounts/'}
|
||||
return franceconnect
|
||||
|
||||
assert User.objects.count() == 1
|
||||
franceconnect.login_with_fc_fixed_params(app)
|
||||
assert User.objects.count() == 1
|
||||
assert app.session['_auth_user_id'] == str(user.pk)
|
||||
def test_enabled(self, settings, app, franceconnect, authenticator, caplog):
|
||||
authenticator.link_by_email = True
|
||||
authenticator.save()
|
||||
|
||||
user = User(email='john.doe@example.com', first_name='John', last_name='Doe', ou=get_default_ou())
|
||||
user.set_password('toto')
|
||||
user.save()
|
||||
franceconnect.user_info['email'] = user.email
|
||||
|
||||
assert User.objects.count() == 1
|
||||
franceconnect.login_with_fc_fixed_params(app)
|
||||
assert User.objects.count() == 1
|
||||
assert '_auth_user_id' in app.session
|
||||
|
||||
def test_disabled(self, settings, app, franceconnect, authenticator, caplog):
|
||||
authenticator.link_by_email = False
|
||||
authenticator.save()
|
||||
|
||||
user = User(email='john.doe@example.com', first_name='John', last_name='Doe', ou=get_default_ou())
|
||||
user.set_password('toto')
|
||||
user.save()
|
||||
franceconnect.user_info['email'] = user.email
|
||||
|
||||
assert User.objects.count() == 1
|
||||
response = franceconnect.login_with_fc_fixed_params(app)
|
||||
assert User.objects.count() == 1
|
||||
assert '_auth_user_id' not in app.session
|
||||
|
||||
# no login, so we must have produced a logout request toward FC
|
||||
response = franceconnect.handle_logout(app, response.location)
|
||||
response = response.maybe_follow()
|
||||
assert 'Your FranceConnect email address' in response.pyquery('.messages .warning').text()
|
||||
|
||||
|
||||
def test_link_after_login_with_password(app, franceconnect, simple_user):
|
||||
|
|
|
@ -418,6 +418,7 @@ def test_authenticators_fc(app, superuser):
|
|||
'client_id',
|
||||
'client_secret',
|
||||
'scopes',
|
||||
'link_by_email',
|
||||
None,
|
||||
]
|
||||
assert 'phone' not in resp.pyquery('#id_scopes').html()
|
||||
|
|
Loading…
Reference in New Issue