TimelineInner {
use super::EncryptedMessage;
trace!("Retrying decryption");
+
+ let push_rules_context = self.room_data_provider.push_rules_and_context().await;
+
let should_retry = |session_id: &str| {
if let Some(session_ids) = &session_ids {
session_ids.contains(session_id)
@@ -422,10 +425,17 @@ impl TimelineInner {
continue;
};
+ let push_actions = push_rules_context
+ .as_ref()
+ .map(|(push_rules, push_context)| {
+ push_rules.get_actions(&event.event, push_context).to_owned()
+ })
+ .unwrap_or_default();
+
let result = handle_remote_event(
event.event.cast(),
event.encryption_info,
- event.push_actions,
+ push_actions,
TimelineItemPosition::Update(idx),
&mut state,
&self.room_data_provider,
@@ -710,6 +720,7 @@ pub(super) trait RoomDataProvider {
fn own_user_id(&self) -> &UserId;
async fn profile(&self, user_id: &UserId) -> Option;
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap;
+ async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)>;
}
#[async_trait]
@@ -747,6 +758,26 @@ impl RoomDataProvider for room::Common {
}
}
}
+
+ async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)> {
+ match self.push_context().await {
+ Ok(Some(push_context)) => match self.client().account().push_rules().await {
+ Ok(push_rules) => Some((push_rules, push_context)),
+ Err(e) => {
+ error!("Could not get push rules: {e}");
+ None
+ }
+ },
+ Ok(None) => {
+ debug!("Could not aggregate push context");
+ None
+ }
+ Err(e) => {
+ error!("Could not get push context: {e}");
+ None
+ }
+ }
+ }
}
/// Handle a remote event.
diff --git a/crates/matrix-sdk/src/room/timeline/tests/encryption.rs b/crates/matrix-sdk/src/room/timeline/tests/encryption.rs
index 3deba7770..de221f8b2 100644
--- a/crates/matrix-sdk/src/room/timeline/tests/encryption.rs
+++ b/crates/matrix-sdk/src/room/timeline/tests/encryption.rs
@@ -101,6 +101,7 @@ async fn retry_message_decryption() {
assert_matches!(event.encryption_info(), Some(_));
let text = assert_matches!(event.content(), TimelineItemContent::Message(msg) => msg.body());
assert_eq!(text, "It's a secret to everybody");
+ assert!(!event.is_highlighted());
}
#[async_test]
@@ -310,3 +311,87 @@ async fn retry_edit_and_more() {
"Another message"
);
}
+
+#[async_test]
+async fn retry_message_decryption_highlighted() {
+ const SESSION_ID: &str = "C25PoE+4MlNidQD0YU5ibZqHawV0zZ/up7R8vYJBYTY";
+ const SESSION_KEY: &[u8] = b"\
+ -----BEGIN MEGOLM SESSION DATA-----\n\
+ AUBvCG7VHqpYOpNJoIVxsTS1Qyu83w6xFDw67qDe1edSAAAACrnzwQzFMw//BB9iNKTviUfGPEKD9XlL9f8N\
+ svGCe971WnKLqWJjtrc42UfyDXH0fz4HXeCN1b104GlzWVFp0r+9RuQpPsP3IZ1DxWPm/xsotr3N4BY3pdgK\
+ wpbCq3oD9bQ0jcYqajrWfmEagSInobo9jd6CPyj6kz7mU/SXwva+aoYB8fVJptdYbIXQbvD8t9vS5SC6ZGlP\
+ CpcJBscXIq79HpWgDjnfvUNZiITlazFcgPB8zI78MwISm4FX/4KAwxjWf0eGNwKPiTP8fjXpxKurgnMQEET/\
+ nVb/r4yIO1Z8rM6vmzoTcQvUc5pXmAGhcLGWN6Q06D3hBuWw0etCKRW5bqcMRit5wmawvBV6j+QNKSPKy7xQ\
+ zQhzx9TFfgGZ7rRsl9EPxn0FB/EJNHOkbqYqOmKix9jbh820jRG9i4vD+x+U6iXGpRPyb2S8w+1f9n3uH3yI\
+ 0XWypoX/eEh7cJv9YChq4Wst4UkP2l6ztP8H/dWXfDYHddkMMKnveeb3sjWRjJep7Ih3W5PyMmxfge85DryB\
+ Sgvx6TKvtiC4zOKp1VStbXNgrpipWixhXP2F8BkDmJJvDYO1idWU2NbDJZY6AkKockUscnovpmV1yhovm83Y\
+ sAZRyV3W2MlFpA5qAgdXWlBA4WZ/jus/Mey0dqFZtvDS6fC1S4cx5p6hXBwADLRjIiqq2dpn49+aUwqPMn/b\
+ FM8H2PpVkKgrA+tx8LNQD+FWDfp6MyhmEJEvk9r5vU9LtTXtZl4toYvNY0UHUBbZj2xF9U9Z9A\n\
+ -----END MEGOLM SESSION DATA-----";
+
+ let timeline = TestTimeline::new();
+ let mut stream = timeline.subscribe().await;
+
+ timeline
+ .handle_live_message_event(
+ &BOB,
+ RoomEncryptedEventContent::new(
+ EncryptedEventScheme::MegolmV1AesSha2(
+ MegolmV1AesSha2ContentInit {
+ ciphertext: "\
+ AwgAEpABNOd7Rxpc/98gaaOanApQ/h40uNyYE/aiFd8PKeQPH65bwuxBy/glodmteryH\
+ 4t5d0cKSPjb+996yK90+A8YUevQKBuC+/+4iRF2CSqMNvArdOCnFHJdZBuCyRP6W82DZ\
+ sR1w5X/tKGs/A9egJdxomLCzMRZarayTXUlgMT8Kj7E9zKOgyLEZGki6Y9IPybfrU3+S\
+ b4VbF7RKY395/lIZFiLvJ5hUT+Ao1k13opeTE9GHtdOK0GzQPVFLnN61pRa3K/vV9Otk\
+ D0QbVS/4mE3C29+yIC1lEkwA"
+ .to_owned(),
+ sender_key: "peI8cfSKqZvTOAfY0Od2e7doDpJ1cxdBsOhSceTLU3E".to_owned(),
+ device_id: "KDCTEHOVSS".into(),
+ session_id: SESSION_ID.into(),
+ }
+ .into(),
+ ),
+ None,
+ ),
+ )
+ .await;
+
+ assert_eq!(timeline.inner.items().await.len(), 2);
+
+ let _day_divider =
+ assert_matches!(stream.next().await, Some(VectorDiff::PushBack { value }) => value);
+ let item = assert_matches!(stream.next().await, Some(VectorDiff::PushBack { value }) => value);
+ let event = item.as_event().unwrap();
+ let session_id = assert_matches!(
+ event.content(),
+ TimelineItemContent::UnableToDecrypt(
+ EncryptedMessage::MegolmV1AesSha2 { session_id, .. },
+ ) => session_id
+ );
+ assert_eq!(session_id, SESSION_ID);
+
+ let own_user_id = user_id!("@example:matrix.org");
+ let exported_keys = decrypt_room_key_export(Cursor::new(SESSION_KEY), "1234").unwrap();
+
+ let olm_machine = OlmMachine::new(own_user_id, "SomeDeviceId".into()).await;
+ olm_machine.import_room_keys(exported_keys, false, |_, _| {}).await.unwrap();
+
+ timeline
+ .inner
+ .retry_event_decryption(
+ room_id!("!rYtFvMGENJleNQVJzb:matrix.org"),
+ &olm_machine,
+ Some(iter::once(SESSION_ID).collect()),
+ )
+ .await;
+
+ assert_eq!(timeline.inner.items().await.len(), 2);
+
+ let item =
+ assert_matches!(stream.next().await, Some(VectorDiff::Set { index: 1, value }) => value);
+ let event = item.as_event().unwrap().as_remote().unwrap();
+ assert_matches!(event.encryption_info(), Some(_));
+ let text = assert_matches!(event.content(), TimelineItemContent::Message(msg) => msg.body());
+ assert_eq!(text, "A secret to everybody but Alice");
+ assert!(event.is_highlighted());
+}
diff --git a/crates/matrix-sdk/src/room/timeline/tests/mod.rs b/crates/matrix-sdk/src/room/timeline/tests/mod.rs
index 9105846af..3603a3e66 100644
--- a/crates/matrix-sdk/src/room/timeline/tests/mod.rs
+++ b/crates/matrix-sdk/src/room/timeline/tests/mod.rs
@@ -35,9 +35,13 @@ use ruma::{
RedactedMessageLikeEventContent, RedactedStateEventContent, StateEventContent,
StaticStateEventContent,
},
+ int,
+ power_levels::NotificationPowerLevels,
+ push::{PushConditionRoomCtx, Ruleset},
+ room_id,
serde::Raw,
- server_name, user_id, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId,
- OwnedUserId, TransactionId, UserId,
+ server_name, uint, user_id, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId,
+ OwnedTransactionId, OwnedUserId, TransactionId, UserId,
};
use serde_json::{json, Value as JsonValue};
@@ -305,4 +309,19 @@ impl RoomDataProvider for TestRoomDataProvider {
async fn read_receipts_for_event(&self, _event_id: &EventId) -> IndexMap {
IndexMap::new()
}
+
+ async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)> {
+ let push_rules = Ruleset::server_default(&ALICE);
+ let push_context = PushConditionRoomCtx {
+ room_id: room_id!("!my_room:server.name").to_owned(),
+ member_count: uint!(2),
+ user_id: ALICE.to_owned(),
+ user_display_name: "Alice".to_owned(),
+ users_power_levels: BTreeMap::new(),
+ default_power_level: int!(0),
+ notification_power_levels: NotificationPowerLevels::new(),
+ };
+
+ Some((push_rules, push_context))
+ }
}