ruma_federation_api/space/get_hierarchy/
v1.rs

1//! `/v1/` ([spec])
2//!
3//! [spec]: https://spec.matrix.org/latest/server-server-api/#get_matrixfederationv1hierarchyroomid
4
5use ruma_common::{
6    api::{request, response},
7    metadata,
8    room::RoomSummary,
9    OwnedRoomId,
10};
11
12use crate::{authentication::ServerSignatures, space::SpaceHierarchyParentSummary};
13
14metadata! {
15    method: GET,
16    rate_limited: false,
17    authentication: ServerSignatures,
18    path: "/_matrix/federation/v1/hierarchy/{room_id}",
19}
20
21/// Request type for the `hierarchy` endpoint.
22#[request]
23pub struct Request {
24    /// The room ID of the space to get a hierarchy for.
25    #[ruma_api(path)]
26    pub room_id: OwnedRoomId,
27
28    /// Whether or not the server should only consider suggested rooms.
29    ///
30    /// Suggested rooms are annotated in their `m.space.child` event contents.
31    #[ruma_api(query)]
32    #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
33    pub suggested_only: bool,
34}
35
36/// Response type for the `hierarchy` endpoint.
37#[response]
38pub struct Response {
39    /// A summary of the space’s children.
40    ///
41    /// Rooms which the requesting server cannot peek/join will be excluded.
42    pub children: Vec<RoomSummary>,
43
44    /// The list of room IDs the requesting server doesn’t have a viable way to peek/join.
45    ///
46    /// Rooms which the responding server cannot provide details on will be outright
47    /// excluded from the response instead.
48    pub inaccessible_children: Vec<OwnedRoomId>,
49
50    /// A summary of the requested room.
51    pub room: SpaceHierarchyParentSummary,
52}
53
54impl Request {
55    /// Creates a `Request` with the given room ID.
56    pub fn new(room_id: OwnedRoomId) -> Self {
57        Self { room_id, suggested_only: false }
58    }
59}
60
61impl Response {
62    /// Creates a new `Response` with the given room summary.
63    pub fn new(room_summary: SpaceHierarchyParentSummary) -> Self {
64        Self { children: Vec::new(), inaccessible_children: Vec::new(), room: room_summary }
65    }
66}
67
68#[cfg(all(test, feature = "client"))]
69mod tests {
70    use ruma_common::{api::IncomingResponse, OwnedRoomId};
71    use serde_json::{json, to_vec as to_json_vec};
72
73    use super::Response;
74
75    #[test]
76    fn deserialize_response() {
77        let body = json!({
78            "children": [
79                {
80                    "room_id": "!a:localhost",
81                    "num_joined_members": 6,
82                    "world_readable": true,
83                    "guest_can_join": false,
84                    "join_rule": "public",
85                },
86            ],
87            "inaccessible_children": [],
88            "room": {
89                "room_id": "!room:localhost",
90                "num_joined_members": 5,
91                "world_readable": false,
92                "guest_can_join": false,
93                "join_rule": "restricted",
94                "allowed_room_ids": ["!otherroom:localhost"],
95                "type": "space",
96                "children_state": [
97                    {
98                        "content": {
99                            "via": [
100                                "example.org"
101                            ]
102                        },
103                        "origin_server_ts": 1_629_413_349,
104                        "sender": "@alice:example.org",
105                        "state_key": "!a:example.org",
106                        "type": "m.space.child"
107                    }
108                ],
109            },
110        });
111        let response = http::Response::new(to_json_vec(&body).unwrap());
112
113        let response = Response::try_from_http_response(response).unwrap();
114
115        assert_eq!(response.room.summary.room_id, "!room:localhost");
116        let space_child = response.room.children_state[0].deserialize().unwrap();
117        assert_eq!(space_child.state_key, "!a:example.org");
118        assert_eq!(response.inaccessible_children, &[] as &[OwnedRoomId]);
119        assert_eq!(response.children[0].room_id, "!a:localhost");
120    }
121}