diff --git a/src/app/[[...panel]]/page.tsx b/src/app/[[...panel]]/page.tsx index 0b0dcaa..e7d05dd 100644 --- a/src/app/[[...panel]]/page.tsx +++ b/src/app/[[...panel]]/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useEffect, useState } from 'react' -import { usePathname } from 'next/navigation' +import { usePathname, useRouter } from 'next/navigation' import { NavRail } from '@/components/layout/nav-rail' import { HeaderBar } from '@/components/layout/header-bar' import { LiveFeed } from '@/components/layout/live-feed' @@ -42,6 +42,7 @@ import { useServerEvents } from '@/lib/use-server-events' import { useMissionControl } from '@/store' export default function Home() { + const router = useRouter() const { connect } = useWebSocket() const { activeTab, setActiveTab, setCurrentUser, setDashboardMode, setGatewayAvailable, setSubscription, setUpdateAvailable, liveFeedOpen, toggleLiveFeed } = useMissionControl() @@ -62,7 +63,13 @@ export default function Home() { // Fetch current user fetch('/api/auth/me') - .then(res => res.ok ? res.json() : null) + .then(async (res) => { + if (res.ok) return res.json() + if (res.status === 401) { + router.replace(`/login?next=${encodeURIComponent(pathname)}`) + } + return null + }) .then(data => { if (data?.user) setCurrentUser(data.user) }) .catch(() => {}) @@ -120,7 +127,7 @@ export default function Home() { const wsUrl = explicitWsUrl || `${gatewayProto}://${gatewayHost}:${gatewayPort}` connect(wsUrl, wsToken) }) - }, [connect, setCurrentUser, setDashboardMode, setGatewayAvailable, setSubscription, setUpdateAvailable]) + }, [connect, pathname, router, setCurrentUser, setDashboardMode, setGatewayAvailable, setSubscription, setUpdateAvailable]) if (!isClient) { return ( diff --git a/src/components/panels/agent-squad-panel-phase3.tsx b/src/components/panels/agent-squad-panel-phase3.tsx index 8905d31..9cbe4b3 100644 --- a/src/components/panels/agent-squad-panel-phase3.tsx +++ b/src/components/panels/agent-squad-panel-phase3.tsx @@ -89,7 +89,14 @@ export function AgentSquadPanelPhase3() { setSyncToast(null) try { const response = await fetch('/api/agents/sync', { method: 'POST' }) + if (response.status === 401) { + window.location.assign('/login?next=%2Fagents') + return + } const data = await response.json() + if (response.status === 403) { + throw new Error('Admin access required for agent sync') + } if (!response.ok) throw new Error(data.error || 'Sync failed') setSyncToast(`Synced ${data.synced} agents (${data.created} new, ${data.updated} updated)`) fetchAgents() @@ -109,7 +116,17 @@ export function AgentSquadPanelPhase3() { if (agents.length === 0) setLoading(true) const response = await fetch('/api/agents') - if (!response.ok) throw new Error('Failed to fetch agents') + if (response.status === 401) { + window.location.assign('/login?next=%2Fagents') + return + } + if (response.status === 403) { + throw new Error('Access denied') + } + if (!response.ok) { + const data = await response.json().catch(() => ({})) + throw new Error(data.error || 'Failed to fetch agents') + } const data = await response.json() setAgents(data.agents || []) diff --git a/src/components/panels/settings-panel.tsx b/src/components/panels/settings-panel.tsx index 08912c8..78f747d 100644 --- a/src/components/panels/settings-panel.tsx +++ b/src/components/panels/settings-panel.tsx @@ -43,12 +43,17 @@ export function SettingsPanel() { const fetchSettings = useCallback(async () => { try { const res = await fetch('/api/settings') + if (res.status === 401) { + window.location.assign('/login?next=%2Fsettings') + return + } if (res.status === 403) { setError('Admin access required') return } if (!res.ok) { - setError('Failed to load settings') + const data = await res.json().catch(() => ({})) + setError(data.error || 'Failed to load settings') return } const data = await res.json()