From f3ff87adaec17e20656a88e56d27a23ff7b0dc30 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Mon, 10 Aug 2020 17:33:23 +0200
Subject: [PATCH 1/2] auth_fc: update info on the FC accout related user
 (#45199)

---
 src/authentic2_auth_fc/backends.py |  3 +-
 tests/auth_fc/test_auth_fc.py      | 48 ++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/src/authentic2_auth_fc/backends.py b/src/authentic2_auth_fc/backends.py
index 72685a8b..47004344 100644
--- a/src/authentic2_auth_fc/backends.py
+++ b/src/authentic2_auth_fc/backends.py
@@ -42,17 +42,17 @@ class FcBackend(ModelBackend):
         except models.FcAccount.DoesNotExist:
             logger.debug(u'user with the sub %s does not exist.', sub)
         else:
             user = account.user
             logger.debug(u'found user %s with sub %s', user, sub)
             if not user.is_active:
                 logger.info(u'user %s login refused, it is inactive', user)
                 raise PermissionDenied
-        if user_info:
+        if user_info and not user:
             User = get_user_model()
             user_qs = User.objects.filter(**kwargs.get('user_filter', {}))
             if user_qs.count() > 1:
                 return
             if user_qs.exists():
                 user = user_qs.get()
 
             if not user:
@@ -71,16 +71,17 @@ class FcBackend(ModelBackend):
                 else:
                     logger.debug(
                         u'user creation enabled with fc_account (sub : %s - token : %s)',
                         sub,
                         json.dumps(kwargs['token']),
                     )
                     hooks.call_hooks('event', name='fc-create', user=user, sub=sub)
 
+        if user_info:
             # always handle given_name and family_name
             updated = []
             if user_info.get('given_name') and user.first_name != user_info['given_name']:
                 user.first_name = user_info['given_name']
                 updated.append('given name: "%s"' % user_info['given_name'])
             if user_info.get('family_name') and user.last_name != user_info['family_name']:
                 user.last_name = user_info['family_name']
                 updated.append('family name: "%s"' % user_info['family_name'])
diff --git a/tests/auth_fc/test_auth_fc.py b/tests/auth_fc/test_auth_fc.py
index c1c7d740..f02c9002 100644
--- a/tests/auth_fc/test_auth_fc.py
+++ b/tests/auth_fc/test_auth_fc.py
@@ -342,8 +342,56 @@ def test_create_missing_email(settings, app, franceconnect, hooks):
     del franceconnect.user_info['email']
     response = app.get('/login/?service=portail&next=/idp/')
     response = response.click(href='callback')
 
     response = franceconnect.handle_authorization(app, response.location, status=302)
     assert User.objects.count() == 1
 
     response = app.get('/accounts/', status=200)
+
+
+def test_update_fc_email(settings, app, franceconnect):
+    settings.A2_EMAIL_IS_UNIQUE = True
+
+    user1 = User(email='john.doe@example.com', first_name='John', last_name='Doe')
+    user1.save()
+    models.FcAccount.objects.create(user=user1, sub='1234')
+
+    user2 = User(email='joe@example.com', first_name='Joe', last_name='Dalton')
+    user2.save()
+    models.FcAccount.objects.create(user=user2, sub='4567')
+
+    # user1 FC email has changed
+    assert franceconnect.sub == '1234'
+    assert franceconnect.user_info['given_name'] == 'Ÿuñe'
+    franceconnect.user_info['email'] = 'jhonny@example.com'
+
+    # connection using FC sub 1234 will affect user1 (as expected)
+    franceconnect.login_with_fc_fixed_params(app)
+    assert User.objects.get(pk=user1.pk).email == 'jhonny@example.com'
+    assert User.objects.get(pk=user1.pk).first_name == 'Ÿuñe'
+    assert User.objects.get(pk=user2.pk).email == 'joe@example.com'
+    assert app.session['_auth_user_id'] == str(user1.pk)
+
+
+def test_update_fc_redondant_email(settings, app, franceconnect):
+    settings.A2_EMAIL_IS_UNIQUE = True
+
+    user1 = User(email='john.doe@example.com', first_name='John', last_name='Doe')
+    user1.save()
+    models.FcAccount.objects.create(user=user1, sub='1234')
+
+    user2 = User(email='joe@example.com', first_name='Joe', last_name='Dalton')
+    user2.save()
+    models.FcAccount.objects.create(user=user2, sub='4567')
+
+    # user1 FC email has changed and provide user2 email
+    assert franceconnect.sub == '1234'
+    assert franceconnect.user_info['given_name'] == 'Ÿuñe'
+    franceconnect.user_info['email'] = 'joe@example.com'
+
+    # connection using FC sub 1234 will affect user2
+    franceconnect.login_with_fc_fixed_params(app)
+    assert User.objects.get(pk=user1.pk).email == 'joe@example.com'
+    assert User.objects.get(pk=user1.pk).first_name == 'Ÿuñe'
+    assert User.objects.get(pk=user2.pk).email == 'joe@example.com'
+    assert app.session.get('_auth_user_id')
-- 
2.30.2

