diff --git a/osf/models/user.py b/osf/models/user.py index 560c7ea1324..72ca2b8f3f8 100644 --- a/osf/models/user.py +++ b/osf/models/user.py @@ -728,6 +728,11 @@ def merge_user(self, user): if self == user: raise ValueError('Cannot merge a user into itself') + # Capture content to SHARE reindex BEFORE merge transfers contributors + # After merge, user.contributed and user.preprints will be empty + nodes_to_reindex = list(user.contributed) + preprints_to_reindex = list(user.preprints.all()) + # Move over the other user's attributes # TODO: confirm for system_tag in user.system_tags.all(): @@ -859,13 +864,13 @@ def merge_user(self, user): from api.share.utils import update_share - for node in user.contributed: + for node in nodes_to_reindex: try: update_share(node) except Exception as e: logger.exception(f'Failed to SHARE reindex node {node._id} during user merge: {e}') - for preprint in user.preprints.all(): + for preprint in preprints_to_reindex: try: update_share(preprint) except Exception as e: diff --git a/osf_tests/test_user.py b/osf_tests/test_user.py index 14ea4969eaa..a2fc5b0e92a 100644 --- a/osf_tests/test_user.py +++ b/osf_tests/test_user.py @@ -442,6 +442,41 @@ def test_merge_drafts(self, user): assert not draft_five.has_permission(user2, permissions.READ) assert not draft_five.is_contributor(user2) + @mock.patch('api.share.utils.update_share') + def test_merge_user_triggers_share_reindex(self, mock_update_share): + from osf.models import Preprint + + user = AuthUserFactory() + user2 = AuthUserFactory() + + node_one = ProjectFactory(creator=user2, title='node_one') + node_two = ProjectFactory(title='node_two') + node_two.add_contributor(user2) + + preprint_one = PreprintFactory(creator=user2, title='preprint_one') + preprint_two = PreprintFactory(title='preprint_two') + preprint_two.add_contributor(user2) + + user.merge_user(user2) + + # Verify update_share was called for both nodes + nodes_reindexed = [ + call[0][0] for call in mock_update_share.call_args_list + if isinstance(call[0][0], AbstractNode) + ] + assert len(nodes_reindexed) == 2 + assert node_one in nodes_reindexed + assert node_two in nodes_reindexed + + # Verify update_share was called for both preprints + preprints_reindexed = [ + call[0][0] for call in mock_update_share.call_args_list + if isinstance(call[0][0], Preprint) + ] + assert len(preprints_reindexed) == 2 + assert preprint_one in preprints_reindexed + assert preprint_two in preprints_reindexed + def test_cant_create_user_without_username(self): u = OSFUser() # No username given with pytest.raises(ValidationError):