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:
@@ -17,6 +17,7 @@
|
||||
events_trigger
|
||||
} 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';
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
@@ -166,174 +167,45 @@
|
||||
>
|
||||
<td class="event_file__file align-middle">
|
||||
{#if $events_sess.pres_mgmt?.show_field_edit__filename != event_file_obj.event_file_id}
|
||||
<button
|
||||
type="button"
|
||||
disabled={!allow_basic &&
|
||||
!allow_moderator &&
|
||||
!$ae_loc.trusted_access}
|
||||
onclick={() => {
|
||||
// ae_promises[event_file_obj.event_file_id]
|
||||
ae_promises[event_file_obj.event_file_id] =
|
||||
api.download_hosted_file({
|
||||
api_cfg: $ae_api,
|
||||
hosted_file_id: event_file_obj.hosted_file_id,
|
||||
return_file: true,
|
||||
filename: event_file_obj.filename,
|
||||
auto_download: true,
|
||||
log_lvl: 0
|
||||
});
|
||||
<div class="flex flex-col gap-2">
|
||||
<AE_Comp_Hosted_Files_Download_Button
|
||||
hosted_file_id={event_file_obj?.hosted_file_id}
|
||||
hosted_file_obj={event_file_obj}
|
||||
show_divider={true}
|
||||
show_direct_download={ae_tmp.show__direct_download}
|
||||
max_filename={30}
|
||||
classes="btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96"
|
||||
/>
|
||||
|
||||
}}
|
||||
class="btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96"
|
||||
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}`}
|
||||
>
|
||||
{#await ae_promises[event_file_obj.event_file_id]}
|
||||
<span class="fas fa-spinner fa-spin mx-1"></span>
|
||||
<span class="">
|
||||
Downloading
|
||||
{#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}%
|
||||
{/if}
|
||||
:
|
||||
</span>
|
||||
{:then}
|
||||
<!-- <span class="fas fa-download mx-1"></span> -->
|
||||
<span
|
||||
class="fas fa-{ae_util.file_extension_icon(
|
||||
event_file_obj.extension
|
||||
)}"
|
||||
></span>
|
||||
<!-- <span class="text-sm">
|
||||
Download:
|
||||
</span> -->
|
||||
{/await}
|
||||
|
||||
<span class="grow">
|
||||
{ae_util.shorten_filename({
|
||||
filename: event_file_obj.filename,
|
||||
max_length: 30
|
||||
})}
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="badge preset-tonal-success hover:preset-filled-success-500 text-sm"
|
||||
class:hidden={!event_file_obj.file_purpose}
|
||||
>
|
||||
{event_file_obj.file_purpose}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<span
|
||||
class="px-4 py-2 flex flex-col gap-0.5"
|
||||
class:hidden={!ae_tmp.show__direct_download}
|
||||
>
|
||||
<div class="flex flex-row gap-0.5">
|
||||
<span class="text-xs text-gray-500 w-32">
|
||||
Original:
|
||||
</span>
|
||||
<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"
|
||||
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}`}
|
||||
{#if ae_tmp.show__direct_download}
|
||||
<div
|
||||
class="px-4 py-2 flex flex-col gap-0.5 bg-surface-100/50 rounded-lg border border-surface-500/10"
|
||||
>
|
||||
<span class="fas fa-download mx-1"></span>
|
||||
<span class="hidden"> Download </span>
|
||||
</a>
|
||||
<!-- {#if clipboard_success}Copied!{:else}Copy Access Link{/if} -->
|
||||
<!-- <span class="fas fa-copy mx-1"></span> -->
|
||||
<!-- <Clipboard
|
||||
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`)}
|
||||
bind:success={clipboard_success}
|
||||
class="w-24"
|
||||
>
|
||||
{#if clipboard_success}Copied!{:else}Copy Link{/if}
|
||||
</Clipboard> -->
|
||||
<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`
|
||||
)}
|
||||
btn_text="Copy Link"
|
||||
btn_title="Copy the direct download link to the clipboard."
|
||||
btn_class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500 float-right m-1"
|
||||
></MyClipboard>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-0.5">
|
||||
<span class="text-xs text-gray-500 w-32">
|
||||
Session Name:
|
||||
</span>
|
||||
<a
|
||||
href="{$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"
|
||||
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}`}
|
||||
>
|
||||
<span class="fas fa-download mx-1"></span>
|
||||
<span class="hidden"> Renamed </span>
|
||||
</a>
|
||||
<!-- <Clipboard
|
||||
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`)}
|
||||
bind:success={clipboard_success}
|
||||
class="w-24"
|
||||
>
|
||||
{#if clipboard_success}Copied!{:else}Copy Renamed{/if}
|
||||
</Clipboard> -->
|
||||
<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`
|
||||
)}
|
||||
btn_text="Copy Renamed"
|
||||
btn_title="Copy the renamed download link to the clipboard."
|
||||
btn_class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500 float-right m-1"
|
||||
></MyClipboard>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-0.5">
|
||||
<span class="text-xs text-gray-500 w-32">
|
||||
Presentation Name:
|
||||
</span>
|
||||
<a
|
||||
href="{$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"
|
||||
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}`}
|
||||
>
|
||||
<span class="fas fa-download mx-1"></span>
|
||||
<span class="hidden"> Renamed </span>
|
||||
</a>
|
||||
<!-- {#if clipboard_success}Copied!{:else}Copy Access Link{/if} -->
|
||||
<!-- <span class="fas fa-copy mx-1"></span> -->
|
||||
<!-- <Clipboard
|
||||
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`)}
|
||||
bind:success={clipboard_success}
|
||||
class="w-24"
|
||||
>
|
||||
{#if clipboard_success}Copied!{:else}Copy Renamed{/if}
|
||||
</Clipboard> -->
|
||||
<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`
|
||||
)}
|
||||
btn_text="Copy Renamed"
|
||||
btn_title="Copy the renamed download link to the clipboard."
|
||||
btn_class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500 float-right m-1"
|
||||
></MyClipboard>
|
||||
</div>
|
||||
</span>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<span class="text-[10px] font-bold uppercase opacity-50 w-24">
|
||||
Access Link:
|
||||
</span>
|
||||
<MyClipboard
|
||||
value={encodeURI(
|
||||
`${$ae_api.base_url}/v3/action/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 Original"
|
||||
btn_title="Copy the direct download link to the clipboard."
|
||||
btn_class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500"
|
||||
></MyClipboard>
|
||||
|
||||
<MyClipboard
|
||||
value={encodeURI(
|
||||
`${$ae_api.base_url}/v3/action/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 download link to the clipboard."
|
||||
btn_class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500"
|
||||
></MyClipboard>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Show change filename input field here -->
|
||||
<span class="flex flex-col gap-1 text-sm">
|
||||
@@ -386,7 +258,7 @@
|
||||
})
|
||||
.then(function (update_results) {
|
||||
console.log(
|
||||
`Update results:`,
|
||||
`Update results:`,
|
||||
update_results
|
||||
);
|
||||
$events_sess.pres_mgmt.show_field_edit__filename = false;
|
||||
@@ -440,7 +312,7 @@
|
||||
class:preset-tonal-warning={$events_sess.pres_mgmt
|
||||
.show_field_edit__filename ==
|
||||
event_file_obj.event_file_id}
|
||||
title={`Rename this file? "${event_file_obj.filename}"`}
|
||||
title={`Rename this file? "${event_file_obj.filename}"}`}
|
||||
>
|
||||
<span class="fas fa-edit mx-1"></span>
|
||||
{#if $events_sess.pres_mgmt?.show_field_edit__filename == event_file_obj.event_file_id}
|
||||
@@ -467,7 +339,7 @@
|
||||
})
|
||||
.then(function (update_results) {
|
||||
console.log(
|
||||
`Update results:`,
|
||||
`Update results:`,
|
||||
update_results
|
||||
);
|
||||
|
||||
@@ -491,7 +363,8 @@
|
||||
title="Hide this file from the presentation launcher"
|
||||
>
|
||||
<!-- Users see this as the "Archive" option button -->
|
||||
<!-- {@html (event_file_obj?.hide ? '<span class="fas fa-archive m-1"></span> Unarchive' : '<span class="fas fa-archive m-1"></span> Archive')} -->
|
||||
<!-- {@html (event_file_obj?.hide ? '<span class="fas fa-archive m-1"></span> Unarchive' : '<span class="fas fa-archive m-1"></span> Archive')}
|
||||
-->
|
||||
|
||||
{#await ae_promises.update__event_file_obj}
|
||||
<span class="fas fa-spinner fa-spin mx-1"></span>
|
||||
@@ -504,10 +377,6 @@
|
||||
{:else}
|
||||
<span class="fas fa-eye-slash m-1"></span> Hide
|
||||
{/if}
|
||||
|
||||
<!-- {@html (event_file_obj?.hide ? '<span class="fas fa-eye m-1"></span> Unhide?' : '<span class="fas fa-eye-slash m-1"></span> Hide?')} -->
|
||||
<!-- <span class="fas fa-save mx-1"></span>
|
||||
Save {event_file_obj.extension} filename? -->
|
||||
{/await}
|
||||
</button>
|
||||
|
||||
@@ -592,7 +461,7 @@
|
||||
})
|
||||
.then(function (update_results) {
|
||||
console.log(
|
||||
`Update results:`,
|
||||
`Update results:`,
|
||||
update_results
|
||||
);
|
||||
$slct_trigger =
|
||||
@@ -765,4 +634,4 @@
|
||||
</section>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user