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

Fix room upgrades creating an empty room when auth fails #12696

Merged
merged 10 commits into from
May 16, 2022
1 change: 1 addition & 0 deletions changelog.d/12696.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a long-standing bug where an empty room would be created when a user with an insufficient power level tried to upgrade a room.
64 changes: 39 additions & 25 deletions synapse/handlers/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import attr
from typing_extensions import TypedDict

import synapse.events.snapshot
clokep marked this conversation as resolved.
Show resolved Hide resolved
from synapse.api.constants import (
EventContentFields,
EventTypes,
Expand Down Expand Up @@ -196,6 +197,31 @@ async def upgrade_room(
400, "An upgrade for this room is currently in progress"
)

# Check whether the user has the power level to carry out the upgrade.
# `check_auth_rules_from_context` will check that they are in the room and have
# the required power level to send the tombstone event.
(
tombstone_event,
tombstone_context,
) = await self.event_creation_handler.create_event(
requester,
{
"type": EventTypes.Tombstone,
"state_key": "",
"room_id": old_room_id,
"sender": user_id,
"content": {
"body": "This room has been replaced",
"replacement_room": None, # Use a placeholder value for now
squahtx marked this conversation as resolved.
Show resolved Hide resolved
},
},
)
old_room_version = await self.store.get_room_version(old_room_id)
validate_event_for_room_version(old_room_version, tombstone_event)
await self._event_auth_handler.check_auth_rules_from_context(
old_room_version, tombstone_event, tombstone_context
)

# Upgrade the room
#
# If this user has sent multiple upgrade requests for the same room
Expand All @@ -207,18 +233,29 @@ async def upgrade_room(
requester,
old_room_id,
new_version, # args for _upgrade_room
tombstone_event,
tombstone_context,
)

return ret

async def _upgrade_room(
self, requester: Requester, old_room_id: str, new_version: RoomVersion
self,
requester: Requester,
old_room_id: str,
new_version: RoomVersion,
tombstone_event: EventBase,
tombstone_context: synapse.events.snapshot.EventContext,
) -> str:
"""
Args:
requester: the user requesting the upgrade
old_room_id: the id of the room to be replaced
new_versions: the version to upgrade the room to
tombstone_event: a template for the tombstone event to send to the old room.
`content["replacement_room"]` will be filled in the the id of the new
room.
tombstone_context: the context for the tombstone event

Raises:
ShadowBanError if the requester is shadow-banned.
Expand All @@ -237,30 +274,7 @@ async def _upgrade_room(
)

logger.info("Creating new room %s to replace %s", new_room_id, old_room_id)

# we create and auth the tombstone event before properly creating the new
# room, to check our user has perms in the old room.
(
tombstone_event,
tombstone_context,
) = await self.event_creation_handler.create_event(
requester,
{
"type": EventTypes.Tombstone,
"state_key": "",
"room_id": old_room_id,
"sender": user_id,
"content": {
"body": "This room has been replaced",
"replacement_room": new_room_id,
},
},
)
old_room_version = await self.store.get_room_version(old_room_id)
validate_event_for_room_version(old_room_version, tombstone_event)
await self._event_auth_handler.check_auth_rules_from_context(
old_room_version, tombstone_event, tombstone_context
)
tombstone_event.content["replacement_room"] = new_room_id
squahtx marked this conversation as resolved.
Show resolved Hide resolved

await self.clone_existing_room(
requester,
Expand Down