You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Clarin9/Redirect to login when an identifier resolves to a restricted object (#876) (#1429)
* Clarin9/Redirect to login when an identifier resolves to a restricted object (#876)
`lookupGuard` collapsed every failed lookup into a single boolean, so a 401/403
from `/server/api/pid/find` was indistinguishable from a genuine 404: an
anonymous user opening a restricted item by handle got "No item found for the
identifier ..." and had no way to authenticate.
Branch on `RemoteData.statusCode` and delegate the 401/403 case to the shared
`returnForbiddenUrlTreeOrLoginOnFalse` operator, which returns a UrlTree to the
login page for anonymous users (remembering `state.url` so they come back to the
identifier after logging in) and to the forbidden page for authenticated ones.
Any other failure - 404 included - still activates the route so
ObjectNotFoundComponent keeps rendering.
This makes `/handle/...` and `/id/...` behave like `/items/:id`, which already
gets this through `itemPageResolver` -> `redirectOn4xx`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Review feedback: keep the SSR response honest and harden the guard spec
- Set the 401/403 status on the server response before redirecting. Without it
SSR would serve the login page with HTTP 200 under the identifier's own URL,
and server.ts would store that in the bot cache for a day. No-op in the browser.
- Add take(1): returnForbiddenUrlTreeOrLoginOnFalse combines with
isAuthenticated(), a store selector that never completes, so the guard's
observable relied on the router's own first() to terminate.
- Reword the fallback comment - it is the catch-all for 404, 501, 5xx and
status-less failures, not 404 only (Copilot) - and drop the claim that the
authenticated branch behaves identically to /items/:id (a UrlTree rewrites the
address bar, redirectOn4xx uses skipLocationChange).
- Spec: use a non-completing isAuthenticated stub, assert the guard emits exactly
once and completes, cover a failure with no status code and 401-while-
authenticated, assert the server response status, and add a
TestBed.runInInjectionContext case so the injected defaults are exercised.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Make the injection-context spec fail if the guard stops emitting
It asserted inside a subscribe callback with no done(), so it would have passed
silently had the observable never emitted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Shorten the lookup guard comments
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Assert the SSR status for the two remaining restricted-lookup cases
401+authenticated and 403+anonymous went through the same setStatus call but
were not covered. Verified: all four assertions fail without it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Cover the whole non-401/403 fallback, 501 and 422 included
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments