@@ -205,6 +205,9 @@ pub enum RouteError {
205
205
#[ error( "invalid login token" ) ]
206
206
InvalidLoginToken ,
207
207
208
+ #[ error( "user is locked" ) ]
209
+ UserLocked ,
210
+
208
211
#[ error( "failed to provision device" ) ]
209
212
ProvisionDeviceFailed ( #[ source] anyhow:: Error ) ,
210
213
}
@@ -263,6 +266,11 @@ impl IntoResponse for RouteError {
263
266
error : "Invalid login token" ,
264
267
status : StatusCode :: FORBIDDEN ,
265
268
} ,
269
+ Self :: UserLocked => MatrixError {
270
+ errcode : "M_USER_LOCKED" ,
271
+ error : "User account has been locked" ,
272
+ status : StatusCode :: UNAUTHORIZED ,
273
+ } ,
266
274
} ;
267
275
268
276
( sentry_event_id, response) . into_response ( )
@@ -506,7 +514,13 @@ async fn token_login(
506
514
browser_session. id = %browser_session_id,
507
515
"Attempt to exchange login token but browser session is not active"
508
516
) ;
509
- return Err ( RouteError :: InvalidLoginToken ) ;
517
+ return Err (
518
+ if browser_session. finished_at . is_none ( ) && browser_session. user . locked_at . is_some ( ) {
519
+ RouteError :: UserLocked
520
+ } else {
521
+ RouteError :: InvalidLoginToken
522
+ } ,
523
+ ) ;
510
524
}
511
525
512
526
// We're about to create a device, let's explicitly acquire a lock, so that
@@ -565,9 +579,13 @@ async fn user_password_login(
565
579
. user ( )
566
580
. find_by_username ( username)
567
581
. await ?
568
- . filter ( mas_data_model :: User :: is_valid )
582
+ . filter ( |user| user . deactivated_at . is_none ( ) )
569
583
. ok_or ( RouteError :: UserNotFound ) ?;
570
584
585
+ if user. locked_at . is_some ( ) {
586
+ return Err ( RouteError :: UserLocked ) ;
587
+ }
588
+
571
589
// Check the rate limit
572
590
limiter. check_password ( requester, & user) ?;
573
591
0 commit comments