tuwunel_api_client/room/
event.rs1use axum::extract::State;
2use futures::{TryFutureExt, future::join};
3use ruma::api::client::room::get_room_event;
4use tuwunel_core::{
5 Err, Result, err,
6 result::IsErrOr,
7 utils::{BoolExt, FutureBoolExt, TryFutureExtExt, future::OptionFutureExt},
8};
9use tuwunel_matrix::{Event, Pdu};
10
11use crate::{Ruma, is_ignored_pdu, with_membership};
12
13pub(crate) async fn get_room_event_route(
17 State(services): State<crate::State>,
18 body: Ruma<get_room_event::v3::Request>,
19) -> Result<get_room_event::v3::Response> {
20 let sender_user = body.sender_user();
21 let event_id = &body.event_id;
22 let room_id = &body.room_id;
23
24 let event = services
25 .timeline
26 .get_pdu(event_id)
27 .map_err(|_| err!(Request(NotFound("Event {} not found.", event_id))));
28
29 let retained_event = body
30 .include_unredacted_content
31 .then_async(async || {
32 let is_admin = services.admin.user_is_admin(sender_user);
33
34 let can_redact = services
35 .config
36 .rooms
37 .redaction
38 .allow_room_admins_to_request_unredacted_events
39 .then_async(|| {
40 services
41 .state_accessor
42 .get_power_levels(room_id)
43 .map_ok_or(false, |power_levels| {
44 power_levels.for_user(sender_user) >= power_levels.redact
45 })
46 })
47 .unwrap_or(false);
48
49 if is_admin.or(can_redact).await {
50 services
51 .retention
52 .get_original_pdu(event_id)
53 .await
54 .map_err(|_| err!(Request(NotFound("Event {} not found.", event_id))))
55 } else {
56 Err!(Request(Forbidden("You are not allowed to see the original event")))
57 }
58 });
59
60 let (event, retained_event) = join(event, retained_event).await;
61
62 let event: Result<Pdu> = retained_event
63 .filter(|_| event.as_ref().is_err_or(Event::is_redacted))
64 .unwrap_or(event);
65
66 let event = event?;
67
68 if event.room_id() != room_id
69 || !services
70 .state_accessor
71 .user_can_see_event(sender_user, &event)
72 .await
73 {
74 return Err!(Request(NotFound("Event not found.")));
75 }
76
77 if is_ignored_pdu(&services, &event, body.sender_user()).await {
78 return Err!(HttpJson(NOT_FOUND, {
79 "errcode": "M_SENDER_IGNORED",
80 "error": "You have ignored the user that sent this event",
81 "sender": event.sender().as_str(),
82 }));
83 }
84
85 debug_assert!(event.event_id() == event_id, "Fetched PDU must match requested");
86
87 let event = event.served_to(Some(sender_user));
88 let encrypted = services
89 .state_accessor
90 .is_encrypted_room(room_id)
91 .await;
92
93 let event = with_membership(&services, event, sender_user, encrypted).await;
94 let event = services
95 .pdu_metadata
96 .bundle_aggregations(sender_user, event)
97 .await;
98
99 Ok(get_room_event::v3::Response { event: event.into_format() })
100}