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

Commit

Permalink
Better handling of odd PLs during room upgrades
Browse files Browse the repository at this point in the history
Fixes handling of rooms where we have permission to send the tombstone, but not
other state. We need to (a) fail more gracefully when we can't send the PLs in
the old room, and (b) not set the PLs in the new room until we are done with
the other stuff.
  • Loading branch information
richvdh committed Oct 26, 2018
1 parent 54bbe71 commit db24d7f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 44 deletions.
1 change: 1 addition & 0 deletions changelog.d/4099.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support for replacing rooms with new ones
125 changes: 81 additions & 44 deletions synapse/handlers/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,53 +136,91 @@ def upgrade_room(self, requester, old_room_id, new_version):
requester, tombstone_event, tombstone_context,
)

# and finally, shut down the PLs in the old room, and update them in the new
# room.
old_room_state = yield tombstone_context.get_current_state_ids(self.store)
old_room_pl_event_id = old_room_state.get((EventTypes.PowerLevels, ""))

if old_room_pl_event_id is None:
logger.warning(
"Not supported: upgrading a room with no PL event. Not setting PLs "
"in old room.",
yield self._update_upgraded_room_pls(
requester, old_room_id, new_room_id, old_room_state,
)

defer.returnValue(new_room_id)

@defer.inlineCallbacks
def _update_upgraded_room_pls(
self, requester, old_room_id, new_room_id, old_room_state,
):
"""Send updated power levels in both rooms after an upgrade
Args:
requester (synapse.types.Requester): the user requesting the upgrade
old_room_id (unicode): the id of the room to be replaced
new_room_id (unicode): the id of the replacement room
old_room_state (dict[tuple[str, str], str]): the state map for the old room
Returns:
Deferred
"""
old_room_pl_event_id = old_room_state.get((EventTypes.PowerLevels, ""))

if old_room_pl_event_id is None:
logger.warning(
"Not supported: upgrading a room with no PL event. Not setting PLs "
"in old room.",
)
return

old_room_pl_state = yield self.store.get_event(old_room_pl_event_id)

# we try to stop regular users from speaking by setting the PL required
# to send regular events and invites to 'Moderator' level. That's normally
# 50, but if the default PL in a room is 50 or more, then we set the
# required PL above that.

pl_content = dict(old_room_pl_state.content)
users_default = int(pl_content.get("users_default", 0))
restricted_level = max(users_default + 1, 50)

updated = False
for v in ("invite", "events_default"):
current = int(pl_content.get(v, 0))
if current < restricted_level:
logger.info(
"Setting level for %s in %s to %i (was %i)",
v, old_room_id, restricted_level, current,
)
pl_content[v] = restricted_level
updated = True
else:
# we try to stop regular users from speaking by setting the PL required
# to send regular events and invites to 'Moderator' level. That's normally
# 50, but if the default PL in a room is 50 or more, then we set the
# required PL above that.

old_room_pl_state = yield self.store.get_event(old_room_pl_event_id)
pl_content = dict(old_room_pl_state.content)
users_default = int(pl_content.get("users_default", 0))
restricted_level = max(users_default + 1, 50)

updated = False
for v in ("invite", "events_default"):
current = int(pl_content.get(v, 0))
if current < restricted_level:
logger.debug(
"Setting level for %s in %s to %i (was %i)",
v, old_room_id, restricted_level, current,
)
pl_content[v] = restricted_level
updated = True
else:
logger.debug(
"Not setting level for %s (already %i)",
v, current,
)

if updated:
yield self.event_creation_handler.create_and_send_nonmember_event(
requester, {
"type": EventTypes.PowerLevels,
"state_key": '',
"room_id": old_room_id,
"sender": user_id,
"content": pl_content,
}, ratelimit=False,
)

defer.returnValue(new_room_id)
logger.info(
"Not setting level for %s (already %i)",
v, current,
)

if updated:
try:
yield self.event_creation_handler.create_and_send_nonmember_event(
requester, {
"type": EventTypes.PowerLevels,
"state_key": '',
"room_id": old_room_id,
"sender": requester.user.to_string(),
"content": pl_content,
}, ratelimit=False,
)
except AuthError as e:
logger.warning("Unable to update PLs in old room: %s", e)

logger.info("Setting correct PLs in new room")
yield 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": old_room_pl_state.content,
}, ratelimit=False,
)

@defer.inlineCallbacks
def clone_exiting_room(
Expand Down Expand Up @@ -223,7 +261,6 @@ def clone_exiting_room(
initial_state = dict()

types_to_copy = (
(EventTypes.PowerLevels, ""),
(EventTypes.JoinRules, ""),
(EventTypes.Name, ""),
(EventTypes.Topic, ""),
Expand Down

0 comments on commit db24d7f

Please sign in to comment.