tuwunel_api/client/admin/rooms/
mod.rs1mod block;
4mod context;
5mod delete_room;
6mod delete_status;
7mod forward_extremities;
8mod hierarchy;
9mod join;
10mod list_rooms;
11mod make_room_admin;
12mod messages;
13mod purge_history;
14mod room_details;
15mod room_members;
16mod state;
17mod timestamp_to_event;
18
19use futures::{
20 FutureExt, StreamExt, TryFutureExt,
21 future::{join, join3, join5},
22};
23use ruma::{
24 RoomId, UInt,
25 events::{
26 StateEventType,
27 room::{
28 guest_access::RoomGuestAccessEventContent,
29 history_visibility::RoomHistoryVisibilityEventContent,
30 },
31 },
32 uint,
33};
34use synapse_admin_api::rooms::list_rooms::v1::RoomDetails;
35use tuwunel_core::{Result, matrix::Event, utils::TryFutureExtExt};
36use tuwunel_service::Services;
37
38pub(crate) use self::{
39 block::{admin_get_room_block_route, admin_set_room_block_route},
40 context::admin_room_context_route,
41 delete_room::{admin_delete_room_v1_route, admin_delete_room_v2_route},
42 delete_status::{admin_delete_status_by_id_route, admin_delete_status_by_room_route},
43 forward_extremities::{
44 admin_delete_forward_extremities_route, admin_get_forward_extremities_route,
45 },
46 hierarchy::admin_room_hierarchy_route,
47 join::admin_join_room_route,
48 list_rooms::admin_list_rooms_route,
49 make_room_admin::admin_make_room_admin_route,
50 messages::admin_room_messages_route,
51 purge_history::{
52 admin_purge_history_by_event_route, admin_purge_history_route,
53 admin_purge_history_status_route,
54 },
55 room_details::admin_room_details_route,
56 room_members::admin_room_members_route,
57 state::admin_room_state_route,
58 timestamp_to_event::admin_room_timestamp_to_event_route,
59};
60
61const DELETE_ROOM_ACTION: &str = "shutdown_and_purge_room";
64
65const PURGE_HISTORY_ACTION: &str = "purge_history";
68
69async fn room_row(services: &Services, room_id: &RoomId) -> RoomDetails {
72 let name = services.state_accessor.get_name(room_id).ok();
73
74 let canonical_alias = services
75 .state_accessor
76 .get_canonical_alias(room_id)
77 .ok();
78
79 let room_type = services
80 .state_accessor
81 .get_room_type(room_id)
82 .ok();
83
84 let encryption = services
85 .state_accessor
86 .get_room_encryption(room_id)
87 .map_ok(|algorithm| algorithm.to_string())
88 .ok();
89
90 let join_rules = services
91 .state_accessor
92 .get_join_rules(room_id)
93 .map(|join_rule| Some(join_rule.kind()));
94
95 let guest_access = services
96 .state_accessor
97 .room_state_get_content(room_id, &StateEventType::RoomGuestAccess, "")
98 .map_ok(|content: RoomGuestAccessEventContent| content.guest_access)
99 .ok();
100
101 let history_visibility = services
102 .state_accessor
103 .room_state_get_content(room_id, &StateEventType::RoomHistoryVisibility, "")
104 .map_ok(|content: RoomHistoryVisibilityEventContent| content.history_visibility)
105 .ok();
106
107 let create = services
108 .state_accessor
109 .get_create(room_id)
110 .map(Result::ok);
111
112 let version = services
113 .state
114 .get_room_version(room_id)
115 .map_ok(|version| version.to_string())
116 .ok();
117
118 let public = services.directory.is_public_room(room_id);
119
120 let joined_members = services
121 .state_cache
122 .room_joined_count(room_id)
123 .map(|count| count_to_uint(count.ok()));
124
125 let joined_local_members = services
126 .state_cache
127 .local_users_in_room(room_id)
128 .count()
129 .map(usize_to_uint);
130
131 let state_events = state_event_count(services, room_id);
132
133 let (
134 (name, canonical_alias, room_type, encryption, join_rules),
135 (guest_access, history_visibility, create, version, public),
136 (joined_members, joined_local_members, state_events),
137 ) = join(
138 join5(name, canonical_alias, room_type, encryption, join_rules),
139 join(
140 join5(guest_access, history_visibility, create, version, public),
141 join3(joined_members, joined_local_members, state_events),
142 ),
143 )
144 .map(|(head, (mid, tail))| (head, mid, tail))
145 .boxed()
146 .await;
147
148 let (creator, federatable) = create
149 .map(|create| (Some(create.sender().to_owned()), create.federate().unwrap_or(true)))
150 .unwrap_or((None, true));
151
152 RoomDetails {
153 room_id: room_id.to_owned(),
154 name,
155 canonical_alias,
156 joined_members,
157 joined_local_members,
158 version,
159 creator,
160 encryption,
161 federatable,
162 public,
163 join_rules,
164 guest_access,
165 history_visibility,
166 state_events,
167 room_type,
168 }
169}
170
171async fn state_event_count(services: &Services, room_id: &RoomId) -> UInt {
172 let Ok(shortstatehash) = services
173 .state
174 .get_room_shortstatehash(room_id)
175 .await
176 else {
177 return uint!(0);
178 };
179
180 let count = services
181 .state_accessor
182 .state_full_ids(shortstatehash)
183 .count()
184 .await;
185
186 usize_to_uint(count)
187}
188
189fn count_to_uint(count: Option<u64>) -> UInt {
190 count
191 .and_then(|count| count.try_into().ok())
192 .unwrap_or_else(|| uint!(0))
193}
194
195fn usize_to_uint(count: usize) -> UInt { count.try_into().unwrap_or_else(|_| uint!(0)) }