Skip to main content

tuwunel_api/client/admin/media/
delete_user_media.rs

1use axum::extract::State;
2use futures::StreamExt;
3use ruma::UInt;
4use synapse_admin_api::media::delete_user_media::v1 as delete_user_media;
5use tuwunel_core::{
6	Err, Result,
7	utils::stream::{IterStream, WidebandExt},
8};
9
10use super::{select_page, usize_from};
11use crate::{Ruma, client::admin::require_admin};
12
13/// # `DELETE /_synapse/admin/v1/users/{user_id}/media`
14///
15/// Deletes a single page of the user's media per call; callers loop to drain,
16/// mirroring Synapse (the remaining media reorders after each page, so there is
17/// no continuation token).
18pub(crate) async fn admin_delete_user_media_route(
19	State(services): State<crate::State>,
20	body: Ruma<delete_user_media::Request>,
21) -> Result<delete_user_media::Response> {
22	require_admin(&services, body.sender_user()).await?;
23
24	if !services
25		.globals
26		.server_is_ours(body.user_id.server_name())
27	{
28		return Err!(Request(InvalidParam("Can only look up local users")));
29	}
30
31	if !services.users.exists(&body.user_id).await {
32		return Err!(Request(NotFound("User not found")));
33	}
34
35	let entries = services.media.user_media(&body.user_id).await?;
36
37	let from = body.from.map(usize_from).unwrap_or(0);
38	let limit = body.limit.map(usize_from).unwrap_or(100);
39
40	let page = select_page(entries, body.order_by.as_ref(), body.dir, from, limit);
41
42	let deleted_media: Vec<String> = page
43		.iter()
44		.stream()
45		.wide_filter_map(async |entry| {
46			let mxc = entry.mxc.parts().ok()?;
47
48			services
49				.media
50				.delete(&mxc)
51				.await
52				.ok()
53				.map(|()| mxc.media_id.to_owned())
54		})
55		.collect()
56		.await;
57
58	let total = UInt::try_from(deleted_media.len()).unwrap_or(UInt::MAX);
59
60	Ok(delete_user_media::Response { deleted_media, total })
61}