13
13
# limitations under the License.
14
14
from http import HTTPStatus
15
15
16
+ from twisted .internet .defer import ensureDeferred
16
17
from twisted .test .proto_helpers import MemoryReactor
17
18
18
19
from synapse .api .errors import NotFoundError
19
20
from synapse .rest import admin , devices , room , sync
20
- from synapse .rest .client import account , login , register
21
+ from synapse .rest .client import account , keys , login , register
21
22
from synapse .server import HomeServer
23
+ from synapse .types import JsonDict , create_requester
22
24
from synapse .util import Clock
23
25
24
26
from tests import unittest
@@ -208,8 +210,13 @@ class DehydratedDeviceTestCase(unittest.HomeserverTestCase):
208
210
login .register_servlets ,
209
211
register .register_servlets ,
210
212
devices .register_servlets ,
213
+ keys .register_servlets ,
211
214
]
212
215
216
+ def prepare (self , reactor : MemoryReactor , clock : Clock , hs : HomeServer ) -> None :
217
+ self .registration = hs .get_registration_handler ()
218
+ self .message_handler = hs .get_device_message_handler ()
219
+
213
220
def test_PUT (self ) -> None :
214
221
"""Sanity-check that we can PUT a dehydrated device.
215
222
@@ -234,3 +241,128 @@ def test_PUT(self) -> None:
234
241
self .assertEqual (channel .code , HTTPStatus .OK , channel .json_body )
235
242
device_id = channel .json_body .get ("device_id" )
236
243
self .assertIsInstance (device_id , str )
244
+
245
+ @unittest .override_config (
246
+ {"experimental_features" : {"msc2697_enabled" : False , "msc3814_enabled" : True }}
247
+ )
248
+ def test_dehydrate_msc3814 (self ) -> None :
249
+ user = self .register_user ("mikey" , "pass" )
250
+ token = self .login (user , "pass" , device_id = "device1" )
251
+ content : JsonDict = {
252
+ "device_data" : {
253
+ "algorithm" : "m.dehydration.v1.olm" ,
254
+ },
255
+ "initial_device_display_name" : "foo bar" ,
256
+ }
257
+ channel = self .make_request (
258
+ "PUT" ,
259
+ "_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device" ,
260
+ content = content ,
261
+ access_token = token ,
262
+ shorthand = False ,
263
+ )
264
+ self .assertEqual (channel .code , 200 )
265
+ device_id = channel .json_body .get ("device_id" )
266
+ assert device_id is not None
267
+ self .assertIsInstance (device_id , str )
268
+
269
+ # test that you can upload keys for this device
270
+ content = {
271
+ "device_keys" : {
272
+ "algorithms" : ["m.olm.v1.curve25519-aes-sha2" , "m.megolm.v1.aes-sha2" ],
273
+ "device_id" : f"{ device_id } " ,
274
+ "keys" : {
275
+ "curve25519:JLAFKJWSCS" : "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI" ,
276
+ "ed25519:JLAFKJWSCS" : "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" ,
277
+ },
278
+ "signatures" : {
279
+ "@alice:example.com" : {
280
+ "ed25519:JLAFKJWSCS" : "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
281
+ }
282
+ },
283
+ "user_id" : f"{ user } " ,
284
+ },
285
+ }
286
+ channel = self .make_request (
287
+ "POST" ,
288
+ f"/_matrix/client/r0/keys/upload/{ device_id } " ,
289
+ content = content ,
290
+ access_token = token ,
291
+ )
292
+ self .assertEqual (channel .code , 200 )
293
+
294
+ # test that we can now GET the dehydrated device info
295
+ channel = self .make_request (
296
+ "GET" ,
297
+ "_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device" ,
298
+ access_token = token ,
299
+ shorthand = False ,
300
+ )
301
+ self .assertEqual (channel .code , 200 )
302
+ returned_device_id = channel .json_body .get ("device_id" )
303
+ self .assertEqual (returned_device_id , device_id )
304
+ device_data = channel .json_body .get ("device_data" )
305
+ expected_device_data = {
306
+ "algorithm" : "m.dehydration.v1.olm" ,
307
+ }
308
+ self .assertEqual (device_data , expected_device_data )
309
+
310
+ # create another device for the user
311
+ (
312
+ new_device_id ,
313
+ _ ,
314
+ _ ,
315
+ _ ,
316
+ ) = self .get_success (
317
+ self .registration .register_device (
318
+ user_id = user ,
319
+ device_id = None ,
320
+ initial_display_name = "new device" ,
321
+ )
322
+ )
323
+ requester = create_requester (user , device_id = new_device_id )
324
+
325
+ # Send a message to the dehydrated device
326
+ ensureDeferred (
327
+ self .message_handler .send_device_message (
328
+ requester = requester ,
329
+ message_type = "test.message" ,
330
+ messages = {user : {device_id : {"body" : "test_message" }}},
331
+ )
332
+ )
333
+ self .pump ()
334
+
335
+ # make sure we can fetch the message with our dehydrated device id
336
+ channel = self .make_request (
337
+ "POST" ,
338
+ f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{ device_id } /events" ,
339
+ content = {},
340
+ access_token = token ,
341
+ shorthand = False ,
342
+ )
343
+ self .assertEqual (channel .code , 200 )
344
+ expected_content = {"body" : "test_message" }
345
+ self .assertEqual (channel .json_body ["events" ][0 ]["content" ], expected_content )
346
+ next_batch_token = channel .json_body .get ("next_batch" )
347
+
348
+ # fetch messages again and make sure that the message was deleted and we are returned an
349
+ # empty array
350
+ content = {"next_batch" : next_batch_token }
351
+ channel = self .make_request (
352
+ "POST" ,
353
+ f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{ device_id } /events" ,
354
+ content = content ,
355
+ access_token = token ,
356
+ shorthand = False ,
357
+ )
358
+ self .assertEqual (channel .code , 200 )
359
+ self .assertEqual (channel .json_body ["events" ], [])
360
+
361
+ # make sure that the dehydrated device id is deleted after we received the messages
362
+ channel = self .make_request (
363
+ "GET" ,
364
+ "_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device" ,
365
+ access_token = token ,
366
+ shorthand = False ,
367
+ )
368
+ self .assertEqual (channel .code , 404 )
0 commit comments