Skip to content

Commit 08dd18d

Browse files
committed
feat(common): Add TimelineEvent::timestamp.
This patch adds the `timestamp` field to `TimelineEvent`. It's a copy of the `origin_server_ts` value, parsed as an `Option<MilliSecondsSinceUnixEpoch>`. It's `None` if the parsing failed, or if the `TimelineEvent` was deserialised from a version before this new field was added. A new `extract_timestamp` function is added for this purpose. It protects against malicious `origin_server_ts` where the value can be set to year 2100 for example. The only protection we are adding here is to take the `min(origin_server_ts, now())`, so that the event can never been “in the future”. It doesn't protect against a malicious value like 0. It's non-trivial to define a minimum timestamp for an event. When a `TimelineEvent` is mapped from one kind to another kind, the `timestamp` is carried over. To achieve that, new `to_decrypted` and `to_utd` methods are added. The rest of the code is updated accordingly.
1 parent 4cc1cd1 commit 08dd18d

File tree

8 files changed

+322
-50
lines changed

8 files changed

+322
-50
lines changed

crates/matrix-sdk-base/src/latest_event.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,7 @@ mod tests {
790790
}
791791
},
792792
"thread_summary": "None",
793+
"timestamp": null,
793794
}
794795
}
795796
})

crates/matrix-sdk-base/src/response_processors/e2ee/decrypt.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use matrix_sdk_common::deserialized_responses::TimelineEvent;
1616
use matrix_sdk_crypto::RoomEventDecryptionResult;
17-
use ruma::{RoomId, events::AnySyncTimelineEvent, serde::Raw};
17+
use ruma::RoomId;
1818

1919
use super::{super::verification, E2EE};
2020
use crate::Result;
@@ -26,31 +26,36 @@ use crate::Result;
2626
/// application, returns `Err`.
2727
///
2828
/// Returns `Ok(None)` if encryption is not configured.
29+
///
30+
/// The returned [`TimelineEvent`] has no push actions set up. It's the
31+
/// responsibility of the caller to set them.
2932
pub async fn sync_timeline_event(
3033
e2ee: E2EE<'_>,
31-
event: &Raw<AnySyncTimelineEvent>,
34+
event: &TimelineEvent,
3235
room_id: &RoomId,
3336
) -> Result<Option<TimelineEvent>> {
3437
let Some(olm) = e2ee.olm_machine else { return Ok(None) };
3538

3639
Ok(Some(
3740
match olm
38-
.try_decrypt_room_event(event.cast_ref_unchecked(), room_id, e2ee.decryption_settings)
41+
.try_decrypt_room_event(
42+
event.raw().cast_ref_unchecked(),
43+
room_id,
44+
e2ee.decryption_settings,
45+
)
3946
.await?
4047
{
4148
RoomEventDecryptionResult::Decrypted(decrypted) => {
4249
// Note: the push actions are set by the caller.
43-
let timeline_event = TimelineEvent::from_decrypted(decrypted, None);
50+
let timeline_event = event.to_decrypted(decrypted, None);
4451

4552
if let Ok(sync_timeline_event) = timeline_event.raw().deserialize() {
4653
verification::process_if_relevant(&sync_timeline_event, e2ee, room_id).await?;
4754
}
4855

4956
timeline_event
5057
}
51-
RoomEventDecryptionResult::UnableToDecrypt(utd_info) => {
52-
TimelineEvent::from_utd(event.clone(), utd_info)
53-
}
58+
RoomEventDecryptionResult::UnableToDecrypt(utd_info) => event.to_utd(utd_info),
5459
},
5560
))
5661
}

crates/matrix-sdk-base/src/response_processors/latest_event.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ async fn decrypt_sync_room_event(
116116
{
117117
RoomEventDecryptionResult::Decrypted(decrypted) => {
118118
// We're fine not setting the push actions for the latest event.
119+
120+
// TODO: we should use `TimelineEvent::to_decrypted`
121+
// but this whole code is about to get soon removed by
122+
// https://github.com/matrix-org/matrix-rust-sdk/pull/5624.
119123
let event = TimelineEvent::from_decrypted(decrypted, None);
120124

121125
if let Ok(sync_timeline_event) = event.raw().deserialize() {
@@ -127,6 +131,9 @@ async fn decrypt_sync_room_event(
127131
}
128132

129133
RoomEventDecryptionResult::UnableToDecrypt(utd_info) => {
134+
// TODO: we should use `TimelineEvent::to_utd`
135+
// but this whole code is about to get soon removed by
136+
// https://github.com/matrix-org/matrix-rust-sdk/pull/5624.
130137
TimelineEvent::from_utd(event.clone(), utd_info)
131138
}
132139
};

crates/matrix-sdk-base/src/response_processors/timeline.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use matrix_sdk_common::{deserialized_responses::TimelineEvent, timer};
1616
#[cfg(feature = "e2e-encryption")]
1717
use ruma::events::SyncMessageLikeEvent;
1818
use ruma::{
19-
UInt, UserId, assign,
19+
MilliSecondsSinceUnixEpoch, UInt, UserId, assign,
2020
events::{AnySyncMessageLikeEvent, AnySyncTimelineEvent},
2121
push::{Action, PushConditionRoomCtx},
2222
};
@@ -31,6 +31,7 @@ use crate::{Result, Room, RoomInfo, sync::Timeline};
3131
///
3232
/// For each event:
3333
/// - will try to decrypt it,
34+
/// - will fix the `origin_server_ts` if considered invalid,
3435
/// - will process verification,
3536
/// - will process redaction,
3637
/// - will process notification.
@@ -46,14 +47,15 @@ pub async fn build<'notification, 'e2ee>(
4647
) -> Result<Timeline> {
4748
let _timer = timer!(tracing::Level::TRACE, "build a timeline from sync");
4849

50+
let now = MilliSecondsSinceUnixEpoch::now();
4951
let mut timeline = Timeline::new(timeline_inputs.limited, timeline_inputs.prev_batch);
5052
let mut push_condition_room_ctx = get_push_room_context(context, room, room_info).await?;
5153
let room_id = room.room_id();
5254

5355
for raw_event in timeline_inputs.raw_events {
5456
// Start by assuming we have a plaintext event. We'll replace it with a
5557
// decrypted or UTD event below if necessary.
56-
let mut timeline_event = TimelineEvent::from_plaintext(raw_event);
58+
let mut timeline_event = TimelineEvent::from_plaintext_with_max_timestamp(raw_event, now);
5759

5860
// Do some special stuff on the `timeline_event` before collecting it.
5961
match timeline_event.raw().deserialize() {
@@ -94,7 +96,7 @@ pub async fn build<'notification, 'e2ee>(
9496
if let Some(decrypted_timeline_event) =
9597
Box::pin(e2ee::decrypt::sync_timeline_event(
9698
e2ee.clone(),
97-
timeline_event.raw(),
99+
&timeline_event,
98100
room_id,
99101
))
100102
.await?

crates/matrix-sdk-base/src/room/room_info.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,8 @@ mod tests {
13691369
"latest_event": {
13701370
"event": {
13711371
"kind": {"PlainText": {"event": {"sender": "@u:i.uk"}}},
1372-
"thread_summary": "None"
1372+
"thread_summary": "None",
1373+
"timestamp": null,
13731374
},
13741375
},
13751376
"new_latest_event": "None",

0 commit comments

Comments
 (0)