diff --git a/src/service/rooms/roles/mod.rs b/src/service/rooms/roles/mod.rs index 068598ad..04c469aa 100644 --- a/src/service/rooms/roles/mod.rs +++ b/src/service/rooms/roles/mod.rs @@ -205,6 +205,9 @@ pub async fn ensure_default_roles(&self, space_id: &RoomId) -> Result { return Ok(()); } + let sender = self.services.globals.server_user.as_ref(); + let state_lock = self.services.state.mutex.lock(space_id).await; + let roles_event_type = roles_event_type(); if self .services @@ -228,9 +231,6 @@ pub async fn ensure_default_roles(&self, space_id: &RoomId) -> Result { let content = SpaceRolesEventContent { roles }; - let sender = self.services.globals.server_user.as_ref(); - let state_lock = self.services.state.mutex.lock(space_id).await; - let pdu = PduBuilder { event_type: ruma::events::TimelineEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned()), content: to_raw_value(&content).map_err(|e| { @@ -733,8 +733,8 @@ pub async fn validate_pl_change( } let space_data: Vec<(Vec<(OwnedUserId, HashSet)>, BTreeMap)> = { - let user_roles_guard = self.user_roles.read().await; let roles_guard = self.roles.read().await; + let user_roles_guard = self.user_roles.read().await; parent_spaces .iter() .filter_map(|ps| { @@ -798,10 +798,6 @@ pub async fn validate_pl_change( /// Space roles to join a room. #[implement(Service)] pub async fn check_join_allowed(&self, room_id: &RoomId, user_id: &UserId) -> Result { - if !self.is_enabled() { - return Ok(()); - } - let parent_spaces = self.get_parent_spaces(room_id).await; if parent_spaces.is_empty() { return Ok(()); @@ -851,65 +847,71 @@ impl Service { pending.insert(space_id.clone()) }; - let Ok(_permit) = this.enforcement_semaphore.acquire().await else { - return; - }; + async { + let Ok(_permit) = this.enforcement_semaphore.acquire().await else { + return; + }; - this.populate_space(&space_id).await; + this.populate_space(&space_id).await; - match event_type.as_str() { - | SPACE_ROLES_EVENT_TYPE => { - this.sync_power_levels_for_children(&space_id).await; - let space_members: Vec = this - .services - .state_cache - .room_members(&space_id) - .map(ToOwned::to_owned) - .collect() - .await; - for member in &space_members { - if let Err(e) = - Box::pin(this.kick_unqualified_from_rooms(&space_id, member)).await - { - debug_warn!(user_id = %member, error = ?e, "Role definition revalidation kick failed"); - } - } - }, - | SPACE_ROLE_MEMBER_EVENT_TYPE => { - if let Ok(user_id) = UserId::parse(state_key.as_str()) { - if let Err(e) = this.auto_join_qualifying_rooms(&space_id, user_id).await - { - debug_warn!(user_id = %user_id, error = ?e, "Space role auto-join failed"); - } - if let Err(e) = - Box::pin(this.kick_unqualified_from_rooms(&space_id, user_id)).await - { - debug_warn!(user_id = %user_id, error = ?e, "Space role auto-kick failed"); - } + match event_type.as_str() { + | SPACE_ROLES_EVENT_TYPE => { this.sync_power_levels_for_children(&space_id).await; - } - }, - | SPACE_ROLE_ROOM_EVENT_TYPE => { - if let Ok(target_room) = RoomId::parse(state_key.as_str()) { - let members: Vec = this + let space_members: Vec = this .services .state_cache - .room_members(target_room) + .room_members(&space_id) .map(ToOwned::to_owned) .collect() .await; - for member in &members { + for member in &space_members { if let Err(e) = Box::pin(this.kick_unqualified_from_rooms(&space_id, member)) .await { - debug_warn!(user_id = %member, error = ?e, "Space role requirement kick failed"); + debug_warn!(user_id = %member, error = ?e, "Role definition revalidation kick failed"); } } - } - }, - | _ => {}, + }, + | SPACE_ROLE_MEMBER_EVENT_TYPE => { + if let Ok(user_id) = UserId::parse(state_key.as_str()) { + if let Err(e) = + this.auto_join_qualifying_rooms(&space_id, user_id).await + { + debug_warn!(user_id = %user_id, error = ?e, "Space role auto-join failed"); + } + if let Err(e) = + Box::pin(this.kick_unqualified_from_rooms(&space_id, user_id)) + .await + { + debug_warn!(user_id = %user_id, error = ?e, "Space role auto-kick failed"); + } + this.sync_power_levels_for_children(&space_id).await; + } + }, + | SPACE_ROLE_ROOM_EVENT_TYPE => { + if let Ok(target_room) = RoomId::parse(state_key.as_str()) { + let members: Vec = this + .services + .state_cache + .room_members(target_room) + .map(ToOwned::to_owned) + .collect() + .await; + for member in &members { + if let Err(e) = + Box::pin(this.kick_unqualified_from_rooms(&space_id, member)) + .await + { + debug_warn!(user_id = %member, error = ?e, "Space role requirement kick failed"); + } + } + } + }, + | _ => {}, + } } + .await; this.pending_enforcement.write().await.remove(&space_id); }); @@ -1077,10 +1079,18 @@ pub async fn kick_unqualified_from_rooms(&self, space_id: &RoomId, user_id: &Use continue; } - if self - .user_qualifies_for_room(space_id, child_room_id, user_id) - .await - { + let all_parents = self.get_parent_spaces(child_room_id).await; + let mut qualifies_in_any = false; + for parent in &all_parents { + if self + .user_qualifies_for_room(parent, child_room_id, user_id) + .await + { + qualifies_in_any = true; + break; + } + } + if qualifies_in_any { continue; }