tuwunel_api/server/
event_auth.rs1use std::{borrow::Borrow, iter::once};
2
3use axum::extract::State;
4use futures::StreamExt;
5use ruma::{
6 RoomId,
7 api::{error::ErrorKind, federation::authorization::get_event_authorization},
8};
9use tuwunel_core::{
10 Error, Result,
11 utils::stream::{BroadbandExt, ReadyExt},
12};
13
14use super::AccessCheck;
15use crate::Ruma;
16
17pub(crate) async fn get_event_authorization_route(
23 State(services): State<crate::State>,
24 body: Ruma<get_event_authorization::v1::Request>,
25) -> Result<get_event_authorization::v1::Response> {
26 AccessCheck {
27 services: &services,
28 origin: body.origin(),
29 room_id: &body.room_id,
30 event_id: None,
31 }
32 .check()
33 .await?;
34
35 let event = services
36 .timeline
37 .get_pdu_json(&body.event_id)
38 .await
39 .map_err(|_| Error::BadRequest(ErrorKind::NotFound, "Event not found."))?;
40
41 let room_id_str = event
42 .get("room_id")
43 .and_then(|val| val.as_str())
44 .ok_or_else(|| Error::bad_database("Invalid event in database."))?;
45
46 let room_id = <&RoomId>::try_from(room_id_str)
47 .map_err(|_| Error::bad_database("Invalid room_id in event in database."))?;
48
49 let room_version = services.state.get_room_version(room_id).await?;
50
51 let auth_chain = services
52 .auth_chain
53 .event_ids_iter(room_id, &room_version, once(body.event_id.borrow()))
54 .ready_filter_map(Result::ok)
55 .broad_filter_map(async |id| {
56 let pdu = services.timeline.get_pdu_json(&id).await.ok()?;
57
58 let pdu = services
59 .federation
60 .format_pdu_into(pdu, Some(&room_version))
61 .await;
62
63 Some(pdu)
64 })
65 .collect()
66 .await;
67
68 Ok(get_event_authorization::v1::Response { auth_chain })
69}