Skip to main content

tuwunel_api/client/admin/devices/
update_device.rs

1use axum::extract::State;
2use ruma::api::client::device::{Device, DisplayName};
3use synapse_admin_api::devices::update_device::v1 as update_device;
4use tuwunel_core::{Err, Result};
5
6use super::require_local_user;
7use crate::{Ruma, client::admin::require_admin};
8
9/// Synapse's `MAX_DEVICE_DISPLAY_NAME_LEN`.
10const MAX_DISPLAY_NAME_LEN: usize = 100;
11
12/// # `PUT /_synapse/admin/v2/users/{user_id}/devices/{device_id}`
13///
14/// Only `display_name` is honored; an omitted one leaves it unchanged.
15pub(crate) async fn admin_update_device_route(
16	State(services): State<crate::State>,
17	body: Ruma<update_device::Request>,
18) -> Result<update_device::Response> {
19	require_admin(&services, body.sender_user()).await?;
20
21	let user_id = &body.user_id;
22
23	require_local_user(&services, user_id).await?;
24
25	let Ok(device) = services
26		.users
27		.get_device_metadata(user_id, &body.device_id)
28		.await
29	else {
30		return Err!(Request(NotFound("No device found")));
31	};
32
33	let Some(display_name) = &body.display_name else {
34		return Ok(update_device::Response {});
35	};
36
37	if display_name.chars().count() > MAX_DISPLAY_NAME_LEN {
38		return Err!(Request(InvalidParam("Device display name is too long")));
39	}
40
41	let display_name = DisplayName::from(display_name.as_str());
42	let notify = device.display_name.as_ref() != Some(&display_name);
43	let device = Device {
44		display_name: Some(display_name),
45		..device
46	};
47
48	services
49		.users
50		.put_device_metadata(user_id, notify, &device);
51
52	Ok(update_device::Response {})
53}