feat: restore auth state from backend session on app load

Call GET /api/v1/users/me on startup to rehydrate Zustand auth store
from the existing JToken cookie, so login survives page refresh.
This commit is contained in:
zetaloop
2026-04-24 05:07:44 +08:00
parent 2ab075d173
commit ff03532da4
+25 -1
View File
@@ -3,11 +3,34 @@
import { GlobalLoginDialog } from "@/components/global-login-dialog" import { GlobalLoginDialog } from "@/components/global-login-dialog"
import { ThemeSyncEffect } from "@/components/theme-sync" import { ThemeSyncEffect } from "@/components/theme-sync"
import { TooltipProvider } from "@/components/ui/tooltip" import { TooltipProvider } from "@/components/ui/tooltip"
import { getCurrentUserForLogin } from "@/lib/api"
import { useAuthStore } from "@/store/auth"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query" import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { ThemeProvider } from "next-themes" import { ThemeProvider } from "next-themes"
import { useState } from "react" import { useEffect, useRef, useState } from "react"
import { Toaster } from "sonner" import { Toaster } from "sonner"
function AuthBootstrap() {
const login = useAuthStore((s) => s.login)
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
const tried = useRef(false)
useEffect(() => {
if (tried.current || isAuthenticated) return
tried.current = true
getCurrentUserForLogin()
.then((user) => {
login(user, user.verifiedRoles ?? ["consumer"])
})
.catch(() => {
// no valid session — stay logged out
})
}, [login, isAuthenticated])
return null
}
export function Providers({ children }: { children: React.ReactNode }) { export function Providers({ children }: { children: React.ReactNode }) {
const [queryClient] = useState( const [queryClient] = useState(
() => () =>
@@ -26,6 +49,7 @@ export function Providers({ children }: { children: React.ReactNode }) {
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange> <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
<TooltipProvider> <TooltipProvider>
<ThemeSyncEffect /> <ThemeSyncEffect />
<AuthBootstrap />
{children} {children}
<Toaster richColors position="top-center" /> <Toaster richColors position="top-center" />
<GlobalLoginDialog /> <GlobalLoginDialog />