fix room version comparisons

Fixes a set of bugs introduced by 00b77144c1,
where we replaced explicit `RoomVersionId` matches with `version < V11`
comparisons. The `Ord` impl on `RoomVersionId` does not work like that,
and is in fact a lexicographic string comparison[1]. The most visible
effect of these bugs is that incoming redaction events would sometimes
be ignored.

Instead of reverting to the explicit matches, which were quite verbose,
I implemented a `RoomVersion` struct that has flags for each property
that we care about. This is similar to the approach used by ruma[2] and
synapse[3].

[1]: 7cfa3be0c6/crates/ruma-common/src/identifiers/room_version_id.rs (L136)
[2]: 7cfa3be0c6/crates/ruma-state-res/src/room_version.rs
[3]: c856ae4724/synapse/api/room_versions.py
This commit is contained in:
Benjamin Lee 2024-09-24 21:26:06 -07:00
parent ad37eae869
commit 9add9a1e96
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4
8 changed files with 237 additions and 199 deletions

View file

@ -24,14 +24,14 @@ use ruma::{
},
int,
serde::JsonObject,
CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId, RoomVersionId,
CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId,
};
use serde_json::{json, value::to_raw_value};
use tracing::{info, warn};
use crate::{
api::client_server::invite_helper, service::pdu::PduBuilder, services, Ar,
Error, Ra, Result,
api::client_server::invite_helper, service::pdu::PduBuilder, services,
utils::room_version::RoomVersion, Ar, Error, Ra, Result,
};
/// # `POST /_matrix/client/r0/createRoom`
@ -114,7 +114,7 @@ pub(crate) async fn create_room_route(
}
}
let room_version = match body.room_version.clone() {
let room_version_id = match body.room_version.clone() {
Some(room_version) => {
if services()
.globals
@ -131,6 +131,7 @@ pub(crate) async fn create_room_route(
}
None => services().globals.default_room_version(),
};
let room_version = RoomVersion::try_from(&room_version_id)?;
let content = match &body.creation_content {
Some(content) => {
@ -138,30 +139,20 @@ pub(crate) async fn create_room_route(
.deserialize_as::<CanonicalJsonObject>()
.expect("Invalid creation content");
match &room_version {
room_version if *room_version < RoomVersionId::V11 => {
content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Invalid creation content",
)
})?,
);
}
// V11 removed the "creator" key
RoomVersionId::V11 => {}
_ => {
return Err(Error::BadServerResponse(
"Unsupported room version.",
))
}
if room_version.create_event_creator_prop {
content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Invalid creation content",
)
})?,
);
}
content.insert(
"room_version".into(),
json!(room_version.as_str()).try_into().map_err(|_| {
json!(room_version_id.as_str()).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Invalid creation content",
@ -171,16 +162,10 @@ pub(crate) async fn create_room_route(
content
}
None => {
let content = match &room_version {
room_version if *room_version < RoomVersionId::V11 => {
RoomCreateEventContent::new_v1(sender_user.to_owned())
}
RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
_ => {
return Err(Error::BadServerResponse(
"Unsupported room version.",
))
}
let content = if room_version.create_event_creator_prop {
RoomCreateEventContent::new_v1(sender_user.to_owned())
} else {
RoomCreateEventContent::new_v11()
};
let mut content = serde_json::from_str::<CanonicalJsonObject>(
to_raw_value(&content)
@ -195,7 +180,7 @@ pub(crate) async fn create_room_route(
.unwrap();
content.insert(
"room_version".into(),
json!(room_version.as_str()).try_into().map_err(|_| {
json!(room_version_id.as_str()).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Invalid creation content",
@ -598,6 +583,7 @@ pub(crate) async fn upgrade_room_route(
"This server does not support that room version.",
));
}
let new_version = RoomVersion::try_from(&body.new_version)?;
// Create a replacement room
let replacement_room = RoomId::new(services().globals.server_name());
@ -661,23 +647,18 @@ pub(crate) async fn upgrade_room_route(
// Send a m.room.create event containing a predecessor field and the
// applicable room_version
match &body.new_version {
room_version if *room_version < RoomVersionId::V11 => {
create_event_content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Error forming creation event",
)
})?,
);
}
RoomVersionId::V11 => {
// "creator" key no longer exists in V11 rooms
create_event_content.remove("creator");
}
_ => return Err(Error::BadServerResponse("Unsupported room version.")),
if new_version.create_event_creator_prop {
create_event_content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(
ErrorKind::BadJson,
"Error forming creation event",
)
})?,
);
} else {
create_event_content.remove("creator");
}
create_event_content.insert(
"room_version".into(),