From a4e1522875358ce620e9cc3baaa86ac324211587 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Fri, 8 Nov 2024 18:11:11 -0800 Subject: [PATCH] generalize `get_room_version` There are other fields of `m.room.create` events that are useful to individually extract without caring about the values of other fields. --- src/api/client_server/membership.rs | 7 ++++-- src/api/server_server.rs | 22 +++++++++++++---- src/service/rooms/state.rs | 38 ++++++++++++++++++++++------- src/service/rooms/timeline.rs | 26 ++++++++++++++------ 4 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index c07a07c9..7d6c9cdb 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -38,6 +38,7 @@ use crate::{ service::{ globals::SigningKeys, pdu::{gen_event_id_canonical_json, PduBuilder}, + rooms::state::ExtractVersion, }, services, utils, Ar, Error, PduEvent, Ra, Result, }; @@ -1324,8 +1325,10 @@ pub(crate) async fn invite_helper( (pdu, pdu_json, invite_room_state) }; - let room_version_id = - services().rooms.state.get_room_version(room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(room_id)?; let response = services() .sending diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 95b40fea..edba5291 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -72,6 +72,7 @@ use crate::{ service::{ globals::SigningKeys, pdu::{gen_event_id_canonical_json, PduBuilder}, + rooms::state::ExtractVersion, }, services, utils::{self, dbg_truncate_str, MxcData}, @@ -712,7 +713,10 @@ pub(crate) fn parse_incoming_pdu( "Invalid room id in pdu", ))?; - let room_version_id = services().rooms.state.get_room_version(&room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(&room_id)?; let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) @@ -754,7 +758,12 @@ pub(crate) async fn send_transaction_message_route( "Invalid room id in pdu", ))?; - if services().rooms.state.get_room_version(&room_id).is_err() { + if services() + .rooms + .state + .get_create_content::(&room_id) + .is_err() + { debug!(%room_id, "This server is not in the room"); continue; } @@ -1514,8 +1523,10 @@ pub(crate) async fn create_join_event_template_route( } } - let room_version_id = - services().rooms.state.get_room_version(&body.room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(&body.room_id)?; if !body.ver.contains(&room_version_id) { return Err(Error::BadRequest( ErrorKind::IncompatibleRoomVersion { @@ -1620,7 +1631,8 @@ async fn create_join_event( // We do not add the event_id field to the pdu here because of signature and // hashes checks - let room_version_id = services().rooms.state.get_room_version(room_id)?; + let room_version_id = + services().rooms.state.get_create_content::(room_id)?; let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else { diff --git a/src/service/rooms/state.rs b/src/service/rooms/state.rs index 4702a76b..72741417 100644 --- a/src/service/rooms/state.rs +++ b/src/service/rooms/state.rs @@ -7,14 +7,14 @@ use std::{ use ruma::{ api::client::error::ErrorKind, events::{ - room::{create::RoomCreateEventContent, member::MembershipState}, - AnyStrippedStateEvent, StateEventType, TimelineEventType, + room::member::MembershipState, AnyStrippedStateEvent, StateEventType, + TimelineEventType, }, serde::Raw, state_res::{self, StateMap}, EventId, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId, }; -use serde::Deserialize; +use serde::{de::DeserializeOwned, Deserialize}; use tracing::warn; use super::{short::ShortStateHash, state_compressor::CompressedStateEvent}; @@ -31,6 +31,26 @@ mod data; pub(crate) use data::Data; +pub(crate) trait ExtractCreateContent: DeserializeOwned { + type Extract; + + fn extract(self) -> Self::Extract; +} + +/// Extract the `room_version` from an `m.room.create` event +#[derive(Deserialize)] +pub(crate) struct ExtractVersion { + room_version: RoomVersionId, +} + +impl ExtractCreateContent for ExtractVersion { + type Extract = RoomVersionId; + + fn extract(self) -> Self::Extract { + self.room_version + } +} + pub(crate) struct Service { pub(crate) db: &'static dyn Data, } @@ -315,22 +335,22 @@ impl Service { self.db.set_room_state(room_id, shortstatehash) } - /// Returns the room's version. + /// Returns the value of a field of an `m.room.create` event's `content`. #[tracing::instrument(skip(self))] - pub(crate) fn get_room_version( + pub(crate) fn get_create_content( &self, room_id: &RoomId, - ) -> Result { + ) -> Result { let create_event = services().rooms.state_accessor.room_state_get( room_id, &StateEventType::RoomCreate, "", )?; - let create_event_content: RoomCreateEventContent = create_event + let content_field = create_event .as_ref() .map(|create_event| { - serde_json::from_str(create_event.content.get()).map_err( + serde_json::from_str::(create_event.content.get()).map_err( |error| { warn!(%error, "Invalid create event"); Error::BadDatabase("Invalid create event in db.") @@ -345,7 +365,7 @@ impl Service { ) })?; - Ok(create_event_content.room_version) + Ok(content_field.extract()) } #[tracing::instrument(skip(self))] diff --git a/src/service/rooms/timeline.rs b/src/service/rooms/timeline.rs index 0cd751dd..382c3aca 100644 --- a/src/service/rooms/timeline.rs +++ b/src/service/rooms/timeline.rs @@ -36,6 +36,7 @@ use crate::{ appservice::NamespaceRegex, globals::{marker, SigningKeys}, pdu::{EventHash, PduBuilder}, + rooms::state::ExtractVersion, }, services, utils::{self, on_demand_hashmap::KeyToken, room_version::RoomVersion}, @@ -476,8 +477,10 @@ impl Service { match pdu.kind { TimelineEventType::RoomRedaction => { - let room_version_id = - services().rooms.state.get_room_version(&pdu.room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(&pdu.room_id)?; let room_version = RoomVersion::try_from(&room_version_id)?; if room_version.redaction_event_redacts_in_content { let content = serde_json::from_str::< @@ -774,8 +777,11 @@ impl Service { .collect(); // If there was no create event yet, assume we are creating a room - let room_version_id = - services().rooms.state.get_room_version(room_id).or_else(|_| { + let room_version_id = services() + .rooms + .state + .get_create_content::(room_id) + .or_else(|_| { if event_type == TimelineEventType::RoomCreate { let content = serde_json::from_str::( @@ -1064,8 +1070,10 @@ impl Service { // If redaction event is not authorized, do not append it to the // timeline if pdu.kind == TimelineEventType::RoomRedaction { - let room_version_id = - services().rooms.state.get_room_version(&pdu.room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(&pdu.room_id)?; let room_version = RoomVersion::try_from(&room_version_id)?; if room_version.redaction_event_redacts_in_content { let content = @@ -1257,8 +1265,10 @@ impl Service { )?; } - let room_version_id = - services().rooms.state.get_room_version(&pdu.room_id)?; + let room_version_id = services() + .rooms + .state + .get_create_content::(&pdu.room_id)?; pdu.redact(room_version_id, reason)?; self.replace_pdu(