Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 2e2d8cc

Browse files
authored
Update the server notices user profile in room if changed. (#12115)
1 parent 7851a2c commit 2e2d8cc

File tree

3 files changed

+148
-4
lines changed

3 files changed

+148
-4
lines changed

Diff for: changelog.d/12115.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug that updating the server notices user profile (display name/avatar URL) in the configuration would not be applied to pre-existing rooms. Contributed by Jorge Florian.

Diff for: synapse/server_notices/server_notices_manager.py

+55-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from synapse.api.constants import EventTypes, Membership, RoomCreationPreset
1818
from synapse.events import EventBase
19-
from synapse.types import UserID, create_requester
19+
from synapse.types import Requester, UserID, create_requester
2020
from synapse.util.caches.descriptors import cached
2121

2222
if TYPE_CHECKING:
@@ -35,6 +35,7 @@ def __init__(self, hs: "HomeServer"):
3535
self._room_creation_handler = hs.get_room_creation_handler()
3636
self._room_member_handler = hs.get_room_member_handler()
3737
self._event_creation_handler = hs.get_event_creation_handler()
38+
self._message_handler = hs.get_message_handler()
3839
self._is_mine_id = hs.is_mine_id
3940
self._server_name = hs.hostname
4041

@@ -107,6 +108,10 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
107108

108109
assert self._is_mine_id(user_id), "Cannot send server notices to remote users"
109110

111+
requester = create_requester(
112+
self.server_notices_mxid, authenticated_entity=self._server_name
113+
)
114+
110115
rooms = await self._store.get_rooms_for_local_user_where_membership_is(
111116
user_id, [Membership.INVITE, Membership.JOIN]
112117
)
@@ -125,6 +130,12 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
125130
room.room_id,
126131
user_id,
127132
)
133+
await self._update_notice_user_profile_if_changed(
134+
requester,
135+
room.room_id,
136+
self._config.servernotices.server_notices_mxid_display_name,
137+
self._config.servernotices.server_notices_mxid_avatar_url,
138+
)
128139
return room.room_id
129140

130141
# apparently no existing notice room: create a new one
@@ -143,9 +154,6 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
143154
"avatar_url": self._config.servernotices.server_notices_mxid_avatar_url,
144155
}
145156

