use axum::extract::State; use futures::{FutureExt, future::try_join}; use ruma::{MilliSecondsSinceUnixEpoch, OwnedRoomId, api::federation::event::get_event}; use tuwunel_core::{Result, err}; use super::AccessCheck; use crate::Ruma; /// # `GET /_matrix/federation/v1/event/{eventId}` /// /// Retrieves a single event from the server. /// /// - Only works if a user of this server is currently invited or joined the /// room pub(crate) async fn get_event_route( State(services): State, body: Ruma, ) -> Result { let event = services .timeline .get_pdu_json(&body.event_id) .await .map_err(|_| err!(Request(NotFound("Event not found."))))?; let room_id: OwnedRoomId = event .get("room_id") .and_then(|val| val.as_str()) .ok_or_else(|| err!(Database("Invalid event in database.")))? .try_into() .map_err(|_| err!(Database("Invalid room_id in event in database.")))?; let access_check = AccessCheck { services: &services, origin: body.origin(), room_id: &room_id, event_id: Some(&body.event_id), }; let pdu = services .federation .format_pdu_into(event, None) .map(Ok); let ((), pdu) = try_join(access_check.check(), pdu).await?; Ok(get_event::v1::Response { origin: services.globals.server_name().to_owned(), origin_server_ts: MilliSecondsSinceUnixEpoch::now(), pdu, }) }