fix(membership): perform stricter checks when choosing an authorized user

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
Matthias Ahouansou 2024-04-03 18:48:51 -04:00 committed by June
parent 68e64392f0
commit 5c30d2b2b0

View file

@ -20,7 +20,6 @@ use ruma::{
room::{ room::{
join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent}, join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent},
member::{MembershipState, RoomMemberEventContent}, member::{MembershipState, RoomMemberEventContent},
power_levels::RoomPowerLevelsEventContent,
}, },
StateEventType, TimelineEventType, StateEventType, TimelineEventType,
}, },
@ -880,11 +879,6 @@ pub(crate) async fn join_room_by_id_helper(
.rooms .rooms
.state_accessor .state_accessor
.room_state_get(room_id, &StateEventType::RoomJoinRules, "")?; .room_state_get(room_id, &StateEventType::RoomJoinRules, "")?;
let power_levels_event =
services()
.rooms
.state_accessor
.room_state_get(room_id, &StateEventType::RoomPowerLevels, "")?;
let join_rules_event_content: Option<RoomJoinRulesEventContent> = join_rules_event let join_rules_event_content: Option<RoomJoinRulesEventContent> = join_rules_event
.as_ref() .as_ref()
@ -895,15 +889,6 @@ pub(crate) async fn join_room_by_id_helper(
}) })
}) })
.transpose()?; .transpose()?;
let power_levels_event_content: Option<RoomPowerLevelsEventContent> = power_levels_event
.as_ref()
.map(|power_levels_event| {
serde_json::from_str(power_levels_event.content.get()).map_err(|e| {
warn!("Invalid power levels event: {}", e);
Error::bad_database("Invalid power levels event in db.")
})
})
.transpose()?;
let restriction_rooms = match join_rules_event_content { let restriction_rooms = match join_rules_event_content {
Some(RoomJoinRulesEventContent { Some(RoomJoinRulesEventContent {
@ -919,51 +904,29 @@ pub(crate) async fn join_room_by_id_helper(
_ => Vec::new(), _ => Vec::new(),
}; };
let authorized_user = restriction_rooms let authorized_user = if restriction_rooms.iter().any(|restriction_room_id| {
.iter()
.find_map(|restriction_room_id| {
if !services()
.rooms
.state_cache
.is_joined(sender_user, restriction_room_id)
.ok()?
{
return None;
}
let authorized_user = power_levels_event_content
.as_ref()
.and_then(|c| {
c.users
.iter()
.filter(|(uid, i)| {
uid.server_name() == services().globals.server_name()
&& **i > ruma::int!(0) && services()
.rooms
.state_cache
.is_joined(uid, restriction_room_id)
.unwrap_or(false)
})
.max_by_key(|(_, i)| *i)
.map(|(u, _)| u.to_owned())
})
.or_else(|| {
services() services()
.rooms .rooms
.state_cache .state_cache
.room_members(restriction_room_id) .is_joined(sender_user, restriction_room_id)
.unwrap_or(false)
}) {
services()
.rooms
.state_cache
.room_members(room_id)
.filter_map(Result::ok) .filter_map(Result::ok)
.find(|uid| { .find(|auth_user| {
uid.server_name() == services().globals.server_name() auth_user.server_name() == services().globals.server_name()
&& services() && services()
.rooms .rooms
.state_accessor .state_accessor
.user_can_invite(uid, restriction_room_id) .user_can_invite(room_id, auth_user, sender_user)
.unwrap_or(false) .unwrap_or(false)
}) })
}); } else {
Some(authorized_user) None
}) };
.flatten();
let event = RoomMemberEventContent { let event = RoomMemberEventContent {
membership: MembershipState::Join, membership: MembershipState::Join,
@ -1001,8 +964,7 @@ pub(crate) async fn join_room_by_id_helper(
if !restriction_rooms.is_empty() if !restriction_rooms.is_empty()
&& servers && servers
.iter() .iter()
.filter(|s| *s != services().globals.server_name()) .all(|s| *s != services().globals.server_name())
.count() > 0
{ {
info!( info!(
"We couldn't do the join locally, maybe federation can help to satisfy the restricted join \ "We couldn't do the join locally, maybe federation can help to satisfy the restricted join \