feat(v3-auth): modernize hosted file access with simplified bypass pattern

- Roll out platform-wide standard for unauthenticated binary access using '?key=[account_id]' query parameter.
- Update API helpers (get, post, patch) to recognize 'key' bypass and strip account context headers accordingly.
- Refactor IDAA Bulletin Board to restore inline image rendering and edit-mode previews.
- Modernize Events Launcher (Layout, Sync, Session View) to use V3 Action URLs with verified auth.
- Update HTML generators in 'ae_utils.ts' to support the new authenticated URL structure.
- Harden 'ae_comp__event_file_obj_tbl' CSV export and clipboard links with V3 standard patterns.
This commit is contained in:
Scott Idem
2026-02-03 18:37:55 -05:00
parent 6634c9aef0
commit 0809ad3eac
21 changed files with 412 additions and 701 deletions

View File

@@ -220,11 +220,14 @@
let obj_id = obj_parts[1];
let obj_filename = cmd_parts[2];
api.download_hosted_file({
api.get_object({
api_cfg: $ae_api,
hosted_file_id: obj_id,
return_file: true,
filename: obj_filename,
endpoint: `/v3/action/hosted_file/${obj_id}/download`,
params: {
filename: obj_filename,
key: $ae_api.account_id
},
return_blob: true,
auto_download: true,
log_lvl: 1
});
@@ -764,9 +767,9 @@
{#if $events_sess.launcher.modal__open_event_file_id}
<img
src="{$ae_api.base_url}/event/file/{$events_sess.launcher
src="{$ae_api.base_url}/v3/action/event_file/{$events_sess.launcher
.modal__open_event_file_id}/download?filename={$events_slct.event_file_obj
.filename}&x_no_account_id_token=direct-download"
.filename}&key={$ae_api.account_id}"
alt="Poster"
class="min-h-28 min-w-md max-h-full max-w-full"
/>

View File

@@ -129,7 +129,8 @@
currently_syncing = file_obj.filename;
$events_sess.launcher.sync_stats.currently_syncing = currently_syncing;
const url = `${$ae_api.base_url}/hosted_file/${file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(file_obj.filename)}`;
// Use the PROVEN endpoint path from api.ts that is known to work in Default Mode.
const url = `${$ae_api.base_url}/v3/action/hosted_file/${file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(file_obj.filename)}&key=${$ae_api.account_id}`;
const result = await native.download_to_cache({
url, cache_root, hash: file_obj.hash_sha256,
api_key: $ae_api.api_secret_key, account_id: $ae_api.account_id,

View File

@@ -60,6 +60,7 @@
import { events_loc, events_sess, events_slct } from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte';
import Element_ae_crud from '$lib/elements/element_ae_crud.svelte';
// Import the relay
@@ -104,7 +105,7 @@
open_file_status_message = 'Downloading file to cache...';
// Use the PROVEN endpoint path from api.ts that is known to work in Default Mode.
const url = `${$ae_api.base_url}/hosted_file/${event_file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(event_file_obj.filename)}`;
const url = `${$ae_api.base_url}/v3/action/hosted_file/${event_file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(event_file_obj.filename)}&x_no_account_id_token=direct-download`;
const dl_result = await native.download_to_cache({
url,
@@ -118,7 +119,7 @@
open_file_status = 'error';
open_file_status_message = `Download failed: ${dl_result.error}`;
setTimeout(() => open_file_clicked = false, 5000);
return;
return false;
}
}
@@ -141,6 +142,7 @@
}
setTimeout(() => open_file_clicked = false, 5000);
return launch_result.success;
}
// 2. ONSITE MODE (Browser with Modified Extensions)
else if ($events_loc.launcher.app_mode === 'onsite') {
@@ -153,16 +155,20 @@
filename = event_file_obj.filename + 'win';
}
ae_promises[event_file_id] = api.download_hosted_file({
const dl_promise = api.get_object({
api_cfg: $ae_api,
hosted_file_id: event_file_obj.hosted_file_id,
return_file: true,
filename: filename,
endpoint: `/v3/action/hosted_file/${event_file_obj.hosted_file_id}/download`,
params: {
filename: filename,
x_no_account_id_token: 'direct-download'
},
return_blob: true,
auto_download: true,
log_lvl: 1
});
setTimeout(() => open_file_clicked = false, 5000);
return dl_promise;
}
// 3. DEFAULT MODE (Standard Browser)
else {
@@ -170,11 +176,14 @@
open_file_status = 'downloading_default';
open_file_status_message = 'Downloading...';
ae_promises[event_file_id] = api.download_hosted_file({
const dl_promise = api.get_object({
api_cfg: $ae_api,
hosted_file_id: event_file_obj.hosted_file_id,
return_file: true,
filename: event_file_obj.filename,
endpoint: `/v3/action/hosted_file/${event_file_obj.hosted_file_id}/download`,
params: {
filename: event_file_obj.filename,
x_no_account_id_token: 'direct-download'
},
return_blob: true,
auto_download: true,
log_lvl: 1
});
@@ -185,6 +194,7 @@
}
setTimeout(() => open_file_clicked = false, 5000);
return dl_promise;
}
}
@@ -215,61 +225,66 @@
<span class="event_file_action grow max-w-full flex flex-row flex-wrap gap-1 items-center justify-center">
{#if session_type == 'poster' || open_method == 'modal'}
<button
type="button"
onclick={() => {
<AE_Comp_Hosted_Files_Download_Button
hosted_file_id={event_file_id}
hosted_file_obj={event_file_obj}
classes="btn btn-sm md:btn-md lg:btn-lg preset-tonal-primary border border-primary-500 min-w-96"
click={() => {
modal__open_event_file_id = event_file_id;
modal__event_file_obj = event_file_obj;
if (!modal__title) modal__title = event_file_obj.filename;
$events_slct.event_file_id = event_file_id;
$events_slct.event_file_obj = event_file_obj;
}}
class:preset-tonal-success={$events_slct.event_file_id == event_file_id}
class="btn btn-sm md:btn-md lg:btn-lg preset-tonal-primary border border-primary-500 min-w-96"
>
{#if screen_saver_exts.includes(event_file_obj.extension)}
<span class="fas fa-chart-bar m-1" class:hidden={hide_launch_icon}></span> Open Poster
{:else}
<span class="fas fa-paper-plane m-1" class:hidden={hide_launch_icon}></span>
{ae_util.shorten_filename({ filename: event_file_obj.filename, max_length: max_filename_length })}
{/if}
</button>
{#snippet label()}
{#if screen_saver_exts.includes(event_file_obj.extension)}
<span class="fas fa-chart-bar m-1" class:hidden={hide_launch_icon}></span> Open Poster
{:else}
<span class="fas fa-paper-plane m-1" class:hidden={hide_launch_icon}></span>
{ae_util.shorten_filename({ filename: event_file_obj.filename, max_length: max_filename_length })}
{/if}
{/snippet}
</AE_Comp_Hosted_Files_Download_Button>
{:else}
<button
type="button"
onclick={handle_open_file}
class:outline-2={$events_slct.event_file_id == event_file_id}
class="btn {btn_size} gap-1 justify-between min-w-full w-full max-w-96 preset-tonal-primary border border-primary-500"
<AE_Comp_Hosted_Files_Download_Button
hosted_file_id={event_file_id}
hosted_file_obj={event_file_obj}
classes="btn {btn_size} gap-1 justify-between min-w-full w-full max-w-96 preset-tonal-primary border border-primary-500"
click={handle_open_file}
>
<span class="shrink text-xs border-r border-gray-400 pr-1">
{#await ae_promises[event_file_id]}
<span class="fas fa-spinner fa-spin mx-0.5"></span>
<span>
{#if $ae_sess.api_download_kv[event_file_obj.hosted_file_id]}
{$ae_sess.api_download_kv[event_file_obj.hosted_file_id].percent_completed}%
{:else}
...
{#snippet label()}
{@const file_id = event_file_obj.hosted_file_id}
<span class="shrink text-xs border-r border-gray-400 pr-1">
{#await ae_promises[event_file_id]}
<span class="fas fa-spinner fa-spin mx-0.5"></span>
<span>
{#if $ae_sess.api_download_kv[file_id]}
{$ae_sess.api_download_kv[file_id].percent_completed}%
{:else}
...
{/if}
</span>
{:then result}
<span class="fas fa-{ae_util.file_extension_icon(event_file_obj.extension)} mx-0.5"></span>
{event_file_obj.extension}
{#if result === null || result === false}
<span class="text-error-500"><span class="fas fa-exclamation-triangle mx-1"></span>Failed!</span>
{/if}
</span>
{:then result}
<span class="fas fa-{ae_util.file_extension_icon(event_file_obj.extension)} mx-0.5"></span>
{event_file_obj.extension}
{#if result === null || result === false}
<span class="text-error-500"><span class="fas fa-exclamation-triangle mx-1"></span>Failed!</span>
{/if}
{:catch error}
<span class="text-error-500" title={error?.message}><span class="fas fa-exclamation-circle mx-0.5"></span>Error!</span>
{/await}
</span>
{:catch error}
<span class="text-error-500" title={error?.message}><span class="fas fa-exclamation-circle mx-0.5"></span>Error!</span>
{/await}
</span>
<span class="grow {text_size} {text_size_md} w-full max-w-full overflow-hidden text-ellipsis {btn_text_align}">
{ae_util.shorten_string({ string: event_file_obj.filename_no_ext, begin_length: 45, max_length: 65 })}
</span>
<span class="grow {text_size} {text_size_md} w-full max-w-full overflow-hidden text-ellipsis {btn_text_align}">
{ae_util.shorten_string({ string: event_file_obj.filename_no_ext, begin_length: 45, max_length: 65 })}
</span>
<span class="badge my-0 py-0.5 preset-tonal-success hover:preset-filled-success-500 text-xs xl:text-sm" class:hidden={!event_file_obj.file_purpose}>
{event_file_obj.file_purpose}
</span>
</button>
<span class="badge my-0 py-0.5 preset-tonal-success hover:preset-filled-success-500 text-xs xl:text-sm" class:hidden={!event_file_obj.file_purpose}>
{event_file_obj.file_purpose}
</span>
{/snippet}
</AE_Comp_Hosted_Files_Download_Button>
{/if}
</span>

View File

@@ -409,7 +409,7 @@
<!-- <Launcher_file_cont {event_file_obj} hide_created_on={false} show_bak_download={($ae_loc.trusted_access || $events_loc.launcher.trusted_access)} open_file_as={$lq__event_session_obj.type_code} poster_title={$lq__event_session_obj.title} /> -->
<!-- <a
href="{$ae_api.base_url}/event/file/{event_file_obj.event_file_id}/download?filename={event_file_obj.filename}&x_no_account_id_token=direct-download"
href="{$ae_api.base_url}/event/file/{event_file_obj.event_file_id}/download?filename={event_file_obj.filename}&key={$ae_api.account_id}"
class="btn btn-sm variant-soft-secondary m-0.5 *:hover:inline"
class:hidden={!ae_tmp.show__direct_download}
title={`Download this file:\n${event_file_obj.filename}\n[API] SHA256: ${event_file_obj.hash_sha256.slice(0, 10)}... Hosted ID: ${event_file_obj.hosted_file_id} Event File ID: ${event_file_obj.event_file_id}`}

View File

@@ -168,13 +168,13 @@
csv_row.push(
encodeURI(
`${$ae_api.base_url}/event/file/${ae_obj_li[i]?.event_file_id}/download?filename=${ae_util.clean_filename(ae_obj_li[i]?.filename)}&x_no_account_id_token=direct-download`
`${$ae_api.base_url}/event/file/${ae_obj_li[i]?.event_file_id}/download?filename=${ae_util.clean_filename(ae_obj_li[i]?.filename)}&key=${$ae_api.account_id}`
)
);
csv_row.push(
encodeURI(
`${$ae_api.base_url}/event/file/${ae_obj_li[i]?.event_file_id}/download?filename=${ae_obj_li[i]?.event_session_code}-${ae_util.clean_filename(ae_obj_li[i]?.filename)}&x_no_account_id_token=direct-download`
`${$ae_api.base_url}/event/file/${ae_obj_li[i]?.event_file_id}/download?filename=${ae_obj_li[i]?.event_session_code}-${ae_util.clean_filename(ae_obj_li[i]?.filename)}&key=${$ae_api.account_id}`
)
);
@@ -394,7 +394,7 @@
<a
href="{$ae_api.base_url}/event/file/{event_file_obj?.event_file_id}/download?filename={ae_util.clean_filename(
event_file_obj?.filename
)}&x_no_account_id_token=direct-download"
)}&key=${$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline"
title={`Download this file:\n${ae_util.clean_filename(event_file_obj?.filename)}\n[API] SHA256: ${event_file_obj?.hash_sha256.slice(0, 10)}...\nHosted ID: ${event_file_obj?.hosted_file_id} Event File ID: ${event_file_obj?.event_file_id}`}
>
@@ -403,7 +403,7 @@
</a>
<!-- <button
type="button"
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${ae_util.clean_filename(event_file_obj?.filename)}&x_no_account_id_token=direct-download`)}
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${ae_util.clean_filename(event_file_obj?.filename)}&key=${$ae_api.account_id}`)}
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs"
title="Copy the direct download file link: {ae_util.clean_filename(event_file_obj?.filename ?? 'unknown')}"
>
@@ -415,7 +415,7 @@
<MyClipboard
value={encodeURI(
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${ae_util.clean_filename(event_file_obj?.filename)}&x_no_account_id_token=direct-download`
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${ae_util.clean_filename(event_file_obj?.filename)}&key=${$ae_api.account_id}`
)}
btn_text="Copy Link"
btn_title="Copy the direct download file link: {ae_util.clean_filename(
@@ -435,7 +435,7 @@
.clean_filename(event_file_obj?.event_presentation_name)
.substring(0, 20)}-{ae_util.clean_filename(
event_file_obj?.event_presenter_full_name
)}.{event_file_obj?.extension}&x_no_account_id_token=direct-download"
)}.{event_file_obj?.extension}&key=${$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline"
title={`Download renamed with session name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`}
>
@@ -444,7 +444,7 @@
</a>
<!-- <button
type="button"
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&x_no_account_id_token=direct-download`)}
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&key=${$ae_api.account_id}`)}
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs"
title="Copy the renamed file link"
>
@@ -455,7 +455,7 @@
</button> -->
<MyClipboard
value={encodeURI(
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&x_no_account_id_token=direct-download`
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&key=${$ae_api.account_id}`
)}
btn_text="Copy Renamed"
btn_title="Copy the renamed file link"
@@ -475,7 +475,7 @@
.clean_filename(event_file_obj?.event_presentation_name)
.substring(0, 20)}-{ae_util.clean_filename(
event_file_obj?.event_presenter_full_name
)}.{event_file_obj?.extension}&x_no_account_id_token=direct-download"
)}.{event_file_obj?.extension}&key=${$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline"
title={`Download renamed with presentation name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`}
>
@@ -484,7 +484,7 @@
</a>
<!-- <button
type="button"
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&x_no_account_id_token=direct-download`)}
use:clipboard={encodeURI(`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&key=${$ae_api.account_id}`)}
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs"
title="Copy the renamed file link"
>
@@ -495,7 +495,7 @@
</button> -->
<MyClipboard
value={encodeURI(
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&x_no_account_id_token=direct-download`
`${$ae_api.base_url}/event/file/${event_file_obj?.event_file_id}/download?filename=${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}&key=${$ae_api.account_id}`
)}
btn_text="Copy Renamed"
btn_title="Copy the renamed file link"