mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-18 08:11:24 +01:00
fix room version comparisons
Fixes a set of bugs introduced by00b77144c1, 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:
parent
ad37eae869
commit
9add9a1e96
8 changed files with 237 additions and 199 deletions
|
|
@ -80,6 +80,8 @@ pub(crate) enum Error {
|
|||
AdminCommand(&'static str),
|
||||
#[error("from {0}: {1}")]
|
||||
Redaction(OwnedServerName, ruma::canonical_json::RedactionError),
|
||||
#[error("unsupported room version {0}")]
|
||||
UnsupportedRoomVersion(ruma::RoomVersionId),
|
||||
#[error("{0} in {1}")]
|
||||
InconsistentRoomState(&'static str, ruma::OwnedRoomId),
|
||||
}
|
||||
|
|
@ -146,6 +148,10 @@ impl Error {
|
|||
_ => StatusCode::BAD_REQUEST,
|
||||
},
|
||||
),
|
||||
Self::UnsupportedRoomVersion(_) => (
|
||||
ErrorKind::UnsupportedRoomVersion,
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
),
|
||||
Self::Conflict(_) => (Unknown, StatusCode::CONFLICT),
|
||||
_ => (Unknown, StatusCode::INTERNAL_SERVER_ERROR),
|
||||
};
|
||||
|
|
|
|||
87
src/utils/room_version.rs
Normal file
87
src/utils/room_version.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use ruma::RoomVersionId;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
/// Properties that we care about in grapevine that differ between supported
|
||||
/// room versions.
|
||||
///
|
||||
/// This is similar to [`ruma::state_res::RoomVersion`], except that it has
|
||||
/// properties that are relevant to us instead of only properties relevant to
|
||||
/// ruma state resolution.
|
||||
///
|
||||
/// When branching for different room versions, prefer constructing a
|
||||
/// `RoomVersion` and branching on it's properties over branching based on the
|
||||
/// [`RoomVersionId`] directly. If there is a relevant property that is not
|
||||
/// already included in `RoomVersion`, add it. In particular, comparisons like
|
||||
/// `room_version_id < RoomVersionId::V11` do not work, because room versions
|
||||
/// do not have a defined order. Ruma implements `PartialOrd` on `RoomVersionId`
|
||||
/// as a lexicographic string comparison, which is almost certainly not what you
|
||||
/// want.
|
||||
pub(crate) struct RoomVersion {
|
||||
/// Whether `m.room.create` state events have a `creator` property.
|
||||
///
|
||||
/// The `creator` property is always equivalent to the event `sender`, and
|
||||
/// was [removed][spec] in v11.
|
||||
///
|
||||
/// [spec]: https://spec.matrix.org/v1.11/rooms/v11/#remove-the-creator-property-of-mroomcreate-events
|
||||
pub(crate) create_event_creator_prop: bool,
|
||||
|
||||
/// Whether the `redacts` property of `m.room.redaction` events is a
|
||||
/// property in the event `content` or a top-level property of the event.
|
||||
///
|
||||
/// This property was [moved][spec] from top-level to `content` in v11.
|
||||
///
|
||||
/// [spec]: https://spec.matrix.org/v1.11/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property
|
||||
pub(crate) redaction_event_redacts_in_content: bool,
|
||||
}
|
||||
|
||||
// Allowed so that we can use struct-update syntax for incremental changes
|
||||
// between versions even when all fields change.
|
||||
#[allow(clippy::needless_update)]
|
||||
mod known_versions {
|
||||
use super::RoomVersion;
|
||||
|
||||
pub(super) const V6: RoomVersion = RoomVersion {
|
||||
create_event_creator_prop: true,
|
||||
redaction_event_redacts_in_content: false,
|
||||
};
|
||||
|
||||
pub(super) const V7: RoomVersion = RoomVersion {
|
||||
..V6
|
||||
};
|
||||
|
||||
pub(super) const V8: RoomVersion = RoomVersion {
|
||||
..V7
|
||||
};
|
||||
|
||||
pub(super) const V9: RoomVersion = RoomVersion {
|
||||
..V8
|
||||
};
|
||||
|
||||
pub(super) const V10: RoomVersion = RoomVersion {
|
||||
..V9
|
||||
};
|
||||
|
||||
pub(super) const V11: RoomVersion = RoomVersion {
|
||||
create_event_creator_prop: false,
|
||||
redaction_event_redacts_in_content: true,
|
||||
..V10
|
||||
};
|
||||
}
|
||||
|
||||
/// May return an error for unsupported room versions.
|
||||
impl TryFrom<&RoomVersionId> for RoomVersion {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(version: &RoomVersionId) -> Result<RoomVersion, Error> {
|
||||
match version {
|
||||
RoomVersionId::V6 => Ok(known_versions::V6),
|
||||
RoomVersionId::V7 => Ok(known_versions::V7),
|
||||
RoomVersionId::V8 => Ok(known_versions::V8),
|
||||
RoomVersionId::V9 => Ok(known_versions::V9),
|
||||
RoomVersionId::V10 => Ok(known_versions::V10),
|
||||
RoomVersionId::V11 => Ok(known_versions::V11),
|
||||
_ => Err(Error::UnsupportedRoomVersion(version.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue