fix(downloads): file download honours the per-tab account (?account=)
A plain <a> file download can't send the X-Siftlode-Account header, so current_user resolved it to the session-default account — 404 'Unknown download' when the tab acts as a non-default wallet account that owns the file. resolved_user_id now also honours a ?account= query param (the same wallet-gated selection the WebSocket already uses), and downloadFileUrl appends the active account id. Verified: default account -> 404, ?account=<owner> -> 206 with the right Content-Disposition.
This commit is contained in:
parent
7d1ed24fea
commit
0045d41a74
2 changed files with 11 additions and 2 deletions
|
|
@ -683,7 +683,10 @@ def resolved_user_id(request: Request) -> tuple[int | None, bool]:
|
||||||
"""
|
"""
|
||||||
default_id = request.session.get("user_id")
|
default_id = request.session.get("user_id")
|
||||||
wallet = request.session.get("account_ids") or []
|
wallet = request.session.get("account_ids") or []
|
||||||
hdr = request.headers.get(ACTIVE_ACCOUNT_HEADER)
|
# Header for normal XHR; ?account= for contexts that can't set headers (WebSocket, and a
|
||||||
|
# plain <a> file download). Both are wallet-gated below, so neither can impersonate an
|
||||||
|
# account that never signed into this browser.
|
||||||
|
hdr = request.headers.get(ACTIVE_ACCOUNT_HEADER) or request.query_params.get("account")
|
||||||
if hdr:
|
if hdr:
|
||||||
try:
|
try:
|
||||||
hid = int(hdr)
|
hid = int(hdr)
|
||||||
|
|
|
||||||
|
|
@ -1044,7 +1044,13 @@ export const api = {
|
||||||
req(`/api/downloads/${id}/share`, { method: "POST", body: JSON.stringify({ email }) }),
|
req(`/api/downloads/${id}/share`, { method: "POST", body: JSON.stringify({ email }) }),
|
||||||
unshareDownload: (id: number, email: string) =>
|
unshareDownload: (id: number, email: string) =>
|
||||||
req(`/api/downloads/${id}/share/${encodeURIComponent(email)}`, { method: "DELETE" }),
|
req(`/api/downloads/${id}/share/${encodeURIComponent(email)}`, { method: "DELETE" }),
|
||||||
downloadFileUrl: (id: number): string => `/api/downloads/${id}/file`,
|
// A plain <a> navigation can't send the X-Siftlode-Account header, so pass the active
|
||||||
|
// account via ?account= (same wallet-gated selection the WebSocket uses) — otherwise the
|
||||||
|
// download resolves to the session-default account and 404s for a per-tab account's file.
|
||||||
|
downloadFileUrl: (id: number): string => {
|
||||||
|
const a = getActiveAccount();
|
||||||
|
return a != null ? `/api/downloads/${id}/file?account=${a}` : `/api/downloads/${id}/file`;
|
||||||
|
},
|
||||||
|
|
||||||
// admin
|
// admin
|
||||||
adminDownloads: (): Promise<DownloadJob[]> => req("/api/admin/downloads"),
|
adminDownloads: (): Promise<DownloadJob[]> => req("/api/admin/downloads"),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue