From e7c70854ab8022a1ca446a0cef958282deac96ac Mon Sep 17 00:00:00 2001 From: Devin R Date: Fri, 3 Jul 2020 16:52:35 -0400 Subject: [PATCH] sdk_base: message events in message queue have content redacted The MessageQueue holds MessageEventStub so when a redaction event is encountered the redacted event's content can be replaced. The Unsigned field redacted_because is also populated with the redaction event itself with the addition of a room_id Stub -> full event. --- matrix_sdk_base/src/models/message.rs | 40 +++++++++----- matrix_sdk_base/src/models/room.rs | 77 ++++++++++++++++++++++++--- matrix_sdk_test/src/test_json/mod.rs | 5 +- 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/matrix_sdk_base/src/models/message.rs b/matrix_sdk_base/src/models/message.rs index f7d2141b..a798ae8d 100644 --- a/matrix_sdk_base/src/models/message.rs +++ b/matrix_sdk_base/src/models/message.rs @@ -7,28 +7,42 @@ use std::cmp::Ordering; use std::ops::{Deref, DerefMut}; use std::vec::IntoIter; -use crate::events::AnyMessageEventStub; +use crate::events::{AnyMessageEventContent, AnyMessageEventStub, MessageEventStub}; use serde::{de, ser, Serialize}; const MESSAGE_QUEUE_CAP: usize = 35; +pub type SyncMessageEvent = MessageEventStub; + /// A queue that holds the 35 most recent messages received from the server. #[derive(Clone, Debug, Default)] pub struct MessageQueue { - msgs: Vec, + pub(crate) msgs: Vec, } -/// A wrapper for `ruma_events::AnyMessageEventStub` that allows implementation of +/// A wrapper for `ruma_events::SyncMessageEvent` that allows implementation of /// Eq, Ord and the Partial versions of the traits. /// /// `MessageWrapper` also implements Deref and DerefMut so accessing the events contents /// are simplified. #[derive(Clone, Debug, Serialize)] -pub struct MessageWrapper(pub AnyMessageEventStub); +pub struct MessageWrapper(pub SyncMessageEvent); + +impl MessageWrapper { + pub fn clone_into_any_content(event: &AnyMessageEventStub) -> SyncMessageEvent { + MessageEventStub { + content: event.content().clone(), + sender: event.sender().clone(), + origin_server_ts: event.origin_server_ts().clone(), + event_id: event.event_id().clone(), + unsigned: event.unsigned().clone(), + } + } +} impl Deref for MessageWrapper { - type Target = AnyMessageEventStub; + type Target = SyncMessageEvent; fn deref(&self) -> &Self::Target { &self.0 @@ -43,7 +57,7 @@ impl DerefMut for MessageWrapper { impl PartialEq for MessageWrapper { fn eq(&self, other: &MessageWrapper) -> bool { - self.0.event_id() == other.0.event_id() + self.0.event_id == other.0.event_id } } @@ -51,7 +65,7 @@ impl Eq for MessageWrapper {} impl PartialOrd for MessageWrapper { fn partial_cmp(&self, other: &MessageWrapper) -> Option { - Some(self.0.origin_server_ts().cmp(&other.0.origin_server_ts())) + Some(self.0.origin_server_ts.cmp(&other.0.origin_server_ts)) } } @@ -68,7 +82,7 @@ impl PartialEq for MessageQueue { .msgs .iter() .zip(other.msgs.iter()) - .all(|(msg_a, msg_b)| msg_a.event_id() == msg_b.event_id()) + .all(|(msg_a, msg_b)| msg_a.event_id == msg_b.event_id) } } @@ -83,10 +97,10 @@ impl MessageQueue { /// Inserts a `MessageEvent` into `MessageQueue`, sorted by by `origin_server_ts`. /// /// Removes the oldest element in the queue if there are more than 10 elements. - pub fn push(&mut self, msg: AnyMessageEventStub) -> bool { + pub fn push(&mut self, msg: SyncMessageEvent) -> bool { // only push new messages into the queue if let Some(latest) = self.msgs.last() { - if msg.origin_server_ts() < latest.origin_server_ts() && self.msgs.len() >= 10 { + if msg.origin_server_ts < latest.origin_server_ts && self.msgs.len() >= 10 { return false; } } @@ -131,7 +145,7 @@ pub(crate) mod ser_deser { where D: de::Deserializer<'de>, { - let messages: Vec = de::Deserialize::deserialize(deserializer)?; + let messages: Vec = de::Deserialize::deserialize(deserializer)?; let mut msgs = vec![]; for msg in messages { @@ -172,7 +186,7 @@ mod test { let mut room = Room::new(&id, &user); let json: &serde_json::Value = &test_json::MESSAGE_TEXT; - let msg = serde_json::from_value::(json.clone()).unwrap(); + let msg = serde_json::from_value::(json.clone()).unwrap(); let mut msgs = MessageQueue::new(); msgs.push(msg.clone()); @@ -218,7 +232,7 @@ mod test { let mut room = Room::new(&id, &user); let json: &serde_json::Value = &test_json::MESSAGE_TEXT; - let msg = serde_json::from_value::(json.clone()).unwrap(); + let msg = serde_json::from_value::(json.clone()).unwrap(); let mut msgs = MessageQueue::new(); msgs.push(msg.clone()); diff --git a/matrix_sdk_base/src/models/room.rs b/matrix_sdk_base/src/models/room.rs index ab2218f2..730887c7 100644 --- a/matrix_sdk_base/src/models/room.rs +++ b/matrix_sdk_base/src/models/room.rs @@ -34,18 +34,34 @@ use crate::events::room::{ }; use crate::events::{ - Algorithm, AnyRoomEventStub, AnyStateEventStub, AnyStrippedStateEventStub, EventType, - StateEventStub, StrippedStateEventStub, + Algorithm, AnyMessageEventContent, AnyRoomEventStub, AnyStateEventStub, + AnyStrippedStateEventStub, EventJson, EventType, StateEventStub, StrippedStateEventStub, }; #[cfg(feature = "messages")] -use crate::events::{room::redaction::RedactionEventStub, AnyMessageEventStub}; +use crate::events::{ + room::redaction::{RedactionEvent, RedactionEventStub}, + AnyMessageEventStub, +}; use crate::identifiers::{RoomAliasId, RoomId, UserId}; use crate::js_int::{Int, UInt}; use serde::{Deserialize, Serialize}; +#[cfg(feature = "messages")] +fn full_event_from_stub(event: RedactionEventStub, room_id: RoomId) -> RedactionEvent { + RedactionEvent { + content: event.content, + redacts: event.redacts, + event_id: event.event_id, + unsigned: event.unsigned, + sender: event.sender, + origin_server_ts: event.origin_server_ts, + room_id, + } +} + #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] /// `RoomName` allows the calculation of a text room name. pub struct RoomName { @@ -618,7 +634,8 @@ impl Room { #[cfg(feature = "messages")] #[cfg_attr(docsrs, doc(cfg(feature = "messages")))] pub fn handle_message(&mut self, event: &AnyMessageEventStub) -> bool { - self.messages.push(event.clone()) + let message = MessageWrapper::clone_into_any_content(event); + self.messages.push(message) } /// Handle a room.redaction event and update the `MessageQueue` if necessary. @@ -630,9 +647,12 @@ impl Room { if let Some(msg) = self .messages .iter_mut() - .find(|msg| &event.redacts == msg.event_id()) + .find(|msg| event.redacts == msg.event_id) { - *msg = MessageWrapper(AnyMessageEventStub::RoomRedaction(event.clone())); + msg.content = AnyMessageEventContent::RoomRedaction(event.content.clone()); + + let redaction = full_event_from_stub(event.clone(), self.room_id.clone()); + msg.unsigned.redacted_because = Some(EventJson::from(redaction)); true } else { false @@ -1152,6 +1172,51 @@ mod test { assert_eq!(vec!["example2"], room_names); } + #[cfg(feature = "messages")] + #[async_test] + async fn message_queue_redaction_event() { + let room_id = get_room_id(); + + let mut response = sync_response(SyncResponseFile::DefaultWithSummary); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + let client = BaseClient::new().unwrap(); + client.restore_login(session).await.unwrap(); + client.receive_sync_response(&mut response).await.unwrap(); + + let json = serde_json::json!({ + "content": { + "reason": "😀" + }, + "event_id": "$151957878228ssqrJ:localhost", + "origin_server_ts": 151957878, + "sender": "@example:localhost", + "type": "m.room.redaction", + "redacts": "$152037280074GZeOm:localhost" + }); + let mut event: EventJson = serde_json::from_value(json).unwrap(); + client + .receive_joined_timeline_event(&room_id, &mut event) + .await + .unwrap(); + + for room in client.joined_rooms().read().await.values() { + let queue = &room.read().await.messages; + println!("{:?}", queue); + if let crate::events::AnyMessageEventContent::RoomRedaction(content) = + &queue.msgs[0].content + { + assert_eq!(content.reason, Some("😀".to_string())); + } else { + panic!("message event in message queue should be redacted") + } + } + } + #[async_test] #[cfg(not(target_arch = "wasm32"))] async fn encryption_info_test() { diff --git a/matrix_sdk_test/src/test_json/mod.rs b/matrix_sdk_test/src/test_json/mod.rs index 406f2023..474a397f 100644 --- a/matrix_sdk_test/src/test_json/mod.rs +++ b/matrix_sdk_test/src/test_json/mod.rs @@ -9,7 +9,8 @@ pub mod sync; pub use events::{ ALIAS, ALIASES, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, LOGOUT, MEMBER, - MESSAGE_EDIT, MESSAGE_TEXT, NAME, POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, REACTION, - REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES, TYPING, + MESSAGE_EDIT, MESSAGE_TEXT, NAME, POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, REACTION, REDACTED, + REDACTED_INVALID, REDACTED_STATE, REDACTION, REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES, + TYPING, }; pub use sync::{DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, MORE_SYNC, SYNC};