mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-25 05:00:07 +00:00
fix(web): no broken Dashboard nav path for delegated-only MSP users [Phase 3b follow-up]
Addresses a Codex finding: Phase 3b made delegated-only MSP users non-regular (so they get the group nav), which also rendered the Dashboard link for them — but /dashboard classifies the same user as regular and bounced them to /progress. So clicking Dashboard sent an MSP admin to the end-user progress portal. Fixed on both ends: - GlobalSidebar: gate the Dashboard link on isAdminOrOperator || hasGlobalScope (genuine own-tenant/platform users), not merely !isRegularUser. A delegated-only admin has no own-tenant stake, so the link is hidden; their entry point is the Fleet group. - /dashboard: a delegated-only user who reaches it by deep link now redirects to /fleet instead of /progress, consistent with the AuthGate landing. Web tsc clean; 476 web tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,11 +144,12 @@ function HomeContent() {
|
||||
disabled: isRegularUser,
|
||||
});
|
||||
|
||||
// Redirect regular users (non-admin, non-operator, no platform scope) to the progress portal — they
|
||||
// must never see the session list. A read-only Global Reader has cross-tenant read scope → stays.
|
||||
// Redirect users without own-tenant/platform scope away from the session list. A delegated ("MSP") admin
|
||||
// manages OTHER tenants and belongs on the fleet overview, not the end-user progress portal; everyone else
|
||||
// without scope goes to /progress. A read-only Global Reader has cross-tenant read scope → stays.
|
||||
useEffect(() => {
|
||||
if (user && !user.isTenantAdmin && !user.isGlobalAdmin && !user.isGlobalReader && user.role !== 'Operator') {
|
||||
router.replace("/progress");
|
||||
router.replace(user.isDelegated ? "/fleet" : "/progress");
|
||||
}
|
||||
}, [user, router]);
|
||||
|
||||
|
||||
@@ -399,14 +399,18 @@ export function GlobalSidebar({ children }: { children: ReactNode }) {
|
||||
// Regular users see minimal nav. A read-only Global Reader has platform scope, and a delegated MSP admin
|
||||
// has fleet scope → both get the (group-filtered) nav rather than the minimal regular-user list.
|
||||
const isRegularUser = !isAdminOrOperator && !hasFleetScope;
|
||||
// The Dashboard (own-tenant session list) is only meaningful for a genuine own-tenant/platform user.
|
||||
// A delegated-only MSP admin has no own-tenant stake — /dashboard would just bounce them to /fleet —
|
||||
// so hide the link for them; their entry point is the Fleet group.
|
||||
const showDashboard = isAdminOrOperator || hasGlobalScope;
|
||||
|
||||
const renderNavContent = (isMobile = false) => (
|
||||
<>
|
||||
{/* Global nav — only when authenticated */}
|
||||
{isAuthenticated && (
|
||||
<>
|
||||
{/* Dashboard — hidden for regular users (no admin/operator access) */}
|
||||
{!isRegularUser && (
|
||||
{/* Dashboard — own-tenant session list; hidden for regular users AND delegated-only MSP admins */}
|
||||
{showDashboard && (
|
||||
<ul className="space-y-0.5">
|
||||
{renderGlobalItem(DASHBOARD_ITEM)}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user