mirror of
https://github.com/element-hq/synapse.git
synced 2026-04-26 23:55:33 +00:00
WIP
This commit is contained in:
+46
-10
@@ -21,6 +21,7 @@
|
||||
//! Classes for representing Events.
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
str::FromStr,
|
||||
sync::{Arc, RwLock},
|
||||
@@ -595,8 +596,6 @@ struct EventCommonFields {
|
||||
type_: Box<str>,
|
||||
signatures: Signatures,
|
||||
|
||||
room_id: Option<Box<str>>,
|
||||
|
||||
#[serde(default)]
|
||||
unsigned: JsonObjectMutable,
|
||||
|
||||
@@ -616,7 +615,7 @@ struct Event {
|
||||
#[pymethods]
|
||||
impl Event {
|
||||
#[new]
|
||||
fn new<'a, 'py>(
|
||||
fn new_from_py<'a, 'py>(
|
||||
py: Python<'py>,
|
||||
event_dict: &'a Bound<'py, PyAny>,
|
||||
room_version: &'a Bound<'py, PyAny>,
|
||||
@@ -648,7 +647,7 @@ impl Event {
|
||||
|
||||
let event_format_v3_v4_plus: EventFormatV3V4Container = depythonize(event_dict)?;
|
||||
|
||||
event_format_v3_v4_plus.check_valid(room_version)?;
|
||||
event_format_v3_v4_plus.validate(room_version)?;
|
||||
|
||||
let internal_metadata = Py::new(py, EventInternalMetadata::new(internal_metadata_dict)?)?;
|
||||
|
||||
@@ -701,10 +700,9 @@ impl Event {
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn room_id(&self) -> Option<&str> {
|
||||
fn room_id(&self) -> PyResult<Cow<'_, str>> {
|
||||
match &self.inner {
|
||||
EventFormatEnum::V3V4Plus(format) => format.common_fields.room_id.as_deref(),
|
||||
// ...
|
||||
EventFormatEnum::V3V4Plus(format) => Ok(format.room_id(&self.event_id)?),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,6 +921,7 @@ enum EventFormatEnum {
|
||||
struct EventFormatV3V4Plus {
|
||||
auth_events: Vec<String>,
|
||||
prev_events: Vec<String>,
|
||||
room_id: Option<Box<str>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -934,8 +933,28 @@ struct EventFormatV3V4Container {
|
||||
}
|
||||
|
||||
impl EventFormatV3V4Container {
|
||||
fn check_valid(&self, room_version: &RoomVersion) -> Result<(), Error> {
|
||||
if self.common_fields.room_id.is_none() {
|
||||
fn room_id(&self, event_id: &EventID) -> Result<Cow<'_, str>, Error> {
|
||||
if let Some(room_id) = self.specific_fields.room_id.as_deref() {
|
||||
return Ok(room_id.into());
|
||||
}
|
||||
|
||||
// Ensure that this is a create event, as all other events must
|
||||
// have a room ID.
|
||||
if &*self.common_fields.type_ != "m.room.create" {
|
||||
bail!("Event '{event_id}' has no room ID");
|
||||
}
|
||||
|
||||
// The room ID is derived from the event ID by replacing the
|
||||
// leading '$' with a '!'.
|
||||
let mut room_id = String::with_capacity(event_id.len());
|
||||
room_id.push('!');
|
||||
room_id.push_str(&event_id[1..]);
|
||||
|
||||
Ok(room_id.into())
|
||||
}
|
||||
|
||||
fn validate(&self, room_version: &RoomVersion) -> Result<(), Error> {
|
||||
if self.specific_fields.room_id.is_none() {
|
||||
// Only create events in event formats v4 plus can have a missing room_id.
|
||||
if room_version.event_format != EventFormatVersions::ROOM_V4_PLUS {
|
||||
bail!("room_id is required for event formats v3 and below");
|
||||
@@ -953,6 +972,8 @@ impl EventFormatV3V4Container {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use signed_json::json;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
@@ -966,7 +987,7 @@ mod tests {
|
||||
assert_eq!(&*event.common_fields.type_, "m.room.create");
|
||||
|
||||
assert_eq!(
|
||||
event.common_fields.room_id.as_deref(),
|
||||
event.specific_fields.room_id.as_deref(),
|
||||
Some("!qVoJSympOqdUQRUfiC:localhost:8800")
|
||||
);
|
||||
|
||||
@@ -996,4 +1017,19 @@ mod tests {
|
||||
serde_json::from_str::<serde_json::Value>(json).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_room_id_for_create_event() {
|
||||
let json = r#"{"auth_events":[],"prev_events":[],"type":"m.room.create","sender":"@erikj:jki.re","content":{"room_version":"12","predecessor":{"room_id":"!VuNGkDTdbMOOxSmuDa:jki.re"}},"depth":1,"state_key":"","origin_server_ts":1775568141481,"hashes":{"sha256":"qBX+glsKvogXFrvsEN0eh13pO2kpuE6o/b4yREPtOqw"},"signatures":{"jki.re":{"ed25519:auto":"n/4gHQRagk3r1r24L/7a+oaMMf9cysVfQRYdjpDZcf4ppkVym33rhTW18Vy4zMa1L5nsWLkxsBvbrRRDYUOhBQ"}},"unsigned":{"age_ts":1775568141481}}"#;
|
||||
let event_value: serde_json::Value = serde_json::from_str(json).unwrap();
|
||||
|
||||
let event: EventFormatV3V4Container = serde_json::from_str(json).unwrap();
|
||||
|
||||
let event_id = calculate_event_id(&event_value, &RoomVersion::V12).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&*event.room_id(&event_id).unwrap(),
|
||||
"!BeXKh925K_M46DwsuJFR0EyBpE1P7CFUDGuWW4xw55Y"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-68
@@ -112,7 +112,7 @@ pub fn redact(event: &Value, room_version: &RoomVersion) -> anyhow::Result<Value
|
||||
]);
|
||||
|
||||
// Earlier room versions had additional allowed keys
|
||||
if !use_updated_redaction_rules(room_version) {
|
||||
if !room_version.updated_redaction_rules {
|
||||
allowed_keys.extend([(PREV_STATE, ()), (MEMBERSHIP, ()), (ORIGIN, ())]);
|
||||
}
|
||||
|
||||
@@ -140,10 +140,10 @@ pub fn redact(event: &Value, room_version: &RoomVersion) -> anyhow::Result<Value
|
||||
match event_type {
|
||||
M_ROOM_MEMBER => {
|
||||
add_content_field(membership_field::MEMBERSHIP);
|
||||
if use_restricted_join_rule_fix(room_version) {
|
||||
if room_version.restricted_join_rule_fix {
|
||||
add_content_field(membership_field::JOIN_AUTHORISED_VIA_USERS_SERVER);
|
||||
}
|
||||
if use_updated_redaction_rules(room_version) {
|
||||
if room_version.updated_redaction_rules {
|
||||
// Preserve the signed field under third_party_invite.
|
||||
if let Some(third_party_invite) =
|
||||
event_content.get(membership_field::THIRD_PARTY_INVITE)
|
||||
@@ -163,7 +163,7 @@ pub fn redact(event: &Value, room_version: &RoomVersion) -> anyhow::Result<Value
|
||||
}
|
||||
}
|
||||
M_ROOM_CREATE => {
|
||||
if use_updated_redaction_rules(room_version) {
|
||||
if room_version.updated_redaction_rules {
|
||||
// MSC2176 rules state that create events cannot have their `content` redacted.
|
||||
if let Some(event_content_object) = event_content.as_object() {
|
||||
for (field, _value) in event_content_object {
|
||||
@@ -171,18 +171,18 @@ pub fn redact(event: &Value, room_version: &RoomVersion) -> anyhow::Result<Value
|
||||
}
|
||||
}
|
||||
}
|
||||
if !use_implicit_room_creator(room_version) {
|
||||
if !room_version.implicit_room_creator {
|
||||
// Some room versions give meaning to `creator`
|
||||
add_content_field(create_field::CREATOR);
|
||||
}
|
||||
if use_room_ids_as_hashes(room_version) {
|
||||
if room_version.msc4291_room_ids_as_hashes {
|
||||
// room_id is not allowed on the create event as it's derived from the event ID
|
||||
allowed_keys.remove(ROOM_ID);
|
||||
}
|
||||
}
|
||||
M_ROOM_JOIN_RULES => {
|
||||
add_content_field(join_rules_field::JOIN_RULE);
|
||||
if use_restricted_join_rule(room_version) {
|
||||
if room_version.restricted_join_rule {
|
||||
add_content_field(join_rules_field::ALLOW);
|
||||
}
|
||||
}
|
||||
@@ -195,17 +195,17 @@ pub fn redact(event: &Value, room_version: &RoomVersion) -> anyhow::Result<Value
|
||||
add_content_field(power_levels_field::BAN);
|
||||
add_content_field(power_levels_field::KICK);
|
||||
add_content_field(power_levels_field::REDACT);
|
||||
if use_updated_redaction_rules(room_version) {
|
||||
if room_version.updated_redaction_rules {
|
||||
add_content_field(power_levels_field::INVITE);
|
||||
}
|
||||
}
|
||||
M_ROOM_ALIASES if use_special_case_aliases_auth(room_version) => {
|
||||
M_ROOM_ALIASES if room_version.special_case_aliases_auth => {
|
||||
add_content_field(aliases_field::ALIASES);
|
||||
}
|
||||
M_ROOM_HISTORY_VISIBILITY => {
|
||||
add_content_field(history_visibility_field::HISTORY_VISIBILITY)
|
||||
}
|
||||
M_ROOM_REDACTION if use_updated_redaction_rules(room_version) => {
|
||||
M_ROOM_REDACTION if room_version.updated_redaction_rules => {
|
||||
add_content_field(redaction_field::REDACTS);
|
||||
}
|
||||
_ => (),
|
||||
@@ -261,64 +261,6 @@ pub fn redact_internal(event: &Value, room_version: &RoomVersion) -> anyhow::Res
|
||||
Ok(redacted)
|
||||
}
|
||||
|
||||
/// Whether the `redacts` field has been moved from the top level to inside `content` for the given
|
||||
/// room version. The top-level `origin`, `membership`, and `prev_state` properties are no longer
|
||||
/// protected from redaction. The `m.room.create` event now keeps the entire content property. The
|
||||
/// `m.room.redaction` event keeps the `redacts` property under `content`. The
|
||||
/// `m.room.power_levels` event keeps the `invite` property under `content`.
|
||||
///
|
||||
/// Added in room version 11.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v11/#redactions>
|
||||
pub fn use_updated_redaction_rules(room_version: &RoomVersion) -> bool {
|
||||
room_version.updated_redaction_rules
|
||||
}
|
||||
|
||||
/// Whether `m.room.aliases` has significant meaning.
|
||||
/// This means that the `aliases` property under `content` is no longer kept for the `m.room.aliases`
|
||||
/// event type.
|
||||
///
|
||||
/// Removed in room version 6.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v6/#redactions>
|
||||
fn use_special_case_aliases_auth(room_version_id: &RoomVersion) -> bool {
|
||||
room_version_id.special_case_aliases_auth
|
||||
}
|
||||
|
||||
/// `m.room.join_rules` events now keep `allow` in addition to other keys in `content` when being
|
||||
/// redacted.
|
||||
///
|
||||
/// Added in room version 8.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v8/#redactions>
|
||||
fn use_restricted_join_rule(room_version_id: &RoomVersion) -> bool {
|
||||
room_version_id.restricted_join_rule
|
||||
}
|
||||
|
||||
/// `m.room.member` events now keep `join_authorised_via_users_server` in addition to other keys in
|
||||
/// `content` when being redacted.
|
||||
///
|
||||
/// Added in room version 9.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v9/#redactions>
|
||||
fn use_restricted_join_rule_fix(room_version_id: &RoomVersion) -> bool {
|
||||
room_version_id.restricted_join_rule_fix
|
||||
}
|
||||
|
||||
/// The content of a `m.room.create` event no longer has a `creator` property, which previously was
|
||||
/// always equivalent to the `sender` of the event.
|
||||
///
|
||||
/// Added in room version 11.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v11/#redactions>
|
||||
fn use_implicit_room_creator(room_version_id: &RoomVersion) -> bool {
|
||||
room_version_id.implicit_room_creator
|
||||
}
|
||||
|
||||
/// Whether room ids are hashes, or still the older localpart:domain style.
|
||||
/// Returns true if the room_id is a hash for the given room version.
|
||||
///
|
||||
/// Added in room version 12.
|
||||
/// <https://spec.matrix.org/v1.16/rooms/v12/#redactions>
|
||||
pub fn use_room_ids_as_hashes(room_version_id: &RoomVersion) -> bool {
|
||||
room_version_id.msc4291_room_ids_as_hashes
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
Reference in New Issue
Block a user