diff --git a/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx index 8efe81cce..4c32d0b0e 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx @@ -13,13 +13,15 @@ import { Logo } from "@/components/Logo"; import { ModelProviderConnectionsPanel } from "@/components/settings/model-connections/model-provider-connections-panel"; import { Button } from "@/components/ui/button"; import { useGlobalLoadingEffect } from "@/hooks/use-global-loading"; -import { getBearerToken, redirectToLogin } from "@/lib/auth-utils"; +import { useSession } from "@/hooks/use-session"; +import { redirectToLogin } from "@/lib/auth-utils"; import { hasEnabledChatModel, isLlmOnboardingComplete } from "@/lib/onboarding"; export default function OnboardPage() { const router = useRouter(); const params = useParams(); const searchSpaceId = Number(params.search_space_id); + const session = useSession(); const { data: globalConnections = [], isLoading: globalLoading } = useAtomValue( globalModelConnectionsAtom ); @@ -29,8 +31,8 @@ export default function OnboardPage() { useAtomValue(globalLlmConfigStatusAtom); useEffect(() => { - if (!getBearerToken()) redirectToLogin(); - }, []); + if (session.status === "unauthenticated") redirectToLogin(); + }, [session.status]); const hasUsableChatModel = useMemo( () => hasEnabledChatModel([...globalConnections, ...connections]), @@ -43,7 +45,8 @@ export default function OnboardPage() { connections ); - const isLoading = globalLoading || rolesLoading || globalConfigStatusLoading; + const isLoading = + session.status === "loading" || globalLoading || rolesLoading || globalConfigStatusLoading; // Onboarding only applies when no global_llm_config.yaml exists. If a global // config is present (or onboarding is already complete), leave this page. diff --git a/surfsense_web/app/dashboard/dashboard-shell.tsx b/surfsense_web/app/dashboard/dashboard-shell.tsx index f84cd56eb..1198996b7 100644 --- a/surfsense_web/app/dashboard/dashboard-shell.tsx +++ b/surfsense_web/app/dashboard/dashboard-shell.tsx @@ -3,31 +3,32 @@ import { useEffect, useState } from "react"; import { USER_QUERY_KEY } from "@/atoms/user/user-query.atoms"; import { useGlobalLoadingEffect } from "@/hooks/use-global-loading"; -import { ensureTokensFromElectron, getBearerToken, redirectToLogin } from "@/lib/auth-utils"; +import { useSession } from "@/hooks/use-session"; +import { ensureTokensFromElectron, redirectToLogin } from "@/lib/auth-utils"; import { queryClient } from "@/lib/query-client/client"; export function DashboardShell({ children }: { children: React.ReactNode }) { const [isCheckingAuth, setIsCheckingAuth] = useState(true); + const session = useSession(); // Use the global loading screen - spinner animation won't reset useGlobalLoadingEffect(isCheckingAuth); useEffect(() => { async function checkAuth() { - let token = getBearerToken(); - if (!token) { - const synced = await ensureTokensFromElectron(); - if (synced) token = getBearerToken(); + if (typeof window !== "undefined" && window.electronAPI) { + await ensureTokensFromElectron(); } - if (!token) { + if (session.status === "loading") return; + if (session.status === "unauthenticated") { redirectToLogin(); return; } queryClient.invalidateQueries({ queryKey: [...USER_QUERY_KEY] }); setIsCheckingAuth(false); } - checkAuth(); - }, []); + void checkAuth(); + }, [session.status]); // Return null while loading - the global provider handles the loading UI if (isCheckingAuth) { diff --git a/surfsense_web/atoms/agent/agent-flags-query.atom.ts b/surfsense_web/atoms/agent/agent-flags-query.atom.ts index 30158deaa..0b1798e51 100644 --- a/surfsense_web/atoms/agent/agent-flags-query.atom.ts +++ b/surfsense_web/atoms/agent/agent-flags-query.atom.ts @@ -1,6 +1,6 @@ import { atomWithQuery } from "jotai-tanstack-query"; import { agentFlagsApiService } from "@/lib/apis/agent-flags-api.service"; -import { getBearerToken } from "@/lib/auth-utils"; +import { isAuthenticated } from "@/lib/auth-utils"; export const AGENT_FLAGS_QUERY_KEY = ["agent", "flags"] as const; @@ -12,6 +12,6 @@ export const AGENT_FLAGS_QUERY_KEY = ["agent", "flags"] as const; export const agentFlagsAtom = atomWithQuery(() => ({ queryKey: AGENT_FLAGS_QUERY_KEY, staleTime: 10 * 60 * 1000, - enabled: !!getBearerToken(), + enabled: isAuthenticated(), queryFn: () => agentFlagsApiService.get(), })); diff --git a/surfsense_web/atoms/model-connections/model-connections-query.atoms.ts b/surfsense_web/atoms/model-connections/model-connections-query.atoms.ts index 04dad9b21..709b51966 100644 --- a/surfsense_web/atoms/model-connections/model-connections-query.atoms.ts +++ b/surfsense_web/atoms/model-connections/model-connections-query.atoms.ts @@ -1,26 +1,26 @@ import { atomWithQuery } from "jotai-tanstack-query"; import { modelConnectionsApiService } from "@/lib/apis/model-connections-api.service"; -import { getBearerToken } from "@/lib/auth-utils"; +import { isAuthenticated } from "@/lib/auth-utils"; import { cacheKeys } from "@/lib/query-client/cache-keys"; import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms"; export const globalModelConnectionsAtom = atomWithQuery(() => ({ queryKey: cacheKeys.modelConnections.global(), - enabled: !!getBearerToken(), + enabled: isAuthenticated(), staleTime: 10 * 60 * 1000, queryFn: () => modelConnectionsApiService.getGlobalConnections(), })); export const globalLlmConfigStatusAtom = atomWithQuery(() => ({ queryKey: cacheKeys.modelConnections.globalConfigStatus(), - enabled: !!getBearerToken(), + enabled: isAuthenticated(), staleTime: 60 * 60 * 1000, queryFn: () => modelConnectionsApiService.getGlobalLlmConfigStatus(), })); export const modelProvidersAtom = atomWithQuery(() => ({ queryKey: cacheKeys.modelConnections.providers(), - enabled: !!getBearerToken(), + enabled: isAuthenticated(), staleTime: 60 * 60 * 1000, queryFn: () => modelConnectionsApiService.getModelProviders(), })); diff --git a/surfsense_web/atoms/user/user-query.atoms.ts b/surfsense_web/atoms/user/user-query.atoms.ts index 4b6717440..68ec329be 100644 --- a/surfsense_web/atoms/user/user-query.atoms.ts +++ b/surfsense_web/atoms/user/user-query.atoms.ts @@ -1,6 +1,6 @@ import { atomWithQuery } from "jotai-tanstack-query"; import { userApiService } from "@/lib/apis/user-api.service"; -import { getBearerToken } from "@/lib/auth-utils"; +import { isAuthenticated } from "@/lib/auth-utils"; export const USER_QUERY_KEY = ["user", "me"] as const; const userQueryFn = () => userApiService.getMe(); @@ -12,7 +12,8 @@ export const currentUserAtom = atomWithQuery(() => { // are now pushed via Zero (queries.user.me()), so /users/me only // needs to fire once per session for the static profile fields. staleTime: Infinity, - enabled: !!getBearerToken(), + enabled: isAuthenticated(), + retry: false, queryFn: userQueryFn, }; });