146-
requester = create_requester(
147-
self.server_notices_mxid, authenticated_entity=self._server_name
148-
)
149157
info, _ = await self._room_creation_handler.create_room(
150158
requester,
151159
config={
@@ -194,3 +202,46 @@ async def maybe_invite_user_to_room(self, user_id: str, room_id: str) -> None:
194202
room_id=room_id,
195203
action="invite",
196204
)
205+
206+
async def _update_notice_user_profile_if_changed(
207+
self,
208+
requester: Requester,
209+
room_id: str,
210+
display_name: Optional[str],
211+
avatar_url: Optional[str],
212+
) -> None:
213+
"""
214+
Updates the notice user's profile if it's different from what is in the room.
215+
216+
Args:
217+
requester: The user who is performing the update.
218+
room_id: The ID of the server notice room
219+
display_name: The displayname of the server notice user
220+
avatar_url: The avatar url of the server notice user
221+
"""
222+
logger.debug("Checking whether notice user profile has changed for %s", room_id)
223+
224+
assert self.server_notices_mxid is not None
225+
226+
notice_user_data_in_room = await self._message_handler.get_room_data(
227+
self.server_notices_mxid,
228+
room_id,
229+
EventTypes.Member,
230+
self.server_notices_mxid,
231+
)
232+
233+
assert notice_user_data_in_room is not None
234+
235+
notice_user_profile_changed = (
236+
display_name != notice_user_data_in_room.content.get("displayname")
237+
or avatar_url != notice_user_data_in_room.content.get("avatar_url")
238+
)
239+
if notice_user_profile_changed:
240+
logger.info("Updating notice user profile in room %s", room_id)
241+
await self._room_member_handler.update_membership(
242+
requester=requester,
243+
target=UserID.from_string(self.server_notices_mxid),
244+
room_id=room_id,
245+
action="join",
246+
content={"displayname": display_name, "avatar_url": avatar_url},
247+
)

Diff for: tests/rest/admin/test_server_notice.py

+92
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,98 @@ def test_send_server_notice_delete_room(self) -> None:
409409
# second room has new ID
410410
self.assertNotEqual(first_room_id, second_room_id)
411411

412+
@override_config({"server_notices": {"system_mxid_localpart": "notices"}})
413+
def test_update_notice_user_name_when_changed(self) -> None:
414+
"""
415+
Tests that existing server notices user name in room is updated after
416+
server notice config changes.
417+
"""
418+
server_notice_request_content = {
419+
"user_id": self.other_user,
420+
"content": {"msgtype": "m.text", "body": "test msg one"},
421+
}
422+
423+
self.make_request(
424+
"POST",
425+
self.url,
426+
access_token=self.admin_user_tok,
427+
content=server_notice_request_content,
428+
)
429+
430+
# simulate a change in server config after a server restart.
431+
new_display_name = "new display name"
432+
self.server_notices_manager._config.servernotices.server_notices_mxid_display_name = (
433+
new_display_name
434+
)
435+
self.server_notices_manager.get_or_create_notice_room_for_user.cache.invalidate_all()
436+
437+
self.make_request(
438+
"POST",
439+
self.url,
440+
access_token=self.admin_user_tok,
441+
content=server_notice_request_content,
442+
)
443+
444+
invited_rooms = self._check_invite_and_join_status(self.other_user, 1, 0)
445+
notice_room_id = invited_rooms[0].room_id
446+
self.helper.join(
447+
room=notice_room_id, user=self.other_user, tok=self.other_user_token
448+
)
449+
450+
notice_user_state_in_room = self.helper.get_state(
451+
notice_room_id,
452+
"m.room.member",
453+
self.other_user_token,
454+
state_key="@notices:test",
455+
)
456+
self.assertEqual(notice_user_state_in_room["displayname"], new_display_name)
457+
458+
@override_config({"server_notices": {"system_mxid_localpart": "notices"}})
459+
def test_update_notice_user_avatar_when_changed(self) -> None:
460+
"""
461+
Tests that existing server notices user avatar in room is updated when is
462+
different from the one in homeserver config.
463+
"""
464+
server_notice_request_content = {
465+
"user_id": self.other_user,
466+
"content": {"msgtype": "m.text", "body": "test msg one"},
467+
}
468+
469+
self.make_request(
470+
"POST",
471+
self.url,
472+
access_token=self.admin_user_tok,
473+
content=server_notice_request_content,
474+
)
475+
476+
# simulate a change in server config after a server restart.
477+
new_avatar_url = "test/new-url"
478+
self.server_notices_manager._config.servernotices.server_notices_mxid_avatar_url = (
479+
new_avatar_url
480+
)
481+
self.server_notices_manager.get_or_create_notice_room_for_user.cache.invalidate_all()
482+
483+
self.make_request(
484+
"POST",
485+
self.url,
486+
access_token=self.admin_user_tok,
487+
content=server_notice_request_content,
488+
)
489+
490+
invited_rooms = self._check_invite_and_join_status(self.other_user, 1, 0)
491+
notice_room_id = invited_rooms[0].room_id
492+
self.helper.join(
493+
room=notice_room_id, user=self.other_user, tok=self.other_user_token
494+
)
495+
496+
notice_user_state = self.helper.get_state(
497+
notice_room_id,
498+
"m.room.member",
499+
self.other_user_token,
500+
state_key="@notices:test",
501+
)
502+
self.assertEqual(notice_user_state["avatar_url"], new_avatar_url)
503+
412504
def _check_invite_and_join_status(
413505
self, user_id: str, expected_invites: int, expected_memberships: int
414506
) -> List[RoomsForUser]:

0 commit comments

Comments
 (0)