summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--changelog.d/4099.feature1
-rw-r--r--synapse/handlers/room.py125
2 files changed, 82 insertions, 44 deletions
diff --git a/changelog.d/4099.feature b/changelog.d/4099.feature
new file mode 100644
index 0000000000..a3f7dbdcdd
--- /dev/null
+++ b/changelog.d/4099.feature
@@ -0,0 +1 @@
+Support for replacing rooms with new ones
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 8e48c1ca6a..70085db625 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -136,53 +136,91 @@ class RoomCreationHandler(BaseHandler):
                 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(
@@ -223,7 +261,6 @@ class RoomCreationHandler(BaseHandler):
         initial_state = dict()
 
         types_to_copy = (
-            (EventTypes.PowerLevels, ""),
             (EventTypes.JoinRules, ""),
             (EventTypes.Name, ""),
             (EventTypes.Topic, ""),