tuwunel_api/client/admin/rooms/
delete_room.rs1use axum::extract::State;
2use ruma::{RoomId, UserId};
3use synapse_admin_api::rooms::delete_room::{
4 v1::{Request as V1Request, Response as V1Response, ShutdownRoom},
5 v2::{Request as V2Request, Response as V2Response},
6};
7use tuwunel_core::Result;
8use tuwunel_service::rooms::delete::ShutdownRoom as Summary;
9
10use crate::{Ruma, client::admin::require_admin};
11
12pub(crate) async fn admin_delete_room_v1_route(
19 State(services): State<crate::State>,
20 body: Ruma<V1Request>,
21) -> Result<V1Response> {
22 require_admin(&services, body.sender_user()).await?;
23
24 let summary =
25 run_shutdown(&services, &body.room_id, body.sender_user(), body.block, body.purge).await;
26
27 Ok(V1Response { result: into_response(summary) })
28}
29
30pub(crate) async fn admin_delete_room_v2_route(
35 State(services): State<crate::State>,
36 body: Ruma<V2Request>,
37) -> Result<V2Response> {
38 require_admin(&services, body.sender_user()).await?;
39
40 let room_id = body.room_id.clone();
41 let sender = body.sender_user().to_owned();
42 let (block, purge) = (body.block, body.purge);
43
44 let work = async move {
45 let summary = run_shutdown(&services, &room_id, &sender, block, purge).await;
46
47 Ok(serde_json::to_value(summary)?)
48 };
49
50 let delete_id = services
51 .tasks
52 .spawn(super::DELETE_ROOM_ACTION, body.room_id.to_string(), work)
53 .to_string();
54
55 Ok(V2Response { delete_id })
56}
57
58async fn run_shutdown(
62 services: &crate::State,
63 room_id: &RoomId,
64 sender: &UserId,
65 block: bool,
66 purge: bool,
67) -> Summary {
68 let state_lock = services.state.mutex.lock(room_id).await;
69
70 let summary = if purge {
71 services
72 .delete
73 .delete_room(room_id, false, state_lock)
74 .await
75 .unwrap_or_default()
76 } else {
77 services
78 .delete
79 .shutdown_room(room_id, &state_lock)
80 .await
81 };
82
83 if block {
84 services.metadata.block_room(room_id, sender);
85 }
86
87 summary
88}
89
90fn into_response(summary: Summary) -> ShutdownRoom {
91 ShutdownRoom {
92 kicked_users: summary.kicked_users,
93 failed_to_kick_users: summary.failed_to_kick_users,
94 local_aliases: summary
95 .local_aliases
96 .iter()
97 .map(ToString::to_string)
98 .collect(),
99 new_room_id: summary.new_room_id,
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use ruma::{room_alias_id, user_id};
106 use tuwunel_service::rooms::delete::ShutdownRoom as Summary;
107
108 use super::{ShutdownRoom, into_response};
109
110 #[test]
114 fn v1_field_map_agrees_with_v2_json_round_trip() {
115 let summary = Summary {
116 kicked_users: vec![user_id!("@alice:example.org").to_owned()],
117 failed_to_kick_users: vec![user_id!("@bob:example.org").to_owned()],
118 local_aliases: vec![room_alias_id!("#lounge:example.org").to_owned()],
119 new_room_id: None,
120 };
121
122 let via_field_map = into_response(summary.clone());
123
124 let via_json: ShutdownRoom =
125 serde_json::from_value(serde_json::to_value(&summary).unwrap()).unwrap();
126
127 assert_eq!(
128 serde_json::to_value(&via_field_map).unwrap(),
129 serde_json::to_value(&via_json).unwrap(),
130 );
131 }
132}