From d133a85fe384373da6a12e6c9cc23917a97843ae Mon Sep 17 00:00:00 2001 From: Acbox Date: Sun, 29 Mar 2026 17:43:42 +0800 Subject: [PATCH] fix(web): attach JWT token to file download URL to fix auth error Browser tag downloads don't send Authorization headers, causing "missing or malformed jwt" errors. Pass token via query param which the backend JWT middleware already supports. --- .../components/file-manager/file-viewer.vue | 20 +++++++--------- .../web/src/components/file-manager/index.vue | 24 ++++++++----------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/apps/web/src/components/file-manager/file-viewer.vue b/apps/web/src/components/file-manager/file-viewer.vue index 87ccd00f..9f82ad18 100644 --- a/apps/web/src/components/file-manager/file-viewer.vue +++ b/apps/web/src/components/file-manager/file-viewer.vue @@ -2,7 +2,7 @@ import { ref, watch, computed, onBeforeUnmount } from 'vue' import { useI18n } from 'vue-i18n' import { toast } from 'vue-sonner' -import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' +import { File, Download, X } from 'lucide-vue-next' import { Button, Spinner } from '@memohai/ui' import { getBotsByBotIdContainerFsRead, @@ -93,7 +93,8 @@ async function handleSave() { } function handleDownload() { - const url = `/api/bots/${props.botId}/container/fs/download?path=${encodeURIComponent(filePath.value)}` + const token = localStorage.getItem('token') ?? '' + const url = `/api/bots/${props.botId}/container/fs/download?path=${encodeURIComponent(filePath.value)}&token=${encodeURIComponent(token)}` const a = document.createElement('a') a.href = url a.download = filename.value @@ -128,8 +129,7 @@ onBeforeUnmount(() => {
- {{ filename }} @@ -157,8 +157,7 @@ onBeforeUnmount(() => { size="sm" @click="handleDownload" > - {{ t('bots.files.download') }} @@ -169,8 +168,7 @@ onBeforeUnmount(() => { class="size-7 p-0" @click="emit('close')" > - @@ -209,8 +207,7 @@ onBeforeUnmount(() => { v-else class="flex h-full flex-col items-center justify-center gap-3 text-muted-foreground" > -

@@ -221,8 +218,7 @@ onBeforeUnmount(() => { size="sm" @click="handleDownload" > - {{ t('bots.files.download') }} diff --git a/apps/web/src/components/file-manager/index.vue b/apps/web/src/components/file-manager/index.vue index f7ea6b9c..8dbb4eeb 100644 --- a/apps/web/src/components/file-manager/index.vue +++ b/apps/web/src/components/file-manager/index.vue @@ -3,7 +3,7 @@ import { ref, watch, onMounted } from 'vue' import { useI18n } from 'vue-i18n' import { useRoute, useRouter } from 'vue-router' import { toast } from 'vue-sonner' -import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' +import { ChevronRight, Folder, Upload, FolderPlus, RefreshCw } from 'lucide-vue-next' import { useSyncedQueryParam } from '@/composables/useSyncedQueryParam' import { Button, @@ -238,7 +238,8 @@ async function handleDelete() { // Download function handleDownload(entry: HandlersFsFileInfo) { - const url = `/api/bots/${props.botId}/container/fs/download?path=${encodeURIComponent(entry.path ?? '')}` + const token = localStorage.getItem('token') ?? '' + const url = `/api/bots/${props.botId}/container/fs/download?path=${encodeURIComponent(entry.path ?? '')}&token=${encodeURIComponent(token)}` const a = document.createElement('a') a.href = url a.download = entry.name ?? 'file' @@ -282,20 +283,18 @@ defineExpose({ navigateTo, openFileByPath }) v-for="(seg, idx) in pathSegments(currentPath)" :key="seg.path" > - @@ -315,8 +314,7 @@ defineExpose({ navigateTo, openFileByPath }) size="sm" @click="triggerUpload" > - {{ t('bots.files.upload') }} @@ -326,8 +324,7 @@ defineExpose({ navigateTo, openFileByPath }) size="sm" @click="openMkdirDialog" > - {{ t('bots.files.newFolder') }} @@ -339,8 +336,7 @@ defineExpose({ navigateTo, openFileByPath }) :disabled="listLoading" @click="() => loadDirectory(currentPath)" > -