Compare commits

..

No commits in common. "607caddacf753f875ff14bebb253b8801b1c74f0" and "f7410283cf3864a5f461dce2174df91edbac527c" have entirely different histories.

2 changed files with 27 additions and 141 deletions

View file

@ -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,13 +16,12 @@ 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] = &[
@ -37,7 +36,7 @@ const TRANSFERABLE_STATE_EVENTS: &[StateEventType; 11] = &[
StateEventType::RoomTopic,
// Not explicitly recommended in spec, but very useful.
StateEventType::SpaceChild,
StateEventType::SpaceParent, // TODO: m.room.policy?
StateEventType::SpaceParent, // TODO: m.room.policy
];
/// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade`
@ -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::<SpaceChildEventContent>(
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 })
}

View file

@ -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<Vec<String>> {
let shortstatehash = self.services.state.get_room_shortstatehash(room_id).await?;
let state_keys: Vec<String> = self
.state_keys(shortstatehash, event_type)
.map(|state_key| state_key.to_string())
.collect()
.await;
Ok(state_keys)
}