mirror of
https://github.com/langgenius/dify.git
synced 2026-05-23 10:29:07 +08:00
fix web lint
This commit is contained in:
@ -93,12 +93,6 @@ catalog:
|
||||
'@napi-rs/keyring': 1.1.6
|
||||
'@next/eslint-plugin-next': 16.2.6
|
||||
'@next/mdx': 16.2.6
|
||||
'@oclif/core': 4.11.1
|
||||
'@oclif/plugin-autocomplete': 3.2.6
|
||||
'@oclif/plugin-help': 6.2.10
|
||||
'@oclif/plugin-not-found': 3.2.18
|
||||
'@oclif/plugin-version': 2.2.16
|
||||
'@oclif/plugin-warn-if-update-available': 3.1.13
|
||||
'@orpc/client': 1.14.3
|
||||
'@orpc/contract': 1.14.3
|
||||
'@orpc/openapi-client': 1.14.3
|
||||
@ -212,7 +206,6 @@ catalog:
|
||||
next: 16.2.6
|
||||
next-themes: 0.4.6
|
||||
nuqs: 2.8.9
|
||||
oclif: 4.15.5
|
||||
open: 10.1.0
|
||||
ora: 8.1.0
|
||||
picocolors: 1.1.0
|
||||
|
||||
@ -18,14 +18,18 @@ type OAuthPendingRedirect = {
|
||||
const getCurrentUnixTimestamp = () => Math.floor(Date.now() / 1000)
|
||||
|
||||
function validate(target: string): string | null {
|
||||
if (typeof window === 'undefined') return null
|
||||
if (typeof window === 'undefined')
|
||||
return null
|
||||
try {
|
||||
const url = new URL(target, window.location.origin)
|
||||
if (url.origin !== window.location.origin) return null
|
||||
if (url.origin !== window.location.origin)
|
||||
return null
|
||||
const allowedKeys = ALLOWED[url.pathname]
|
||||
if (!allowedKeys) return null
|
||||
if (!allowedKeys)
|
||||
return null
|
||||
for (const key of url.searchParams.keys()) {
|
||||
if (!allowedKeys.has(key)) return null
|
||||
if (!allowedKeys.has(key))
|
||||
return null
|
||||
}
|
||||
return url.pathname + (url.search || '')
|
||||
}
|
||||
@ -39,13 +43,18 @@ function validate(target: string): string | null {
|
||||
// /device tabs don't clobber each other. 15-min TTL drops stale values.
|
||||
// Same-origin + exact-path whitelist prevents open-redirect.
|
||||
export const setPostLoginRedirect = (value: string | null) => {
|
||||
if (typeof window === 'undefined') return
|
||||
if (typeof window === 'undefined')
|
||||
return
|
||||
if (value === null) {
|
||||
try { sessionStorage.removeItem(DEVICE_REDIRECT_KEY) } catch {}
|
||||
try {
|
||||
sessionStorage.removeItem(DEVICE_REDIRECT_KEY)
|
||||
}
|
||||
catch {}
|
||||
return
|
||||
}
|
||||
const safe = validate(value)
|
||||
if (!safe) return
|
||||
if (!safe)
|
||||
return
|
||||
try {
|
||||
sessionStorage.setItem(DEVICE_REDIRECT_KEY, JSON.stringify({ target: safe, ts: Date.now() }))
|
||||
}
|
||||
@ -53,7 +62,8 @@ export const setPostLoginRedirect = (value: string | null) => {
|
||||
}
|
||||
|
||||
function getDeviceRedirect(): string | null {
|
||||
if (typeof window === 'undefined') return null
|
||||
if (typeof window === 'undefined')
|
||||
return null
|
||||
let raw: string | null = null
|
||||
try {
|
||||
raw = sessionStorage.getItem(DEVICE_REDIRECT_KEY)
|
||||
@ -62,11 +72,14 @@ function getDeviceRedirect(): string | null {
|
||||
catch {
|
||||
return null
|
||||
}
|
||||
if (!raw) return null
|
||||
if (!raw)
|
||||
return null
|
||||
try {
|
||||
const parsed = JSON.parse(raw)
|
||||
if (typeof parsed?.target !== 'string' || typeof parsed?.ts !== 'number') return null
|
||||
if (Date.now() - parsed.ts > DEVICE_TTL_MS) return null
|
||||
if (typeof parsed?.target !== 'string' || typeof parsed?.ts !== 'number')
|
||||
return null
|
||||
if (Date.now() - parsed.ts > DEVICE_TTL_MS)
|
||||
return null
|
||||
return validate(parsed.target)
|
||||
}
|
||||
catch {
|
||||
@ -124,6 +137,7 @@ export const resolvePostLoginRedirect = (searchParams?: ReadonlyURLSearchParams)
|
||||
}
|
||||
}
|
||||
const device = getDeviceRedirect()
|
||||
if (device) return device
|
||||
if (device)
|
||||
return device
|
||||
return getOAuthPendingRedirect()
|
||||
}
|
||||
|
||||
@ -22,9 +22,14 @@ const DEVICE_BASE = '/openapi/v1/oauth/device'
|
||||
// switches on `code` to choose user-facing copy / view; never render
|
||||
// `status` or raw body to the user.
|
||||
export class DeviceFlowError extends Error {
|
||||
constructor(public code: string, public status: number) {
|
||||
code: string
|
||||
status: number
|
||||
|
||||
constructor(code: string, status: number) {
|
||||
super(code)
|
||||
this.name = 'DeviceFlowError'
|
||||
this.code = code
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +40,8 @@ async function failFromResponse(res: Response): Promise<never> {
|
||||
let serverCode = ''
|
||||
try {
|
||||
const body = await res.clone().json()
|
||||
if (body && typeof body.error === 'string') serverCode = body.error
|
||||
if (body && typeof body.error === 'string')
|
||||
serverCode = body.error
|
||||
}
|
||||
catch { /* non-JSON body — fall through to status mapping */ }
|
||||
|
||||
@ -44,12 +50,18 @@ async function failFromResponse(res: Response): Promise<never> {
|
||||
}
|
||||
|
||||
function statusFallbackCode(status: number): string {
|
||||
if (status === 429) return 'rate_limited'
|
||||
if (status === 401) return 'no_session'
|
||||
if (status === 403) return 'forbidden'
|
||||
if (status === 404) return 'not_found'
|
||||
if (status === 409) return 'conflict'
|
||||
if (status >= 500) return 'server_error'
|
||||
if (status === 429)
|
||||
return 'rate_limited'
|
||||
if (status === 401)
|
||||
return 'no_session'
|
||||
if (status === 403)
|
||||
return 'forbidden'
|
||||
if (status === 404)
|
||||
return 'not_found'
|
||||
if (status === 409)
|
||||
return 'conflict'
|
||||
if (status >= 500)
|
||||
return 'server_error'
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
@ -69,7 +81,8 @@ export async function deviceLookup(user_code: string): Promise<DeviceLookupReply
|
||||
const res = await fetch(`${DEVICE_BASE}/lookup?user_code=${encodeURIComponent(user_code)}`, {
|
||||
method: 'GET',
|
||||
})
|
||||
if (!res.ok) await failFromResponse(res)
|
||||
if (!res.ok)
|
||||
await failFromResponse(res)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
@ -83,7 +96,8 @@ export async function deviceApproveAccount(user_code: string): Promise<{ status:
|
||||
},
|
||||
body: JSON.stringify({ user_code }),
|
||||
})
|
||||
if (!res.ok) await failFromResponse(res)
|
||||
if (!res.ok)
|
||||
await failFromResponse(res)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
@ -97,7 +111,8 @@ export async function deviceDenyAccount(user_code: string): Promise<{ status: 'd
|
||||
},
|
||||
body: JSON.stringify({ user_code }),
|
||||
})
|
||||
if (!res.ok) await failFromResponse(res)
|
||||
if (!res.ok)
|
||||
await failFromResponse(res)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
@ -116,7 +131,8 @@ export async function fetchApprovalContext(): Promise<ApprovalContext> {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
})
|
||||
if (!res.ok) await failFromResponse(res)
|
||||
if (!res.ok)
|
||||
await failFromResponse(res)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
@ -130,5 +146,6 @@ export async function approveExternal(ctx: ApprovalContext, user_code: string):
|
||||
},
|
||||
body: JSON.stringify({ user_code }),
|
||||
})
|
||||
if (!res.ok) await failFromResponse(res)
|
||||
if (!res.ok)
|
||||
await failFromResponse(res)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user