Files
continuwuity/src/api/client/keys.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

538 lines
15 KiB
Rust
Raw Normal View History

2021-07-14 07:07:08 +00:00
use std::{
2022-10-05 20:34:31 +02:00
collections::{hash_map, BTreeMap, HashMap, HashSet},
2024-07-07 03:39:35 +00:00
time::Instant,
2022-10-05 20:34:31 +02:00
};
2024-03-05 19:48:54 -05:00
2024-07-16 08:05:25 +00:00
use axum::extract::State;
2024-08-08 17:18:30 +00:00
use conduit::{err, utils, utils::math::continue_exponential_backoff_secs, Err, Error, Result};
use futures::{stream::FuturesUnordered, StreamExt};
2020-08-12 23:32:39 +02:00
use ruma::{
api::{
client::{
error::ErrorKind,
2022-02-18 15:33:14 +01:00
keys::{claim_keys, get_key_changes, get_keys, upload_keys, upload_signatures, upload_signing_keys},
uiaa::{AuthFlow, AuthType, UiaaInfo},
2020-07-30 18:14:47 +02:00
},
federation,
2020-07-30 18:14:47 +02:00
},
2021-12-22 19:41:33 +01:00
serde::Raw,
2022-10-09 17:26:53 +02:00
DeviceKeyAlgorithm, OwnedDeviceId, OwnedUserId, UserId,
2020-07-30 18:14:47 +02:00
};
use serde_json::json;
2020-07-30 18:14:47 +02:00
2021-07-14 07:07:08 +00:00
use super::SESSION_ID_LENGTH;
2024-08-08 17:18:30 +00:00
use crate::{
service::{users::parse_master_key, Services},
Ruma,
};
2024-03-05 19:48:54 -05:00
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/upload`
///
/// Publish end-to-end encryption keys for the sender device.
///
/// - Adds one time keys
/// - If there are no device keys yet: Adds device keys (TODO: merge with
/// existing keys?)
2024-07-16 08:05:25 +00:00
pub(crate) async fn upload_keys_route(
State(services): State<crate::State>, body: Ruma<upload_keys::v3::Request>,
) -> Result<upload_keys::v3::Response> {
2020-10-18 20:33:12 +02:00
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
2024-03-05 19:48:54 -05:00
2021-12-22 19:41:33 +01:00
for (key_key, key_value) in &body.one_time_keys {
2024-07-16 08:05:25 +00:00
services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.add_one_time_key(sender_user, sender_device, key_key, key_value)
.await?;
2020-07-30 18:14:47 +02:00
}
2024-03-05 19:48:54 -05:00
2020-07-30 18:14:47 +02:00
if let Some(device_keys) = &body.device_keys {
2021-08-31 19:14:37 +02:00
// TODO: merge this and the existing event?
2020-07-30 18:14:47 +02:00
// This check is needed to assure that signatures are kept
2024-07-16 08:05:25 +00:00
if services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.get_device_keys(sender_user, sender_device)
.await
.is_err()
2024-03-25 17:05:11 -04:00
{
2024-07-16 08:05:25 +00:00
services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.add_device_keys(sender_user, sender_device, device_keys)
.await;
2020-07-30 18:14:47 +02:00
}
}
2024-03-05 19:48:54 -05:00
2022-02-18 15:33:14 +01:00
Ok(upload_keys::v3::Response {
2024-07-16 08:05:25 +00:00
one_time_key_counts: services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.count_one_time_keys(sender_user, sender_device)
.await,
2022-01-22 16:58:32 +01:00
})
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/query`
///
/// Get end-to-end encryption keys for the given users.
///
/// - Always fetches users from other servers over federation
/// - Gets master keys, self-signing keys, user signing keys and device keys.
/// - The master and self-signing keys contain signatures that the user is
/// allowed to see
2024-07-16 08:05:25 +00:00
pub(crate) async fn get_keys_route(
State(services): State<crate::State>, body: Ruma<get_keys::v3::Request>,
) -> Result<get_keys::v3::Response> {
2020-10-18 20:33:12 +02:00
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2020-07-30 18:14:47 +02:00
2024-04-28 18:30:19 -04:00
get_keys_helper(
2024-07-27 07:17:07 +00:00
&services,
Some(sender_user),
&body.device_keys,
|u| u == sender_user,
true, // Always allow local users to see device names of other local users
)
2024-04-28 18:30:19 -04:00
.await
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/claim`
///
/// Claims one-time keys
2024-07-16 08:05:25 +00:00
pub(crate) async fn claim_keys_route(
State(services): State<crate::State>, body: Ruma<claim_keys::v3::Request>,
) -> Result<claim_keys::v3::Response> {
2024-07-27 07:17:07 +00:00
claim_keys_helper(&services, &body.one_time_keys).await
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/device_signing/upload`
///
/// Uploads end-to-end key information for the sender user.
///
/// - Requires UIAA to verify password
2024-04-22 23:48:57 -04:00
pub(crate) async fn upload_signing_keys_route(
2024-07-16 08:05:25 +00:00
State(services): State<crate::State>, body: Ruma<upload_signing_keys::v3::Request>,
2022-02-18 15:33:14 +01:00
) -> Result<upload_signing_keys::v3::Response> {
2020-10-18 20:33:12 +02:00
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
2024-03-05 19:48:54 -05:00
2020-07-30 18:14:47 +02:00
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
2021-10-13 10:16:45 +02:00
stages: vec![AuthType::Password],
2020-07-30 18:14:47 +02:00
}],
completed: Vec::new(),
2024-03-02 20:55:02 -05:00
params: Box::default(),
2020-07-30 18:14:47 +02:00
session: None,
auth_error: None,
};
2024-03-05 19:48:54 -05:00
2020-07-30 18:14:47 +02:00
if let Some(auth) = &body.auth {
2024-07-16 08:05:25 +00:00
let (worked, uiaainfo) = services
2024-03-25 17:05:11 -04:00
.uiaa
2024-08-08 17:18:30 +00:00
.try_auth(sender_user, sender_device, auth, &uiaainfo)
.await?;
2020-07-30 18:14:47 +02:00
if !worked {
return Err(Error::Uiaa(uiaainfo));
}
// Success!
2021-07-14 12:31:38 +02:00
} else if let Some(json) = body.json_body {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
2024-07-16 08:05:25 +00:00
services
2024-03-25 17:05:11 -04:00
.uiaa
2024-08-08 17:18:30 +00:00
.create(sender_user, sender_device, &uiaainfo, &json);
2021-07-14 12:31:38 +02:00
return Err(Error::Uiaa(uiaainfo));
2020-07-30 18:14:47 +02:00
} else {
2021-07-14 12:31:38 +02:00
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
2020-07-30 18:14:47 +02:00
}
2024-03-05 19:48:54 -05:00
2020-07-30 18:14:47 +02:00
if let Some(master_key) = &body.master_key {
2024-08-08 17:18:30 +00:00
services
.users
.add_cross_signing_keys(
sender_user,
master_key,
&body.self_signing_key,
&body.user_signing_key,
true, // notify so that other users see the new keys
)
.await?;
2020-07-30 18:14:47 +02:00
}
2024-03-05 19:48:54 -05:00
2022-02-18 15:33:14 +01:00
Ok(upload_signing_keys::v3::Response {})
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/signatures/upload`
///
/// Uploads end-to-end key signatures from the sender user.
2024-04-22 23:48:57 -04:00
pub(crate) async fn upload_signatures_route(
2024-07-16 08:05:25 +00:00
State(services): State<crate::State>, body: Ruma<upload_signatures::v3::Request>,
2022-02-18 15:33:14 +01:00
) -> Result<upload_signatures::v3::Response> {
2020-10-18 20:33:12 +02:00
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2024-03-05 19:48:54 -05:00
for (user_id, keys) in &body.signed_keys {
for (key_id, key) in keys {
let key = serde_json::to_value(key)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid key JSON"))?;
2024-03-05 19:48:54 -05:00
for signature in key
2020-07-30 18:14:47 +02:00
.get("signatures")
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Missing signatures field."))?
2020-10-18 20:33:12 +02:00
.get(sender_user.to_string())
2020-07-30 18:14:47 +02:00
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Invalid user in signatures field."))?
.as_object()
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Invalid signature."))?
.clone()
{
// Signature validation?
let signature = (
signature.0,
signature
.1
.as_str()
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Invalid signature value."))?
.to_owned(),
);
2024-08-08 17:18:30 +00:00
2024-07-16 08:05:25 +00:00
services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.sign_key(user_id, key_id, signature, sender_user)
.await?;
2024-03-05 19:48:54 -05:00
}
}
2020-07-30 18:14:47 +02:00
}
2024-03-05 19:48:54 -05:00
2022-02-18 15:33:14 +01:00
Ok(upload_signatures::v3::Response {
failures: BTreeMap::new(), // TODO: integrate
})
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/client/r0/keys/changes`
///
/// Gets a list of users who have updated their device identity keys since the
/// previous sync token.
///
/// - TODO: left users
2024-04-22 23:48:57 -04:00
pub(crate) async fn get_key_changes_route(
2024-07-16 08:05:25 +00:00
State(services): State<crate::State>, body: Ruma<get_key_changes::v3::Request>,
2024-04-22 23:48:57 -04:00
) -> Result<get_key_changes::v3::Response> {
2020-10-18 20:33:12 +02:00
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2024-03-05 19:48:54 -05:00
2020-07-30 18:14:47 +02:00
let mut device_list_updates = HashSet::new();
2024-03-05 19:48:54 -05:00
2024-08-08 17:18:30 +00:00
let from = body
.from
.parse()
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `from`."))?;
let to = body
.to
.parse()
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `to`."))?;
2020-07-30 18:14:47 +02:00
device_list_updates.extend(
2024-07-16 08:05:25 +00:00
services
2022-10-05 20:34:31 +02:00
.users
2024-08-08 17:18:30 +00:00
.keys_changed(sender_user.as_str(), from, Some(to))
.map(ToOwned::to_owned)
.collect::<Vec<_>>()
.await,
2020-07-30 18:14:47 +02:00
);
2024-03-05 19:48:54 -05:00
2024-08-08 17:18:30 +00:00
let mut rooms_joined = services.rooms.state_cache.rooms_joined(sender_user).boxed();
while let Some(room_id) = rooms_joined.next().await {
2020-07-30 18:14:47 +02:00
device_list_updates.extend(
2024-07-16 08:05:25 +00:00
services
2022-10-05 20:34:31 +02:00
.users
2024-10-01 02:47:39 +00:00
.keys_changed(room_id.as_str(), from, Some(to))
2024-08-08 17:18:30 +00:00
.map(ToOwned::to_owned)
.collect::<Vec<_>>()
.await,
2020-07-30 18:14:47 +02:00
);
}
2024-08-08 17:18:30 +00:00
2022-02-18 15:33:14 +01:00
Ok(get_key_changes::v3::Response {
2020-07-30 18:14:47 +02:00
changed: device_list_updates.into_iter().collect(),
left: Vec::new(), // TODO
2022-01-22 16:58:32 +01:00
})
2020-07-30 18:14:47 +02:00
}
2024-08-08 17:18:30 +00:00
pub(crate) async fn get_keys_helper<F>(
2024-07-16 08:05:25 +00:00
services: &Services, sender_user: Option<&UserId>, device_keys_input: &BTreeMap<OwnedUserId, Vec<OwnedDeviceId>>,
allowed_signatures: F, include_display_names: bool,
2024-08-08 17:18:30 +00:00
) -> Result<get_keys::v3::Response>
where
F: Fn(&UserId) -> bool + Send + Sync,
{
let mut master_keys = BTreeMap::new();
let mut self_signing_keys = BTreeMap::new();
let mut user_signing_keys = BTreeMap::new();
let mut device_keys = BTreeMap::new();
2024-03-05 19:48:54 -05:00
2021-08-26 18:59:10 +02:00
let mut get_over_federation = HashMap::new();
2024-03-05 19:48:54 -05:00
for (user_id, device_ids) in device_keys_input {
2024-04-29 17:53:19 -04:00
let user_id: &UserId = user_id;
2024-07-22 07:43:51 +00:00
if !services.globals.user_is_local(user_id) {
2024-03-25 17:05:11 -04:00
get_over_federation
.entry(user_id.server_name())
.or_insert_with(Vec::new)
.push((user_id, device_ids));
2021-07-20 21:17:15 +02:00
continue;
}
2024-03-05 19:48:54 -05:00
if device_ids.is_empty() {
let mut container = BTreeMap::new();
2024-08-08 17:18:30 +00:00
let mut devices = services.users.all_device_ids(user_id).boxed();
while let Some(device_id) = devices.next().await {
if let Ok(mut keys) = services.users.get_device_keys(user_id, device_id).await {
2024-07-16 08:05:25 +00:00
let metadata = services
.users
2024-08-08 17:18:30 +00:00
.get_device_metadata(user_id, device_id)
.await
.map_err(|_| err!(Database("all_device_keys contained nonexistent device.")))?;
2024-03-05 19:48:54 -05:00
add_unsigned_device_display_name(&mut keys, metadata, include_display_names)
2024-08-08 17:18:30 +00:00
.map_err(|_| err!(Database("invalid device keys in database")))?;
2024-03-05 19:48:54 -05:00
2024-08-08 17:18:30 +00:00
container.insert(device_id.to_owned(), keys);
}
2024-03-05 19:48:54 -05:00
}
2024-08-08 17:18:30 +00:00
2021-11-26 20:36:40 +01:00
device_keys.insert(user_id.to_owned(), container);
} else {
for device_id in device_ids {
let mut container = BTreeMap::new();
2024-08-08 17:18:30 +00:00
if let Ok(mut keys) = services.users.get_device_keys(user_id, device_id).await {
2024-07-16 08:05:25 +00:00
let metadata = services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.get_device_metadata(user_id, device_id)
.await
.map_err(|_| err!(Request(InvalidParam("Tried to get keys for nonexistent device."))))?;
2024-03-05 19:48:54 -05:00
add_unsigned_device_display_name(&mut keys, metadata, include_display_names)
2024-08-08 17:18:30 +00:00
.map_err(|_| err!(Database("invalid device keys in database")))?;
2021-11-26 20:36:40 +01:00
container.insert(device_id.to_owned(), keys);
}
2024-08-08 17:18:30 +00:00
2021-11-26 20:36:40 +01:00
device_keys.insert(user_id.to_owned(), container);
}
2024-03-05 19:48:54 -05:00
}
2024-08-08 17:18:30 +00:00
if let Ok(master_key) = services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.get_master_key(sender_user, user_id, &allowed_signatures)
.await
2024-03-25 17:05:11 -04:00
{
2021-11-26 20:36:40 +01:00
master_keys.insert(user_id.to_owned(), master_key);
}
2024-08-08 17:18:30 +00:00
if let Ok(self_signing_key) = services
.users
.get_self_signing_key(sender_user, user_id, &allowed_signatures)
.await
{
2021-11-26 20:36:40 +01:00
self_signing_keys.insert(user_id.to_owned(), self_signing_key);
}
2024-04-29 17:53:19 -04:00
if Some(user_id) == sender_user {
2024-08-08 17:18:30 +00:00
if let Ok(user_signing_key) = services.users.get_user_signing_key(user_id).await {
2021-11-26 20:36:40 +01:00
user_signing_keys.insert(user_id.to_owned(), user_signing_key);
2024-03-05 19:48:54 -05:00
}
}
}
2024-03-05 19:48:54 -05:00
let mut failures = BTreeMap::new();
2024-03-05 19:48:54 -05:00
let back_off = |id| async {
2024-07-16 08:05:25 +00:00
match services
2024-03-25 17:05:11 -04:00
.globals
.bad_query_ratelimiter
.write()
2024-07-04 03:26:19 +00:00
.expect("locked")
2024-03-25 17:05:11 -04:00
.entry(id)
{
hash_map::Entry::Vacant(e) => {
e.insert((Instant::now(), 1));
},
hash_map::Entry::Occupied(mut e) => {
2024-05-05 20:40:58 -04:00
*e.get_mut() = (Instant::now(), e.get().1.saturating_add(1));
},
}
};
2024-03-05 19:48:54 -05:00
2021-10-13 11:51:30 +02:00
let mut futures: FuturesUnordered<_> = get_over_federation
2021-08-26 18:59:10 +02:00
.into_iter()
.map(|(server, vec)| async move {
2024-07-16 08:05:25 +00:00
if let Some((time, tries)) = services
2024-03-25 17:05:11 -04:00
.globals
.bad_query_ratelimiter
.read()
2024-07-04 03:26:19 +00:00
.expect("locked")
2024-03-25 17:05:11 -04:00
.get(server)
{
// Exponential backoff
2024-07-07 03:39:35 +00:00
const MIN: u64 = 5 * 60;
const MAX: u64 = 60 * 60 * 24;
if continue_exponential_backoff_secs(MIN, MAX, time.elapsed(), *tries) {
2024-08-01 10:58:27 +00:00
return (server, Err!(BadServerResponse("bad query from {server:?}, still backing off")));
2024-03-05 19:48:54 -05:00
}
}
2024-03-05 19:48:54 -05:00
2021-08-26 18:59:10 +02:00
let mut device_keys_input_fed = BTreeMap::new();
for (user_id, keys) in vec {
2021-11-26 20:36:40 +01:00
device_keys_input_fed.insert(user_id.to_owned(), keys.clone());
2021-08-26 18:59:10 +02:00
}
2024-04-22 12:03:51 -07:00
let request = federation::keys::get_keys::v1::Request {
device_keys: device_keys_input_fed,
};
2024-07-16 08:05:25 +00:00
let response = services
2024-04-22 12:03:51 -07:00
.sending
.send_federation_request(server, request)
.await;
(server, Ok(response))
2021-08-26 18:59:10 +02:00
})
2021-10-13 11:51:30 +02:00
.collect();
2024-03-05 19:48:54 -05:00
2021-08-26 18:59:10 +02:00
while let Some((server, response)) = futures.next().await {
if let Ok(Ok(response)) = response {
for (user, masterkey) in response.master_keys {
2024-08-08 17:18:30 +00:00
let (master_key_id, mut master_key) = parse_master_key(&user, &masterkey)?;
2024-08-08 17:18:30 +00:00
if let Ok(our_master_key) = services
.users
.get_key(&master_key_id, sender_user, &user, &allowed_signatures)
.await
{
2024-08-08 17:18:30 +00:00
let (_, our_master_key) = parse_master_key(&user, &our_master_key)?;
master_key.signatures.extend(our_master_key.signatures);
2023-07-16 16:50:03 +02:00
}
let json = serde_json::to_value(master_key).expect("to_value always works");
let raw = serde_json::from_value(json).expect("Raw::from_value always works");
2024-08-08 17:18:30 +00:00
services
.users
.add_cross_signing_keys(
&user, &raw, &None, &None,
false, /* Dont notify. A notification would trigger another key request resulting in an
* endless loop */
)
.await?;
2024-04-22 12:03:51 -07:00
master_keys.insert(user.clone(), raw);
}
2024-03-05 19:48:54 -05:00
self_signing_keys.extend(response.self_signing_keys);
device_keys.extend(response.device_keys);
} else {
back_off(server.to_owned()).await;
failures.insert(server.to_string(), json!({}));
2024-03-05 19:48:54 -05:00
}
2021-07-20 21:17:15 +02:00
}
2024-03-05 19:48:54 -05:00
2022-02-18 15:33:14 +01:00
Ok(get_keys::v3::Response {
failures,
device_keys,
master_keys,
self_signing_keys,
user_signing_keys,
})
}
2021-12-22 19:41:33 +01:00
fn add_unsigned_device_display_name(
keys: &mut Raw<ruma::encryption::DeviceKeys>, metadata: ruma::api::client::device::Device,
include_display_names: bool,
2021-12-22 19:41:33 +01:00
) -> serde_json::Result<()> {
if let Some(display_name) = metadata.display_name {
let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?;
2024-03-05 19:48:54 -05:00
2021-12-22 19:41:33 +01:00
let unsigned = object.entry("unsigned").or_insert_with(|| json!({}));
if let serde_json::Value::Object(unsigned_object) = unsigned {
if include_display_names {
unsigned_object.insert("device_display_name".to_owned(), display_name.into());
} else {
unsigned_object.insert(
"device_display_name".to_owned(),
Some(metadata.device_id.as_str().to_owned()).into(),
);
}
2021-12-22 19:41:33 +01:00
}
2024-03-05 19:48:54 -05:00
2021-12-22 19:41:33 +01:00
*keys = Raw::from_json(serde_json::value::to_raw_value(&object)?);
}
2024-03-05 19:48:54 -05:00
2021-12-22 19:41:33 +01:00
Ok(())
}
2021-08-31 19:14:37 +02:00
pub(crate) async fn claim_keys_helper(
2024-07-16 08:05:25 +00:00
services: &Services, one_time_keys_input: &BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, DeviceKeyAlgorithm>>,
2022-02-18 15:33:14 +01:00
) -> Result<claim_keys::v3::Response> {
let mut one_time_keys = BTreeMap::new();
2024-03-05 19:48:54 -05:00
let mut get_over_federation = BTreeMap::new();
2024-03-05 19:48:54 -05:00
for (user_id, map) in one_time_keys_input {
2024-07-22 07:43:51 +00:00
if !services.globals.user_is_local(user_id) {
2024-03-25 17:05:11 -04:00
get_over_federation
.entry(user_id.server_name())
.or_insert_with(Vec::new)
.push((user_id, map));
}
2024-03-05 19:48:54 -05:00
let mut container = BTreeMap::new();
for (device_id, key_algorithm) in map {
2024-08-08 17:18:30 +00:00
if let Ok(one_time_keys) = services
2024-03-25 17:05:11 -04:00
.users
2024-08-08 17:18:30 +00:00
.take_one_time_key(user_id, device_id, key_algorithm)
.await
2024-03-25 17:05:11 -04:00
{
let mut c = BTreeMap::new();
c.insert(one_time_keys.0, one_time_keys.1);
container.insert(device_id.clone(), c);
2024-03-05 19:48:54 -05:00
}
}
one_time_keys.insert(user_id.clone(), container);
}
2024-03-05 19:48:54 -05:00
2021-08-26 18:59:10 +02:00
let mut failures = BTreeMap::new();
2024-03-05 19:48:54 -05:00
2022-10-12 10:42:59 +02:00
let mut futures: FuturesUnordered<_> = get_over_federation
.into_iter()
.map(|(server, vec)| async move {
let mut one_time_keys_input_fed = BTreeMap::new();
2022-10-12 10:42:59 +02:00
for (user_id, keys) in vec {
one_time_keys_input_fed.insert(user_id.clone(), keys.clone());
}
(
server,
2024-07-16 08:05:25 +00:00
services
2022-10-12 10:42:59 +02:00
.sending
.send_federation_request(
server,
federation::keys::claim_keys::v1::Request {
one_time_keys: one_time_keys_input_fed,
},
)
.await,
)
})
.collect();
2024-03-05 19:48:54 -05:00
2022-10-12 10:42:59 +02:00
while let Some((server, response)) = futures.next().await {
match response {
Ok(keys) => {
one_time_keys.extend(keys.one_time_keys);
},
Err(_e) => {
failures.insert(server.to_string(), json!({}));
2024-03-05 19:48:54 -05:00
},
2022-10-12 10:42:59 +02:00
}
2021-08-26 18:59:10 +02:00
}
2024-03-05 19:48:54 -05:00
2022-02-18 15:33:14 +01:00
Ok(claim_keys::v3::Response {
2021-08-26 18:59:10 +02:00
failures,
one_time_keys,
})
}