From e826d8e1e4b86fe4b11908b0fa953187b67fddca Mon Sep 17 00:00:00 2001 From: Naincy Chourasia Date: Thu, 16 Jul 2026 11:00:03 +0000 Subject: [PATCH 1/4] fix: clear full_name during user retirement --- credentials/apps/api/v2/tests/test_views.py | 13 +++++++++++ credentials/apps/api/v2/views.py | 24 ++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/credentials/apps/api/v2/tests/test_views.py b/credentials/apps/api/v2/tests/test_views.py index a0c1b65cc..f7aa36425 100644 --- a/credentials/apps/api/v2/tests/test_views.py +++ b/credentials/apps/api/v2/tests/test_views.py @@ -691,3 +691,16 @@ def test_existing_and_non_existing_users(self): response = self.call_api(self.service_user, data) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, expected_response) + + def test_clears_full_name_for_replaced_user(self): + """Verify username replacement also clears full_name for user retirement.""" + user = UserFactory(full_name="Jane Example") + new_username = f"{user.username}_retired" + + response = self.call_api(self.service_user, {"username_mappings": [{user.username: new_username}]}) + + self.assertEqual(response.status_code, 200) + user.refresh_from_db() + self.assertEqual(user.username, new_username) + self.assertEqual(user.full_name, "") + diff --git a/credentials/apps/api/v2/views.py b/credentials/apps/api/v2/views.py index 00b0de9c4..f3244f0ec 100644 --- a/credentials/apps/api/v2/views.py +++ b/credentials/apps/api/v2/views.py @@ -263,32 +263,20 @@ def _replace_username_for_all_models(self, current_username, new_username, repla with transaction.atomic(): num_rows_changed = 0 for model, column in replacement_locations: - num_rows_changed += model.objects.filter(**{column: current_username}).update( - **{column: new_username} - ) + update_kwargs = {column: new_username} + # Clear full_name for user retirement anonymization + if model._meta.label_lower == "core.user" and column == "username": + update_kwargs["full_name"] = "" + num_rows_changed += model.objects.filter(**{column: current_username}).update(**update_kwargs) except Exception as exc: log.exception( "Unable to change username from %s to %s. Failed on table %s because %s", current_username, new_username, - model.__class__.__name__, + model._meta.label_lower, exc, ) return False - if num_rows_changed == 0: - log.info( - "Unable to change username from %s to %s because %s doesn't exist.", - current_username, - new_username, - current_username, - ) - else: - log.info( - "Successfully changed username from %s to %s.", - current_username, - new_username, - ) - return True class CourseCertificateViewSet( From 87c7602020c78f4360882ed8bd26f6e83ae43030 Mon Sep 17 00:00:00 2001 From: Naincy Chourasia Date: Thu, 16 Jul 2026 11:07:22 +0000 Subject: [PATCH 2/4] fix: clear full_name during user retirement --- credentials/apps/api/v2/views.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/credentials/apps/api/v2/views.py b/credentials/apps/api/v2/views.py index f3244f0ec..8f1b42ee5 100644 --- a/credentials/apps/api/v2/views.py +++ b/credentials/apps/api/v2/views.py @@ -273,10 +273,38 @@ def _replace_username_for_all_models(self, current_username, new_username, repla "Unable to change username from %s to %s. Failed on table %s because %s", current_username, new_username, - model._meta.label_lower, + model.__class__.__name__, exc, ) return False + if num_rows_changed == 0: + log.info( + "Unable to change username from %s to %s because %s doesn't exist.", + current_username, + new_username, + current_username, + ) + else: + log.info( + "Successfully changed username from %s to %s.", + current_username, + new_username, + ) + return True + if num_rows_changed == 0: + log.info( + "Unable to change username from %s to %s because %s doesn't exist.", + current_username, + new_username, + current_username, + ) + else: + log.info( + "Successfully changed username from %s to %s.", + current_username, + new_username, + ) + return True class CourseCertificateViewSet( From dd90b1e7d1b042753c6d21be133251b2d8841d6b Mon Sep 17 00:00:00 2001 From: Naincy Chourasia Date: Thu, 16 Jul 2026 11:08:28 +0000 Subject: [PATCH 3/4] fix: clear full_name during user retirement --- credentials/apps/api/v2/views.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/credentials/apps/api/v2/views.py b/credentials/apps/api/v2/views.py index 8f1b42ee5..c1d984444 100644 --- a/credentials/apps/api/v2/views.py +++ b/credentials/apps/api/v2/views.py @@ -291,20 +291,6 @@ def _replace_username_for_all_models(self, current_username, new_username, repla new_username, ) return True - if num_rows_changed == 0: - log.info( - "Unable to change username from %s to %s because %s doesn't exist.", - current_username, - new_username, - current_username, - ) - else: - log.info( - "Successfully changed username from %s to %s.", - current_username, - new_username, - ) - return True class CourseCertificateViewSet( From e657ffadac82082a6a704df02691b0fd19ff5aa0 Mon Sep 17 00:00:00 2001 From: Naincy Chourasia Date: Thu, 16 Jul 2026 11:11:49 +0000 Subject: [PATCH 4/4] fix: clear full_name during user retirement --- credentials/apps/api/v2/tests/test_views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/credentials/apps/api/v2/tests/test_views.py b/credentials/apps/api/v2/tests/test_views.py index f7aa36425..905ca97d8 100644 --- a/credentials/apps/api/v2/tests/test_views.py +++ b/credentials/apps/api/v2/tests/test_views.py @@ -703,4 +703,3 @@ def test_clears_full_name_for_replaced_user(self): user.refresh_from_db() self.assertEqual(user.username, new_username) self.assertEqual(user.full_name, "") -