refactor(web): remove admin token refresh flow
This commit is contained in:
@@ -68,8 +68,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
}, [requiresAuth, router])
|
}, [requiresAuth, router])
|
||||||
|
|
||||||
async function signOut() {
|
async function signOut() {
|
||||||
const current = readSession()
|
await logout()
|
||||||
await logout(current?.refreshToken)
|
|
||||||
setSession(null)
|
setSession(null)
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
router.replace("/dashboard/login")
|
router.replace("/dashboard/login")
|
||||||
|
|||||||
+1
-4
@@ -30,13 +30,10 @@ export async function fetchProfile() {
|
|||||||
return request<AuthSession>("/api/auth/profile")
|
return request<AuthSession>("/api/auth/profile")
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logout(refreshToken?: string) {
|
export async function logout() {
|
||||||
try {
|
try {
|
||||||
await request("/api/auth/logout", {
|
await request("/api/auth/logout", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
|
||||||
refreshToken,
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
clearSession()
|
clearSession()
|
||||||
|
|||||||
+6
-54
@@ -1,4 +1,4 @@
|
|||||||
import { clearSession, readSession, writeSession, type AuthSession } from "@/lib/auth"
|
import { clearSession, readSession } from "@/lib/auth"
|
||||||
|
|
||||||
const API_BASE_URL =
|
const API_BASE_URL =
|
||||||
process.env.NEXT_PUBLIC_API_BASE_URL?.trim() || ""
|
process.env.NEXT_PUBLIC_API_BASE_URL?.trim() || ""
|
||||||
@@ -12,7 +12,6 @@ type JsonResult<T> = {
|
|||||||
|
|
||||||
type RequestOptions = RequestInit & {
|
type RequestOptions = RequestInit & {
|
||||||
skipAuth?: boolean
|
skipAuth?: boolean
|
||||||
retryOnAuthError?: boolean
|
|
||||||
baseUrl?: string
|
baseUrl?: string
|
||||||
onResponse?: (response: Response) => void
|
onResponse?: (response: Response) => void
|
||||||
}
|
}
|
||||||
@@ -20,6 +19,9 @@ type RequestOptions = RequestInit & {
|
|||||||
async function parseResult<T>(response: Response) {
|
async function parseResult<T>(response: Response) {
|
||||||
const payload = (await response.json()) as JsonResult<T>
|
const payload = (await response.json()) as JsonResult<T>
|
||||||
if (!response.ok || !payload.success) {
|
if (!response.ok || !payload.success) {
|
||||||
|
if (payload.errorCode === 3000 || payload.errorCode === 3002) {
|
||||||
|
clearSession()
|
||||||
|
}
|
||||||
const error = new Error(payload.message || "请求失败")
|
const error = new Error(payload.message || "请求失败")
|
||||||
;(error as Error & { errorCode?: number }).errorCode = payload.errorCode
|
;(error as Error & { errorCode?: number }).errorCode = payload.errorCode
|
||||||
throw error
|
throw error
|
||||||
@@ -27,40 +29,11 @@ async function parseResult<T>(response: Response) {
|
|||||||
return payload.data
|
return payload.data
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshAccessToken() {
|
|
||||||
const session = readSession()
|
|
||||||
if (!session?.refreshToken) {
|
|
||||||
clearSession()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await request<AuthSession>(
|
|
||||||
"/api/auth/refresh_token",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({ refreshToken: session.refreshToken }),
|
|
||||||
skipAuth: true,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
||||||
const merged = {
|
|
||||||
...data,
|
|
||||||
refreshToken: data.refreshToken || session.refreshToken,
|
|
||||||
}
|
|
||||||
writeSession(merged)
|
|
||||||
return merged
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function request<T>(
|
export async function request<T>(
|
||||||
path: string,
|
path: string,
|
||||||
options: RequestOptions = {},
|
options: RequestOptions = {}
|
||||||
retryOnAuthError = true
|
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const { headers, skipAuth, baseUrl, onResponse, ...rest } = options
|
const { headers, skipAuth, baseUrl, onResponse, ...rest } = options
|
||||||
delete (rest as RequestOptions).retryOnAuthError
|
|
||||||
delete (rest as RequestOptions).baseUrl
|
delete (rest as RequestOptions).baseUrl
|
||||||
delete (rest as RequestOptions).onResponse
|
delete (rest as RequestOptions).onResponse
|
||||||
const session = readSession()
|
const session = readSession()
|
||||||
@@ -85,26 +58,5 @@ export async function request<T>(
|
|||||||
})
|
})
|
||||||
onResponse?.(response)
|
onResponse?.(response)
|
||||||
|
|
||||||
try {
|
return parseResult<T>(response)
|
||||||
return await parseResult<T>(response)
|
|
||||||
} catch (error) {
|
|
||||||
const errorCode = (error as Error & { errorCode?: number }).errorCode
|
|
||||||
if (
|
|
||||||
!skipAuth &&
|
|
||||||
retryOnAuthError &&
|
|
||||||
(errorCode === 3000 || errorCode === 3002) &&
|
|
||||||
session?.refreshToken
|
|
||||||
) {
|
|
||||||
const refreshed = await refreshAccessToken()
|
|
||||||
if (!refreshed) {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
return request<T>(path, options, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorCode === 3000 || errorCode === 3002) {
|
|
||||||
clearSession()
|
|
||||||
}
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ export type AuthUser = {
|
|||||||
|
|
||||||
export type AuthSession = {
|
export type AuthSession = {
|
||||||
accessToken: string
|
accessToken: string
|
||||||
refreshToken: string
|
|
||||||
expiresAt?: string
|
expiresAt?: string
|
||||||
user: AuthUser
|
user: AuthUser
|
||||||
permissions: string[]
|
permissions: string[]
|
||||||
|
|||||||
Reference in New Issue
Block a user