1use clap::Subcommand;
2use futures::stream::StreamExt;
3use ruma::{OwnedDeviceId, OwnedRoomId, OwnedUserId};
4use tuwunel_core::Result;
5
6use crate::{admin_command, admin_command_dispatch};
7
8#[admin_command_dispatch]
9#[derive(Debug, Subcommand)]
10pub(crate) enum UsersCommand {
12 CountUsers,
13
14 IterUsers,
15
16 PasswordHash {
17 user_id: OwnedUserId,
18 },
19
20 ListDevices {
21 user_id: OwnedUserId,
22 },
23
24 ListDevicesMetadata {
25 user_id: OwnedUserId,
26 },
27
28 GetDeviceMetadata {
29 user_id: OwnedUserId,
30 device_id: OwnedDeviceId,
31 },
32
33 GetDevicesVersion {
34 user_id: OwnedUserId,
35 },
36
37 CountOneTimeKeys {
38 user_id: OwnedUserId,
39 device_id: OwnedDeviceId,
40 },
41
42 GetDeviceKeys {
43 user_id: OwnedUserId,
44 device_id: OwnedDeviceId,
45 },
46
47 GetUserSigningKey {
48 user_id: OwnedUserId,
49 },
50
51 GetMasterKey {
52 user_id: OwnedUserId,
53 },
54
55 GetToDeviceEvents {
56 user_id: OwnedUserId,
57 device_id: OwnedDeviceId,
58 },
59
60 GetLatestBackup {
61 user_id: OwnedUserId,
62 },
63
64 GetLatestBackupVersion {
65 user_id: OwnedUserId,
66 },
67
68 GetBackupAlgorithm {
69 user_id: OwnedUserId,
70 version: String,
71 },
72
73 GetAllBackups {
74 user_id: OwnedUserId,
75 version: String,
76 },
77
78 GetRoomBackups {
79 user_id: OwnedUserId,
80 version: String,
81 room_id: OwnedRoomId,
82 },
83
84 GetBackupSession {
85 user_id: OwnedUserId,
86 version: String,
87 room_id: OwnedRoomId,
88 session_id: String,
89 },
90
91 GetSharedRooms {
92 user_a: OwnedUserId,
93 user_b: OwnedUserId,
94 },
95
96 SearchLdap {
97 user_id: OwnedUserId,
98 },
99
100 AuthLdap {
101 user_dn: String,
102 password: String,
103 },
104}
105
106#[admin_command]
107async fn auth_ldap(&self, user_dn: String, password: String) -> Result {
108 let timer = tokio::time::Instant::now();
109 let result = self
110 .services
111 .users
112 .auth_ldap(&user_dn, &password)
113 .await;
114 let query_time = timer.elapsed();
115
116 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
117 .await
118}
119
120#[admin_command]
121async fn search_ldap(&self, user_id: OwnedUserId) -> Result {
122 let timer = tokio::time::Instant::now();
123 let result = self.services.users.search_ldap(&user_id).await;
124 let query_time = timer.elapsed();
125
126 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
127 .await
128}
129
130#[admin_command]
131async fn get_shared_rooms(&self, user_a: OwnedUserId, user_b: OwnedUserId) -> Result {
132 let timer = tokio::time::Instant::now();
133 let result: Vec<_> = self
134 .services
135 .state_cache
136 .get_shared_rooms(&user_a, &user_b)
137 .map(ToOwned::to_owned)
138 .collect()
139 .await;
140 let query_time = timer.elapsed();
141
142 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
143 .await
144}
145
146#[admin_command]
147async fn get_backup_session(
148 &self,
149 user_id: OwnedUserId,
150 version: String,
151 room_id: OwnedRoomId,
152 session_id: String,
153) -> Result {
154 let timer = tokio::time::Instant::now();
155 let result = self
156 .services
157 .key_backups
158 .get_session(&user_id, &version, &room_id, &session_id)
159 .await;
160 let query_time = timer.elapsed();
161
162 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
163 .await
164}
165
166#[admin_command]
167async fn get_room_backups(
168 &self,
169 user_id: OwnedUserId,
170 version: String,
171 room_id: OwnedRoomId,
172) -> Result {
173 let timer = tokio::time::Instant::now();
174 let result = self
175 .services
176 .key_backups
177 .get_room(&user_id, &version, &room_id)
178 .await;
179 let query_time = timer.elapsed();
180
181 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
182 .await
183}
184
185#[admin_command]
186async fn get_all_backups(&self, user_id: OwnedUserId, version: String) -> Result {
187 let timer = tokio::time::Instant::now();
188 let result = self
189 .services
190 .key_backups
191 .get_all(&user_id, &version)
192 .await;
193 let query_time = timer.elapsed();
194
195 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
196 .await
197}
198
199#[admin_command]
200async fn get_backup_algorithm(&self, user_id: OwnedUserId, version: String) -> Result {
201 let timer = tokio::time::Instant::now();
202 let result = self
203 .services
204 .key_backups
205 .get_backup(&user_id, &version)
206 .await;
207 let query_time = timer.elapsed();
208
209 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
210 .await
211}
212
213#[admin_command]
214async fn get_latest_backup_version(&self, user_id: OwnedUserId) -> Result {
215 let timer = tokio::time::Instant::now();
216 let result = self
217 .services
218 .key_backups
219 .get_latest_backup_version(&user_id)
220 .await;
221 let query_time = timer.elapsed();
222
223 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
224 .await
225}
226
227#[admin_command]
228async fn get_latest_backup(&self, user_id: OwnedUserId) -> Result {
229 let timer = tokio::time::Instant::now();
230 let result = self
231 .services
232 .key_backups
233 .get_latest_backup(&user_id)
234 .await;
235 let query_time = timer.elapsed();
236
237 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
238 .await
239}
240
241#[admin_command]
242async fn iter_users(&self) -> Result {
243 let timer = tokio::time::Instant::now();
244 let result: Vec<OwnedUserId> = self
245 .services
246 .users
247 .stream()
248 .map(Into::into)
249 .collect()
250 .await;
251
252 let query_time = timer.elapsed();
253
254 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
255 .await
256}
257
258#[admin_command]
259async fn count_users(&self) -> Result {
260 let timer = tokio::time::Instant::now();
261 let result = self.services.users.count().await;
262 let query_time = timer.elapsed();
263
264 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
265 .await
266}
267
268#[admin_command]
269async fn password_hash(&self, user_id: OwnedUserId) -> Result {
270 let timer = tokio::time::Instant::now();
271 let result = self.services.users.password_hash(&user_id).await;
272 let query_time = timer.elapsed();
273
274 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
275 .await
276}
277
278#[admin_command]
279async fn list_devices(&self, user_id: OwnedUserId) -> Result {
280 let timer = tokio::time::Instant::now();
281 let devices = self
282 .services
283 .users
284 .all_device_ids(&user_id)
285 .map(ToOwned::to_owned)
286 .collect::<Vec<_>>()
287 .await;
288
289 let query_time = timer.elapsed();
290
291 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{devices:#?}\n```"))
292 .await
293}
294
295#[admin_command]
296async fn list_devices_metadata(&self, user_id: OwnedUserId) -> Result {
297 let timer = tokio::time::Instant::now();
298 let devices = self
299 .services
300 .users
301 .all_devices_metadata(&user_id)
302 .collect::<Vec<_>>()
303 .await;
304 let query_time = timer.elapsed();
305
306 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{devices:#?}\n```"))
307 .await
308}
309
310#[admin_command]
311async fn get_device_metadata(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result {
312 let timer = tokio::time::Instant::now();
313 let device = self
314 .services
315 .users
316 .get_device_metadata(&user_id, &device_id)
317 .await;
318 let query_time = timer.elapsed();
319
320 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{device:#?}\n```"))
321 .await
322}
323
324#[admin_command]
325async fn get_devices_version(&self, user_id: OwnedUserId) -> Result {
326 let timer = tokio::time::Instant::now();
327 let device = self
328 .services
329 .users
330 .get_devicelist_version(&user_id)
331 .await;
332 let query_time = timer.elapsed();
333
334 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{device:#?}\n```"))
335 .await
336}
337
338#[admin_command]
339async fn count_one_time_keys(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result {
340 let timer = tokio::time::Instant::now();
341 let result = self
342 .services
343 .users
344 .count_one_time_keys(&user_id, &device_id)
345 .await;
346 let query_time = timer.elapsed();
347
348 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
349 .await
350}
351
352#[admin_command]
353async fn get_device_keys(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result {
354 let timer = tokio::time::Instant::now();
355 let result = self
356 .services
357 .users
358 .get_device_keys(&user_id, &device_id)
359 .await;
360 let query_time = timer.elapsed();
361
362 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
363 .await
364}
365
366#[admin_command]
367async fn get_user_signing_key(&self, user_id: OwnedUserId) -> Result {
368 let timer = tokio::time::Instant::now();
369 let result = self
370 .services
371 .users
372 .get_user_signing_key(&user_id)
373 .await;
374 let query_time = timer.elapsed();
375
376 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
377 .await
378}
379
380#[admin_command]
381async fn get_master_key(&self, user_id: OwnedUserId) -> Result {
382 let timer = tokio::time::Instant::now();
383 let result = self
384 .services
385 .users
386 .get_master_key(None, &user_id, &|_| true)
387 .await;
388 let query_time = timer.elapsed();
389
390 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
391 .await
392}
393
394#[admin_command]
395async fn get_to_device_events(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result {
396 let timer = tokio::time::Instant::now();
397 let result = self
398 .services
399 .users
400 .get_to_device_events(&user_id, &device_id, None, None)
401 .collect::<Vec<_>>()
402 .await;
403 let query_time = timer.elapsed();
404
405 self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
406 .await
407}