diff --git a/changelog.d/18471.misc b/changelog.d/18471.misc
new file mode 100644
index 0000000000..b36712bea3
--- /dev/null
+++ b/changelog.d/18471.misc
@@ -0,0 +1 @@
+Don't move invited users to new room when shutting down room.
\ No newline at end of file
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 386375d64b..763f99e028 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -1806,7 +1806,7 @@ class RoomShutdownHandler:
] = None,
) -> Optional[ShutdownRoomResponse]:
"""
- Shuts down a room. Moves all local users and room aliases automatically
+ Shuts down a room. Moves all joined local users and room aliases automatically
to a new room if `new_room_user_id` is set. Otherwise local users only
leave the room without any information.
@@ -1949,16 +1949,17 @@ class RoomShutdownHandler:
# Join users to new room
if new_room_user_id:
- assert new_room_id is not None
- await self.room_member_handler.update_membership(
- requester=target_requester,
- target=target_requester.user,
- room_id=new_room_id,
- action=Membership.JOIN,
- content={},
- ratelimit=False,
- require_consent=False,
- )
+ if membership == Membership.JOIN:
+ assert new_room_id is not None
+ await self.room_member_handler.update_membership(
+ requester=target_requester,
+ target=target_requester.user,
+ room_id=new_room_id,
+ action=Membership.JOIN,
+ content={},
+ ratelimit=False,
+ require_consent=False,
+ )
result["kicked_users"].append(user_id)
if update_result_fct:
diff --git a/tests/rest/admin/test_room.py b/tests/rest/admin/test_room.py
index 8d806082aa..e22dfcba1b 100644
--- a/tests/rest/admin/test_room.py
+++ b/tests/rest/admin/test_room.py
@@ -369,6 +369,47 @@ class DeleteRoomTestCase(unittest.HomeserverTestCase):
self.assertEqual(200, channel.code, msg=channel.json_body)
self._is_blocked(room_id)
+ def test_invited_users_not_joined_to_new_room(self) -> None:
+ """
+ Test that when a new room id is provided, users who are only invited
+ but have not joined original room are not moved to new room.
+ """
+ invitee = self.register_user("invitee", "pass")
+
+ self.helper.invite(
+ self.room_id, self.other_user, invitee, tok=self.other_user_tok
+ )
+
+ # verify that user is invited
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/client/v3/rooms/{self.room_id}/members?membership=invite",
+ access_token=self.other_user_tok,
+ )
+ self.assertEqual(channel.code, 200)
+ self.assertEqual(len(channel.json_body["chunk"]), 1)
+ invite = channel.json_body["chunk"][0]
+ self.assertEqual(invite["state_key"], invitee)
+
+ # shutdown room
+ channel = self.make_request(
+ "DELETE",
+ self.url,
+ {"new_room_user_id": self.admin_user},
+ access_token=self.admin_user_tok,
+ )
+ self.assertEqual(200, channel.code, msg=channel.json_body)
+ self.assertEqual(len(channel.json_body["kicked_users"]), 2)
+
+ # joined member is moved to new room but invited user is not
+ users_in_room = self.get_success(
+ self.store.get_users_in_room(channel.json_body["new_room_id"])
+ )
+ self.assertNotIn(invitee, users_in_room)
+ self.assertIn(self.other_user, users_in_room)
+ self._is_purged(self.room_id)
+ self._has_no_members(self.room_id)
+
def test_shutdown_room_consent(self) -> None:
"""Test that we can shutdown rooms with local users who have not
yet accepted the privacy policy. This used to fail when we tried to
|