mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-07-09 06:01:39 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 261974315e |
Generated
+1
@@ -1121,6 +1121,7 @@ dependencies = [
|
||||
"reqwest",
|
||||
"ruma",
|
||||
"rustyline-async",
|
||||
"sd-notify",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yml",
|
||||
|
||||
+38
-113
@@ -2,7 +2,7 @@
|
||||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{
|
||||
Err, Error, Event, Result, RoomVersion, debug, err, info,
|
||||
Err, Error, Event, Result, debug, err, info,
|
||||
matrix::{StateKey, pdu::PduBuilder},
|
||||
};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
@@ -68,76 +68,37 @@ pub(crate) async fn upgrade_room_route(
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
// First, check if the user has permission to upgrade the room (send tombstone
|
||||
// event)
|
||||
let old_room_state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
// Check tombstone permission by attempting to create (but not send) the event
|
||||
// Note that this does internally call the policy server with a fake room ID,
|
||||
// which may not be good?
|
||||
let tombstone_test_result = services
|
||||
.rooms
|
||||
.timeline
|
||||
.create_hash_and_sign_event(
|
||||
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||
body: "This room has been replaced".to_owned(),
|
||||
replacement_room: RoomId::new(services.globals.server_name()),
|
||||
}),
|
||||
sender_user,
|
||||
Some(&body.room_id),
|
||||
&old_room_state_lock,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Err(_e) = tombstone_test_result {
|
||||
return Err!(Request(Forbidden("User does not have permission to upgrade this room.")));
|
||||
}
|
||||
|
||||
drop(old_room_state_lock);
|
||||
|
||||
// Create a replacement room
|
||||
let room_features = RoomVersion::new(&body.new_version)?;
|
||||
let replacement_room: Option<&RoomId> = if room_features.room_ids_as_hashes {
|
||||
None
|
||||
} else {
|
||||
Some(&RoomId::new(services.globals.server_name()))
|
||||
};
|
||||
let replacement_room_tmp = match replacement_room {
|
||||
| Some(v) => v,
|
||||
| None => &RoomId::new(services.globals.server_name()),
|
||||
};
|
||||
let replacement_room = RoomId::new(services.globals.server_name());
|
||||
|
||||
let _short_id = services
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortroomid(replacement_room_tmp)
|
||||
.get_or_create_shortroomid(&replacement_room)
|
||||
.await;
|
||||
|
||||
// For pre-v12 rooms, send tombstone before creating replacement room
|
||||
let tombstone_event_id = if !room_features.room_ids_as_hashes {
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
// Send a m.room.tombstone event to the old room to indicate that it is not
|
||||
// intended to be used any further
|
||||
let tombstone_event_id = services
|
||||
.rooms
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||
body: "This room has been replaced".to_owned(),
|
||||
replacement_room: replacement_room.unwrap().to_owned(),
|
||||
}),
|
||||
sender_user,
|
||||
Some(&body.room_id),
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
// Change lock to replacement room
|
||||
drop(state_lock);
|
||||
Some(tombstone_event_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let state_lock = services.rooms.state.mutex.lock(replacement_room_tmp).await;
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
// Send a m.room.tombstone event to the old room to indicate that it is not
|
||||
// intended to be used any further Fail if the sender does not have the required
|
||||
// permissions
|
||||
let tombstone_event_id = services
|
||||
.rooms
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||
body: "This room has been replaced".to_owned(),
|
||||
replacement_room: replacement_room.clone(),
|
||||
}),
|
||||
sender_user,
|
||||
Some(&body.room_id),
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Change lock to replacement room
|
||||
drop(state_lock);
|
||||
let state_lock = services.rooms.state.mutex.lock(&replacement_room).await;
|
||||
|
||||
// Get the old room creation event
|
||||
let mut create_event_content: CanonicalJsonObject = services
|
||||
@@ -150,7 +111,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
// Use the m.room.tombstone event as the predecessor
|
||||
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
||||
body.room_id.clone(),
|
||||
tombstone_event_id,
|
||||
Some(tombstone_event_id),
|
||||
));
|
||||
|
||||
// Send a m.room.create event containing a predecessor field and the applicable
|
||||
@@ -171,7 +132,6 @@ pub(crate) async fn upgrade_room_route(
|
||||
// "creator" key no longer exists in V11 rooms
|
||||
create_event_content.remove("creator");
|
||||
},
|
||||
// TODO(hydra): additional_creators
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +159,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
|
||||
}
|
||||
|
||||
let create_event_id = services
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
@@ -213,18 +173,11 @@ pub(crate) async fn upgrade_room_route(
|
||||
timestamp: None,
|
||||
},
|
||||
sender_user,
|
||||
replacement_room,
|
||||
Some(&replacement_room),
|
||||
&state_lock,
|
||||
)
|
||||
.boxed()
|
||||
.await?;
|
||||
let create_id = create_event_id.as_str().replace('$', "!");
|
||||
let (replacement_room, state_lock) = if room_features.room_ids_as_hashes {
|
||||
let parsed_room_id = RoomId::parse(&create_id)?;
|
||||
(Some(parsed_room_id), services.rooms.state.mutex.lock(parsed_room_id).await)
|
||||
} else {
|
||||
(replacement_room, state_lock)
|
||||
};
|
||||
|
||||
// Join the new room
|
||||
services
|
||||
@@ -251,7 +204,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
timestamp: None,
|
||||
},
|
||||
sender_user,
|
||||
replacement_room,
|
||||
Some(&replacement_room),
|
||||
&state_lock,
|
||||
)
|
||||
.boxed()
|
||||
@@ -290,7 +243,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
..Default::default()
|
||||
},
|
||||
sender_user,
|
||||
replacement_room,
|
||||
Some(&replacement_room),
|
||||
&state_lock,
|
||||
)
|
||||
.boxed()
|
||||
@@ -315,7 +268,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
services
|
||||
.rooms
|
||||
.alias
|
||||
.set_alias(alias, replacement_room.unwrap(), sender_user)?;
|
||||
.set_alias(alias, &replacement_room, sender_user)?;
|
||||
}
|
||||
|
||||
// Get the old room power levels
|
||||
@@ -357,27 +310,6 @@ pub(crate) async fn upgrade_room_route(
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
// For v12 rooms, send tombstone AFTER creating replacement room
|
||||
if room_features.room_ids_as_hashes {
|
||||
let old_room_state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
// For v12 rooms, no event reference in predecessor due to cyclic dependency -
|
||||
// could best effort one maybe?
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||
body: "This room has been replaced".to_owned(),
|
||||
replacement_room: replacement_room.unwrap().to_owned(),
|
||||
}),
|
||||
sender_user,
|
||||
Some(&body.room_id),
|
||||
&old_room_state_lock,
|
||||
)
|
||||
.await?;
|
||||
drop(old_room_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
|
||||
@@ -402,9 +334,8 @@ pub(crate) async fn upgrade_room_route(
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"Updating space {space_id} child event for room {} to {}",
|
||||
&body.room_id,
|
||||
replacement_room.unwrap()
|
||||
"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;
|
||||
@@ -428,10 +359,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
.await
|
||||
.ok();
|
||||
// Now, add a new child event for the replacement room
|
||||
debug!(
|
||||
"Adding space child event for room {} in space {space_id}",
|
||||
replacement_room.unwrap()
|
||||
);
|
||||
debug!("Adding space child event for room {replacement_room} in space {space_id}");
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
@@ -444,7 +372,7 @@ pub(crate) async fn upgrade_room_route(
|
||||
suggested: child.suggested,
|
||||
})
|
||||
.expect("event is valid, we just created it"),
|
||||
state_key: Some(replacement_room.unwrap().as_str().into()),
|
||||
state_key: Some(replacement_room.as_str().into()),
|
||||
..Default::default()
|
||||
},
|
||||
sender_user,
|
||||
@@ -455,15 +383,12 @@ pub(crate) async fn upgrade_room_route(
|
||||
.await
|
||||
.ok();
|
||||
debug!(
|
||||
"Finished updating space {space_id} child event for room {} to {}",
|
||||
&body.room_id,
|
||||
replacement_room.unwrap()
|
||||
"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: replacement_room.unwrap().to_owned(),
|
||||
})
|
||||
Ok(upgrade_room::v3::Response { replacement_room })
|
||||
}
|
||||
|
||||
@@ -156,6 +156,7 @@ sentry_telemetry = [
|
||||
]
|
||||
systemd = [
|
||||
"conduwuit-router/systemd",
|
||||
"conduwuit-service/systemd"
|
||||
]
|
||||
journald = [ # This is a stub on non-unix platforms
|
||||
"dep:tracing-journald",
|
||||
|
||||
@@ -40,7 +40,6 @@ io_uring = [
|
||||
"conduwuit-admin/io_uring",
|
||||
"conduwuit-api/io_uring",
|
||||
"conduwuit-service/io_uring",
|
||||
"conduwuit-api/io_uring",
|
||||
]
|
||||
jemalloc = [
|
||||
"conduwuit-admin/jemalloc",
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ pub(crate) async fn start(server: Arc<Server>) -> Result<Arc<Services>> {
|
||||
let services = Services::build(server).await?.start().await?;
|
||||
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Ready])
|
||||
sd_notify::notify(false, &[sd_notify::NotifyState::Ready])
|
||||
.expect("failed to notify systemd of ready state");
|
||||
|
||||
debug!("Started");
|
||||
@@ -78,7 +78,7 @@ pub(crate) async fn stop(services: Arc<Services>) -> Result<()> {
|
||||
debug!("Shutting down...");
|
||||
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Stopping])
|
||||
sd_notify::notify(false, &[sd_notify::NotifyState::Stopping])
|
||||
.expect("failed to notify systemd of stopping state");
|
||||
|
||||
// Wait for all completions before dropping or we'll lose them to the module
|
||||
|
||||
@@ -67,6 +67,9 @@ release_max_log_level = [
|
||||
"tracing/max_level_trace",
|
||||
"tracing/release_max_level_info",
|
||||
]
|
||||
systemd = [
|
||||
"dep:sd-notify",
|
||||
]
|
||||
url_preview = [
|
||||
"dep:image",
|
||||
"dep:webpage",
|
||||
@@ -119,5 +122,9 @@ blurhash.optional = true
|
||||
recaptcha-verify = { version = "0.1.5", default-features = false }
|
||||
ctor.workspace = true
|
||||
|
||||
[target.'cfg(all(unix, target_os = "linux"))'.dependencies]
|
||||
sd-notify.workspace = true
|
||||
sd-notify.optional = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -45,13 +45,16 @@ fn deref(&self) -> &Self::Target { &self.server.config }
|
||||
fn handle_reload(&self) -> Result {
|
||||
if self.server.config.config_reload_signal {
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Reloading])
|
||||
.expect("failed to notify systemd of reloading state");
|
||||
sd_notify::notify(false, &[
|
||||
sd_notify::NotifyState::Reloading,
|
||||
sd_notify::NotifyState::monotonic_usec_now().expect("Failed to read monotonic time"),
|
||||
])
|
||||
.expect("failed to notify systemd of reloading state");
|
||||
|
||||
self.reload(iter::empty())?;
|
||||
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Ready])
|
||||
sd_notify::notify(false, &[sd_notify::NotifyState::Ready])
|
||||
.expect("failed to notify systemd of ready state");
|
||||
}
|
||||
|
||||
|
||||
@@ -274,6 +274,8 @@ fn from_evt(
|
||||
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(pdu.event_id.clone().into()));
|
||||
|
||||
// Check with the policy server
|
||||
// TODO(hydra): Skip this check for create events (why didnt we do this
|
||||
// already?)
|
||||
if room_id.is_some() {
|
||||
trace!(
|
||||
"Checking event {} in room {} with policy server",
|
||||
|
||||
Reference in New Issue
Block a user