From b6818fd4d2108543ce86b5d8bf540e74a89cf27e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 17 Sep 2014 15:05:09 +0100 Subject: [PATCH] SYN-40: When a user updates their displayname or avatar update all their join events for all the rooms they are currently in. --- synapse/handlers/profile.py | 46 +++++++++++++++++++++++++++-- tests/handlers/test_presencelike.py | 11 +++++++ tests/handlers/test_profile.py | 21 +++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py index 023d8c0cf2..dab9b03f04 100644 --- a/synapse/handlers/profile.py +++ b/synapse/handlers/profile.py @@ -15,9 +15,9 @@ from twisted.internet import defer -from synapse.api.errors import SynapseError, AuthError - -from synapse.api.errors import CodeMessageException +from synapse.api.errors import SynapseError, AuthError, CodeMessageException +from synapse.api.constants import Membership +from synapse.api.events.room import RoomMemberEvent from ._base import BaseHandler @@ -97,6 +97,8 @@ class ProfileHandler(BaseHandler): } ) + yield self._update_join_states(target_user) + @defer.inlineCallbacks def get_avatar_url(self, target_user): if target_user.is_mine: @@ -144,6 +146,8 @@ class ProfileHandler(BaseHandler): } ) + yield self._update_join_states(target_user) + @defer.inlineCallbacks def collect_presencelike_data(self, user, state): if not user.is_mine: @@ -180,3 +184,39 @@ class ProfileHandler(BaseHandler): ) defer.returnValue(response) + + @defer.inlineCallbacks + def _update_join_states(self, user): + if not user.is_mine: + return + + joins = yield self.store.get_rooms_for_user_where_membership_is( + user.to_string(), + [Membership.JOIN], + ) + + for j in joins: + snapshot = yield self.store.snapshot_room( + j.room_id, j.state_key, RoomMemberEvent.TYPE, + j.state_key + ) + + content = { + "membership": j.content["membership"], + "prev": j.content["membership"], + } + + yield self.distributor.fire( + "collect_presencelike_data", user, content + ) + + new_event = self.event_factory.create_event( + etype=j.type, + room_id=j.room_id, + state_key=j.state_key, + content=content, + user_id=j.state_key, + ) + + yield self.state_handler.handle_new_event(new_event, snapshot) + yield self._on_new_room_event(new_event, snapshot) diff --git a/tests/handlers/test_presencelike.py b/tests/handlers/test_presencelike.py index 72c55b3667..047752ad68 100644 --- a/tests/handlers/test_presencelike.py +++ b/tests/handlers/test_presencelike.py @@ -65,6 +65,8 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase): "is_presence_visible", "set_profile_displayname", + + "get_rooms_for_user_where_membership_is", ]), handlers=None, resource_for_federation=Mock(), @@ -132,6 +134,10 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase): # Remote user self.u_potato = hs.parse_userid("@potato:remote") + self.mock_get_joined = ( + self.datastore.get_rooms_for_user_where_membership_is + ) + @defer.inlineCallbacks def test_set_my_state(self): self.presence_list = [ @@ -152,6 +158,11 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase): @defer.inlineCallbacks def test_push_local(self): + def get_joined(*args): + return defer.succeed([]) + + self.mock_get_joined.side_effect = get_joined + self.presence_list = [ {"observed_user_id": "@banana:test"}, {"observed_user_id": "@clementine:test"}, diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py index 0a5cebb4cc..ee2be9b6d5 100644 --- a/tests/handlers/test_profile.py +++ b/tests/handlers/test_profile.py @@ -22,6 +22,7 @@ from mock import Mock from synapse.api.errors import AuthError from synapse.server import HomeServer from synapse.handlers.profile import ProfileHandler +from synapse.api.constants import Membership class ProfileHandlers(object): @@ -50,6 +51,7 @@ class ProfileTestCase(unittest.TestCase): "set_profile_displayname", "get_profile_avatar_url", "set_profile_avatar_url", + "get_rooms_for_user_where_membership_is", ]), handlers=None, resource_for_federation=Mock(), @@ -65,6 +67,10 @@ class ProfileTestCase(unittest.TestCase): self.handler = hs.get_handlers().profile_handler + self.mock_get_joined = ( + self.datastore.get_rooms_for_user_where_membership_is + ) + # TODO(paul): Icky signal declarings.. booo hs.get_distributor().declare("changed_presencelike_data") @@ -83,8 +89,15 @@ class ProfileTestCase(unittest.TestCase): mocked_set = self.datastore.set_profile_displayname mocked_set.return_value = defer.succeed(()) + self.mock_get_joined.return_value = defer.succeed([]) + yield self.handler.set_displayname(self.frank, self.frank, "Frank Jr.") + self.mock_get_joined.assert_called_once_with( + self.frank.to_string(), + [Membership.JOIN] + ) + mocked_set.assert_called_with("1234ABCD", "Frank Jr.") @defer.inlineCallbacks @@ -135,7 +148,15 @@ class ProfileTestCase(unittest.TestCase): mocked_set = self.datastore.set_profile_avatar_url mocked_set.return_value = defer.succeed(()) + self.mock_get_joined.return_value = defer.succeed([]) + yield self.handler.set_avatar_url(self.frank, self.frank, "http://my.server/pic.gif") + self.mock_get_joined.assert_called_once_with( + self.frank.to_string(), + [Membership.JOIN] + ) + + mocked_set.assert_called_with("1234ABCD", "http://my.server/pic.gif")