mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-16 03:55:42 -04:00
base: Apply redaction to latest_event in RoomInfo when applicable
This commit is contained in:
committed by
Jonas Platte
parent
0bb7a9de7f
commit
a503dccdcd
@@ -336,7 +336,7 @@ impl BaseClient {
|
||||
SyncRoomRedactionEvent::Original(r),
|
||||
),
|
||||
) => {
|
||||
room_info.handle_redaction(r);
|
||||
room_info.handle_redaction(r, event.event.cast_ref());
|
||||
let raw_event = event.event.clone().cast();
|
||||
changes.add_redaction(room.room_id(), &r.redacts, raw_event);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ use futures_util::stream::{self, StreamExt};
|
||||
use matrix_sdk_common::deserialized_responses::SyncTimelineEvent;
|
||||
#[cfg(all(feature = "e2e-encryption", feature = "experimental-sliding-sync"))]
|
||||
use matrix_sdk_common::ring_buffer::RingBuffer;
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
use ruma::events::AnySyncTimelineEvent;
|
||||
use ruma::{
|
||||
api::client::sync::sync_events::v3::RoomSummary as RumaSummary,
|
||||
events::{
|
||||
@@ -44,11 +46,10 @@ use ruma::{
|
||||
RoomAccountDataEventType,
|
||||
},
|
||||
room::RoomType,
|
||||
serde::Raw,
|
||||
EventId, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId,
|
||||
RoomId, RoomVersionId, UserId,
|
||||
};
|
||||
#[cfg(all(feature = "e2e-encryption", feature = "experimental-sliding-sync"))]
|
||||
use ruma::{events::AnySyncTimelineEvent, serde::Raw};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{debug, info, instrument, warn};
|
||||
|
||||
@@ -851,7 +852,22 @@ impl RoomInfo {
|
||||
}
|
||||
|
||||
/// Handle the given redaction.
|
||||
pub fn handle_redaction(&mut self, event: &OriginalSyncRoomRedactionEvent) {
|
||||
pub fn handle_redaction(
|
||||
&mut self,
|
||||
event: &OriginalSyncRoomRedactionEvent,
|
||||
_raw: &Raw<OriginalSyncRoomRedactionEvent>,
|
||||
) {
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
if let Some(latest_event) = &mut self.latest_event {
|
||||
if latest_event.event_id().as_deref() == Some(&*event.redacts) {
|
||||
let room_version = self.base_info.room_version().unwrap_or(&RoomVersionId::V1);
|
||||
match apply_redaction(&latest_event.event, _raw, room_version) {
|
||||
Some(redacted) => latest_event.event = redacted,
|
||||
None => self.latest_event = None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.base_info.handle_redaction(event);
|
||||
}
|
||||
|
||||
@@ -982,6 +998,41 @@ impl RoomInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
fn apply_redaction(
|
||||
event: &Raw<AnySyncTimelineEvent>,
|
||||
raw_redaction: &Raw<OriginalSyncRoomRedactionEvent>,
|
||||
room_version: &RoomVersionId,
|
||||
) -> Option<Raw<AnySyncTimelineEvent>> {
|
||||
use ruma::canonical_json::redact_in_place;
|
||||
|
||||
let mut event_json = match event.deserialize_as() {
|
||||
Ok(json) => json,
|
||||
Err(e) => {
|
||||
warn!("Failed to deserialize latest event: {e}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let redacted_because = match raw_redaction.try_into() {
|
||||
Ok(rb) => rb,
|
||||
Err(e) => {
|
||||
warn!("Redaction event is not valid canonical JSON: {e}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let redact_result = redact_in_place(&mut event_json, room_version, Some(redacted_because));
|
||||
|
||||
if let Err(e) = redact_result {
|
||||
warn!("Failed to redact latest event: {e}");
|
||||
return None;
|
||||
}
|
||||
|
||||
let raw = Raw::new(&event_json).expect("CanonicalJsonObject must be serializable");
|
||||
Some(raw.cast())
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Room state filter as a bitset.
|
||||
///
|
||||
|
||||
@@ -452,6 +452,7 @@ mod test {
|
||||
sync::{Arc, RwLock as SyncRwLock},
|
||||
};
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use matrix_sdk_common::ring_buffer::RingBuffer;
|
||||
use matrix_sdk_test::async_test;
|
||||
use ruma::{
|
||||
@@ -462,9 +463,10 @@ mod test {
|
||||
avatar::RoomAvatarEventContent,
|
||||
canonical_alias::RoomCanonicalAliasEventContent,
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
message::SyncRoomMessageEvent,
|
||||
},
|
||||
AnySyncStateEvent, AnySyncTimelineEvent, GlobalAccountDataEventContent,
|
||||
StateEventContent,
|
||||
AnySyncMessageLikeEvent, AnySyncStateEvent, AnySyncTimelineEvent,
|
||||
GlobalAccountDataEventContent, StateEventContent,
|
||||
},
|
||||
mxc_uri, room_alias_id, room_id,
|
||||
serde::Raw,
|
||||
@@ -765,6 +767,56 @@ mod test {
|
||||
assert_eq!(ev_id(client_room.latest_event()), "$idb");
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn cached_latest_event_can_be_redacted() {
|
||||
// Given a logged-in client
|
||||
let client = logged_in_client().await;
|
||||
let room_id = room_id!("!r:e.uk");
|
||||
let event_a = json!({
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.room.message",
|
||||
"event_id": "$ida",
|
||||
"origin_server_ts": 12344446,
|
||||
"content": { "body":"A", "msgtype": "m.text" },
|
||||
});
|
||||
|
||||
// When the sliding sync response contains a timeline
|
||||
let room = room_with_timeline(&[event_a]);
|
||||
let response = response_with_room(room_id, room).await;
|
||||
client.process_sliding_sync(&response).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room holds the latest event
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
assert_eq!(ev_id(client_room.latest_event()), "$ida");
|
||||
|
||||
let redaction = json!({
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.room.redaction",
|
||||
"event_id": "$idb",
|
||||
"redacts": "$ida",
|
||||
"origin_server_ts": 12344448,
|
||||
"content": {},
|
||||
});
|
||||
|
||||
// When a redaction for that event is received
|
||||
let room = room_with_timeline(&[redaction]);
|
||||
let response = response_with_room(room_id, room).await;
|
||||
client.process_sliding_sync(&response).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room still holds the latest event
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
let latest_event = client_room.latest_event().unwrap();
|
||||
assert_eq!(latest_event.event_id().unwrap(), "$ida");
|
||||
|
||||
// But it's now redacted
|
||||
assert_matches!(
|
||||
latest_event.event.deserialize().unwrap(),
|
||||
AnySyncTimelineEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(
|
||||
SyncRoomMessageEvent::Redacted(_)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_no_events_we_dont_cache_any() {
|
||||
let events = &[];
|
||||
|
||||
Reference in New Issue
Block a user