Files
continuwuity/src/api/server/user.rs
T

129 lines
3.2 KiB
Rust

use std::time::Duration;
use axum::extract::State;
use conduwuit::{Err, Result};
use futures::{FutureExt, StreamExt, TryFutureExt};
use ruma::{
api::federation::{
device::get_devices::{self, v1::UserDevice},
keys::{claim_keys, get_keys},
},
assign,
};
use crate::{
Ruma,
client::{claim_keys_helper, get_keys_helper},
};
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
///
/// Gets information on all devices of the user.
pub(crate) async fn get_devices_route(
State(services): State<crate::State>,
body: Ruma<get_devices::v1::Request>,
) -> Result<get_devices::v1::Response> {
if !services.globals.user_is_local(&body.user_id) {
return Err!(Request(InvalidParam("Tried to access user from other server.")));
}
let stream_id = services
.users
.get_devicelist_version(&body.user_id)
.await
.unwrap_or(0)
.try_into()
.expect("device list version should fit into a UInt");
let devices = services
.users
.all_devices_metadata(&body.user_id)
.filter_map(async |metadata| {
let device_id = metadata.device_id.clone();
let device_id_clone = device_id.clone();
let device_id_string = device_id.as_str().to_owned();
let device_display_name = if services.globals.allow_device_name_federation() {
metadata.display_name.clone()
} else {
Some(device_id_string)
};
services
.users
.get_device_keys(&body.user_id, &device_id_clone)
.map_ok(|keys| assign!(UserDevice::new(device_id, keys), { device_display_name }))
.map(Result::ok)
.await
})
.collect()
.await;
let master_key = services
.users
.get_master_key(None, &body.user_id, &|u| u.server_name() == body.identity)
.await
.ok();
let self_signing_key = services
.users
.get_self_signing_key(None, &body.user_id, &|u| u.server_name() == body.identity)
.await
.ok();
Ok(assign!(get_devices::v1::Response::new(body.user_id.clone(), stream_id), {
devices, master_key, self_signing_key
}))
}
/// # `POST /_matrix/federation/v1/user/keys/query`
///
/// Gets devices and identity keys for the given users.
pub(crate) async fn get_keys_route(
State(services): State<crate::State>,
body: Ruma<get_keys::v1::Request>,
) -> Result<get_keys::v1::Response> {
if body
.device_keys
.iter()
.any(|(u, _)| !services.globals.user_is_local(u))
{
return Err!(Request(InvalidParam("User does not belong to this server.")));
}
let result = get_keys_helper(
&services,
None,
&body.device_keys,
|u| u.server_name() == body.identity,
services.globals.allow_device_name_federation(),
Duration::from_secs(0),
)
.await?;
Ok(assign!(get_keys::v1::Response::new(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.
pub(crate) async fn claim_keys_route(
State(services): State<crate::State>,
body: Ruma<claim_keys::v1::Request>,
) -> Result<claim_keys::v1::Response> {
if body
.one_time_keys
.iter()
.any(|(u, _)| !services.globals.user_is_local(u))
{
return Err!(Request(InvalidParam("Tried to access user from other server.")));
}
let result =
claim_keys_helper(&services, &body.one_time_keys, Duration::from_secs(0)).await?;
Ok(claim_keys::v1::Response::new(result.one_time_keys))
}