Skip to main content

tuwunel_api/server/
event.rs

1use axum::extract::State;
2use futures::future::try_join;
3use ruma::{MilliSecondsSinceUnixEpoch, OwnedRoomId, api::federation::event::get_event};
4use tuwunel_core::{Result, err};
5
6use super::AccessCheck;
7use crate::Ruma;
8
9/// # `GET /_matrix/federation/v1/event/{eventId}`
10///
11/// Retrieves a single event from the server.
12///
13/// The requesting server must be joined to the room, unless the room is
14/// world-readable or carries a pending knock. The room's ACL and the event's
15/// history visibility are checked independently; either can refuse.
16pub(crate) async fn get_event_route(
17	State(services): State<crate::State>,
18	body: Ruma<get_event::v1::Request>,
19) -> Result<get_event::v1::Response> {
20	let event = services
21		.timeline
22		.get_pdu_json(&body.event_id)
23		.await
24		.map_err(|_| err!(Request(NotFound("Event not found."))))?;
25
26	let room_id: OwnedRoomId = event
27		.get("room_id")
28		.and_then(|val| val.as_str())
29		.ok_or_else(|| err!(Database("Invalid event in database.")))?
30		.try_into()
31		.map_err(|_| err!(Database("Invalid room_id in event in database.")))?;
32
33	let access_check = AccessCheck {
34		services: &services,
35		origin: body.origin(),
36		room_id: &room_id,
37		event_id: Some(&body.event_id),
38	};
39
40	let pdu = async {
41		let event = services
42			.state_accessor
43			.erased_for_server(body.origin(), event)
44			.await;
45
46		let pdu = services
47			.federation
48			.format_pdu_into(event, None)
49			.await;
50
51		Ok(pdu)
52	};
53
54	let ((), pdu) = try_join(access_check.check(), pdu).await?;
55
56	Ok(get_event::v1::Response {
57		origin: services.globals.server_name().to_owned(),
58		origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
59		pdu,
60	})
61}