mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
fix: Apply spam checker to local restricted joins
This commit is contained in:
@@ -33,7 +33,7 @@ use ruma::{
|
|||||||
events::{
|
events::{
|
||||||
StateEventType,
|
StateEventType,
|
||||||
room::{
|
room::{
|
||||||
join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent},
|
join_rules::{AllowRule, JoinRule},
|
||||||
member::{MembershipState, RoomMemberEventContent},
|
member::{MembershipState, RoomMemberEventContent},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -338,6 +338,17 @@ pub async fn join_room_by_id_helper(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if services.antispam.check_all_joins() {
|
||||||
|
if let Err(e) = services
|
||||||
|
.antispam
|
||||||
|
.meowlnir_accept_make_join(room_id.to_owned(), sender_user.to_owned())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
warn!("Antispam prevented user {} from joining room {}: {}", sender_user, room_id, e);
|
||||||
|
return Err!(Request(Forbidden("Antispam rejected join request.")));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if server_in_room {
|
if server_in_room {
|
||||||
join_room_by_id_helper_local(
|
join_room_by_id_helper_local(
|
||||||
services,
|
services,
|
||||||
@@ -736,45 +747,51 @@ async fn join_room_by_id_helper_local(
|
|||||||
state_lock: RoomMutexGuard,
|
state_lock: RoomMutexGuard,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
debug_info!("We can join locally");
|
debug_info!("We can join locally");
|
||||||
|
let join_rules = services.rooms.state_accessor.get_join_rules(room_id).await;
|
||||||
|
|
||||||
let join_rules_event_content = services
|
let mut restricted_join_authorized = None;
|
||||||
.rooms
|
match join_rules {
|
||||||
.state_accessor
|
| JoinRule::Restricted(restricted) | JoinRule::KnockRestricted(restricted) => {
|
||||||
.room_state_get_content::<RoomJoinRulesEventContent>(
|
for restriction in restricted.allow {
|
||||||
room_id,
|
match restriction {
|
||||||
&StateEventType::RoomJoinRules,
|
| AllowRule::RoomMembership(membership) => {
|
||||||
"",
|
if services
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let restriction_rooms = match join_rules_event_content {
|
|
||||||
| Ok(RoomJoinRulesEventContent {
|
|
||||||
join_rule: JoinRule::Restricted(restricted) | JoinRule::KnockRestricted(restricted),
|
|
||||||
}) => restricted
|
|
||||||
.allow
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|a| match a {
|
|
||||||
| AllowRule::RoomMembership(r) => Some(r.room_id),
|
|
||||||
| _ => None,
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
| _ => Vec::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let join_authorized_via_users_server: Option<OwnedUserId> = {
|
|
||||||
if restriction_rooms
|
|
||||||
.iter()
|
|
||||||
.stream()
|
|
||||||
.any(|restriction_room_id| {
|
|
||||||
trace!("Checking if {sender_user} is joined to {restriction_room_id}");
|
|
||||||
services
|
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.is_joined(sender_user, restriction_room_id)
|
.is_joined(sender_user, &membership.room_id)
|
||||||
})
|
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
services
|
restricted_join_authorized = Some(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
| AllowRule::UnstableSpamChecker => {
|
||||||
|
match services
|
||||||
|
.antispam
|
||||||
|
.meowlnir_accept_make_join(room_id.to_owned(), sender_user.to_owned())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
| Ok(()) => {
|
||||||
|
restricted_join_authorized = Some(true);
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
| Err(_) =>
|
||||||
|
return Err!(Request(Forbidden(
|
||||||
|
"Antispam rejected join request."
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
| _ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
| _ => {},
|
||||||
|
};
|
||||||
|
let join_authorized_via_users_server = if restricted_join_authorized.is_none() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
match restricted_join_authorized.unwrap() {
|
||||||
|
| true => services
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.local_users_in_room(room_id)
|
.local_users_in_room(room_id)
|
||||||
@@ -790,10 +807,14 @@ async fn join_room_by_id_helper_local(
|
|||||||
.boxed()
|
.boxed()
|
||||||
.next()
|
.next()
|
||||||
.await
|
.await
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned),
|
||||||
} else {
|
| false => {
|
||||||
trace!("No restriction rooms are joined by {sender_user}");
|
warn!(
|
||||||
None
|
"Join authorization failed for restricted join in room {room_id} for user \
|
||||||
|
{sender_user}"
|
||||||
|
);
|
||||||
|
return Err!(Request(Forbidden("You are not authorized to join this room.")));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -821,16 +842,14 @@ async fn join_room_by_id_helper_local(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
if restriction_rooms.is_empty()
|
if servers.is_empty() || servers.len() == 1 && services.globals.server_is_ours(&servers[0]) {
|
||||||
&& (servers.is_empty()
|
|
||||||
|| servers.len() == 1 && services.globals.server_is_ours(&servers[0]))
|
|
||||||
{
|
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!(
|
warn!(
|
||||||
"We couldn't do the join locally, maybe federation can help to satisfy the restricted \
|
?error,
|
||||||
join requirements"
|
remote_servers = %servers.len()-1,
|
||||||
|
"Could not join restricted room locally, attempting remote join",
|
||||||
);
|
);
|
||||||
let Ok((make_join_response, remote_server)) =
|
let Ok((make_join_response, remote_server)) =
|
||||||
make_join_request(services, sender_user, room_id, servers).await
|
make_join_request(services, sender_user, room_id, servers).await
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ pub(crate) async fn user_can_perform_restricted_join(
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
| Ok(()) => Ok(true),
|
| Ok(()) => Ok(true),
|
||||||
| Err(e) => Err!(Request(Forbidden("Antispam rejected join request."))),
|
| Err(_) => Err!(Request(Forbidden("Antispam rejected join request."))),
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
debug_info!(
|
debug_info!(
|
||||||
|
|||||||
@@ -169,4 +169,14 @@ impl Service {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether all joins should be checked with Meowlnir.
|
||||||
|
/// Is always false if Meowlnir is not configured.
|
||||||
|
pub fn check_all_joins(&self) -> bool {
|
||||||
|
if let Some(Antispam { meowlnir: Some(cfg), .. }) = &self.services.config.antispam {
|
||||||
|
cfg.check_all_joins
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user