From 6bde2d0fe4e5bab40d89fa45f8b828b0792b60cf Mon Sep 17 00:00:00 2001 From: Ginger Date: Thu, 9 Apr 2026 14:53:12 -0400 Subject: [PATCH] refactor: Add function to state_accessor to get create event --- src/admin/user/commands.rs | 31 +++++++------------ src/api/client/directory.rs | 8 ++++- .../event_handler/handle_incoming_pdu.rs | 6 ++-- src/service/rooms/state_accessor/mod.rs | 15 ++++++--- src/service/rooms/state_accessor/user_can.rs | 25 --------------- 5 files changed, 32 insertions(+), 53 deletions(-) diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index d4725a940..4b6589fda 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -732,40 +732,33 @@ pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAli let state_lock = self.services.rooms.state.mutex.lock(&room_id).await; - let room_power_levels: Option = self + let mut room_power_levels = self .services .rooms .state_accessor - .room_state_get_content(&room_id, &StateEventType::RoomPowerLevels, "") - .await - .ok(); + .get_room_power_levels(&room_id) + .await; - let user_can_demote_self = room_power_levels - .as_ref() - .is_some_and(|power_levels_content| { - RoomPowerLevels::from(power_levels_content.clone()) - .user_can_change_user_power_level(&user_id, &user_id) - }) || self - .services - .rooms - .state_accessor - .room_state_get(&room_id, &StateEventType::RoomCreate, "") - .await - .is_ok_and(|event| event.sender() == user_id); + let user_can_demote_self = + room_power_levels.user_can_change_user_power_level(&user_id, &user_id); if !user_can_demote_self { return Err!("User is not allowed to modify their own power levels in the room.",); } - let mut power_levels_content = room_power_levels.unwrap_or_default(); - power_levels_content.users.remove(&user_id); + room_power_levels.users.remove(&user_id); let event_id = self .services .rooms .timeline .build_and_append_pdu( - PduBuilder::state(String::new(), &power_levels_content), + PduBuilder::state( + String::new(), + room_power_levels + .try_into() + .expect("PLs should be valid for room version"), + ), &user_id, Some(&room_id), &state_lock, diff --git a/src/api/client/directory.rs b/src/api/client/directory.rs index 2d82566e3..2e0f60a10 100644 --- a/src/api/client/directory.rs +++ b/src/api/client/directory.rs @@ -147,7 +147,13 @@ pub(crate) async fn set_room_visibility_route( return Err!(Request(Forbidden("Guests cannot publish to room directories"))); } - if !user_can_publish_room(&services, sender_user, &body.room_id).await? { + let room_power_levels = services + .rooms + .state_accessor + .get_room_power_levels(&body.room_id) + .await; + + if !room_power_levels.user_can_send_state(user_id, StateEventType::RoomHistoryVisibility) { return Err!(Request(Forbidden("User is not allowed to publish this room"))); } diff --git a/src/service/rooms/event_handler/handle_incoming_pdu.rs b/src/service/rooms/event_handler/handle_incoming_pdu.rs index ee8d15a09..950c18dca 100644 --- a/src/service/rooms/event_handler/handle_incoming_pdu.rs +++ b/src/service/rooms/event_handler/handle_incoming_pdu.rs @@ -209,11 +209,11 @@ pub async fn handle_incoming_pdu<'a>( } // Fetch create event - let create_event = &(self + let ref create_event = self .services .state_accessor - .room_state_get(room_id, &StateEventType::RoomCreate, "") - .await?); + .get_room_create_event(room_id) + .await; let (incoming_pdu, val) = self .handle_outlier_pdu(origin, create_event, event_id, room_id, value, false) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 908fd8a42..b1eb9e5d3 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -6,7 +6,7 @@ use std::{collections::HashSet, sync::Arc}; use async_trait::async_trait; -use conduwuit::{Event, Result, err}; +use conduwuit::{Event, Pdu, Result, err}; use database::Map; use ruma::{ EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedUserId, RoomId, UserId, @@ -164,6 +164,13 @@ pub async fn is_encrypted_room(&self, room_id: &RoomId) -> bool { .is_ok() } + /// Get a room's create event. + pub async fn get_room_create_event(&self, room_id: &RoomId) -> Pdu { + self.room_state_get(room_id, &StateEventType::RoomCreate, "") + .await + .expect("room should have a create event") + } + /// Get a set of the room's creators. This will always contain a single user /// for room versions 11 and earlier. pub async fn get_room_creators(&self, room_id: &RoomId) -> HashSet { @@ -176,10 +183,8 @@ pub async fn get_room_creators(&self, room_id: &RoomId) -> HashSet .rules() .expect("room version should be known"); - let create_event = self - .room_state_get(room_id, &StateEventType::RoomCreate, "") - .await - .expect("room should have a create event"); + let create_event = self.get_room_create_event(room_id).await; + let create_content: RoomCreateEventContent = create_event .get_content() .expect("create event content should be valid"); diff --git a/src/service/rooms/state_accessor/user_can.rs b/src/service/rooms/state_accessor/user_can.rs index 7b1050d2e..84eef869f 100644 --- a/src/service/rooms/state_accessor/user_can.rs +++ b/src/service/rooms/state_accessor/user_can.rs @@ -44,31 +44,6 @@ pub async fn user_can_redact( ))); } - let create_event = self - .room_state_get(room_id, &StateEventType::RoomCreate, "") - .await?; - let create_event_content: RoomCreateEventContent = create_event.get_content().unwrap(); - let room_version_rules = create_event_content - .room_version - .rules() - .expect("room version should have defined rules"); - if room_version_rules - .authorization - .explicitly_privilege_room_creators - { - let sender_owned = sender.to_owned(); - // NOTE: we don't check the pre-v11 `creator` field because no room version has - // `explicitly_privilege_room_creators` and `use_room_create_sender` set at the - // same time - if sender == create_event.sender() - || create_event_content - .additional_creators - .contains(&sender_owned) - { - return Ok(true); - } - } - let power_levels = self.get_room_power_levels(room_id).await; if power_levels.user_can_redact_event_of_other(sender) {