diff --git a/src/backend/core/authentication/backends.py b/src/backend/core/authentication/backends.py index 09936aa8c..639328582 100644 --- a/src/backend/core/authentication/backends.py +++ b/src/backend/core/authentication/backends.py @@ -134,4 +134,4 @@ def update_user_if_needed(self, user, claims): ) if has_changed: updated_claims = {key: value for key, value in claims.items() if value} - self.UserModel.objects.filter(sub=user.sub).update(**updated_claims) + self.UserModel.objects.filter(id=user.id).update(**updated_claims) diff --git a/src/backend/core/tests/authentication/test_backends.py b/src/backend/core/tests/authentication/test_backends.py index dcc011014..c73099a68 100644 --- a/src/backend/core/tests/authentication/test_backends.py +++ b/src/backend/core/tests/authentication/test_backends.py @@ -130,11 +130,12 @@ def get_userinfo_mocked(*args): ("Jack", "Duy", "jack.duy@example.com"), ], ) -def test_authentication_getter_existing_user_change_fields( +def test_authentication_getter_existing_user_change_fields_sub( first_name, last_name, email, django_assert_num_queries, monkeypatch ): """ - It should update the email or name fields on the user when they change. + It should update the email or name fields on the user when they change + and the user was identified by its "sub". """ klass = OIDCAuthenticationBackend() user = UserFactory( @@ -164,6 +165,48 @@ def get_userinfo_mocked(*args): assert user.short_name == first_name +@pytest.mark.parametrize( + "first_name, last_name, email", + [ + ("Jack", "Doe", "john.doe@example.com"), + ("John", "Duy", "john.doe@example.com"), + ], +) +def test_authentication_getter_existing_user_change_fields_email( + first_name, last_name, email, django_assert_num_queries, monkeypatch +): + """ + It should update the name fields on the user when they change + and the user was identified by its "email" as fallback. + """ + klass = OIDCAuthenticationBackend() + user = UserFactory( + full_name="John Doe", short_name="John", email="john.doe@example.com" + ) + + def get_userinfo_mocked(*args): + return { + "sub": "123", + "email": user.email, + "first_name": first_name, + "last_name": last_name, + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + # One and only one additional update query when a field has changed + with django_assert_num_queries(3): + authenticated_user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == authenticated_user + user.refresh_from_db() + assert user.email == email + assert user.full_name == f"{first_name:s} {last_name:s}" + assert user.short_name == first_name + + def test_authentication_getter_new_user_no_email(monkeypatch): """ If no user matches the user's info sub, a user should be created.