Skip to main content

tuwunel_api/client/admin/mas/
sync_devices.rs

1use axum::extract::State;
2use futures::{StreamExt, TryStreamExt};
3use ruma::OwnedDeviceId;
4use synapse_admin_api::mas::sync_devices::{Request, Response};
5use tuwunel_core::{
6	Result,
7	utils::stream::{IterStream, TryBroadbandExt, automatic_width},
8};
9
10use super::{Mas, existing_user};
11use crate::Ruma;
12
13/// # `POST /_synapse/mas/sync_devices`
14pub(crate) async fn sync_devices_route(
15	_mas: Mas,
16	State(services): State<crate::State>,
17	body: Ruma<Request>,
18) -> Result<Response> {
19	let user_id = existing_user(services, &body.localpart).await?;
20
21	let current: Vec<OwnedDeviceId> = services
22		.users
23		.all_device_ids(&user_id)
24		.map(ToOwned::to_owned)
25		.collect()
26		.await;
27
28	current
29		.iter()
30		.filter(|device_id| !body.devices.contains(*device_id))
31		.stream()
32		.for_each_concurrent(automatic_width(), async |device_id| {
33			services
34				.users
35				.remove_device(&user_id, device_id)
36				.await;
37		})
38		.await;
39
40	body.devices
41		.iter()
42		.filter(|device_id| !current.contains(*device_id))
43		.try_stream()
44		.broad_and_then(async |device_id| {
45			services
46				.users
47				.create_device(&user_id, Some(device_id.as_ref()), (None, None), None, None, None)
48				.await
49				.map(|_| ())
50		})
51		.try_collect::<()>()
52		.await?;
53
54	Ok(Response::new())
55}