Skip to main content

tuwunel_api/server/
hierarchy.rs

1use Accessibility::{Accessible, Inaccessible};
2use Identifier::ServerName;
3use axum::extract::State;
4use futures::{FutureExt, StreamExt};
5use get_hierarchy::v1::{Request, Response};
6use ruma::api::federation::space::get_hierarchy;
7use tuwunel_core::{
8	Err, Result,
9	utils::stream::{BroadbandExt, IterStream},
10};
11use tuwunel_service::rooms::spaces::{Accessibility, Identifier, get_parent_children_via};
12
13use crate::Ruma;
14
15/// # `GET /_matrix/federation/v1/hierarchy/{roomId}`
16///
17/// Gets the space tree in a depth-first manner to locate child rooms of a given
18/// space.
19pub(crate) async fn get_hierarchy_route(
20	State(services): State<crate::State>,
21	body: Ruma<Request>,
22) -> Result<Response> {
23	if !services.metadata.exists(&body.room_id).await {
24		return Err!(Request(NotFound("Room does not exist.")));
25	}
26
27	match services
28		.spaces
29		.get_summary_and_children(&body.room_id, &ServerName(body.origin()), &[])
30		.await?
31	{
32		| Inaccessible => Err!(Request(NotFound("The requested room is inaccessible"))),
33		| Accessible(room) => {
34			let (children, inaccessible_children) =
35				get_parent_children_via(&room, body.suggested_only)
36					.stream()
37					.broad_filter_map(async |(child, _via)| {
38						match services
39							.spaces
40							.get_summary_and_children(&child, &ServerName(body.origin()), &[])
41							.await
42							.ok()?
43						{
44							| Inaccessible => Some((None, Some(child))),
45							| Accessible(summary) => Some((Some(summary), None)),
46						}
47					})
48					.unzip()
49					.map(|(children, inaccessible_children): (Vec<_>, Vec<_>)| {
50						let children = children
51							.into_iter()
52							.flatten()
53							.map(|parent| parent.summary)
54							.collect();
55
56						let inaccessible_children = inaccessible_children
57							.into_iter()
58							.flatten()
59							.collect();
60
61						(children, inaccessible_children)
62					})
63					.await;
64
65			Ok(Response { room, children, inaccessible_children })
66		},
67	}
68}