mirror of
https://github.com/rustfs/console.git
synced 2026-08-28 19:47:21 +08:00
fix : 403 check Unauthorized
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
"singleQuote": false,
|
||||
"jsxSingleQuote": false,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 90,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
|
||||
+42
-27
@@ -17,7 +17,10 @@ interface S3ContextValue {
|
||||
isReady: boolean
|
||||
}
|
||||
|
||||
const S3Context = createContext<S3ContextValue>({ client: null, isReady: false })
|
||||
const S3Context = createContext<S3ContextValue>({
|
||||
client: null,
|
||||
isReady: false,
|
||||
})
|
||||
|
||||
export function S3Provider({ children }: { children: React.ReactNode }) {
|
||||
const { credentials, isAuthenticated, logout } = useAuth()
|
||||
@@ -54,42 +57,54 @@ export function S3Provider({ children }: { children: React.ReactNode }) {
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any -- AWS SDK middleware types are complex */
|
||||
client.middlewareStack.add(
|
||||
((next: any) =>
|
||||
async (args: any) => {
|
||||
try {
|
||||
const response = (await next(args)) as S3Response
|
||||
((next: any) => async (args: any) => {
|
||||
try {
|
||||
const response = (await next(args)) as S3Response
|
||||
|
||||
if (response.response?.body && typeof response.response.body === "string") {
|
||||
const body = response.response.body.trim()
|
||||
if (body.match(/^<\?xml[^>]*\?><[^>]*><\/[^>]*>$/)) {
|
||||
const tagName = body.match(/<([^>]*)><\/\1>/)?.[1]
|
||||
if (tagName) {
|
||||
const propertyName = tagName.replace(/(?:^|_)([a-z])/g, (_, letter: string) =>
|
||||
letter.toUpperCase()
|
||||
)
|
||||
return {
|
||||
response: response.response,
|
||||
[propertyName]: null,
|
||||
}
|
||||
if (response.response?.body && typeof response.response.body === "string") {
|
||||
const body = response.response.body.trim()
|
||||
if (body.match(/^<\?xml[^>]*\?><[^>]*><\/[^>]*>$/)) {
|
||||
const tagName = body.match(/<([^>]*)><\/\1>/)?.[1]
|
||||
if (tagName) {
|
||||
const propertyName = tagName.replace(/(?:^|_)([a-z])/g, (_, letter: string) => letter.toUpperCase())
|
||||
return {
|
||||
response: response.response,
|
||||
[propertyName]: null,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
} catch (error: unknown) {
|
||||
const err = error as { $metadata?: { httpStatusCode?: number }; Code?: string }
|
||||
if (err?.$metadata?.httpStatusCode === 401) {
|
||||
return response
|
||||
} catch (error: unknown) {
|
||||
const err = error as {
|
||||
$metadata?: { httpStatusCode?: number }
|
||||
Code?: string
|
||||
name?: string
|
||||
message?: string
|
||||
}
|
||||
if (err?.$metadata?.httpStatusCode === 401) {
|
||||
logout()
|
||||
window.location.href = getLoginRoute()
|
||||
return { response: { statusCode: 401, headers: {} } }
|
||||
}
|
||||
if (err?.$metadata?.httpStatusCode === 403) {
|
||||
const codeText = (err?.Code || err?.name || "").toLowerCase()
|
||||
const isUnauthorizedAccess = codeText === "unauthorizedaccess"
|
||||
const isInvalidAccessKey = codeText === "invalidaccesskeyid"
|
||||
if (isUnauthorizedAccess || isInvalidAccessKey) {
|
||||
logout()
|
||||
window.location.href = getLoginRoute()
|
||||
return { response: { statusCode: 401, headers: {} } }
|
||||
}
|
||||
if (err?.Code) {
|
||||
throw new Error(err.Code)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}) as any,
|
||||
{ step: "deserialize", name: "handleXmlResponse" }
|
||||
if (err?.Code) {
|
||||
throw new Error(err.Code)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}) as any,
|
||||
{ step: "deserialize", name: "handleXmlResponse" },
|
||||
)
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
|
||||
|
||||
+40
-18
@@ -32,11 +32,7 @@ export class ApiClient {
|
||||
this.errorHandler = handler
|
||||
}
|
||||
|
||||
async request(
|
||||
url: string,
|
||||
options: RequestOptions = {},
|
||||
parseJson: boolean = true
|
||||
) {
|
||||
async request(url: string, options: RequestOptions = {}, parseJson: boolean = true) {
|
||||
url = this.config?.baseUrl ? joinURL(this.config?.baseUrl, url) : url
|
||||
options.headers = { ...this.config?.headers, ...options.headers }
|
||||
if (
|
||||
@@ -59,7 +55,10 @@ export class ApiClient {
|
||||
logger.log("[request] url:", url)
|
||||
logger.log("[request] options:", options)
|
||||
|
||||
const response = await this.$api.fetch(url, options as RequestInit & { body?: BodyInit | null; aws?: Record<string, unknown> })
|
||||
const response = await this.$api.fetch(
|
||||
url,
|
||||
options as RequestInit & { body?: BodyInit | null; aws?: Record<string, unknown> },
|
||||
)
|
||||
|
||||
logger.log("[request] response:", response)
|
||||
|
||||
@@ -70,8 +69,39 @@ export class ApiClient {
|
||||
return
|
||||
}
|
||||
if (response.status === 403) {
|
||||
if (this.errorHandler) {
|
||||
await this.errorHandler.handle403()
|
||||
try {
|
||||
const cloned = response.clone()
|
||||
let codeText = ""
|
||||
try {
|
||||
const data = (await cloned.json()) as Record<string, unknown>
|
||||
let code: string | undefined = (data?.code as string | undefined) || (data?.Code as string | undefined)
|
||||
if (data && typeof data === "object" && "error" in data) {
|
||||
const errObj = (data as { error?: unknown }).error
|
||||
if (errObj && typeof errObj === "object") {
|
||||
const e = errObj as { code?: unknown }
|
||||
if (typeof e.code === "string") code = code ?? e.code
|
||||
}
|
||||
}
|
||||
codeText = typeof code === "string" ? code : ""
|
||||
} catch {
|
||||
codeText = ""
|
||||
}
|
||||
|
||||
const normalizedCode = codeText.toLowerCase()
|
||||
const isUnauthorizedAccess = normalizedCode === "unauthorizedaccess"
|
||||
const isInvalidAccessKey = normalizedCode === "invalidaccesskeyid"
|
||||
|
||||
if (this.errorHandler) {
|
||||
if (isUnauthorizedAccess || isInvalidAccessKey) {
|
||||
await this.errorHandler.handle401()
|
||||
} else {
|
||||
await this.errorHandler.handle403()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if (this.errorHandler) {
|
||||
await this.errorHandler.handle403()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -81,11 +111,7 @@ export class ApiClient {
|
||||
throw new Error(errorMsg)
|
||||
}
|
||||
|
||||
if (
|
||||
response.status === 204 ||
|
||||
response.headers.get("content-length") === "0" ||
|
||||
!response.body
|
||||
) {
|
||||
if (response.status === 204 || response.headers.get("content-length") === "0" || !response.body) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -101,11 +127,7 @@ export class ApiClient {
|
||||
}
|
||||
|
||||
async *streamRequest(url: string, options: RequestOptions = {}) {
|
||||
const response = (await this.request(
|
||||
url,
|
||||
{ method: "GET", ...options },
|
||||
false
|
||||
)) as Response | null
|
||||
const response = (await this.request(url, { method: "GET", ...options }, false)) as Response | null
|
||||
|
||||
if (!response?.body) {
|
||||
throw new Error("No response body")
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import type {
|
||||
ApiErrorHandlerCallback,
|
||||
IApiErrorHandler,
|
||||
} from "@/types/api"
|
||||
import type { ApiErrorHandlerCallback, IApiErrorHandler } from "@/types/api"
|
||||
|
||||
export class ApiErrorHandler implements IApiErrorHandler {
|
||||
private onUnauthorized?: ApiErrorHandlerCallback
|
||||
|
||||
Reference in New Issue
Block a user