From f006aa73b5648028b61e2237f8170bdb137ab344 Mon Sep 17 00:00:00 2001 From: alma Date: Fri, 16 Jan 2026 11:55:59 +0100 Subject: [PATCH] Pages corrections --- lib/s3.ts | 75 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/lib/s3.ts b/lib/s3.ts index 781f882..bb57a54 100644 --- a/lib/s3.ts +++ b/lib/s3.ts @@ -112,30 +112,80 @@ export async function deleteObject(key: string): Promise { export async function listUserObjects(userId: string, folder: string): Promise> { // Normalize folder name to lowercase for consistency const normalizedFolder = folder.toLowerCase(); - const prefix = `user-${userId}/${normalizedFolder}/`; + + // Try both with and without trailing slash to handle different MinIO configurations + const prefixWithSlash = `user-${userId}/${normalizedFolder}/`; + const prefixWithoutSlash = `user-${userId}/${normalizedFolder}`; + + console.log(`[listUserObjects] Listing objects with prefix: ${prefixWithSlash} in bucket: ${S3_CONFIG.bucket}`); const command = new ListObjectsV2Command({ Bucket: S3_CONFIG.bucket, - Prefix: prefix, + Prefix: prefixWithSlash, // Don't use Delimiter to get all objects, not just "folders" }); const response = await s3Client.send(command); const objects = response.Contents || []; + console.log(`[listUserObjects] Found ${objects.length} raw objects for prefix ${prefixWithSlash}`); + + // Log all keys for debugging + if (objects.length > 0) { + console.log(`[listUserObjects] Raw object keys:`, objects.map(obj => obj.Key)); + } else { + // If no objects found with slash, try without slash + console.log(`[listUserObjects] No objects found with slash, trying without slash: ${prefixWithoutSlash}`); + const commandWithoutSlash = new ListObjectsV2Command({ + Bucket: S3_CONFIG.bucket, + Prefix: prefixWithoutSlash, + }); + const responseWithoutSlash = await s3Client.send(commandWithoutSlash); + const objectsWithoutSlash = responseWithoutSlash.Contents || []; + console.log(`[listUserObjects] Found ${objectsWithoutSlash.length} objects without slash`); + if (objectsWithoutSlash.length > 0) { + console.log(`[listUserObjects] Raw object keys (no slash):`, objectsWithoutSlash.map(obj => obj.Key)); + // Merge results + objects.push(...objectsWithoutSlash); + } + } + // Filter out: // - Objects that are "folders" (end with /) // - Placeholder files - // - Objects that don't match the exact prefix (shouldn't happen but safety check) - return objects + // - Objects that don't match our prefix (with or without slash) + const filtered = objects .filter(obj => { - if (!obj.Key) return false; + if (!obj.Key) { + console.log(`[listUserObjects] Skipping object with no Key`); + return false; + } // Exclude folder markers (end with /) - if (obj.Key.endsWith('/')) return false; + if (obj.Key.endsWith('/')) { + console.log(`[listUserObjects] Skipping folder marker: ${obj.Key}`); + return false; + } // Exclude placeholder files - if (obj.Key.includes('.placeholder')) return false; - // Ensure it matches our prefix - if (!obj.Key.startsWith(prefix)) return false; + if (obj.Key.includes('.placeholder')) { + console.log(`[listUserObjects] Skipping placeholder: ${obj.Key}`); + return false; + } + // Ensure it matches our prefix (with or without slash) + if (!obj.Key.startsWith(prefixWithSlash) && !obj.Key.startsWith(prefixWithoutSlash)) { + console.log(`[listUserObjects] Key doesn't match prefix: ${obj.Key} (prefixes: ${prefixWithSlash} or ${prefixWithoutSlash})`); + return false; + } + // Additional check: ensure it's actually in the folder (not a subfolder) + const keyWithoutPrefix = obj.Key.startsWith(prefixWithSlash) + ? obj.Key.substring(prefixWithSlash.length) + : obj.Key.substring(prefixWithoutSlash.length + 1); // +1 for the / after folder name + + // If there's another / in the remaining path, it's in a subfolder, skip it + if (keyWithoutPrefix.includes('/')) { + console.log(`[listUserObjects] Skipping subfolder file: ${obj.Key}`); + return false; + } + return true; }) .map(obj => ({ @@ -144,6 +194,13 @@ export async function listUserObjects(userId: string, folder: string): Promise 0) { + console.log(`[listUserObjects] Filtered object keys:`, filtered.map(obj => obj.key)); + } + + return filtered; } /**