sdk: Get push actions of retried decrypted events in the timeline

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2023-03-22 16:26:00 +01:00
committed by Jonas Platte
parent 98386cf527
commit 5eeea83c19
4 changed files with 140 additions and 5 deletions

View File

@@ -1027,7 +1027,7 @@ impl Common {
///
/// Returns `None` if some data couldn't be found. This should only happen
/// in brand new rooms, while we process its state.
async fn push_context(&self) -> Result<Option<PushConditionRoomCtx>> {
pub(crate) async fn push_context(&self) -> Result<Option<PushConditionRoomCtx>> {
let room_id = self.room_id();
let user_id = self.own_user_id();
let room_info = self.clone_info();

View File

@@ -36,7 +36,7 @@ use ruma::{
relation::Annotation,
AnyMessageLikeEventContent, AnySyncTimelineEvent,
},
push::Action,
push::{Action, PushConditionRoomCtx, Ruleset},
serde::Raw,
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
TransactionId, UserId,
@@ -359,6 +359,9 @@ impl<P: RoomDataProvider> TimelineInner<P> {
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<P: RoomDataProvider> TimelineInner<P> {
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<Profile>;
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap<OwnedUserId, Receipt>;
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.

View File

@@ -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());
}

View File

@@ -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<OwnedUserId, Receipt> {
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))
}
}