1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-08-16 18:01:35 +00:00
conduit/src/api/client_server/space.rs
Matthias Ahouansou 56a51360e0
feat(spaces): hierarchy over federation
fix(spaces): deal with hierarchy recursion
fix(spaces): properly handle max_depth
refactor(spaces): token scheme to prevent clients from modifying max_depth and suggested_only
perf(spaces): use tokens to skip to room to start populating results at
feat(spaces): request hierarchy from servers in via field of child event
2024-10-11 00:04:54 +01:00

56 lines
1.8 KiB
Rust

use std::str::FromStr;
use crate::{service::rooms::spaces::PagnationToken, services, Error, Result, Ruma};
use ruma::{
api::client::{error::ErrorKind, space::get_hierarchy},
UInt,
};
/// # `GET /_matrix/client/v1/rooms/{room_id}/hierarchy``
///
/// Paginates over the space tree in a depth-first manner to locate child rooms of a given space.
pub async fn get_hierarchy_route(
body: Ruma<get_hierarchy::v1::Request>,
) -> Result<get_hierarchy::v1::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let limit = body
.limit
.unwrap_or(UInt::from(10_u32))
.min(UInt::from(100_u32));
let max_depth = body
.max_depth
.unwrap_or(UInt::from(3_u32))
.min(UInt::from(10_u32));
let key = body
.from
.as_ref()
.and_then(|s| PagnationToken::from_str(s).ok());
// Should prevent unexpected behaviour in (bad) clients
if let Some(token) = &key {
if token.suggested_only != body.suggested_only || token.max_depth != max_depth {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
"suggested_only and max_depth cannot change on paginated requests",
));
}
}
services()
.rooms
.spaces
.get_client_hierarchy(
sender_user,
&body.room_id,
usize::try_from(limit)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Limit is too great"))?,
key.map_or(vec![], |token| token.short_room_ids),
usize::try_from(max_depth).map_err(|_| {
Error::BadRequest(ErrorKind::InvalidParam, "Max depth is too great")
})?,
body.suggested_only,
)
.await
}