atagen

macltok

public
Star0
Watch0
8127bd8b03da656d01d946c7a8e80da81653ed3c
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: tests/mentions_decryption.rs

cbb715e11963atagen2026-10-24 23:24 UTC1
use std::time::Duration;
cbb715e11963atagen2026-10-24 23:24 UTC2
cbb715e11963atagen2026-10-24 23:24 UTC3
use futures_util::StreamExt;
cbb715e11963atagen2026-10-24 23:24 UTC4
use matrix_sdk::{
cbb715e11963atagen2026-10-24 23:24 UTC5
    deserialized_responses::TimelineEventKind, event_cache::RedecryptorReport,
cbb715e11963atagen2026-10-24 23:24 UTC6
    test_utils::mocks::MatrixMockServer,
cbb715e11963atagen2026-10-24 23:24 UTC7
};
cbb715e11963atagen2026-10-24 23:24 UTC8
use matrix_sdk_test::{JoinedRoomBuilder, event_factory::EventFactory};
cbb715e11963atagen2026-10-24 23:24 UTC9
use ruma::{RoomVersionId, device_id, event_id, room_id, user_id};
cbb715e11963atagen2026-10-24 23:24 UTC10
use serde_json::json;
cbb715e11963atagen2026-10-24 23:24 UTC11
cbb715e11963atagen2026-10-24 23:24 UTC12
#[tokio::test]
cbb715e11963atagen2026-10-24 23:24 UTC13
async fn late_key_exposes_a_mention_without_a_ui_timeline() {
cbb715e11963atagen2026-10-24 23:24 UTC14
    let server = MatrixMockServer::new().await;
cbb715e11963atagen2026-10-24 23:24 UTC15
    server.mock_crypto_endpoints_preset().await;
cbb715e11963atagen2026-10-24 23:24 UTC16
    let alice_id = user_id!("@alice:localhost");
cbb715e11963atagen2026-10-24 23:24 UTC17
    let bob_id = user_id!("@bob:localhost");
cbb715e11963atagen2026-10-24 23:24 UTC18
    let room_id = room_id!("!mentions-encrypted:localhost");
cbb715e11963atagen2026-10-24 23:24 UTC19
    let event_id = event_id!("$late-mention");
cbb715e11963atagen2026-10-24 23:24 UTC20
    let alice = server
cbb715e11963atagen2026-10-24 23:24 UTC21
        .client_builder_for_crypto_end_to_end(alice_id, device_id!("ALICEDEVICE"))
cbb715e11963atagen2026-10-24 23:24 UTC22
        .build()
cbb715e11963atagen2026-10-24 23:24 UTC23
        .await;
cbb715e11963atagen2026-10-24 23:24 UTC24
    let bob = server
cbb715e11963atagen2026-10-24 23:24 UTC25
        .client_builder_for_crypto_end_to_end(bob_id, device_id!("BOBDEVICE"))
cbb715e11963atagen2026-10-24 23:24 UTC26
        .build()
cbb715e11963atagen2026-10-24 23:24 UTC27
        .await;
cbb715e11963atagen2026-10-24 23:24 UTC28
    bob.event_cache().subscribe().unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC29
    server.exchange_e2ee_identities(&alice, &bob).await;
cbb715e11963atagen2026-10-24 23:24 UTC30
cbb715e11963atagen2026-10-24 23:24 UTC31
    let factory = EventFactory::new().room(room_id).sender(alice_id);
cbb715e11963atagen2026-10-24 23:24 UTC32
    let joined = JoinedRoomBuilder::new(room_id)
cbb715e11963atagen2026-10-24 23:24 UTC33
        .add_state_event(factory.create(alice_id, RoomVersionId::V1))
cbb715e11963atagen2026-10-24 23:24 UTC34
        .add_state_event(factory.room_encryption())
cbb715e11963atagen2026-10-24 23:24 UTC35
        .add_state_event(factory.member(alice_id))
cbb715e11963atagen2026-10-24 23:24 UTC36
        .add_state_event(factory.member(bob_id));
cbb715e11963atagen2026-10-24 23:24 UTC37
    server.sync_room(&alice, joined.clone()).await;
cbb715e11963atagen2026-10-24 23:24 UTC38
    server.sync_room(&bob, joined).await;
cbb715e11963atagen2026-10-24 23:24 UTC39
cbb715e11963atagen2026-10-24 23:24 UTC40
    let room = alice.get_room(room_id).unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC41
    let (encrypted_event, send) = server.mock_room_send().ok_with_capture(event_id, alice_id);
cbb715e11963atagen2026-10-24 23:24 UTC42
    let _send = send.mock_once().mount_as_scoped().await;
cbb715e11963atagen2026-10-24 23:24 UTC43
    let (_keys, room_key) = server.mock_capture_put_to_device(alice_id).await;
cbb715e11963atagen2026-10-24 23:24 UTC44
    server
cbb715e11963atagen2026-10-24 23:24 UTC45
        .mock_get_members()
cbb715e11963atagen2026-10-24 23:24 UTC46
        .ok(vec![
cbb715e11963atagen2026-10-24 23:24 UTC47
            factory.member(alice_id).into_raw(),
cbb715e11963atagen2026-10-24 23:24 UTC48
            factory.member(bob_id).into_raw(),
cbb715e11963atagen2026-10-24 23:24 UTC49
        ])
cbb715e11963atagen2026-10-24 23:24 UTC50
        .mock_once()
cbb715e11963atagen2026-10-24 23:24 UTC51
        .mount()
cbb715e11963atagen2026-10-24 23:24 UTC52
        .await;
cbb715e11963atagen2026-10-24 23:24 UTC53
    room.send_raw(
cbb715e11963atagen2026-10-24 23:24 UTC54
        "m.room.message",
cbb715e11963atagen2026-10-24 23:24 UTC55
        json!({
cbb715e11963atagen2026-10-24 23:24 UTC56
            "msgtype": "m.text",
cbb715e11963atagen2026-10-24 23:24 UTC57
            "body": "a private mention",
cbb715e11963atagen2026-10-24 23:24 UTC58
            "m.mentions": { "user_ids": [bob_id] }
cbb715e11963atagen2026-10-24 23:24 UTC59
        }),
cbb715e11963atagen2026-10-24 23:24 UTC60
    )
cbb715e11963atagen2026-10-24 23:24 UTC61
    .await
cbb715e11963atagen2026-10-24 23:24 UTC62
    .unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC63
    let encrypted_event = encrypted_event.await.unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC64
    let room_key = room_key.await;
cbb715e11963atagen2026-10-24 23:24 UTC65
cbb715e11963atagen2026-10-24 23:24 UTC66
    let mut sync_updates = bob.subscribe_to_all_room_updates();
cbb715e11963atagen2026-10-24 23:24 UTC67
    let mut cache_updates = bob.event_cache().subscribe_to_room_generic_updates();
cbb715e11963atagen2026-10-24 23:24 UTC68
    let mut reports = bob.event_cache().subscribe_to_decryption_reports();
cbb715e11963atagen2026-10-24 23:24 UTC69
    server
cbb715e11963atagen2026-10-24 23:24 UTC70
        .sync_room(
cbb715e11963atagen2026-10-24 23:24 UTC71
            &bob,
cbb715e11963atagen2026-10-24 23:24 UTC72
            JoinedRoomBuilder::new(room_id).add_timeline_event(encrypted_event),
cbb715e11963atagen2026-10-24 23:24 UTC73
        )
cbb715e11963atagen2026-10-24 23:24 UTC74
        .await;
cbb715e11963atagen2026-10-24 23:24 UTC75
    let update = sync_updates.recv().await.unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC76
    let event = &update.joined[room_id].timeline.events[0];
cbb715e11963atagen2026-10-24 23:24 UTC77
    assert!(matches!(
cbb715e11963atagen2026-10-24 23:24 UTC78
        event.kind,
cbb715e11963atagen2026-10-24 23:24 UTC79
        TimelineEventKind::UnableToDecrypt { .. }
cbb715e11963atagen2026-10-24 23:24 UTC80
    ));
cbb715e11963atagen2026-10-24 23:24 UTC81
    tokio::time::timeout(Duration::from_secs(5), async {
cbb715e11963atagen2026-10-24 23:24 UTC82
        while cache_updates.recv().await.unwrap().room_id != room_id {}
cbb715e11963atagen2026-10-24 23:24 UTC83
    })
cbb715e11963atagen2026-10-24 23:24 UTC84
    .await
cbb715e11963atagen2026-10-24 23:24 UTC85
    .unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC86
cbb715e11963atagen2026-10-24 23:24 UTC87
    server
cbb715e11963atagen2026-10-24 23:24 UTC88
        .mock_sync()
cbb715e11963atagen2026-10-24 23:24 UTC89
        .ok_and_run(&bob, |sync| {
cbb715e11963atagen2026-10-24 23:24 UTC90
            sync.add_to_device_event(room_key.deserialize_as().unwrap());
cbb715e11963atagen2026-10-24 23:24 UTC91
        })
cbb715e11963atagen2026-10-24 23:24 UTC92
        .await;
cbb715e11963atagen2026-10-24 23:24 UTC93
    tokio::time::timeout(Duration::from_secs(5), async {
cbb715e11963atagen2026-10-24 23:24 UTC94
        while let Some(report) = reports.next().await {
cbb715e11963atagen2026-10-24 23:24 UTC95
            if let Ok(RedecryptorReport::ResolvedUtds {
cbb715e11963atagen2026-10-24 23:24 UTC96
                room_id: resolved,
cbb715e11963atagen2026-10-24 23:24 UTC97
                events,
cbb715e11963atagen2026-10-24 23:24 UTC98
            }) = report
cbb715e11963atagen2026-10-24 23:24 UTC99
            {
cbb715e11963atagen2026-10-24 23:24 UTC100
                if resolved == room_id && events.contains(event_id) {
cbb715e11963atagen2026-10-24 23:24 UTC101
                    return;
cbb715e11963atagen2026-10-24 23:24 UTC102
                }
cbb715e11963atagen2026-10-24 23:24 UTC103
            }
cbb715e11963atagen2026-10-24 23:24 UTC104
        }
cbb715e11963atagen2026-10-24 23:24 UTC105
        panic!("decryption reports ended before the mention was decrypted");
cbb715e11963atagen2026-10-24 23:24 UTC106
    })
cbb715e11963atagen2026-10-24 23:24 UTC107
    .await
cbb715e11963atagen2026-10-24 23:24 UTC108
    .unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC109
cbb715e11963atagen2026-10-24 23:24 UTC110
    let room = bob.get_room(room_id).unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC111
    let (cache, _cache_handles) = room.event_cache().await.unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC112
    let decrypted = cache.find_event(event_id).await.unwrap().unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC113
    assert!(matches!(decrypted.kind, TimelineEventKind::Decrypted(_)));
cbb715e11963atagen2026-10-24 23:24 UTC114
    let content = decrypted
cbb715e11963atagen2026-10-24 23:24 UTC115
        .raw()
cbb715e11963atagen2026-10-24 23:24 UTC116
        .get_field::<serde_json::Value>("content")
cbb715e11963atagen2026-10-24 23:24 UTC117
        .unwrap()
cbb715e11963atagen2026-10-24 23:24 UTC118
        .unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC119
    assert_eq!(content["body"], "a private mention");
cbb715e11963atagen2026-10-24 23:24 UTC120
    assert_eq!(content["m.mentions"]["user_ids"], json!([bob_id]));
cbb715e11963atagen2026-10-24 23:24 UTC121
    let push_actions = room
cbb715e11963atagen2026-10-24 23:24 UTC122
        .event_push_actions(decrypted.raw())
cbb715e11963atagen2026-10-24 23:24 UTC123
        .await
cbb715e11963atagen2026-10-24 23:24 UTC124
        .unwrap()
cbb715e11963atagen2026-10-24 23:24 UTC125
        .unwrap();
cbb715e11963atagen2026-10-24 23:24 UTC126
    assert!(push_actions.iter().any(|action| action.should_notify()));
cbb715e11963atagen2026-10-24 23:24 UTC127
    assert_eq!(cache.events().await.unwrap().len(), 1);
cbb715e11963atagen2026-10-24 23:24 UTC128
}