-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨(backend) add full_name and short_name to user model and API
The full_name and short_name field are synchronized with the OIDC token upon each login.
- Loading branch information
1 parent
e642506
commit ea07469
Showing
9 changed files
with
196 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
src/backend/core/migrations/0006_add_user_full_name_and_short_name.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Generated by Django 5.1.1 on 2024-09-29 03:47 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('core', '0005_remove_document_is_public_alter_document_link_reach_and_more'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='user', | ||
name='full_name', | ||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='full name'), | ||
), | ||
migrations.AddField( | ||
model_name='user', | ||
name='short_name', | ||
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='short name'), | ||
), | ||
migrations.AlterField( | ||
model_name='user', | ||
name='language', | ||
field=models.CharField(choices="(('en-us', 'English'), ('fr-fr', 'French'))", default='en-us', help_text='The language in which the user wants to see the interface.', max_length=10, verbose_name='language'), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,77 @@ def get_userinfo_mocked(*args): | |
assert user == db_user | ||
|
||
|
||
def test_authentication_getter_existing_user_with_email( | ||
django_assert_num_queries, monkeypatch | ||
): | ||
""" | ||
When the user's info contains an email and targets an existing user, | ||
""" | ||
klass = OIDCAuthenticationBackend() | ||
user = UserFactory(full_name="John Doe", short_name="John") | ||
|
||
def get_userinfo_mocked(*args): | ||
return { | ||
"sub": user.sub, | ||
"email": user.email, | ||
"first_name": "John", | ||
"last_name": "Doe", | ||
} | ||
|
||
monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) | ||
|
||
# Only 1 query because email and names have not changed | ||
with django_assert_num_queries(1): | ||
authenticated_user = klass.get_or_create_user( | ||
access_token="test-token", id_token=None, payload=None | ||
) | ||
|
||
assert user == authenticated_user | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"first_name, last_name, email", | ||
[ | ||
("Jack", "Doe", "[email protected]"), | ||
("John", "Duy", "[email protected]"), | ||
("John", "Doe", "[email protected]"), | ||
("Jack", "Duy", "[email protected]"), | ||
], | ||
) | ||
def test_authentication_getter_existing_user_change_fields( | ||
first_name, last_name, email, django_assert_num_queries, monkeypatch | ||
): | ||
""" | ||
It should update the email or name fields on the user when they change. | ||
""" | ||
klass = OIDCAuthenticationBackend() | ||
user = UserFactory( | ||
full_name="John Doe", short_name="John", email="[email protected]" | ||
) | ||
|
||
def get_userinfo_mocked(*args): | ||
return { | ||
"sub": user.sub, | ||
"email": 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(2): | ||
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. | ||
|
@@ -56,6 +127,8 @@ def get_userinfo_mocked(*args): | |
|
||
assert user.sub == "123" | ||
assert user.email is None | ||
assert user.full_name is None | ||
assert user.short_name is None | ||
assert user.password == "!" | ||
assert models.User.objects.count() == 1 | ||
|
||
|
@@ -81,6 +154,8 @@ def get_userinfo_mocked(*args): | |
|
||
assert user.sub == "123" | ||
assert user.email == email | ||
assert user.full_name == "John Doe" | ||
assert user.short_name == "John" | ||
assert user.password == "!" | ||
assert models.User.objects.count() == 1 | ||
|
||
|
@@ -116,14 +191,19 @@ def test_authentication_get_userinfo_json_response(): | |
responses.add( | ||
responses.GET, | ||
re.compile(r".*/userinfo"), | ||
json={"name": "John Doe", "email": "[email protected]"}, | ||
json={ | ||
"first_name": "John", | ||
"last_name": "Doe", | ||
"email": "[email protected]", | ||
}, | ||
status=200, | ||
) | ||
|
||
oidc_backend = OIDCAuthenticationBackend() | ||
result = oidc_backend.get_userinfo("fake_access_token", None, None) | ||
|
||
assert result["name"] == "John Doe" | ||
assert result["first_name"] == "John" | ||
assert result["last_name"] == "Doe" | ||
assert result["email"] == "[email protected]" | ||
|
||
|
||
|
@@ -137,14 +217,19 @@ def test_authentication_get_userinfo_token_response(monkeypatch): | |
) | ||
|
||
def mock_verify_token(self, token): # pylint: disable=unused-argument | ||
return {"name": "Jane Doe", "email": "[email protected]"} | ||
return { | ||
"first_name": "Jane", | ||
"last_name": "Doe", | ||
"email": "[email protected]", | ||
} | ||
|
||
monkeypatch.setattr(OIDCAuthenticationBackend, "verify_token", mock_verify_token) | ||
|
||
oidc_backend = OIDCAuthenticationBackend() | ||
result = oidc_backend.get_userinfo("fake_access_token", None, None) | ||
|
||
assert result["name"] == "Jane Doe" | ||
assert result["first_name"] == "Jane" | ||
assert result["last_name"] == "Doe" | ||
assert result["email"] == "[email protected]" | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters