feat: Support MSC4494

This commit is contained in:
timedout committed 2026-10-02 18:10:17 +01:00
1 parent f1d9537b14
commit 43ee11bb00
3 files changed
+45 -6

No files matched your search

+1
View File
@@ -383,6 +383,7 @@ features = [
"unstable-msc4354",
"unstable-msc4480",
"unstable-msc4466",
"unstable-msc4494",
"unstable-extensible-events",
]
+2
View File
@@ -46,5 +46,7 @@ pub fn unstable_features() -> BTreeMap<String, bool> {
("computer.gingershaped.msc4466".to_owned(), true),
// web push (https://github.com/matrix-org/matrix-spec-proposals/pull/4174)
("org.matrix.msc4174".to_owned(), true),
// Membership-based invite blocking (https://github.com/matrix-org/matrix-spec-proposals/pull/4494)
("uk.timedout.msc4494".to_owned(), true),
])
}
+42 -6
View File
@@ -4,7 +4,7 @@
};
use conduwuit::{
Err, Result, debug_error, debug_warn, err, error, info, trace,
Err, Result, debug, debug_error, debug_warn, err, error, info, trace,
utils::{self, stream::TryIgnore},
warn,
};
@@ -16,10 +16,12 @@
api::client::profile::PropagateTo,
events::{
GlobalAccountDataEventType, ignored_user_list::IgnoredUserListEvent,
push_rules::PushRulesEvent, room::message::RoomMessageEventContent,
invite_permission_config::InvitePermissionAction, push_rules::PushRulesEvent,
room::message::RoomMessageEventContent,
},
profile::ProfileFieldValue,
push::Ruleset,
room::JoinRule,
};
use ruminuwuity::invite_permission_config::{FilterLevel, InvitePermissionConfigEvent};
@@ -105,13 +107,47 @@ pub async fn invite_filter_level(
if stable.is_err() && unstable.is_err() {
return FilterLevel::Allow;
}
stable
.unwrap_or_else(|_| unstable.unwrap())
.content
.user_filter_level(sender_user)
let content = stable.unwrap_or_else(|_| unstable.unwrap()).content;
let verdict = content.user_filter_level(sender_user);
if verdict != FilterLevel::Allow {
return verdict;
}
// Apply other layers of invite blocking first, so that user/server
// denies take priority over implicit allows.
if content.default_action != Some(InvitePermissionAction::DenyPublic)
&& self
.check_msc4494_mutual_room(sender_user, recipient_user)
.await
{
FilterLevel::Block
} else {
FilterLevel::Allow
}
}
}
/// Checks that sender and recipient share at least one rule that has a join
/// rule other than `public`.
async fn check_msc4494_mutual_room(&self, sender: &UserId, recipient: &UserId) -> bool {
let mut mutual_rooms = std::pin::pin!(
self.services
.state_cache
.get_shared_rooms(sender, recipient)
);
while let Some(room_id) = mutual_rooms.next().await {
if self.services.state_accessor.get_join_rules(&room_id).await != JoinRule::Public {
debug!(
%sender,
%recipient,
%room_id,
"Sender and recipient share a non-public room"
);
return true;
}
}
false
}
/// Check if a user is an admin
#[inline]
pub async fn is_admin(&self, user_id: &UserId) -> bool {