@@ -103,6 +103,14 @@ pub struct RequestBody {
103
103
104
104
#[ serde( default ) ]
105
105
refresh_token : bool ,
106
+
107
+ /// ID of the client device.
108
+ /// If this does not correspond to a known client device, a new device will
109
+ /// be created. The given device ID must not be the same as a
110
+ /// cross-signing key ID. The server will auto-generate a device_id if
111
+ /// this is not specified.
112
+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
113
+ device_id : Option < String > ,
106
114
}
107
115
108
116
#[ derive( Debug , Serialize , Deserialize ) ]
@@ -310,6 +318,7 @@ pub(crate) async fn post(
310
318
& homeserver,
311
319
user,
312
320
password,
321
+ input. device_id , // TODO check for validity
313
322
)
314
323
. await ?
315
324
}
@@ -446,6 +455,7 @@ async fn user_password_login(
446
455
homeserver : & dyn HomeserverConnection ,
447
456
username : String ,
448
457
password : String ,
458
+ requested_device_id : Option < String > ,
449
459
) -> Result < ( CompatSession , User ) , RouteError > {
450
460
// Try getting the localpart out of the MXID
451
461
let username = homeserver. localpart ( & username) . unwrap_or ( & username) ;
@@ -498,9 +508,14 @@ async fn user_password_login(
498
508
// Lock the user sync to make sure we don't get into a race condition
499
509
repo. user ( ) . acquire_lock_for_sync ( & user) . await ?;
500
510
501
- // Now that the user credentials have been verified, start a new compat session
502
- let device = Device :: generate ( & mut rng) ;
503
511
let mxid = homeserver. mxid ( & user. username ) ;
512
+
513
+ // Now that the user credentials have been verified, start a new compat session
514
+ let device = if let Some ( requested_device_id) = requested_device_id {
515
+ Device :: from ( requested_device_id)
516
+ } else {
517
+ Device :: generate ( & mut rng)
518
+ } ;
504
519
homeserver
505
520
. create_device ( & mxid, device. as_str ( ) )
506
521
. await
0 commit comments