From 69232e8b9e4d232493889c659bf40f905c3f8402 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 14 Aug 2025 12:22:24 +0100 Subject: [PATCH 1/4] Only send one power levels event in upgraded rooms The second attempt to send a power levels event was not MSC4289-aware - it would drop the request back down to PL0 when copying the old room's power levels a second time. The second attempt to send power levels didn't appear to do anything useful anyways. So simply removing it fixes both the bug, and saves a state event. Fixes https://github.com/element-hq/synapse/issues/18810 --- synapse/handlers/room.py | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 47bd139ca71..fe2d348ee31 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -419,34 +419,27 @@ async def _upgrade_room( old_room_id, new_room_id ) - # finally, shut down the PLs in the old room, and update them in the new - # room. - await self._update_upgraded_room_pls( + # finally, shut down the PLs in the old room + await self._shutdown_power_levels_in_upgraded_room( requester, old_room_id, - new_room_id, old_room_state, - additional_creators, ) return new_room_id - async def _update_upgraded_room_pls( + async def _shutdown_power_levels_in_upgraded_room( self, requester: Requester, old_room_id: str, - new_room_id: str, old_room_state: StateMap[str], - additional_creators: Optional[List[str]], ) -> None: - """Send updated power levels in both rooms after an upgrade + """Send updated power levels in the old room after it has been upgraded Args: requester: the user requesting the upgrade old_room_id: the id of the room to be replaced - new_room_id: the id of the replacement room old_room_state: the state map for the old room - additional_creators: Additional creators in the new room. Raises: ShadowBanError if the requester is shadow-banned. """ @@ -502,28 +495,6 @@ async def _update_upgraded_room_pls( except AuthError as e: logger.warning("Unable to update PLs in old room: %s", e) - new_room_version = await self.store.get_room_version(new_room_id) - if new_room_version.msc4289_creator_power_enabled: - self._remove_creators_from_pl_users_map( - old_room_pl_state.content.get("users", {}), - requester.user.to_string(), - additional_creators, - ) - - await self.event_creation_handler.create_and_send_nonmember_event( - requester, - { - "type": EventTypes.PowerLevels, - "state_key": "", - "room_id": new_room_id, - "sender": requester.user.to_string(), - "content": copy_and_fixup_power_levels_contents( - old_room_pl_state.content - ), - }, - ratelimit=False, - ) - def _calculate_upgraded_room_creation_content( self, old_room_create_event: EventBase, @@ -686,7 +657,6 @@ async def clone_existing_room( user_power_levels[user_id] = needed_power_level if new_room_version.msc4289_creator_power_enabled: - # the creator(s) cannot be in the users map self._remove_creators_from_pl_users_map( user_power_levels, user_id, From 5cc9b77b676c135f9a8865d2378e9a931c4553f5 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 14 Aug 2025 12:22:32 +0100 Subject: [PATCH 2/4] Update doc comment --- synapse/events/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synapse/events/utils.py b/synapse/events/utils.py index cae27136cec..feadf29df27 100644 --- a/synapse/events/utils.py +++ b/synapse/events/utils.py @@ -763,8 +763,8 @@ def copy_and_fixup_power_levels_contents( integer, e.g. `"`100"` instead of 100. Such strings are converted to integers in the returned dictionary (hence "fixup" in the function name). - Note that future room versions will outlaw such stringy power levels (see - https://github.com/matrix-org/matrix-spec/issues/853). + Note that room versions 10+ outlaws such stringy power levels (see + https://github.com/matrix-org/matrix-spec-proposals/pull/3667). Raises: TypeError if the input does not look like a valid power levels event content From 5db22b0c43d0a92eb85e69faf75f79c12767ede6 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 14 Aug 2025 15:01:06 +0100 Subject: [PATCH 3/4] Grant power level to `additional_creators` on upgrade --- synapse/handlers/room.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index fe2d348ee31..ca9851c7d14 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -656,6 +656,27 @@ async def clone_existing_room( if current_power_level_int < needed_power_level: user_power_levels[user_id] = needed_power_level + # If downgrading from a room that supports MSC4289 to one that doesn't... + if ( + old_room_create_event.room_version.msc4289_creator_power_enabled + and not new_room_version.msc4289_creator_power_enabled + ): + # Additionally raise the power levels of all `additional_creators` in the old + # room to the `needed_power_level` in the new room. + old_room_additional_creators = old_room_create_event.content.get( + "additional_creators", [] + ) + for user_id in old_room_additional_creators: + old_power_level = user_power_levels.get(user_id, users_default) + try: + old_power_level = int(old_power_level) # type: ignore[arg-type] + except (TypeError, ValueError): + old_power_level = 0 + + # Raise the requester's power level in the new room if necessary + if old_power_level < needed_power_level: + user_power_levels[user_id] = needed_power_level + if new_room_version.msc4289_creator_power_enabled: self._remove_creators_from_pl_users_map( user_power_levels, From b005c6d12a079e1cf2d9179d3f7c33e904bec015 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 14 Aug 2025 16:28:15 +0100 Subject: [PATCH 4/4] newsfile --- changelog.d/18818.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/18818.bugfix diff --git a/changelog.d/18818.bugfix b/changelog.d/18818.bugfix new file mode 100644 index 00000000000..dea342a1001 --- /dev/null +++ b/changelog.d/18818.bugfix @@ -0,0 +1 @@ +Fix a bug where room creators would be set to the default power level when downgrading v12 rooms. \ No newline at end of file