views: show warning to users with a mail linked to another FC account (fixes #21292)

The warning will help them connect their FC account to normally
registered account.
This commit is contained in:
Benjamin Dauvergne 2018-02-11 22:42:43 +01:00
parent c701e61043
commit 0f877b75a9
2 changed files with 57 additions and 5 deletions

View File

@ -405,11 +405,11 @@ class LoginOrLinkView(PopupViewMixin, FcOAuthSessionViewMixin, View):
user = authenticate(sub=self.sub, user_info=self.user_info,
token=self.token)
else:
self.logger.warning(u'account with email %s already linked to another sub '
u'%s, logging anyway',
email, user.fc_accounts.values_list('sub', flat=True))
# login the user anyway, but do not update its user_info, it's not ideal
a2_utils.simulate_login(user, 'france-connect', service_slug=self.service_slug)
messages.warning(
request,
_('Your FranceConnect email \'%s\' is already used by another account, '
'so we cannot create an account for you, please create an account '
'with another email then link your FranceConnect.') % email)
return self.redirect(request)
if user:
a2_utils.login(request, user, 'france-connect', service_slug=self.service_slug)

View File

@ -162,3 +162,55 @@ def test_login_email_is_unique(app, fc_settings, caplog):
with httmock.HTTMock(access_token_response, user_info_response):
response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
assert User.objects.count() == 1
assert app.session['_auth_user_id']
def test_login_email_is_unique_and_already_linked(app, fc_settings, caplog):
callback = reverse('fc-login-or-link')
response = app.get(callback, status=302)
location = response['Location']
state = check_authorization_url(location)
EMAIL = 'john.doe@example.com'
SUB = '1234'
user = User.objects.create(email=EMAIL, first_name='John', last_name='Doe')
models.FcAccount.objects.create(user=user, sub='4567', token='xxx', user_info='{}')
@httmock.urlmatch(path=r'.*/token$')
def access_token_response(url, request):
parsed = {x: y[0] for x, y in urlparse.parse_qs(request.body).items()}
assert set(parsed.keys()) == set(['code', 'client_id', 'client_secret', 'redirect_uri',
'grant_type'])
assert parsed['code'] == 'zzz'
assert parsed['client_id'] == 'xxx'
assert parsed['client_secret'] == 'yyy'
assert parsed['grant_type'] == 'authorization_code'
assert callback in parsed['redirect_uri']
id_token = {
'sub': SUB,
'aud': 'xxx',
'nonce': state,
'exp': timestamp_from_datetime(now() + datetime.timedelta(seconds=1000)),
'iss': 'https://fcp.integ01.dev-franceconnect.fr/',
}
return json.dumps({
'access_token': 'uuu',
'id_token': hmac_jwt(id_token, 'yyy')
})
@httmock.urlmatch(path=r'.*userinfo$')
def user_info_response(url, request):
assert request.headers['Authorization'] == 'Bearer uuu'
return json.dumps({
'sub': '1234',
'family_name': u'Frédérique',
'given_name': u'Ÿuñe',
'email': EMAIL,
})
fc_settings.A2_EMAIL_IS_UNIQUE = True
with httmock.HTTMock(access_token_response, user_info_response):
response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
assert 'is already used' in str(response)
assert User.objects.count() == 1
assert '_auth_user_id' not in app.session