-
Notifications
You must be signed in to change notification settings - Fork 220
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move server event filtering logic to rust (#17928)
### Pull Request Checklist <!-- Please read https://element-hq.github.io/synapse/latest/development/contributing_guide.html before submitting your pull request --> * [X] Pull request is based on the develop branch * [X] Pull request includes a [changelog file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog). The entry should: - Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from `EventStore` to `EventWorkerStore`.". - Use markdown where necessary, mostly for `code blocks`. - End with either a period (.) or an exclamation mark (!). - Start with a capital letter. - Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry. * [X] [Code style](https://element-hq.github.io/synapse/latest/code_style.html) is correct (run the [linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))
- Loading branch information
Showing
9 changed files
with
265 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Move server event filtering logic to rust. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* This file is licensed under the Affero General Public License (AGPL) version 3. | ||
* | ||
* Copyright (C) 2024 New Vector, Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* See the GNU Affero General Public License for more details: | ||
* <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
*/ | ||
|
||
use std::collections::HashMap; | ||
|
||
use pyo3::{exceptions::PyValueError, pyfunction, PyResult}; | ||
|
||
use crate::{ | ||
identifier::UserID, | ||
matrix_const::{ | ||
HISTORY_VISIBILITY_INVITED, HISTORY_VISIBILITY_JOINED, MEMBERSHIP_INVITE, MEMBERSHIP_JOIN, | ||
}, | ||
}; | ||
|
||
#[pyfunction(name = "event_visible_to_server")] | ||
pub fn event_visible_to_server_py( | ||
sender: String, | ||
target_server_name: String, | ||
history_visibility: String, | ||
erased_senders: HashMap<String, bool>, | ||
partial_state_invisible: bool, | ||
memberships: Vec<(String, String)>, // (state_key, membership) | ||
) -> PyResult<bool> { | ||
event_visible_to_server( | ||
sender, | ||
target_server_name, | ||
history_visibility, | ||
erased_senders, | ||
partial_state_invisible, | ||
memberships, | ||
) | ||
.map_err(|e| PyValueError::new_err(format!("{e}"))) | ||
} | ||
|
||
/// Return whether the target server is allowed to see the event. | ||
/// | ||
/// For a fully stated room, the target server is allowed to see an event E if: | ||
/// - the state at E has world readable or shared history vis, OR | ||
/// - the state at E says that the target server is in the room. | ||
/// | ||
/// For a partially stated room, the target server is allowed to see E if: | ||
/// - E was created by this homeserver, AND: | ||
/// - the partial state at E has world readable or shared history vis, OR | ||
/// - the partial state at E says that the target server is in the room. | ||
pub fn event_visible_to_server( | ||
sender: String, | ||
target_server_name: String, | ||
history_visibility: String, | ||
erased_senders: HashMap<String, bool>, | ||
partial_state_invisible: bool, | ||
memberships: Vec<(String, String)>, // (state_key, membership) | ||
) -> anyhow::Result<bool> { | ||
if let Some(&erased) = erased_senders.get(&sender) { | ||
if erased { | ||
return Ok(false); | ||
} | ||
} | ||
|
||
if partial_state_invisible { | ||
return Ok(false); | ||
} | ||
|
||
if history_visibility != HISTORY_VISIBILITY_INVITED | ||
&& history_visibility != HISTORY_VISIBILITY_JOINED | ||
{ | ||
return Ok(true); | ||
} | ||
|
||
let mut visible = false; | ||
for (state_key, membership) in memberships { | ||
let state_key = UserID::try_from(state_key.as_ref()) | ||
.map_err(|e| anyhow::anyhow!(format!("invalid user_id ({state_key}): {e}")))?; | ||
if state_key.server_name() != target_server_name { | ||
return Err(anyhow::anyhow!( | ||
"state_key.server_name ({}) does not match target_server_name ({target_server_name})", | ||
state_key.server_name() | ||
)); | ||
} | ||
|
||
match membership.as_str() { | ||
MEMBERSHIP_INVITE => { | ||
if history_visibility == HISTORY_VISIBILITY_INVITED { | ||
visible = true; | ||
break; | ||
} | ||
} | ||
MEMBERSHIP_JOIN => { | ||
visible = true; | ||
break; | ||
} | ||
_ => continue, | ||
} | ||
} | ||
|
||
Ok(visible) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* This file is licensed under the Affero General Public License (AGPL) version 3. | ||
* | ||
* Copyright (C) 2024 New Vector, Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* See the GNU Affero General Public License for more details: | ||
* <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
*/ | ||
|
||
//! # Matrix Identifiers | ||
//! | ||
//! This module contains definitions and utilities for working with matrix identifiers. | ||
use std::{fmt, ops::Deref}; | ||
|
||
/// Errors that can occur when parsing a matrix identifier. | ||
#[derive(Clone, Debug, PartialEq)] | ||
pub enum IdentifierError { | ||
IncorrectSigil, | ||
MissingColon, | ||
} | ||
|
||
impl fmt::Display for IdentifierError { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{:?}", self) | ||
} | ||
} | ||
|
||
/// A Matrix user_id. | ||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct UserID(String); | ||
|
||
impl UserID { | ||
/// Returns the `localpart` of the user_id. | ||
pub fn localpart(&self) -> &str { | ||
&self[1..self.colon_pos()] | ||
} | ||
|
||
/// Returns the `server_name` / `domain` of the user_id. | ||
pub fn server_name(&self) -> &str { | ||
&self[self.colon_pos() + 1..] | ||
} | ||
|
||
/// Returns the position of the ':' inside of the user_id. | ||
/// Used when splitting the user_id into it's respective parts. | ||
fn colon_pos(&self) -> usize { | ||
self.find(':').unwrap() | ||
} | ||
} | ||
|
||
impl TryFrom<&str> for UserID { | ||
type Error = IdentifierError; | ||
|
||
/// Will try creating a `UserID` from the provided `&str`. | ||
/// Can fail if the user_id is incorrectly formatted. | ||
fn try_from(s: &str) -> Result<Self, Self::Error> { | ||
if !s.starts_with('@') { | ||
return Err(IdentifierError::IncorrectSigil); | ||
} | ||
|
||
if s.find(':').is_none() { | ||
return Err(IdentifierError::MissingColon); | ||
} | ||
|
||
Ok(UserID(s.to_string())) | ||
} | ||
} | ||
|
||
impl Deref for UserID { | ||
type Target = str; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl fmt::Display for UserID { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* This file is licensed under the Affero General Public License (AGPL) version 3. | ||
* | ||
* Copyright (C) 2024 New Vector, Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* See the GNU Affero General Public License for more details: | ||
* <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
*/ | ||
|
||
//! # Matrix Constants | ||
//! | ||
//! This module contains definitions for constant values described by the matrix specification. | ||
pub const HISTORY_VISIBILITY_WORLD_READABLE: &str = "world_readable"; | ||
pub const HISTORY_VISIBILITY_SHARED: &str = "shared"; | ||
pub const HISTORY_VISIBILITY_INVITED: &str = "invited"; | ||
pub const HISTORY_VISIBILITY_JOINED: &str = "joined"; | ||
|
||
pub const MEMBERSHIP_BAN: &str = "ban"; | ||
pub const MEMBERSHIP_LEAVE: &str = "leave"; | ||
pub const MEMBERSHIP_KNOCK: &str = "knock"; | ||
pub const MEMBERSHIP_INVITE: &str = "invite"; | ||
pub const MEMBERSHIP_JOIN: &str = "join"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.