mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-05-01 14:16:15 +00:00
🔐 feat(auth): integrate backend session login + 2FA; add HTTP client and route guards
- 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.
This commit is contained in:
@@ -1,6 +1,19 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
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')({
|
||||
component: AuthenticatedLayout,
|
||||
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 />
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user