Skip to main content

tuwunel_service/rooms/event_handler/
acl_check.rs

1use ruma::{
2	RoomId, ServerName,
3	events::{StateEventType, room::server_acl::RoomServerAclEventContent},
4};
5use tuwunel_core::{Err, Result, debug, implement, trace, warn};
6
7/// Returns Ok if the acl allows the server
8#[implement(super::Service)]
9#[tracing::instrument(skip_all, level = "debug")]
10pub async fn acl_check(&self, server_name: &ServerName, room_id: &RoomId) -> Result {
11	let Ok(acl_event_content) = self
12		.services
13		.state_accessor
14		.room_state_get_content(room_id, &StateEventType::RoomServerAcl, "")
15		.await
16		.map(|c: RoomServerAclEventContent| c)
17		.inspect(|acl| trace!(%room_id, "ACL content found: {acl:?}"))
18		.inspect_err(|e| trace!(%room_id, "No ACL content found: {e:?}"))
19	else {
20		return Ok(());
21	};
22
23	if acl_event_content.allow.is_empty() {
24		warn!(%room_id, "Ignoring broken ACL event (allow key is empty)");
25		return Ok(());
26	}
27
28	if acl_event_content
29		.deny
30		.contains(&String::from("*"))
31		&& acl_event_content
32			.allow
33			.contains(&String::from("*"))
34	{
35		warn!(%room_id, "Ignoring broken ACL event (allow key and deny key both contain wildcard \"*\"");
36		return Ok(());
37	}
38
39	if acl_event_content.is_allowed(server_name) {
40		trace!("server {server_name} is allowed by ACL");
41		Ok(())
42	} else {
43		debug!("Server {server_name} was denied by room ACL in {room_id}");
44		Err!(Request(Forbidden("Server was denied by room ACL")))
45	}
46}