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.
This commit is contained in:
Charles Hall 2024-11-08 18:11:11 -08:00
parent c9c30fba30
commit a4e1522875
No known key found for this signature in database
GPG key ID: 7B8E0645816E07CF
4 changed files with 69 additions and 24 deletions

View file

@ -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::<ExtractVersion>(room_id)?;
let response = services()
.sending

View file

@ -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::<ExtractVersion>(&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::<ExtractVersion>(&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::<ExtractVersion>(&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::<ExtractVersion>(room_id)?;
let Ok((event_id, value)) =
gen_event_id_canonical_json(pdu, &room_version_id)
else {

View file

@ -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<T: ExtractCreateContent>(
&self,
room_id: &RoomId,
) -> Result<RoomVersionId> {
) -> Result<T::Extract> {
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::<T>(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))]

View file

@ -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::<ExtractVersion>(&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::<ExtractVersion>(room_id)
.or_else(|_| {
if event_type == TimelineEventType::RoomCreate {
let content =
serde_json::from_str::<RoomCreateEventContent>(
@ -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::<ExtractVersion>(&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::<ExtractVersion>(&pdu.room_id)?;
pdu.redact(room_version_id, reason)?;
self.replace_pdu(