2024-07-16 08:05:25 +00:00
|
|
|
use axum::extract::State;
|
2025-11-01 20:05:01 +00:00
|
|
|
use futures::{FutureExt, StreamExt, TryFutureExt, future::join4};
|
|
|
|
|
use ruma::{
|
|
|
|
|
UserId,
|
|
|
|
|
api::{
|
|
|
|
|
client::device::Device,
|
|
|
|
|
federation::{
|
|
|
|
|
device::get_devices::{self, v1::UserDevice},
|
|
|
|
|
keys::{claim_keys, get_keys},
|
|
|
|
|
},
|
2024-06-05 04:32:58 +00:00
|
|
|
},
|
2025-11-01 20:05:01 +00:00
|
|
|
uint,
|
2024-06-05 04:32:58 +00:00
|
|
|
};
|
2025-11-01 20:05:01 +00:00
|
|
|
use tuwunel_core::{Err, Result, utils::future::TryExtExt};
|
2024-06-05 04:32:58 +00:00
|
|
|
|
|
|
|
|
use crate::{
|
2024-07-22 07:43:51 +00:00
|
|
|
Ruma,
|
2025-02-23 01:17:45 -05:00
|
|
|
client::{claim_keys_helper, get_keys_helper},
|
2024-06-05 04:32:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
|
|
|
|
|
///
|
|
|
|
|
/// Gets information on all devices of the user.
|
2024-07-16 08:05:25 +00:00
|
|
|
pub(crate) async fn get_devices_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
body: Ruma<get_devices::v1::Request>,
|
2024-07-16 08:05:25 +00:00
|
|
|
) -> Result<get_devices::v1::Response> {
|
2025-11-01 20:05:01 +00:00
|
|
|
let user_id = &body.user_id;
|
|
|
|
|
if !services.globals.user_is_local(user_id) {
|
|
|
|
|
return Err!(Request(InvalidParam("Tried to access user from other server.")));
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-11-01 20:05:01 +00:00
|
|
|
let allowed_signatures = |u: &UserId| u.server_name() == body.origin();
|
|
|
|
|
|
|
|
|
|
let master_key = services
|
|
|
|
|
.users
|
|
|
|
|
.get_master_key(None, user_id, &allowed_signatures)
|
|
|
|
|
.ok();
|
|
|
|
|
|
|
|
|
|
let self_signing_key = services
|
|
|
|
|
.users
|
|
|
|
|
.get_self_signing_key(None, user_id, &allowed_signatures)
|
|
|
|
|
.ok();
|
|
|
|
|
|
|
|
|
|
let stream_id = services
|
|
|
|
|
.users
|
|
|
|
|
.get_devicelist_version(user_id)
|
|
|
|
|
.map_ok(TryInto::try_into)
|
|
|
|
|
.map_ok(Result::ok)
|
|
|
|
|
.ok();
|
|
|
|
|
|
|
|
|
|
let devices = services
|
|
|
|
|
.users
|
|
|
|
|
.all_devices_metadata(user_id)
|
|
|
|
|
.filter_map(async |Device { device_id, display_name, .. }: Device| {
|
|
|
|
|
let device_display_name = services
|
|
|
|
|
.config
|
|
|
|
|
.allow_device_name_federation
|
|
|
|
|
.then_some(display_name)
|
|
|
|
|
.flatten()
|
2025-11-02 00:01:48 +00:00
|
|
|
.or_else(|| Some(device_id.as_str().into()));
|
2025-11-01 20:05:01 +00:00
|
|
|
|
|
|
|
|
services
|
|
|
|
|
.users
|
|
|
|
|
.get_device_keys(user_id, &device_id)
|
|
|
|
|
.map_ok(|keys| UserDevice {
|
|
|
|
|
device_id: device_id.clone(),
|
|
|
|
|
device_display_name,
|
|
|
|
|
keys,
|
|
|
|
|
})
|
|
|
|
|
.map(Result::ok)
|
|
|
|
|
.await
|
|
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
let (stream_id, master_key, self_signing_key, devices) =
|
|
|
|
|
join4(stream_id, master_key, self_signing_key, devices)
|
|
|
|
|
.boxed()
|
|
|
|
|
.await;
|
|
|
|
|
|
2024-06-05 04:32:58 +00:00
|
|
|
Ok(get_devices::v1::Response {
|
2025-11-01 20:05:01 +00:00
|
|
|
user_id: body.body.user_id,
|
|
|
|
|
stream_id: stream_id.flatten().unwrap_or_else(|| uint!(0)),
|
|
|
|
|
devices,
|
|
|
|
|
self_signing_key,
|
|
|
|
|
master_key,
|
2024-06-05 04:32:58 +00:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/user/keys/query`
|
|
|
|
|
///
|
|
|
|
|
/// Gets devices and identity keys for the given users.
|
2024-07-16 08:05:25 +00:00
|
|
|
pub(crate) async fn get_keys_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
body: Ruma<get_keys::v1::Request>,
|
2024-07-16 08:05:25 +00:00
|
|
|
) -> Result<get_keys::v1::Response> {
|
2024-07-22 07:43:51 +00:00
|
|
|
if body
|
|
|
|
|
.device_keys
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|(u, _)| !services.globals.user_is_local(u))
|
|
|
|
|
{
|
2025-11-01 20:05:01 +00:00
|
|
|
return Err!(Request(InvalidParam("User does not belong to this server.")));
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let result = get_keys_helper(
|
2024-07-27 07:17:07 +00:00
|
|
|
&services,
|
2024-06-05 04:32:58 +00:00
|
|
|
None,
|
|
|
|
|
&body.device_keys,
|
|
|
|
|
|u| Some(u.server_name()) == body.origin.as_deref(),
|
2025-09-23 02:37:31 +05:00
|
|
|
services.config.allow_device_name_federation,
|
2024-06-05 04:32:58 +00:00
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
Ok(get_keys::v1::Response {
|
|
|
|
|
device_keys: result.device_keys,
|
|
|
|
|
master_keys: result.master_keys,
|
|
|
|
|
self_signing_keys: result.self_signing_keys,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/user/keys/claim`
|
|
|
|
|
///
|
|
|
|
|
/// Claims one-time keys.
|
2024-07-16 08:05:25 +00:00
|
|
|
pub(crate) async fn claim_keys_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
body: Ruma<claim_keys::v1::Request>,
|
2024-07-16 08:05:25 +00:00
|
|
|
) -> Result<claim_keys::v1::Response> {
|
2024-07-22 07:43:51 +00:00
|
|
|
if body
|
|
|
|
|
.one_time_keys
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|(u, _)| !services.globals.user_is_local(u))
|
|
|
|
|
{
|
2025-11-01 20:05:01 +00:00
|
|
|
return Err!(Request(InvalidParam("Tried to access user from other server.")));
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-27 07:17:07 +00:00
|
|
|
let result = claim_keys_helper(&services, &body.one_time_keys).await?;
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2024-12-15 00:05:47 -05:00
|
|
|
Ok(claim_keys::v1::Response { one_time_keys: result.one_time_keys })
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|