diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py index f27c0a475d..05e59c1818 100644 --- a/synapse/handlers/profile.py +++ b/synapse/handlers/profile.py @@ -142,13 +142,10 @@ class ProfileHandler: user_id.to_string() ) ) - # Remove ourselves from the user ID list - users_who_share_rooms.remove(user_id.to_string()) - if users_who_share_rooms: - await self.store.track_profile_updates_per_user( - stream_id=stream_id, - user_ids=users_who_share_rooms, - ) + await self.store.track_profile_updates_per_user( + stream_id=stream_id, + user_ids=users_who_share_rooms, + ) self._notifier.on_new_event( StreamKeyType.PROFILE_UPDATES, stream_id, rooms=room_ids diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index b30fc2adb7..17f0467deb 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -2203,11 +2203,6 @@ class SyncHandler: # Filter down to selected included users user_ids = {user_id for user_id in user_ids if user_id in include_users} - # Remove ourselves - # FIXME?: Should `get_local_users_who_share_room_with_user` even return - # ourselves? - user_ids.discard(user_id) - if not user_ids: return diff --git a/synapse/storage/databases/main/profile.py b/synapse/storage/databases/main/profile.py index 1475ee994c..b8a35314fd 100644 --- a/synapse/storage/databases/main/profile.py +++ b/synapse/storage/databases/main/profile.py @@ -670,7 +670,7 @@ class ProfileWorkerStore(SQLBaseStore): ) -> None: """ Create tracking rows for profile updater per target user interested in profile - updates for the user triggering one. + updates for the user triggering one, including themselves. Args: stream_id: Stream ID referencing a `profile_updates` stream ID. diff --git a/synapse/storage/databases/main/roommember.py b/synapse/storage/databases/main/roommember.py index a645e4f3a5..8c69266d51 100644 --- a/synapse/storage/databases/main/roommember.py +++ b/synapse/storage/databases/main/roommember.py @@ -983,7 +983,10 @@ class RoomMemberWorkerStore(EventsWorkerStore, CacheInvalidationWorkerStore): return user_who_share_room async def get_local_users_who_share_room_with_user(self, user_id: str) -> set[str]: - """Returns the set of local users who share a room with `user_id`""" + """Returns the set of local users who share a room with `user_id`. + + This also includes the `user_id` themselves. + """ room_ids = await self.get_rooms_for_user(user_id) user_who_share_room: set[str] = set() diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py index 82c1e7c435..0bf940d24b 100644 --- a/tests/handlers/test_profile.py +++ b/tests/handlers/test_profile.py @@ -415,6 +415,12 @@ class ProfileTestCase(unittest.HomeserverTestCase): action="joined_room", field_name=None, ), + ProfileUpdate( + stream_id=4, + user_id=self.frank.to_string(), + action="update", + field_name="m.status", + ), ], ) diff --git a/tests/handlers/test_sync.py b/tests/handlers/test_sync.py index f72cf54956..61cf0b0237 100644 --- a/tests/handlers/test_sync.py +++ b/tests/handlers/test_sync.py @@ -1241,7 +1241,8 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): @override_config({"include_profile_updates_in_sync": True}) def test_initial_sync_responds_with_tracked_profile_updates(self) -> None: """Test that with MSC4429 enabled the initial sync response does - contain profile updates for users who share rooms.""" + contain profile updates for users who share rooms, including our + syncing user.""" self.get_success( self.profile_handler.set_field( target_user=UserID.from_string(self.other_user), @@ -1269,6 +1270,7 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): request_key=generate_request_key(), ) ) + assert initial_result.profile_updates[self.user] is not None assert initial_result.profile_updates["@other_user:test"] is not None self.assertEqual( initial_result.profile_updates["@other_user:test"]["m.status"], @@ -1277,6 +1279,7 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): self.assertCountEqual( initial_result.profile_updates.keys(), [ + self.user, "@other_user:test", ], ) @@ -1804,6 +1807,69 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): incremental_result.profile_updates["@third_user:test"]["avatar_url"], ) + @parameterized.expand( + [ + True, + False, + ] + ) + @override_config({"include_profile_updates_in_sync": True}) + def test_incremental_sync_includes_own_profile_updates(self, is_lazy: bool) -> None: + """Test that with MSC4429 enabled the incremental sync response includes + ones own profile updates.""" + requester = create_requester(self.user) + filter_json: dict[str, dict] = { + "org.matrix.msc4429.profile_fields": { + "ids": ["m.status", "displayname", "avatar_url"] + } + } + if is_lazy: + filter_json["room"] = { + "state": { + "lazy_load_members": True, + }, + } + initial_result = self.get_success( + self.sync_handler.wait_for_sync_for_user( + requester, + sync_config=generate_sync_config( + user_id=self.user, + filter_collection=FilterCollection( + hs=self.hs, + filter_json=filter_json, + ), + ), + request_key=generate_request_key(), + ) + ) + self.get_success( + self.profile_handler.set_field( + target_user=UserID.from_string(self.user), + requester=requester, + field_name="m.status", + new_value=json.dumps({"text": "On holiday", "emoji": "🏖"}), + ) + ) + incremental_result = self.get_success( + self.sync_handler.wait_for_sync_for_user( + requester, + since_token=initial_result.next_batch, + sync_config=generate_sync_config( + user_id=self.user, + filter_collection=FilterCollection( + hs=self.hs, + filter_json=filter_json, + ), + ), + request_key=generate_request_key(), + ) + ) + assert incremental_result.profile_updates["@user:test"] is not None + self.assertEqual( + incremental_result.profile_updates["@user:test"]["m.status"], + '{"text": "On holiday", "emoji": "\\ud83c\\udfd6"}', + ) + class SyncStateAfterTestCase(tests.unittest.HomeserverTestCase): """Tests Sync Handler state behavior when using `use_state_after."""