mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-14 12:46:49 +00:00
feat: Support MSC4380 invite blocking
fix: Re-add silently dropped support for MSC4155
This commit is contained in:
2 files changed
+114
-11
No files matched your search
@@ -1,8 +1,13 @@
|
||||
//! Types for invite filtering ([MSC4155]).
|
||||
//! Types for invite filtering ([MSC4155]) and
|
||||
//! invite blocking ([invite-blocking]).
|
||||
//!
|
||||
//! MSC4155: https://github.com/matrix-org/matrix-spec-proposals/pull/4155
|
||||
//! invite-blocking: https://spec.matrix.org/v1.18/client-server-api/#invite-permission
|
||||
|
||||
use ruma::{ServerName, UserId, exports::ruma_macros::EventContent};
|
||||
use ruma::{
|
||||
ServerName, UserId, events::invite_permission_config::InvitePermissionAction,
|
||||
exports::ruma_macros::EventContent,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wildmatch::WildMatch;
|
||||
|
||||
@@ -25,6 +30,21 @@ pub struct InvitePermissionConfigEventContent {
|
||||
#[serde(default = "ruma::serde::default_true")]
|
||||
pub enabled: bool,
|
||||
|
||||
/// The default action chosen by the user that the homeserver should perform
|
||||
/// automatically when receiving an invitation for this account.
|
||||
///
|
||||
/// A missing, invalid or unsupported value means that the user wants to
|
||||
/// receive invites as normal. Other parts of the specification might still
|
||||
/// have effects on invites, like [ignoring users].
|
||||
///
|
||||
/// [ignoring users]: https://spec.matrix.org/v1.18/client-server-api/#ignoring-users
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "ruma::serde::default_on_error",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub default_action: Option<InvitePermissionAction>,
|
||||
|
||||
/// A list of globs matching users which are allowed to send an invite.
|
||||
/// Entries in this list supersede entries in the ignored and blocked lists.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
@@ -77,6 +97,7 @@ impl InvitePermissionConfigEventContent {
|
||||
) -> Self {
|
||||
Self {
|
||||
enabled,
|
||||
default_action: None,
|
||||
allowed_users,
|
||||
ignored_users,
|
||||
blocked_users,
|
||||
@@ -86,12 +107,21 @@ impl InvitePermissionConfigEventContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the default action is configured and set to block.
|
||||
fn are_all_blocked(&self) -> bool {
|
||||
self.default_action
|
||||
.clone()
|
||||
.is_some_and(|action| action == InvitePermissionAction::Block)
|
||||
}
|
||||
|
||||
/// Test the filters against a user id. This function will check both the
|
||||
/// user rules _and_ the server rules.
|
||||
#[must_use]
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
pub fn user_filter_level(&self, user: &UserId) -> FilterLevel {
|
||||
if !self.enabled {
|
||||
if self.are_all_blocked() {
|
||||
FilterLevel::Block
|
||||
} else if !self.enabled {
|
||||
FilterLevel::Allow
|
||||
} else if Self::matches(&self.allowed_users, user.as_str()) {
|
||||
FilterLevel::Allow
|
||||
@@ -132,7 +162,12 @@ impl InvitePermissionConfigEventContent {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruma::{ServerName, UserId, events::GlobalAccountDataEvent};
|
||||
use assign::assign;
|
||||
use ruma::{
|
||||
ServerName, UserId,
|
||||
events::{GlobalAccountDataEvent, invite_permission_config::InvitePermissionAction},
|
||||
user_id,
|
||||
};
|
||||
use serde_json::{from_value as from_json_value, json};
|
||||
|
||||
use crate::invite_permission_config::{FilterLevel, InvitePermissionConfigEventContent};
|
||||
@@ -268,4 +303,58 @@ mod tests {
|
||||
FilterLevel::Ignore
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v118_blocking_enabled_blocks_all() {
|
||||
let event = assign!(
|
||||
InvitePermissionConfigEventContent::default(),
|
||||
{ default_action: Some(InvitePermissionAction::Block) }
|
||||
);
|
||||
let fixtures = [
|
||||
user_id!("@alice:goodguys.org"),
|
||||
user_id!("@alice:goodguys.org:8080"),
|
||||
user_id!("@bob:bar.com"),
|
||||
user_id!("@bob:Bar.com"),
|
||||
user_id!("@kevin:reallybadguys.org"),
|
||||
];
|
||||
assert!(
|
||||
fixtures
|
||||
.iter()
|
||||
.all(|f| event.user_filter_level(f) == FilterLevel::Block)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v118_blocking_enabled_is_uninfluenced_by_msc4155() {
|
||||
let toggled = InvitePermissionConfigEventContent {
|
||||
enabled: false,
|
||||
default_action: Some(InvitePermissionAction::Block),
|
||||
..Default::default()
|
||||
};
|
||||
let only_goodguys = InvitePermissionConfigEventContent {
|
||||
enabled: true,
|
||||
default_action: Some(InvitePermissionAction::Block),
|
||||
allowed_servers: vec!["goodguys.org".to_owned()],
|
||||
ignored_servers: vec!["reallybadguys.org".to_owned()],
|
||||
blocked_servers: vec!["*".to_owned()],
|
||||
..Default::default()
|
||||
};
|
||||
let fixtures = [
|
||||
user_id!("@alice:goodguys.org"),
|
||||
user_id!("@alice:goodguys.org:8080"),
|
||||
user_id!("@bob:bar.com"),
|
||||
user_id!("@bob:Bar.com"),
|
||||
user_id!("@kevin:reallybadguys.org"),
|
||||
];
|
||||
assert!(
|
||||
fixtures
|
||||
.iter()
|
||||
.all(|f| toggled.user_filter_level(f) == FilterLevel::Block)
|
||||
);
|
||||
assert!(
|
||||
fixtures
|
||||
.iter()
|
||||
.all(|f| only_goodguys.user_filter_level(f) == FilterLevel::Block)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -164,13 +164,27 @@ impl Service {
|
||||
if self.user_is_ignored(sender_user, recipient_user).await {
|
||||
FilterLevel::Ignore
|
||||
} else {
|
||||
self.services
|
||||
.account_data
|
||||
.get_global(recipient_user, GlobalAccountDataEventType::InvitePermissionConfig)
|
||||
.await
|
||||
.map_or(FilterLevel::Allow, |config: InvitePermissionConfigEvent| {
|
||||
config.content.user_filter_level(sender_user)
|
||||
})
|
||||
let (stable, unstable) = tokio::join!(
|
||||
self.services
|
||||
.account_data
|
||||
.get_global::<InvitePermissionConfigEvent>(
|
||||
recipient_user,
|
||||
GlobalAccountDataEventType::InvitePermissionConfig
|
||||
),
|
||||
self.services
|
||||
.account_data
|
||||
.get_global::<InvitePermissionConfigEvent>(
|
||||
recipient_user,
|
||||
"org.matrix.msc4155.invite_permission_config".into()
|
||||
) // TODO: MSC4155 probably needs upstreaming to ruma at some point
|
||||
);
|
||||
if stable.is_err() && unstable.is_err() {
|
||||
return FilterLevel::Allow;
|
||||
}
|
||||
stable
|
||||
.unwrap_or_else(|_| unstable.unwrap())
|
||||
.content
|
||||
.user_filter_level(sender_user)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user