tuwunel_api/client/device/
devices_device.rs1use axum::extract::State;
2use ruma::{
3 MilliSecondsSinceUnixEpoch,
4 api::client::device::{delete_device, get_device, update_device},
5};
6use tuwunel_core::{Err, Result, debug, err, utils::string::to_small_string};
7
8use crate::{ClientIp, Ruma, router::auth_uiaa};
9
10pub(crate) async fn get_device_route(
14 State(services): State<crate::State>,
15 body: Ruma<get_device::v3::Request>,
16) -> Result<get_device::v3::Response> {
17 let device = services
18 .users
19 .get_device_metadata(body.sender_user(), &body.body.device_id)
20 .await
21 .map_err(|_| err!(Request(NotFound("Device not found."))))?;
22
23 Ok(get_device::v3::Response { device })
24}
25
26#[tracing::instrument(skip_all, fields(%client), name = "update_device")]
32pub(crate) async fn update_device_route(
33 State(services): State<crate::State>,
34 ClientIp(client): ClientIp,
35 body: Ruma<update_device::v3::Request>,
36) -> Result<update_device::v3::Response> {
37 let sender_user = body.sender_user();
38 let appservice = body.appservice_info.as_ref();
39
40 match services
41 .users
42 .get_device_metadata(sender_user, &body.device_id)
43 .await
44 {
45 | Ok(mut device) => {
46 let notify = device.display_name != body.display_name;
47 device.display_name.clone_from(&body.display_name);
48
49 device
50 .last_seen_ip
51 .clone_from(&Some(to_small_string(client)));
52
53 device
54 .last_seen_ts
55 .clone_from(&Some(MilliSecondsSinceUnixEpoch::now()));
56
57 assert_eq!(device.device_id, body.device_id, "device_id mismatch");
58 services
59 .users
60 .put_device_metadata(sender_user, notify, &device);
61
62 Ok(update_device::v3::Response::new())
63 },
64 | Err(_) => {
65 let Some(appservice) = appservice else {
66 return Err!(Request(NotFound("Device not found.")));
67 };
68
69 if !appservice.registration.device_management {
70 return Err!(Request(NotFound("Device management not enabled for appservice.")));
71 }
72
73 debug!(
74 "Creating new device for {sender_user} from appservice {} as MSC4190 is enabled \
75 and device ID does not exist",
76 appservice.registration.id
77 );
78
79 services
80 .users
81 .create_device(
82 sender_user,
83 Some(&body.device_id),
84 (None, None),
85 None,
86 body.display_name.as_deref(),
87 Some(client),
88 )
89 .await?;
90
91 Ok(update_device::v3::Response::created())
92 },
93 }
94}
95
96pub(crate) async fn delete_device_route(
107 State(services): State<crate::State>,
108 body: Ruma<delete_device::v3::Request>,
109) -> Result<delete_device::v3::Response> {
110 let appservice = body.appservice_info.as_ref();
111
112 if appservice.is_some_and(|appservice| appservice.registration.device_management) {
113 let sender_user = body.sender_user();
114 debug!(
115 "Skipping UIAA for {sender_user} as this is from an appservice and MSC4190 is \
116 enabled"
117 );
118 services
119 .users
120 .remove_device(sender_user, &body.device_id)
121 .await;
122
123 return Ok(delete_device::v3::Response {});
124 }
125
126 let ref sender_user = auth_uiaa(&services, &body).await?;
127
128 services
129 .users
130 .remove_device(sender_user, &body.device_id)
131 .await;
132
133 Ok(delete_device::v3::Response {})
134}