From 5c30d2b2b0ba04ca403b16ca71188bf000d076ce Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 3 Apr 2024 18:48:51 -0400 Subject: [PATCH] fix(membership): perform stricter checks when choosing an authorized user Signed-off-by: strawberry --- src/api/client_server/membership.rs | 84 ++++++++--------------------- 1 file changed, 23 insertions(+), 61 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 9e30d0e9..73e817b6 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -20,7 +20,6 @@ use ruma::{ room::{ join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent}, member::{MembershipState, RoomMemberEventContent}, - power_levels::RoomPowerLevelsEventContent, }, StateEventType, TimelineEventType, }, @@ -880,11 +879,6 @@ pub(crate) async fn join_room_by_id_helper( .rooms .state_accessor .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 = join_rules_event .as_ref() @@ -895,15 +889,6 @@ pub(crate) async fn join_room_by_id_helper( }) }) .transpose()?; - let power_levels_event_content: Option = 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 { Some(RoomJoinRulesEventContent { @@ -919,51 +904,29 @@ pub(crate) async fn join_room_by_id_helper( _ => Vec::new(), }; - let authorized_user = restriction_rooms - .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() + let authorized_user = if restriction_rooms.iter().any(|restriction_room_id| { + services() + .rooms + .state_cache + .is_joined(sender_user, restriction_room_id) + .unwrap_or(false) + }) { + services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(Result::ok) + .find(|auth_user| { + auth_user.server_name() == services().globals.server_name() + && services() .rooms - .state_cache - .room_members(restriction_room_id) - .filter_map(Result::ok) - .find(|uid| { - uid.server_name() == services().globals.server_name() - && services() - .rooms - .state_accessor - .user_can_invite(uid, restriction_room_id) - .unwrap_or(false) - }) - }); - Some(authorized_user) - }) - .flatten(); + .state_accessor + .user_can_invite(room_id, auth_user, sender_user) + .unwrap_or(false) + }) + } else { + None + }; let event = RoomMemberEventContent { membership: MembershipState::Join, @@ -1001,8 +964,7 @@ pub(crate) async fn join_room_by_id_helper( if !restriction_rooms.is_empty() && servers .iter() - .filter(|s| *s != services().globals.server_name()) - .count() > 0 + .all(|s| *s != services().globals.server_name()) { info!( "We couldn't do the join locally, maybe federation can help to satisfy the restricted join \