tuwunel_service/rooms/delete/
mod.rs1use std::sync::Arc;
2
3use futures::{FutureExt, StreamExt};
4use ruma::RoomId;
5use tuwunel_core::{
6 Result, debug,
7 result::LogErr,
8 trace,
9 utils::{ReadyExt, future::BoolExt},
10 warn,
11};
12
13use crate::rooms::timeline::RoomMutexGuard;
14
15pub struct Service {
16 services: Arc<crate::services::OnceServices>,
17}
18
19impl crate::Service for Service {
20 fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
21 Ok(Arc::new(Self { services: args.services.clone() }))
22 }
23
24 fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
25}
26
27impl Service {
28 pub async fn delete_if_empty_local(&self, room_id: &RoomId, state_lock: RoomMutexGuard) {
29 debug_assert!(
30 self.services.config.delete_rooms_after_leave,
31 "Caller must checking if delete_rooms_after_leave configured."
32 );
33
34 let has_local_users = self
35 .services
36 .state_cache
37 .local_users_in_room(room_id)
38 .boxed()
39 .into_future()
40 .map(|(next, ..)| next.as_ref().is_some());
41
42 let has_local_invites = self
43 .services
44 .state_cache
45 .local_users_invited_to_room(room_id)
46 .boxed()
47 .into_future()
48 .map(|(next, ..)| next.as_ref().is_some());
49
50 if has_local_users.or(has_local_invites).await {
51 trace!(?room_id, "Not deleting with local joined or invited");
52 return;
53 }
54
55 debug!(?room_id, "Preparing to delete room...");
56
57 self.services
58 .delete
59 .delete_room(room_id, false, state_lock)
60 .boxed()
61 .await
62 .expect("unhandled error during room deletion");
63 }
64
65 pub async fn delete_room(
66 &self,
67 room_id: &RoomId,
68 force: bool,
69 state_lock: RoomMutexGuard,
70 ) -> Result {
71 debug!("Making all users leave the room {room_id} and forgetting it");
72 let mut users = self
73 .services
74 .state_cache
75 .room_members(room_id)
76 .ready_filter(|user| self.services.globals.user_is_local(user))
77 .boxed();
78
79 while let Some(user_id) = users.next().await {
80 debug!(
81 "Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
82 evicting admins too)",
83 );
84
85 if let Err(e) = self
86 .services
87 .membership
88 .leave(user_id, room_id, Some("Room Deleted".into()), true, &state_lock)
89 .boxed()
90 .await
91 {
92 warn!("Failed to leave room: {e}");
93 }
94 }
95
96 debug!("Deleting all our room aliases for the room");
97 self.services
98 .alias
99 .local_aliases_for_room(room_id)
100 .for_each(async |local_alias| {
101 self.services
102 .alias
103 .remove_alias(local_alias)
104 .await
105 .log_err()
106 .ok();
107 })
108 .await;
109
110 debug!("Removing/unpublishing room from our room directory");
111 self.services.directory.set_not_public(room_id);
112
113 debug!("Deleting room's threads from database");
114 self.services
115 .threads
116 .delete_all_rooms_threads(room_id)
117 .await
118 .log_err()
119 .ok();
120
121 debug!("Deleting all the room's search token IDs from our database");
122 self.services
123 .search
124 .delete_all_search_tokenids_for_room(room_id)
125 .await
126 .log_err()
127 .ok();
128
129 debug!("Deleting all room's forward extremities from our database");
130 self.services
131 .state
132 .delete_all_rooms_forward_extremities(room_id)
133 .await
134 .log_err()
135 .ok();
136
137 debug!("Deleting all the room's event (PDU) references");
138 self.services
139 .pdu_metadata
140 .delete_all_referenced_for_room(room_id)
141 .await
142 .log_err()
143 .ok();
144
145 debug!("Deleting all the room's member counts");
146 self.services
147 .state_cache
148 .delete_room_join_counts(room_id, force)
149 .await
150 .log_err()
151 .ok();
152
153 debug!("Deleting all the room's private read receipts");
154 self.services
155 .read_receipt
156 .delete_all_read_receipts(room_id)
157 .await
158 .log_err()
159 .ok();
160
161 debug!("Deleting the room's last notifications read.");
162 self.services
163 .pusher
164 .delete_room_notification_read(room_id)
165 .await
166 .log_err()
167 .ok();
168
169 debug!("Final stages of deleting the room");
170
171 debug!("Deleting room state hash from our database");
172 self.services
173 .state
174 .delete_room_shortstatehash(room_id, &state_lock)
175 .log_err()
176 .ok();
177
178 debug!("Deleting PDUs");
179 self.services
180 .timeline
181 .delete_pdus(room_id)
182 .await
183 .log_err()
184 .ok();
185
186 debug!("Deleting internal room ID from our database");
187 self.services
188 .short
189 .delete_shortroomid(room_id)
190 .await
191 .log_err()
192 .ok();
193
194 debug!("Successfully deleted room {room_id} from our database");
195 Ok(())
196 }
197}