Skip to main content

tuwunel_service/rooms/state_accessor/
server_can.rs

1use futures::StreamExt;
2use ruma::{
3	EventId, RoomId, ServerName,
4	events::{
5		StateEventType,
6		room::history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
7	},
8};
9use tuwunel_core::{implement, utils::stream::ReadyExt};
10
11/// Whether a server is allowed to see an event through federation, based on
12/// the room's history_visibility at that event's state.
13#[implement(super::Service)]
14#[tracing::instrument(skip_all, level = "trace")]
15pub async fn server_can_see_event(
16	&self,
17	origin: &ServerName,
18	room_id: &RoomId,
19	event_id: &EventId,
20) -> bool {
21	let Ok(shortstatehash) = self
22		.services
23		.state
24		.pdu_shortstatehash(event_id)
25		.await
26	else {
27		return true;
28	};
29
30	let history_visibility = self
31		.state_get_content(shortstatehash, &StateEventType::RoomHistoryVisibility, "")
32		.await
33		.map_or(HistoryVisibility::Shared, |c: RoomHistoryVisibilityEventContent| {
34			c.history_visibility
35		});
36
37	let current_server_members = self
38		.services
39		.state_cache
40		.room_members(room_id)
41		.ready_filter(|member| member.server_name() == origin);
42
43	match history_visibility {
44		| HistoryVisibility::Invited => {
45			// Allow if any member on requesting server was AT LEAST invited, else deny
46			current_server_members
47				.any(|member| self.user_was_invited(shortstatehash, member))
48				.await
49		},
50		| HistoryVisibility::Joined => {
51			// Allow if any member on requested server was joined, else deny
52			current_server_members
53				.any(|member| self.user_was_joined(shortstatehash, member))
54				.await
55		},
56		| HistoryVisibility::WorldReadable | HistoryVisibility::Shared | _ => true,
57	}
58}