fix: show account-not-found message on 404 logout (WT-956)#1367
Merged
Conversation
When Core returns 404 (UserNotFoundException) for the current account it is now distinguished from a generic session expiry: the user gets a dedicated "account not found" notification and is logged out with a userNotFound reason that skips the doomed remote session revoke. - SessionGuard callbacks receive the unauthorized exception so the wiring can branch on its type - add AppLogoutReason.userNotFound; excluded from remote revoke in cleanup - add AccountNotFoundNotification + l10n keys (en/it/uk)
There was a problem hiding this comment.
Pull request overview
This PR distinguishes the “account removed/deactivated” server response (404 UserNotFoundException) from generic unauthorized/session-expired cases by introducing a dedicated logout reason and user-facing notification, while avoiding redundant remote revocation attempts.
Changes:
- Add
AppLogoutReason.userNotFoundand skip remote revoke during cleanup for this terminal case. - Extend
RouterLogoutSessionGuardcallbacks to receive the triggering exception and branch UI/logout behavior accordingly. - Introduce
AccountNotFoundNotificationand a new localization key (notifications_errorSnackBar_accountNotFound) with regenerated l10n outputs.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/l10n/arb/app_en.arb | Adds new snackbar message key/value for “account not found” (EN). |
| lib/l10n/arb/app_it.arb | Adds new snackbar message key/value for “account not found” (IT). |
| lib/l10n/arb/app_uk.arb | Adds new snackbar message key/value for “account not found” (UK). |
| lib/l10n/app_localizations.g.dart | Regenerates base localization interface with the new key. |
| lib/l10n/app_localizations_en.g.dart | Regenerates EN localization implementation for the new key. |
| lib/l10n/app_localizations_it.g.dart | Regenerates IT localization implementation for the new key. |
| lib/l10n/app_localizations_uk.g.dart | Regenerates UK localization implementation for the new key. |
| lib/blocs/app/app_event.dart | Adds AppLogoutReason.userNotFound to represent deleted/deactivated accounts. |
| lib/blocs/app/app_bloc.dart | Skips remote revoke for userNotFound (local cleanup only). |
| lib/app/session/router_logout_session_guard.dart | Passes the unauthorized exception into pre-logout/logout callbacks. |
| lib/app/router/main_shell.dart | Branches logout reason + notification based on UserNotFoundException. |
| lib/app/notifications/models/notification.dart | Adds AccountNotFoundNotification mapping to the new l10n key. |
For an AppLogoutReason.userNotFound logout, render the account-not-found message below the "Signing out..." label on TeardownScreen so the reason is visible during the logout transition, not only in the snackbar.
When the signaling session drops and the cause is a self-care password change/expiry (403 password_change_required), log out with a dedicated reason and show the explanation on TeardownScreen instead of a transient snackbar. - resolve the signaling-session invalidation cause before logging out and carry it via SignalingSessionInvalidationReason (call layer stays free of app-level enums) - add AppLogoutReason.passwordChangeRequired (local cleanup only) - TeardownScreen renders the self-care password-expired message for it - drop the now-unused SelfCarePasswordExpiredNotification (snackbar)
- avoid a second, conflicting AppLogoutRequested when the signaling probe hits an auth error the session guard already owns (return null -> skip onSessionInvalidated); guard them all with try/catch - extract the session-guard callbacks to private methods (single-expression callbacks per AGENTS.md) - fix stale "onBeforeLogout" log message -> "onPreLogout" - reorder teardown_screen_test imports into the 6-group convention
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Make terminal session-invalidation cases distinct and explained to the user instead of a generic "session expired" with no cause. Two cases get dedicated handling: a deactivated/removed account (
404 UserNotFoundException) and a self-care password change/expiry (403 password_change_required).Ticket: [WT-956]. The fatal-crash and parallel-logout parts were already fixed earlier on
develop; this PR finishes the user-facing half.Changes
Account not found (404)
RouterLogoutSessionGuard:performLogout/onPreLogoutcallbacks now receive the unauthorizedException, so the wiring can branch on its type. The guard stays app-agnostic.AppLogoutReason.userNotFound: new terminal reason, excluded from remote revoke (the user record is already gone, a revoke would just 404 again).main_shell.dart: aUserNotFoundExceptionlogs out withuserNotFoundand showsAccountNotFoundNotification; every other unauthorized case keepsserverRejection+SessionExpiredNotification.AccountNotFoundNotification+ l10nnotifications_errorSnackBar_accountNotFound(en/it/uk).Password change required (403)
SignalingSessionInvalidationReason(the call layer stays free of app-level enums); no more transient snackbar for this case.AppLogoutReason.passwordChangeRequired: new reason (local cleanup only; the signaling session is already gone).SelfCarePasswordExpiredNotification.Teardown screen
TeardownScreenshows a reason-specific message below "Signing out...": the account-not-found text foruserNotFound, the self-care password-expired text forpasswordChangeRequired. ReadsAppState.logoutReason, which is still set while teardown renders.