mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-24 16:01:42 +00:00
07a4cb6872
* fix(frontend): branch download UI on shouldDownloadViaClient instead of intercepting in onclick When OpenAPI.TOKEN is set, several download links rendered an `<a href>` to the API and relied on an `onclick` handler to call `e.preventDefault()` and route the request through `downloadViaClient`. This is fragile in embedded contexts (e.g. the whitelabel React SDK) where Svelte's hydrated event listener may not intercept the click in time, so the browser follows the unauthenticated `href` straight to the API. Mirror the drawer pattern already used in `LogViewer` and `FlowStatusViewerInner`: render a `<button>` calling `downloadViaClient` when `shouldDownloadViaClient()` is true, and fall back to the plain `<a href download>` otherwise. Affects the LogViewer top bar, the large- result download in DisplayResult, the inline S3 link in ObjectViewer, the CSV link in ParqetCsvTableRenderer, and FileDownload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): treat custom HEADERS / basic auth as token equivalents in shouldDownloadViaClient Customers wiring the SDK with cookie-bypass auth via custom request headers (e.g. `OpenAPI.HEADERS = getAuthHeaders()` returning a Bearer header) had `shouldDownloadViaClient()` return false because it only checked `OpenAPI.TOKEN`. The plain `<a href download>` branch then followed the link without those headers, so authenticated downloads silently degraded to the cookie path (or failed when there is no cookie). Widen the check to any non-cookie auth: TOKEN, HEADERS, or USERNAME (basic auth). Route `downloadViaClient` through the generated client's `getHeaders` so all configured auth schemes are applied consistently instead of hand-building an Authorization header for TOKEN only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import { OpenAPI } from '$lib/gen'
|
|
import { getHeaders } from '$lib/gen/core/request'
|
|
import { sendUserToast } from '$lib/toast'
|
|
|
|
/**
|
|
* When OpenAPI is configured to authenticate via headers (TOKEN, basic auth,
|
|
* or arbitrary HEADERS) we cannot rely on a plain `<a href>` browser
|
|
* navigation because the browser does not attach those headers. In that case
|
|
* fetch the file via the OpenAPI client (which carries the configured auth)
|
|
* and trigger a download from a blob URL. Cookie-only auth still works with
|
|
* a plain link.
|
|
*
|
|
* `apiPath` should be the path relative to OpenAPI.BASE, starting with `/`
|
|
* (e.g. `/w/foo/job_helpers/download_s3_file?file_key=...`).
|
|
*/
|
|
export function shouldDownloadViaClient(): boolean {
|
|
return Boolean(OpenAPI.TOKEN || OpenAPI.HEADERS || OpenAPI.USERNAME)
|
|
}
|
|
|
|
export async function downloadViaClient(apiPath: string, filename: string): Promise<void> {
|
|
const url = `${OpenAPI.BASE}${apiPath}`
|
|
let response: Response
|
|
try {
|
|
const headers = await getHeaders(OpenAPI, { method: 'GET', url: apiPath })
|
|
response = await fetch(url, { headers, credentials: OpenAPI.CREDENTIALS })
|
|
} catch (e) {
|
|
sendUserToast(`Download failed: ${e}`, true)
|
|
return
|
|
}
|
|
if (!response.ok) {
|
|
sendUserToast(`Download failed: ${response.status} ${response.statusText}`, true)
|
|
return
|
|
}
|
|
const blob = await response.blob()
|
|
const blobUrl = URL.createObjectURL(blob)
|
|
const a = document.createElement('a')
|
|
a.href = blobUrl
|
|
a.download = filename
|
|
document.body.appendChild(a)
|
|
a.click()
|
|
a.remove()
|
|
URL.revokeObjectURL(blobUrl)
|
|
}
|