auth_fc: handle case of multiple FranceConnect accounts with same email (#53409)
This commit is contained in:
parent
86219adc82
commit
7f8353561d
|
@ -24,7 +24,7 @@ from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.views import update_session_auth_hash
|
from django.contrib.auth.views import update_session_auth_hash
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError, transaction
|
||||||
from django.forms import Form
|
from django.forms import Form
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -387,6 +387,17 @@ class LoginOrLinkView(View):
|
||||||
% email,
|
% email,
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
if not created and user.fc_accounts.exists():
|
||||||
|
messages.warning(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
'Your FranceConnect email address "%s" is already used by the '
|
||||||
|
'FranceConnect account of "%s", so we cannot create an account for you. Please create '
|
||||||
|
'an account with another email address then link it to FranceConnect '
|
||||||
|
'using your account management page.'
|
||||||
|
)
|
||||||
|
% (email, user.get_full_name()),
|
||||||
|
)
|
||||||
else: # no email, we cannot disembiguate users, let's create it anyway
|
else: # no email, we cannot disembiguate users, let's create it anyway
|
||||||
user = User.objects.create()
|
user = User.objects.create()
|
||||||
created = True
|
created = True
|
||||||
|
@ -396,13 +407,17 @@ class LoginOrLinkView(View):
|
||||||
user.set_unusable_password()
|
user.set_unusable_password()
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
models.FcAccount.objects.create(
|
# As we intercept IntegrityError and we can never be sure if we are
|
||||||
user=user,
|
# in a transaction or not, we must use one to prevent later SQL
|
||||||
sub=sub,
|
# queries to fail.
|
||||||
order=0,
|
with transaction.atomic():
|
||||||
token=json.dumps(token),
|
models.FcAccount.objects.create(
|
||||||
user_info=json.dumps(user_info),
|
user=user,
|
||||||
)
|
sub=sub,
|
||||||
|
order=0,
|
||||||
|
token=json.dumps(token),
|
||||||
|
user_info=json.dumps(user_info),
|
||||||
|
)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
# uniqueness check failed, as the user is new, it can only mean that the sub is not unique
|
# uniqueness check failed, as the user is new, it can only mean that the sub is not unique
|
||||||
# let's try again
|
# let's try again
|
||||||
|
|
|
@ -28,6 +28,7 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
from authentic2.a2_rbac.models import OrganizationalUnit as OU
|
||||||
from authentic2.a2_rbac.utils import get_default_ou
|
from authentic2.a2_rbac.utils import get_default_ou
|
||||||
from authentic2.apps.journal.models import Event
|
from authentic2.apps.journal.models import Event
|
||||||
from authentic2.custom_user.models import DeletedUser
|
from authentic2.custom_user.models import DeletedUser
|
||||||
|
@ -550,3 +551,26 @@ def test_registration_page(settings, app, franceconnect, hooks):
|
||||||
|
|
||||||
# hook must have been called
|
# hook must have been called
|
||||||
assert hooks.calls['event'][0]['kwargs']['name'] == 'fc-create'
|
assert hooks.calls['event'][0]['kwargs']['name'] == 'fc-create'
|
||||||
|
|
||||||
|
|
||||||
|
def test_same_email_different_sub(app, franceconnect):
|
||||||
|
OU.objects.all().update(email_is_unique=True)
|
||||||
|
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
franceconnect.callback_params = {}
|
||||||
|
|
||||||
|
franceconnect.login_with_fc_fixed_params(app)
|
||||||
|
|
||||||
|
# ok user created
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
# logout
|
||||||
|
app.session.flush()
|
||||||
|
|
||||||
|
# change sub
|
||||||
|
franceconnect.sub = '4567'
|
||||||
|
|
||||||
|
resp = franceconnect.login_with_fc_fixed_params(app).maybe_follow()
|
||||||
|
|
||||||
|
# email collision, sub is different, no new user created
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
assert 'another email address' in resp
|
||||||
|
|
Loading…
Reference in New Issue