@@ -9,7 +9,7 @@ use assert_matches2::assert_let;
9
9
use assign:: assign;
10
10
use matrix_sdk:: {
11
11
assert_next_eq_with_timeout,
12
- crypto:: { format_emojis, SasState } ,
12
+ crypto:: { format_emojis, SasState , UserDevices } ,
13
13
encryption:: {
14
14
backups:: BackupState ,
15
15
recovery:: { Recovery , RecoveryState } ,
@@ -19,17 +19,21 @@ use matrix_sdk::{
19
19
BackupDownloadStrategy , EncryptionSettings , LocalTrust ,
20
20
} ,
21
21
ruma:: {
22
- api:: client:: room:: create_room:: v3:: Request as CreateRoomRequest ,
22
+ api:: client:: {
23
+ message:: send_message_event,
24
+ room:: create_room:: v3:: { Request as CreateRoomRequest , RoomPreset } ,
25
+ } ,
23
26
events:: {
24
27
key:: verification:: { request:: ToDeviceKeyVerificationRequestEvent , VerificationMethod } ,
25
28
room:: message:: {
26
29
MessageType , OriginalSyncRoomMessageEvent , RoomMessageEventContent ,
27
30
SyncRoomMessageEvent ,
28
31
} ,
29
32
secret_storage:: secret:: SecretEventContent ,
30
- GlobalAccountDataEventType , OriginalSyncMessageLikeEvent ,
33
+ GlobalAccountDataEventType , MessageLikeEventType , OriginalSyncMessageLikeEvent ,
31
34
} ,
32
- OwnedEventId ,
35
+ serde:: Raw ,
36
+ OwnedEventId , TransactionId , UserId ,
33
37
} ,
34
38
timeout:: timeout,
35
39
Client ,
@@ -39,7 +43,7 @@ use matrix_sdk_ui::{
39
43
sync_service:: SyncService ,
40
44
} ;
41
45
use similar_asserts:: assert_eq;
42
- use tracing:: { debug, warn} ;
46
+ use tracing:: { debug, info , warn} ;
43
47
44
48
use crate :: helpers:: { SyncTokenAwareClient , TestClientBuilder } ;
45
49
@@ -1175,3 +1179,110 @@ async fn test_recovery_disabling_deletes_secret_storage_secrets() -> Result<()>
1175
1179
1176
1180
Ok ( ( ) )
1177
1181
}
1182
+
1183
+ /// When we invite another user to a room with "joined" history visibility, we
1184
+ /// share the encryption history.
1185
+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
1186
+ async fn test_history_share_on_invite ( ) -> Result < ( ) > {
1187
+ let encryption_settings =
1188
+ EncryptionSettings { auto_enable_cross_signing : true , ..Default :: default ( ) } ;
1189
+
1190
+ let alice = TestClientBuilder :: new ( "alice" )
1191
+ . use_sqlite ( )
1192
+ . encryption_settings ( encryption_settings)
1193
+ . build ( )
1194
+ . await ?;
1195
+
1196
+ let alice_sync_service = Arc :: new (
1197
+ SyncService :: builder ( alice. clone ( ) )
1198
+ . build ( )
1199
+ . await
1200
+ . expect ( "Could not build alice sync service" ) ,
1201
+ ) ;
1202
+
1203
+ alice. encryption ( ) . wait_for_e2ee_initialization_tasks ( ) . await ;
1204
+ alice_sync_service. start ( ) . await ;
1205
+
1206
+ let bob = SyncTokenAwareClient :: new (
1207
+ TestClientBuilder :: new ( "bob" ) . encryption_settings ( encryption_settings) . build ( ) . await ?,
1208
+ ) ;
1209
+
1210
+ {
1211
+ // Alice and Bob share an encrypted room
1212
+ // TODO: get rid of all of this: history sharing should work even if Bob and
1213
+ // Alice do not share a room
1214
+ let alice_shared_room = alice
1215
+ . create_room ( assign ! ( CreateRoomRequest :: new( ) , { preset: Some ( RoomPreset :: PublicChat ) } ) )
1216
+ . await ?;
1217
+ let shared_room_id = alice_shared_room. room_id ( ) ;
1218
+ alice_shared_room. enable_encryption ( ) . await ?;
1219
+ bob. join_room_by_id ( shared_room_id) . await . expect ( "Bob should have joined the room" ) ;
1220
+
1221
+ // Bob sends a message to trigger another sync from Alice, which causes her to
1222
+ // send out the outgoing requests
1223
+ //
1224
+ // FIXME: this appears to be needed due to a bug in the sliding sync client,
1225
+ // which means it does not send out outgoing requests caused by a
1226
+ // /sync response
1227
+ let request = send_message_event:: v3:: Request :: new_raw (
1228
+ shared_room_id. to_owned ( ) ,
1229
+ TransactionId :: new ( ) ,
1230
+ MessageLikeEventType :: Message ,
1231
+ Raw :: new ( & RoomMessageEventContent :: text_plain ( "" ) ) . unwrap ( ) . cast ( ) ,
1232
+ ) ;
1233
+ bob. send ( request) . await ?;
1234
+
1235
+ // Sanity check: Both users see the others' device
1236
+ async fn devices_seen ( client : & Client , other : & UserId ) -> UserDevices {
1237
+ client
1238
+ . olm_machine_for_testing ( )
1239
+ . await
1240
+ . as_ref ( )
1241
+ . unwrap ( )
1242
+ . get_user_devices ( other, Some ( Duration :: from_secs ( 1 ) ) )
1243
+ . await
1244
+ . unwrap ( )
1245
+ }
1246
+
1247
+ let bob_devices = devices_seen ( & alice, bob. user_id ( ) . unwrap ( ) ) . await ;
1248
+ assert_eq ! ( bob_devices. devices( ) . count( ) , 1 , "Alice did not see bob's device" ) ;
1249
+
1250
+ bob. sync_once ( ) . await ?;
1251
+ let alice_devices = devices_seen ( & bob, alice. user_id ( ) . unwrap ( ) ) . await ;
1252
+ assert_eq ! ( alice_devices. devices( ) . count( ) , 1 , "Bob did not see Alice's device" ) ;
1253
+ }
1254
+
1255
+ // Alice creates a room ...
1256
+ let alice_room = alice
1257
+ . create_room ( assign ! ( CreateRoomRequest :: new( ) , {
1258
+ preset: Some ( RoomPreset :: PublicChat ) ,
1259
+ } ) )
1260
+ . await ?;
1261
+ alice_room. enable_encryption ( ) . await ?;
1262
+
1263
+ info ! ( room_id = ?alice_room. room_id( ) , "Alice has created and enabled encryption in the room" ) ;
1264
+
1265
+ // ... and sends a message
1266
+ alice_room
1267
+ . send ( RoomMessageEventContent :: text_plain ( "Hello Bob" ) )
1268
+ . await
1269
+ . expect ( "We should be able to send a message to the room" ) ;
1270
+
1271
+ // Alice invites Bob to the room
1272
+ // TODO: invite Bob rather than just call `share_history`
1273
+ alice_room. share_history ( bob. user_id ( ) . unwrap ( ) ) . await ?;
1274
+
1275
+ let bob_response = bob. sync_once ( ) . await ?;
1276
+
1277
+ // Bob should have received a to-device event with the payload
1278
+ assert_eq ! ( bob_response. to_device. len( ) , 1 ) ;
1279
+ let to_device_event = & bob_response. to_device [ 0 ] ;
1280
+ assert_eq ! (
1281
+ to_device_event. get_field:: <String >( "type" ) . unwrap( ) . unwrap( ) ,
1282
+ "io.element.msc4268.room_key_bundle"
1283
+ ) ;
1284
+
1285
+ // TODO: ensure Bob can decrypt the content
1286
+
1287
+ Ok ( ( ) )
1288
+ }
0 commit comments