Merge pull request #4099 from matrix-org/rav/upgrade_odd_pls

Better handling of odd PLs during room upgrades
This commit is contained in:
Richard van der Hoff 2018-10-29 12:48:51 +00:00 committed by GitHub
commit 56ca578f77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 42 deletions

1
changelog.d/4099.feature Normal file
View file

@ -0,0 +1 @@
Support for replacing rooms with new ones

View file

@ -136,53 +136,91 @@ class RoomCreationHandler(BaseHandler):
requester, tombstone_event, tombstone_context, 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_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: yield self._update_upgraded_room_pls(
logger.warning( requester, old_room_id, new_room_id, old_room_state,
"Not supported: upgrading a room with no PL event. Not setting PLs " )
"in old room.",
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: else:
# we try to stop regular users from speaking by setting the PL required logger.info(
# to send regular events and invites to 'Moderator' level. That's normally "Not setting level for %s (already %i)",
# 50, but if the default PL in a room is 50 or more, then we set the v, current,
# required PL above that. )
old_room_pl_state = yield self.store.get_event(old_room_pl_event_id) if updated:
pl_content = dict(old_room_pl_state.content) try:
users_default = int(pl_content.get("users_default", 0)) yield self.event_creation_handler.create_and_send_nonmember_event(
restricted_level = max(users_default + 1, 50) 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)
updated = False logger.info("Setting correct PLs in new room")
for v in ("invite", "events_default"): yield self.event_creation_handler.create_and_send_nonmember_event(
current = int(pl_content.get(v, 0)) requester, {
if current < restricted_level: "type": EventTypes.PowerLevels,
logger.debug( "state_key": '',
"Setting level for %s in %s to %i (was %i)", "room_id": new_room_id,
v, old_room_id, restricted_level, current, "sender": requester.user.to_string(),
) "content": old_room_pl_state.content,
pl_content[v] = restricted_level }, ratelimit=False,
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)
@defer.inlineCallbacks @defer.inlineCallbacks
def clone_exiting_room( def clone_exiting_room(
@ -223,7 +261,6 @@ class RoomCreationHandler(BaseHandler):
initial_state = dict() initial_state = dict()
types_to_copy = ( types_to_copy = (
(EventTypes.PowerLevels, ""),
(EventTypes.JoinRules, ""), (EventTypes.JoinRules, ""),
(EventTypes.Name, ""), (EventTypes.Name, ""),
(EventTypes.Topic, ""), (EventTypes.Topic, ""),