Projet

Général

Profil

0001-views-show-warning-to-users-with-a-mail-linked-to-an.patch

Benjamin Dauvergne, 11 février 2018 22:43

Télécharger (4,47 ko)

Voir les différences:

Subject: [PATCH] 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.
 src/authentic2_auth_fc/views.py | 10 ++++----
 tests/test_auth_fc.py           | 52 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 5 deletions(-)
src/authentic2_auth_fc/views.py
403 403
                        user = authenticate(sub=self.sub, user_info=self.user_info,
404 404
                                            token=self.token)
405 405
                    else:
406
                        self.logger.warning(u'account with email %s already linked to another sub '
407
                                            u'%s, logging anyway',
408
                                            email, user.fc_accounts.values_list('sub', flat=True))
409
                        # login the user anyway, but do not update its user_info, it's not ideal
410
                        a2_utils.simulate_login(user, 'france-connect', service_slug=self.service_slug)
406
                        messages.warning(
407
                            request,
408
                            _('Your FranceConnect email \'%s\' is already used by another account, '
409
                              'so we cannot create an account for you, please create an account '
410
                              'with another email then link your FranceConnect.') % email)
411 411
                        return self.redirect(request)
412 412
        if user:
413 413
            a2_utils.login(request, user, 'france-connect', service_slug=self.service_slug)
tests/test_auth_fc.py
162 162
    with httmock.HTTMock(access_token_response, user_info_response):
163 163
        response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
164 164
    assert User.objects.count() == 1
165
    assert app.session['_auth_user_id']
166

  
167

  
168
def test_login_email_is_unique_and_already_linked(app, fc_settings, caplog):
169
    callback = reverse('fc-login-or-link')
170
    response = app.get(callback, status=302)
171
    location = response['Location']
172
    state = check_authorization_url(location)
173

  
174
    EMAIL = 'john.doe@example.com'
175
    SUB = '1234'
176
    user = User.objects.create(email=EMAIL, first_name='John', last_name='Doe')
177
    models.FcAccount.objects.create(user=user, sub='4567', token='xxx', user_info='{}')
178

  
179
    @httmock.urlmatch(path=r'.*/token$')
180
    def access_token_response(url, request):
181
        parsed = {x: y[0] for x, y in urlparse.parse_qs(request.body).items()}
182
        assert set(parsed.keys()) == set(['code', 'client_id', 'client_secret', 'redirect_uri',
183
                                          'grant_type'])
184
        assert parsed['code'] == 'zzz'
185
        assert parsed['client_id'] == 'xxx'
186
        assert parsed['client_secret'] == 'yyy'
187
        assert parsed['grant_type'] == 'authorization_code'
188
        assert callback in parsed['redirect_uri']
189
        id_token = {
190
            'sub': SUB,
191
            'aud': 'xxx',
192
            'nonce': state,
193
            'exp': timestamp_from_datetime(now() + datetime.timedelta(seconds=1000)),
194
            'iss': 'https://fcp.integ01.dev-franceconnect.fr/',
195
        }
196
        return json.dumps({
197
            'access_token': 'uuu',
198
            'id_token': hmac_jwt(id_token, 'yyy')
199
        })
200

  
201
    @httmock.urlmatch(path=r'.*userinfo$')
202
    def user_info_response(url, request):
203
        assert request.headers['Authorization'] == 'Bearer uuu'
204
        return json.dumps({
205
            'sub': '1234',
206
            'family_name': u'Frédérique',
207
            'given_name': u'Ÿuñe',
208
            'email': EMAIL,
209
        })
210

  
211
    fc_settings.A2_EMAIL_IS_UNIQUE = True
212
    with httmock.HTTMock(access_token_response, user_info_response):
213
        response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
214
        assert 'is already used' in str(response)
215
    assert User.objects.count() == 1
216
    assert '_auth_user_id' not in app.session
165
-