From 9af9977749d0bd34f14402adee12be8c54b67463 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 Jun 2025 15:27:57 +0200 Subject: [PATCH] updates --- pages/dashboard/file-browser.vue | 1 + server/api/files/delete.ts | 48 ++++++++++++++++++++++++++++---- server/api/files/upload.ts | 7 ++++- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/pages/dashboard/file-browser.vue b/pages/dashboard/file-browser.vue index e4cd93b..fbc6172 100644 --- a/pages/dashboard/file-browser.vue +++ b/pages/dashboard/file-browser.vue @@ -754,6 +754,7 @@ const deleteFile = async () => { body: { fileName: fileToDelete.value.name, isFolder: fileToDelete.value.isFolder, + bucket: fileToDelete.value.bucket || 'client-portal', }, }); diff --git a/server/api/files/delete.ts b/server/api/files/delete.ts index c1967e4..7274acf 100644 --- a/server/api/files/delete.ts +++ b/server/api/files/delete.ts @@ -1,9 +1,10 @@ -import { deleteFile, deleteFolder } from '~/server/utils/minio'; +import { deleteFile, deleteFolder, getMinioClient } from '~/server/utils/minio'; export default defineEventHandler(async (event) => { try { const body = await readBody(event); - const { fileName, isFolder } = body; + const { fileName, isFolder, bucket } = body; + const targetBucket = bucket || 'client-portal'; if (!fileName) { throw createError({ @@ -21,10 +22,47 @@ export default defineEventHandler(async (event) => { } // Delete folder or file based on type - if (isFolder) { - await deleteFolder(fileName); + if (targetBucket === 'client-portal') { + // Use existing functions for default bucket + if (isFolder) { + await deleteFolder(fileName); + } else { + await deleteFile(fileName); + } } else { - await deleteFile(fileName); + // For other buckets, use MinIO client directly + const client = getMinioClient(); + + if (isFolder) { + // List all objects in the folder and delete them + const objectsList: string[] = []; + + await new Promise((resolve, reject) => { + const stream = client.listObjectsV2(targetBucket, fileName, true); + + stream.on('data', (obj) => { + if (obj && obj.name) { + objectsList.push(obj.name); + } + }); + + stream.on('error', reject); + + stream.on('end', async () => { + try { + if (objectsList.length > 0) { + await client.removeObjects(targetBucket, objectsList); + } + resolve(true); + } catch (error) { + reject(error); + } + }); + }); + } else { + // Delete single file + await client.removeObject(targetBucket, fileName); + } } // Log audit event diff --git a/server/api/files/upload.ts b/server/api/files/upload.ts index bf9bd87..2784a09 100644 --- a/server/api/files/upload.ts +++ b/server/api/files/upload.ts @@ -34,7 +34,12 @@ export default defineEventHandler(async (event) => { const fileName = `${timestamp}-${sanitizedName}`; // Construct full path including current folder - const fullPath = currentPath ? `${currentPath}${fileName}` : fileName; + // Ensure currentPath ends with / if it's a folder + let normalizedPath = currentPath; + if (normalizedPath && !normalizedPath.endsWith('/')) { + normalizedPath += '/'; + } + const fullPath = normalizedPath ? `${normalizedPath}${fileName}` : fileName; // Get content type const contentType = mime.lookup(uploadedFile.originalFilename || '') || 'application/octet-stream';