diff --git a/Cargo.lock b/Cargo.lock index 8a28f31a..c426f8f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2520,8 +2520,8 @@ dependencies = [ [[package]] name = "ruma" -version = "0.12.3" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.12.5" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "assign", "js_int", @@ -2540,7 +2540,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.12.2" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "js_int", "ruma-common", @@ -2551,8 +2551,8 @@ dependencies = [ [[package]] name = "ruma-client-api" -version = "0.20.3" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.20.4" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "as_variant", "assign", @@ -2574,8 +2574,8 @@ dependencies = [ [[package]] name = "ruma-common" -version = "0.15.2" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.15.4" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "as_variant", "base64 0.22.1", @@ -2606,8 +2606,8 @@ dependencies = [ [[package]] name = "ruma-events" -version = "0.30.3" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.30.4" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "as_variant", "indexmap 2.9.0", @@ -2630,8 +2630,8 @@ dependencies = [ [[package]] name = "ruma-federation-api" -version = "0.11.1" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.11.2" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "bytes", "headers", @@ -2653,7 +2653,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.10.1" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "js_int", "thiserror 2.0.12", @@ -2661,8 +2661,8 @@ dependencies = [ [[package]] name = "ruma-macros" -version = "0.15.1" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +version = "0.15.2" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "cfg-if", "proc-macro-crate", @@ -2677,7 +2677,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.11.0" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "js_int", "ruma-common", @@ -2689,7 +2689,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.17.1" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -2705,7 +2705,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.13.0" -source = "git+https://github.com/ruma/ruma.git#e65c55fe37343e5fe3366e7bb5fc6fdca4f27655" +source = "git+https://github.com/ruma/ruma.git#7bae3d0c0b8edf008899ac2b04cf9722182eef68" dependencies = [ "js_int", "ruma-common", diff --git a/Cargo.toml b/Cargo.toml index 5455ad79..3406566f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -159,6 +159,7 @@ http-body-util = "0.1.3" [dependencies.ruma] features = [ "appservice-api-c", + "canonical-json", "client-api", "compat-empty-string-null", "compat-get-3pids", diff --git a/src/api/client_server/keys.rs b/src/api/client_server/keys.rs index cd971d24..1b2fc819 100644 --- a/src/api/client_server/keys.rs +++ b/src/api/client_server/keys.rs @@ -548,7 +548,8 @@ fn add_unsigned_device_display_name( metadata: ruma::api::client::device::Device, ) -> serde_json::Result<()> { if let Some(display_name) = metadata.display_name { - let mut object = keys.deserialize_as::>()?; + let mut object = + keys.deserialize_as_unchecked::>()?; let unsigned = object.entry("unsigned").or_insert_with(|| json!({})); if let serde_json::Value::Object(unsigned_object) = unsigned { diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index fcd61a54..0ab45324 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -145,7 +145,7 @@ pub async fn create_room_route( let content = match &body.creation_content { Some(content) => { let mut content = content - .deserialize_as::() + .deserialize_as_unchecked::() .expect("Invalid creation content"); if !rules.use_room_create_sender { diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 6580da6a..29d309c1 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -604,7 +604,7 @@ async fn sync_helper( account_data: GlobalAccountData { events: services() .account_data - .changes_since(None, &sender_user, since)? + .global_changes_since(&sender_user, since)? .into_iter() .filter_map(|(_, v)| { serde_json::from_str(v.json().get()) @@ -1176,7 +1176,7 @@ async fn load_joined_room( account_data: RoomAccountData { events: services() .account_data - .changes_since(Some(room_id), sender_user, since)? + .room_changes_since(room_id, sender_user, since)? .into_iter() .filter_map(|(_, v)| { serde_json::from_str(v.json().get()) @@ -1828,7 +1828,7 @@ pub async fn sync_events_v5_route( global: if body.extensions.account_data.enabled.unwrap_or(false) { services() .account_data - .changes_since(None, &sender_user, globalsince)? + .global_changes_since(&sender_user, globalsince)? .into_iter() .filter_map(|(_, v)| { serde_json::from_str(v.json().get()) diff --git a/src/database/key_value/account_data.rs b/src/database/key_value/account_data.rs index 970b36b5..edbaa68c 100644 --- a/src/database/key_value/account_data.rs +++ b/src/database/key_value/account_data.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use ruma::{ api::client::error::ErrorKind, - events::{AnyEphemeralRoomEvent, RoomAccountDataEventType}, + events::{AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, RoomAccountDataEventType}, serde::Raw, RoomId, UserId, }; @@ -94,25 +94,48 @@ impl service::account_data::Data for KeyValueDatabase { .transpose() } - /// Returns all changes to the account data that happened after `since`. - #[tracing::instrument(skip(self, room_id, user_id, since))] - fn changes_since( + /// Returns all changes to the global account data that happened after `since`. + #[tracing::instrument(skip_all)] + fn global_changes_since( &self, - room_id: Option<&RoomId>, user_id: &UserId, since: u64, - ) -> Result>> { - let mut userdata = HashMap::new(); - - let mut prefix = room_id - .map(|r| r.to_string()) - .unwrap_or_default() - .as_bytes() - .to_vec(); + ) -> Result>> { + let mut prefix = Vec::new(); prefix.push(0xff); prefix.extend_from_slice(user_id.as_bytes()); prefix.push(0xff); + self.changes_since::(prefix, since) + } + + /// Returns all changes to the room account data that happened after `since`. + #[tracing::instrument(skip_all)] + fn room_changes_since( + &self, + room_id: &RoomId, + user_id: &UserId, + since: u64, + ) -> Result>> { + let mut prefix = room_id.to_string().as_bytes().to_vec(); + prefix.push(0xff); + prefix.extend_from_slice(user_id.as_bytes()); + prefix.push(0xff); + + self.changes_since::(prefix, since) + } +} + +impl KeyValueDatabase { + /// Returns all changes to the account data that happened after `since`. + #[tracing::instrument(skip_all)] + fn changes_since( + &self, + prefix: Vec, + since: u64, + ) -> Result>> { + let mut userdata = HashMap::new(); + // Skip the data that's exactly at since, because we sent that last time let mut first_possible = prefix.clone(); first_possible.extend_from_slice(&(since + 1).to_be_bytes()); @@ -129,7 +152,7 @@ impl service::account_data::Data for KeyValueDatabase { )?) .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, ), - serde_json::from_slice::>(&v).map_err(|_| { + serde_json::from_slice::>(&v).map_err(|_| { Error::bad_database("Database contains invalid account data.") })?, )) diff --git a/src/lib.rs b/src/lib.rs index a2406137..e8607b3e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ pub use utils::error::{Error, Result}; pub static SERVICES: RwLock> = RwLock::new(None); pub static SUPPORTED_VERSIONS: LazyLock = LazyLock::new(|| SupportedVersions { versions: BTreeSet::from_iter([MatrixVersion::V1_13]), - features: Vec::new(), + features: BTreeSet::new(), }); pub fn services() -> &'static Services { diff --git a/src/service/account_data/data.rs b/src/service/account_data/data.rs index c7c92981..f60d4f26 100644 --- a/src/service/account_data/data.rs +++ b/src/service/account_data/data.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use crate::Result; use ruma::{ - events::{AnyEphemeralRoomEvent, RoomAccountDataEventType}, + events::{AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, RoomAccountDataEventType}, serde::Raw, RoomId, UserId, }; @@ -25,11 +25,18 @@ pub trait Data: Send + Sync { kind: RoomAccountDataEventType, ) -> Result>>; - /// Returns all changes to the account data that happened after `since`. - fn changes_since( + /// Returns all changes to the global account data that happened after `since`. + fn global_changes_since( &self, - room_id: Option<&RoomId>, user_id: &UserId, since: u64, - ) -> Result>>; + ) -> Result>>; + + /// Returns all changes to the room account data that happened after `since`. + fn room_changes_since( + &self, + room_id: &RoomId, + user_id: &UserId, + since: u64, + ) -> Result>>; } diff --git a/src/service/account_data/mod.rs b/src/service/account_data/mod.rs index f9c49b1a..dc5e0de7 100644 --- a/src/service/account_data/mod.rs +++ b/src/service/account_data/mod.rs @@ -3,7 +3,7 @@ mod data; pub use data::Data; use ruma::{ - events::{AnyEphemeralRoomEvent, RoomAccountDataEventType}, + events::{AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, RoomAccountDataEventType}, serde::Raw, RoomId, UserId, }; @@ -40,14 +40,24 @@ impl Service { self.db.get(room_id, user_id, event_type) } - /// Returns all changes to the account data that happened after `since`. - #[tracing::instrument(skip(self, room_id, user_id, since))] - pub fn changes_since( + /// Returns all changes to the global account data that happened after `since`. + #[tracing::instrument(skip_all)] + pub fn global_changes_since( &self, - room_id: Option<&RoomId>, user_id: &UserId, since: u64, - ) -> Result>> { - self.db.changes_since(room_id, user_id, since) + ) -> Result>> { + self.db.global_changes_since(user_id, since) + } + + /// Returns all changes to the room account data that happened after `since`. + #[tracing::instrument(skip_all)] + pub fn room_changes_since( + &self, + room_id: &RoomId, + user_id: &UserId, + since: u64, + ) -> Result>> { + self.db.room_changes_since(room_id, user_id, since) } } diff --git a/src/service/pdu.rs b/src/service/pdu.rs index bc5e7fae..162626fb 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -5,12 +5,12 @@ use ruma::{ events::{ room::{member::RoomMemberEventContent, redaction::RoomRedactionEventContent}, space::child::HierarchySpaceChildEvent, - AnyEphemeralRoomEvent, AnyMessageLikeEvent, AnyStateEvent, AnyStrippedStateEvent, + AnyInitialStateEvent, AnyMessageLikeEvent, AnyStateEvent, AnyStrippedStateEvent, AnySyncMessageLikeEvent, AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent, StateEvent, TimelineEventType, }, room_version_rules::{RedactionRules, RoomVersionRules}, - serde::Raw, + serde::{JsonCastable, Raw}, state_res, CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, UInt, UserId, }; @@ -197,31 +197,6 @@ impl PduEvent { serde_json::from_value(json).expect("Raw::from_value always works") } - /// This only works for events that are also AnyRoomEvents. - #[tracing::instrument(skip(self))] - pub fn to_any_event(&self) -> Raw { - let mut json = json!({ - "content": self.content, - "type": self.kind, - "event_id": self.event_id, - "sender": self.sender, - "origin_server_ts": self.origin_server_ts, - "room_id": self.room_id, - }); - - if let Some(unsigned) = &self.unsigned { - json["unsigned"] = json!(unsigned); - } - if let Some(state_key) = &self.state_key { - json["state_key"] = json!(state_key); - } - if let Some(redacts) = &self.redacts { - json["redacts"] = json!(redacts); - } - - serde_json::from_value(json).expect("Raw::from_value always works") - } - #[tracing::instrument(skip(self))] pub fn to_room_event(&self) -> Raw { let (redacts, content) = self.copy_redacts(); @@ -499,3 +474,5 @@ pub struct PduBuilder { /// Will be set to current time if None pub timestamp: Option, } + +impl JsonCastable for AnyInitialStateEvent {}