Bug — gelöschte Liste bei direktem URL-Aufruf zeigt Login-Bildschirm statt Weiterleitung #151
Labels
No labels
priority/could
priority/must
priority/should
priority/wont
status/blocked
status/claimed
status/done-migrated
type/bug
type/feature
type/infra
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/todo#151
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Story: Bug — gelöschte Liste bei direktem URL-Aufruf zeigt Login-Bildschirm statt Weiterleitung
As a Nutzer, der eine Liste per direktem Link/URL geöffnet hat,
I want to bei einer inzwischen gelöschten Liste automatisch auf eine andere verfügbare Liste
oder die Gesamtübersicht weitergeleitet zu werden,
so that ich nicht fälschlich den Eindruck bekomme, ausgeloggt zu sein.
Background
Gemeldet vom Nutzer: Ist man z. B. unter
https://todo.moekies.de/list/6und diese Liste wirdgelöscht (z. B. von einem anderen Gerät, oder weil man selbst löscht während man auf ihr ist),
springt die App nicht automatisch auf eine andere Liste/die Gesamtübersicht. Stattdessen erscheint
der Login-Bildschirm, weil die Liste unter der URL nicht mehr existiert — obwohl man weiterhin
eingeloggt ist. Die URL
/list/6bleibt dabei unverändert im Browser stehen.Acceptance criteria:
Zugriff mehr hat, wird zur Gesamtübersicht bzw. zur nächsten verfügbaren Liste weitergeleitet
— nicht zum Login-Bildschirm, solange eine gültige Session besteht.
vorhanden ist.
per direkter URL bereits gelöscht) → Nutzer landet auf der Übersicht, bleibt eingeloggt.
Out of scope for this story:
existiert nicht mehr").
Claiming this - self-contained bug fix, no open questions blocking it. Plan: trace the routing logic that resolves
/list/:id(likelyApplication.tsx/the list-selection effect) to find where a 404/403 on the selected list currently falls through to the login screen instead of redirecting to another list or the overview. Fix should distinguish "no valid session" (real login-required case) from "session valid but this list is gone" (redirect case).Closing - fixed across two commits from two sessions that ended up working this issue concurrently (same Gitea identity, discovered only when pushing):
b6a6d55807- root cause and the main fix. EveryAuthorize*QueryHandler.cs(15 files) threwUnauthorizedAccessException(-> 403) for both "not logged in" and "logged in but no access to this resource", socallApicouldn't distinguish them and force-logged-out on any 403. Fixed by using the already-existingAuthenticationException(-> 401) for the "not logged in" branch specifically; resource-specific branches stay 403 (unchanged IDOR-safe behavior). Added a shareduseRedirectIfListNotFoundhook (wired into TodoList/ShoppingListPage/PantryPage/MasterPackingListPage/PriorityMatrixPage) that redirects to the overview once a URL's list id is confirmed absent from the store, gated on newxListsLoadedflags so it never fires before the initial fetch has settled.7e582a9- a follow-up from the second session's own code review: the shared hook redirected the instant an id looked missing, which racedMasterPackingListCheckoutDialog.tsx's post-checkout navigate andAcceptInvitePage.tsx's post-accept navigate - both jump straight to a just-created/just-joined id before its WebSocket broadcast lands, so a user with that list-type already loaded this session got bounced back to the overview right after checking out a packing list or accepting an invite. Fixed with a 2.5s grace period on top of the loaded gate, cancelled the instant the entity resolves.Tests: 1128 frontend tests (124 files) green, including new regression coverage for both the original bug and the creation/invite-accept race. Backend:
dotnet buildclean (0 errors); the 9 updatedAuthorize*QueryHandlerTests.csfiles need Testcontainers/Docker, unavailable in this sandbox, so verified by close reading instead - flagging that as the one thing worth a human's eye if Docker is available in real CI.A related but out-of-scope hardening item (making the frontend's error handling immune to any future list-scoped call that skips the redirect guard, by design rather than by convention) was drafted as #154 and then closed again once
b6a6d55turned out to already cover its acceptance criteria.Completed and merged to master (commit
b6a6d55). Summary:Root cause: every Authorize*QueryHandler.cs in Checkly/Features/Authorization/ (15 files) threw UnauthorizedAccessException (-> 403) for both "not authenticated at all" and "authenticated but no access to this specific resource" - a deliberate IDOR-safe collapse for the resource case, but it meant the frontend could not tell a genuinely dead session apart from a stale/deleted list, and treated every 403 as a forced logout.
Fix: swapped the "not logged in" branch in all 15 handler files to AuthenticationException (-> 401 via ExceptionHandler.cs), which already existed and was already used correctly elsewhere (LoginUserCommandHandler.cs) but was never wired up here. The resource-specific "not authorized" branches are unchanged - still UnauthorizedAccessException/403, same IDOR-safe behavior as before. callApi (ReactUi/src/api/api.tsx) now does a plain 401 check instead of a special-cased 403 recheck.
Added useRedirectIfListNotFound (new hook), wired into TodoList/ShoppingListPage/PantryPage/MasterPackingListPage/PriorityMatrixPage, which redirects to the overview once a list id from the URL is confirmed absent from the store - gated on a new per-list-type
xListsLoadedflag in store.ts rather than a guessed timeout.An earlier version of this fix added a session recheck inside callApi's own 403 handler instead of fixing the backend; a full 8-angle /code-review (5 of 8 angles independently) found that approach was compensating one layer too high (self-referential recursion risk, thundering-herd redundant rechecks, a silent-stuck-state on a transient recheck failure) - reverted in favor of the backend fix, recorded in ai/roles/memory/04_frontend_engineer_memory.md.
Tests: 9 of the 15 handlers' existing Authorization test files updated to assert AuthenticationException for the not-logged-in case. Docker unavailable in this sandbox so Checkly.Tests (Testcontainers) could not run locally - verified for real in CI instead, now green. Common.Tests (119/119) and Checkly.WebApi.Tests (50/50) green locally. Full frontend suite (npm run build + npm run coverage, 1125 tests, 124 files) green. Full CI (backend build, all 3 backend test suites, frontend, all 4 E2E legs, Docker image build) green on
b6a6d55.