@@ -120,6 +120,7 @@ import Wire.API.UserEvent
120120import Wire.ActivationCodeStore
121121import Wire.ActivationCodeStore qualified as ActivationCode
122122import Wire.AuthenticationSubsystem (AuthenticationSubsystem , internalLookupPasswordResetCode )
123+ import Wire.AuthenticationSubsystem qualified as Auth
123124import Wire.BackendNotificationQueueAccess
124125import Wire.BlockListStore as BlockListStore
125126import Wire.ClientStore (ClientStore )
@@ -626,45 +627,60 @@ changeAccountStatus ::
626627 ( Member (Concurrency 'Unsafe) r ,
627628 Member UserSubsystem r ,
628629 Member Events r ,
629- Member UserStore r
630+ Member UserStore r ,
631+ Member AuthenticationSubsystem r
630632 ) =>
631633 NonEmpty UserId ->
632634 AccountStatus ->
633635 ExceptT AccountStatusError (AppT r ) ()
634636changeAccountStatus usrs status = do
635- -- It is safe to not revoke any cookies here; if no valid access
636- -- token is available, cookies are only validated when calling `POST
637- -- /access`, and access token refresh only works on unsuspended
638- -- users.
639- --
640- -- Evidence: `git grep -Hn --color=never 'UserToken\b' | grep libs/wire-api/src/Wire/API/Routes/Public/`.
641637 ev <- mkUserEvent status
642- lift $ liftSem $ unsafePooledMapConcurrentlyN_ 16 (update ev) usrs
643- where
644- update ::
645- (UserId -> UserEvent ) ->
646- UserId ->
647- Sem r ()
648- update ev u = do
649- UserStore. updateAccountStatus u status
650- User. internalUpdateSearchIndex u
651- Events. generateUserEvent u Nothing (ev u)
638+ lift $ liftSem $ unsafePooledMapConcurrentlyN_ 16 (changeSingleAccountStatusInternal status ev) usrs
652639
653640changeSingleAccountStatus ::
654641 ( Member UserSubsystem r ,
655642 Member Events r ,
656- Member UserStore r
643+ Member UserStore r ,
644+ Member AuthenticationSubsystem r
657645 ) =>
658646 UserId ->
659647 AccountStatus ->
660648 ExceptT AccountStatusError (AppT r ) ()
661649changeSingleAccountStatus uid status = do
662650 unlessM (lift . liftSem $ UserStore. doesUserExist uid) $ throwE AccountNotFound
663651 ev <- mkUserEvent status
664- lift . liftSem $ do
665- UserStore. updateAccountStatus uid status
666- User. internalUpdateSearchIndex uid
667- Events. generateUserEvent uid Nothing (ev uid)
652+ lift . liftSem $ changeSingleAccountStatusInternal status ev uid
653+
654+ changeSingleAccountStatusInternal ::
655+ ( Member UserSubsystem r ,
656+ Member Events r ,
657+ Member UserStore r ,
658+ Member AuthenticationSubsystem r
659+ ) =>
660+ AccountStatus ->
661+ (UserId -> UserEvent ) ->
662+ UserId ->
663+ Sem r ()
664+ changeSingleAccountStatusInternal status ev u = do
665+ -- It is safe to *not* revoke any cookies here; if no valid access
666+ -- token is available, cookies are only validated when calling `POST
667+ -- /access`, and access token refresh only works on unsuspended
668+ -- users.
669+ --
670+ -- Evidence: `git grep -Hn --color=never 'UserToken\b' | grep libs/wire-api/src/Wire/API/Routes/Public/`.
671+ --
672+ -- Having that said, we need to remove all *expired* cookies here,
673+ -- otherwise /login considers the user inactive, see
674+ -- 'mustSuspendInactiveUser'.
675+ --
676+ -- The intuition is that every change of account status can be
677+ -- considered an account activity, so users that have their status
678+ -- changed recently should not be considered inactive, even if they
679+ -- haven't taken any action themselves.
680+ Auth. revokeAllExpiredCookies u
681+ UserStore. updateAccountStatus u status
682+ User. internalUpdateSearchIndex u
683+ Events. generateUserEvent u Nothing (ev u)
668684
669685mkUserEvent ::
670686 (Monad m ) =>
0 commit comments