From 168c55990f2c477e7beccb02bb44a283d1cca25a Mon Sep 17 00:00:00 2001 From: gitlawr Date: Sat, 9 May 2026 17:15:01 +0800 Subject: [PATCH] fix: pick landing route by access predicate to avoid redirect loop Access extensions can narrow ``canSeeAdmin`` to ``false`` even when ``currentUser.is_admin`` is ``true``. The default-landing logic keyed off ``is_admin`` and pushed admin to ``/dashboard``; when ``canSeeAdmin`` is narrowed there, ``Exception`` 403-redirects to ``/``, which re-pushes ``/dashboard``, looping into a blank screen. Switch the landing pick (and the masthead-click handler) to consult the resolved ``access.canSeeAdmin`` predicate instead. Behavior is unchanged for the default access module, where ``canSeeAdmin`` mirrors ``is_admin``. --- src/layouts/index.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx index 5df4a51d..2f7b699e 100644 --- a/src/layouts/index.tsx +++ b/src/layouts/index.tsx @@ -32,6 +32,7 @@ import { matchRoutes, request, setLocale, + useAccess, useAppData, useIntl, useLocation, @@ -156,6 +157,7 @@ export default (props: any) => { }; const { initialState, loading, setInitialState } = initialInfo; + const access = useAccess(); const userConfig = { title: '', @@ -290,7 +292,14 @@ export default (props: any) => { if (!initialState?.currentUser && location.pathname !== loginPath) { history.push(loginPath); } else if (location.pathname === '/') { - const pathname = initialState?.currentUser?.is_admin + // Pick a landing route the caller can actually see. Access + // extensions can narrow ``canSeeAdmin`` to ``false`` even when + // ``currentUser.is_admin`` is ``true``; pushing an admin to + // ``/dashboard`` (gated by ``canSeeAdmin``) in that case + // dead-ends in ``Exception`` 403 → redirect-to-``/`` → + // re-push, looping into a blank screen. Honoring the resolved + // predicate keeps the user on a route they can render. + const pathname = access?.canSeeAdmin ? DEFAULT_ENTER_PAGE.adminForNormal : DEFAULT_ENTER_PAGE.user; history.push(pathname); @@ -300,7 +309,7 @@ export default (props: any) => { const onMenuHeaderClick = (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); - const pagepath = initialState?.currentUser?.is_admin + const pagepath = access?.canSeeAdmin ? DEFAULT_ENTER_PAGE.adminForNormal : DEFAULT_ENTER_PAGE.user;