From 437cb5783a04f41fa31c2906ad4596093f703e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Thu, 4 Mar 2021 11:29:13 +0100 Subject: [PATCH] fix: apply the same appservice sending rules to events coming from federation currently this code is duplicated from database/rooms.rs, when we refactor server_server.rs we should deduplicate it --- src/server_server.rs | 67 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/server_server.rs b/src/server_server.rs index 4ea9bfe..26d7b1d 100644 --- a/src/server_server.rs +++ b/src/server_server.rs @@ -2,6 +2,7 @@ use crate::{client_server, utils, ConduitResult, Database, Error, PduEvent, Resu use get_profile_information::v1::ProfileField; use http::header::{HeaderValue, AUTHORIZATION, HOST}; use log::{info, warn}; +use regex::Regex; use rocket::{get, post, put, response::content::Json, State}; use ruma::{ api::{ @@ -18,6 +19,7 @@ use ruma::{ OutgoingRequest, }, directory::{IncomingFilter, IncomingRoomNetwork}, + events::EventType, EventId, RoomId, ServerName, ServerSigningKeyId, UserId, }; use std::{ @@ -584,9 +586,70 @@ pub async fn send_transaction_message_route<'a>( db.rooms.set_room_state(&room_id, &next_room_state)?; for appservice in db.appservice.iter_all().filter_map(|r| r.ok()) { - db.sending.send_pdu_appservice(&appservice.0, &pdu_id)?; - } + if let Some(namespaces) = appservice.1.get("namespaces") { + let users = namespaces + .get("users") + .and_then(|users| users.as_sequence()) + .map_or_else( + || Vec::new(), + |users| { + users + .iter() + .map(|users| { + users + .get("regex") + .and_then(|regex| regex.as_str()) + .and_then(|regex| Regex::new(regex).ok()) + }) + .filter_map(|o| o) + .collect::>() + }, + ); + let aliases = namespaces + .get("aliases") + .and_then(|users| users.get("regex")) + .and_then(|regex| regex.as_str()) + .and_then(|regex| Regex::new(regex).ok()); + let rooms = namespaces + .get("rooms") + .and_then(|rooms| rooms.as_sequence()); + let room_aliases = db.rooms.room_aliases(&room_id); + + let bridge_user_id = appservice + .1 + .get("sender_localpart") + .and_then(|string| string.as_str()) + .and_then(|string| { + UserId::parse_with_server_name(string, db.globals.server_name()).ok() + }); + + if bridge_user_id.map_or(false, |bridge_user_id| { + db.rooms + .is_joined(&bridge_user_id, room_id) + .unwrap_or(false) + }) || users.iter().any(|users| { + users.is_match(pdu.sender.as_str()) + || pdu.kind == EventType::RoomMember + && pdu + .state_key + .as_ref() + .map_or(false, |state_key| users.is_match(&state_key)) + }) || aliases.map_or(false, |aliases| { + room_aliases + .filter_map(|r| r.ok()) + .any(|room_alias| aliases.is_match(room_alias.as_str())) + }) || rooms.map_or(false, |rooms| rooms.contains(&room_id.as_str().into())) + || db + .rooms + .room_members(&room_id) + .filter_map(|r| r.ok()) + .any(|member| users.iter().any(|regex| regex.is_match(member.as_str()))) + { + db.sending.send_pdu_appservice(&appservice.0, &pdu_id)?; + } + } + } resolved_map.insert(event_id, Ok::<(), String>(())); }