diff --git a/src/api/client/room/upgrade.rs b/src/api/client/room/upgrade.rs index c2c3aa81..ae632235 100644 --- a/src/api/client/room/upgrade.rs +++ b/src/api/client/room/upgrade.rs @@ -2,10 +2,10 @@ use std::cmp::max; use axum::extract::State; use conduwuit::{ - Err, Error, Event, Result, debug, err, info, + Err, Error, Event, Result, err, info, matrix::{StateKey, pdu::PduBuilder}, }; -use futures::{FutureExt, StreamExt}; +use futures::StreamExt; use ruma::{ CanonicalJsonObject, RoomId, RoomVersionId, api::client::{error::ErrorKind, room::upgrade_room}, @@ -16,16 +16,15 @@ use ruma::{ power_levels::RoomPowerLevelsEventContent, tombstone::RoomTombstoneEventContent, }, - space::child::{RedactedSpaceChildEventContent, SpaceChildEventContent}, }, int, }; use serde_json::{json, value::to_raw_value}; -use crate::router::Ruma; +use crate::Ruma; /// Recommended transferable state events list from the spec -const TRANSFERABLE_STATE_EVENTS: &[StateEventType; 11] = &[ +const TRANSFERABLE_STATE_EVENTS: &[StateEventType; 9] = &[ StateEventType::RoomAvatar, StateEventType::RoomEncryption, StateEventType::RoomGuestAccess, @@ -35,9 +34,6 @@ const TRANSFERABLE_STATE_EVENTS: &[StateEventType; 11] = &[ StateEventType::RoomPowerLevels, StateEventType::RoomServerAcl, StateEventType::RoomTopic, - // Not explicitly recommended in spec, but very useful. - StateEventType::SpaceChild, - StateEventType::SpaceParent, // TODO: m.room.policy? ]; /// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade` @@ -54,7 +50,10 @@ pub(crate) async fn upgrade_room_route( State(services): State, body: Ruma, ) -> Result { - // TODO[v12]: Handle additional creators + debug_assert!( + TRANSFERABLE_STATE_EVENTS.is_sorted(), + "TRANSFERABLE_STATE_EVENTS is not sorted" + ); let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if !services.server.supported_room_version(&body.new_version) { @@ -129,7 +128,7 @@ pub(crate) async fn upgrade_room_route( ); }, | _ => { - // "creator" key no longer exists in V11 rooms + // "creator" key no longer exists in V11+ rooms create_event_content.remove("creator"); }, } @@ -176,7 +175,6 @@ pub(crate) async fn upgrade_room_route( &replacement_room, &state_lock, ) - .boxed() .await?; // Join the new room @@ -207,48 +205,35 @@ pub(crate) async fn upgrade_room_route( &replacement_room, &state_lock, ) - .boxed() .await?; // Replicate transferable state events to the new room for event_type in TRANSFERABLE_STATE_EVENTS { - let state_keys = services + let event_content = match services .rooms .state_accessor - .room_state_keys(&body.room_id, event_type) - .await?; - for state_key in state_keys { - let event_content = match services - .rooms - .state_accessor - .room_state_get(&body.room_id, event_type, &state_key) - .await - { - | Ok(v) => v.content().to_owned(), - | Err(_) => continue, // Skipping missing events. - }; - if event_content.get() == "{}" { - // If the event content is empty, we skip it - continue; - } + .room_state_get(&body.room_id, event_type, "") + .await + { + | Ok(v) => v.content().to_owned(), + | Err(_) => continue, // Skipping missing events. + }; - services - .rooms - .timeline - .build_and_append_pdu( - PduBuilder { - event_type: event_type.to_string().into(), - content: event_content, - state_key: Some(StateKey::from(state_key)), - ..Default::default() - }, - sender_user, - &replacement_room, - &state_lock, - ) - .boxed() - .await?; - } + services + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: event_type.to_string().into(), + content: event_content, + state_key: Some(StateKey::new()), + ..Default::default() + }, + sender_user, + &replacement_room, + &state_lock, + ) + .await?; } // Moves any local aliases to the new room @@ -305,90 +290,10 @@ pub(crate) async fn upgrade_room_route( &body.room_id, &state_lock, ) - .boxed() .await?; drop(state_lock); - // Check if the old room has a space parent, and if so, whether we should update - // it (m.space.parent, room_id) - let parents = services - .rooms - .state_accessor - .room_state_keys(&body.room_id, &StateEventType::SpaceParent) - .await?; - - for raw_space_id in parents { - let space_id = RoomId::parse(&raw_space_id)?; - let Ok(child) = services - .rooms - .state_accessor - .room_state_get_content::( - space_id, - &StateEventType::SpaceChild, - body.room_id.as_str(), - ) - .await - else { - // If the space does not have a child event for this room, we can skip it - continue; - }; - debug!( - "Updating space {space_id} child event for room {} to {replacement_room}", - &body.room_id - ); - // First, drop the space's child event - let state_lock = services.rooms.state.mutex.lock(space_id).await; - debug!("Removing space child event for room {} in space {space_id}", &body.room_id); - services - .rooms - .timeline - .build_and_append_pdu( - PduBuilder { - event_type: StateEventType::SpaceChild.into(), - content: to_raw_value(&RedactedSpaceChildEventContent {}) - .expect("event is valid, we just created it"), - state_key: Some(body.room_id.clone().as_str().into()), - ..Default::default() - }, - sender_user, - space_id, - &state_lock, - ) - .boxed() - .await - .ok(); - // Now, add a new child event for the replacement room - debug!("Adding space child event for room {replacement_room} in space {space_id}"); - services - .rooms - .timeline - .build_and_append_pdu( - PduBuilder { - event_type: StateEventType::SpaceChild.into(), - content: to_raw_value(&SpaceChildEventContent { - via: vec![sender_user.server_name().to_owned()], - order: child.order, - suggested: child.suggested, - }) - .expect("event is valid, we just created it"), - state_key: Some(replacement_room.as_str().into()), - ..Default::default() - }, - sender_user, - space_id, - &state_lock, - ) - .boxed() - .await - .ok(); - debug!( - "Finished updating space {space_id} child event for room {} to {replacement_room}", - &body.room_id - ); - drop(state_lock); - } - // Return the replacement room id Ok(upgrade_room::v3::Response { replacement_room }) } diff --git a/src/service/rooms/state_accessor/room_state.rs b/src/service/rooms/state_accessor/room_state.rs index b5306485..89a66f0c 100644 --- a/src/service/rooms/state_accessor/room_state.rs +++ b/src/service/rooms/state_accessor/room_state.rs @@ -91,22 +91,3 @@ pub async fn room_state_get( .and_then(|shortstatehash| self.state_get(shortstatehash, event_type, state_key)) .await } - -/// Returns all state keys for the given `room_id` and `event_type`. -#[implement(super::Service)] -#[tracing::instrument(skip(self), level = "debug")] -pub async fn room_state_keys( - &self, - room_id: &RoomId, - event_type: &StateEventType, -) -> Result> { - let shortstatehash = self.services.state.get_room_shortstatehash(room_id).await?; - - let state_keys: Vec = self - .state_keys(shortstatehash, event_type) - .map(|state_key| state_key.to_string()) - .collect() - .await; - - Ok(state_keys) -}