mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-30 20:11:45 +00:00
- add lib/http.ts: unified fetch wrapper with: - 30s timeout via AbortController - JSON/text parsing and normalized HttpError - Authorization header from cookie - New-Api-User header from persisted user id - get/post/put/patch/del helpers - add types/api.ts: ApiResponse, UserBasic, UserSelf, LoginResponse, Verify2FAResponse, SelfResponse - add lib/auth.ts: persist/restore user in localStorage (get/set/clear helpers) - refactor stores/auth-store.ts: - implement login (POST /api/user/login?turnstile=...), 2FA verify (POST /api/user/login/2fa) - implement fetchSelf (GET /api/user/self), logout (GET /api/user/logout) - persist user on successful login/verify/self - refactor auth/sign-in form: - switch field to "username" (supports username or email), loosen validation - call auth.login, handle 2FA branch → redirect to /otp - refactor OTP form: - call auth.verify2FA; on success, toast + redirect to home - add route guards: - /_authenticated: beforeLoad redirect to /sign-in if no user; silently refresh session via auth.fetchSelf - /(auth)/sign-in: beforeLoad redirect to / if already logged in - update sign-out dialog: use auth.logout and preserve redirect - cleanup: remove mock auth, no direct axios/fetch usage outside http.ts, no Semi UI imports in new code Notes - Backend expects username or email in "username" field. - Turnstile support: pass token via ?turnstile=... during login when enabled. Security - Ensure New-Api-User header matches logged-in user id per backend middleware. - Session-based auth with optional Bearer token via cookie. No breaking changes.
20 lines
680 B
TypeScript
20 lines
680 B
TypeScript
import { createFileRoute, redirect } from '@tanstack/react-router'
|
|
import { useAuthStore } from '@/stores/auth-store'
|
|
import { getStoredUser } from '@/lib/auth'
|
|
import { AuthenticatedLayout } from '@/components/layout/authenticated-layout'
|
|
|
|
export const Route = createFileRoute('/_authenticated')({
|
|
beforeLoad: async ({ location }) => {
|
|
const user = getStoredUser()
|
|
if (!user) {
|
|
throw redirect({ to: '/sign-in', search: { redirect: location.href } })
|
|
}
|
|
},
|
|
component: () => {
|
|
// 进入后尝试刷新一次会话信息(静默失败)
|
|
const { auth } = useAuthStore()
|
|
auth.fetchSelf().catch(() => {})
|
|
return <AuthenticatedLayout />
|
|
},
|
|
})
|