From 008d82f8f7b7f502349c0c1c4c94281face41f4f Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Wed, 17 May 2023 17:31:38 +0200 Subject: [PATCH 1/8] fix: filter folder by eq and startswith --- packages/core/upload/server/services/folder.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/core/upload/server/services/folder.js b/packages/core/upload/server/services/folder.js index d8b5769a156..a046ed2b427 100644 --- a/packages/core/upload/server/services/folder.js +++ b/packages/core/upload/server/services/folder.js @@ -56,16 +56,22 @@ const deleteByIds = async (ids = []) => { // delete files const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({ where: { - $or: pathsToDelete.map((path) => ({ folderPath: { $startsWith: path } })), + $or: pathsToDelete.flatMap((path) => [ + { folderPath: { $eq: path } }, + { folderPath: { $startsWith: `${path}/` } }, + ]), }, }); await Promise.all(filesToDelete.map((file) => getService('upload').remove(file))); - // delete folders + // delete folders and subfolders const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({ where: { - $or: pathsToDelete.map((path) => ({ path: { $startsWith: path } })), + $or: pathsToDelete.flatMap((path) => [ + { path: { $eq: path } }, + { path: { $startsWith: `${path}/` } }, + ]), }, }); From 15e71b69b0d5b435b0edf1dd893549bb52e94272 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Wed, 17 May 2023 17:32:00 +0200 Subject: [PATCH 2/8] test: delete of folder does not delete unintended folders --- .../core/upload/admin/folder-file.test.api.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index 2b3e82d43b5..e6965e5fff1 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -220,6 +220,33 @@ describe('Bulk actions for folders & files', () => { const existingfoldersIds = resFolder.body.data.map((f) => f.id); expect(existingfoldersIds).toEqual(expect.not.arrayContaining([folder.id])); }); + + test('Can delete folders without deleting others with similar name', async () => { + // Ensure the folder algo does not only delete by folders that start with the same path (startswith /1 matches /10 too) + + // Delete all previous folders, so first file path is /1 + await rq + .get('/upload/folders') + .then((res) => res.body.data.map((f) => f.id)) + .then((folderIds) => rq.post('/upload/actions/bulk-delete', { body: { folderIds } })); + + // Create folders + const folder1 = await createFolder('folderToDelete', null); + data.folders = await Promise.all( + Array.from({ length: 20 }).map((_, i) => createFolder(`${i}`, null)) + ); + + // Delete folder1 + await rq.post('/upload/actions/bulk-delete', { body: { folderIds: [folder1.id] } }); + + const afterFolderIds = await rq + .get('/upload/folders') + .then((res) => res.body.data.map((f) => f.id)); + + // Should include all folders except the one we deleted + expect(afterFolderIds.length).toBe(20); + expect(afterFolderIds).toEqual(expect.not.arrayContaining([folder1.id])); + }); }); describe('move', () => { From c4b966a03d1e0cdd4e2856f33790d1091288f84f Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Wed, 17 May 2023 17:36:39 +0200 Subject: [PATCH 3/8] chore: rename test --- api-tests/core/upload/admin/folder-file.test.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index e6965e5fff1..58c041ff0b6 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -221,7 +221,7 @@ describe('Bulk actions for folders & files', () => { expect(existingfoldersIds).toEqual(expect.not.arrayContaining([folder.id])); }); - test('Can delete folders without deleting others with similar name', async () => { + test('Can delete folders without deleting others with similar path', async () => { // Ensure the folder algo does not only delete by folders that start with the same path (startswith /1 matches /10 too) // Delete all previous folders, so first file path is /1 From a1a2453c15ad207504c6269635204925bd4be15d Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Wed, 17 May 2023 17:51:02 +0200 Subject: [PATCH 4/8] chore: rename tests --- api-tests/core/upload/admin/folder-file.test.api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index 58c041ff0b6..4b029b61d6a 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -239,13 +239,13 @@ describe('Bulk actions for folders & files', () => { // Delete folder1 await rq.post('/upload/actions/bulk-delete', { body: { folderIds: [folder1.id] } }); - const afterFolderIds = await rq + const folderIds = await rq .get('/upload/folders') .then((res) => res.body.data.map((f) => f.id)); // Should include all folders except the one we deleted - expect(afterFolderIds.length).toBe(20); - expect(afterFolderIds).toEqual(expect.not.arrayContaining([folder1.id])); + expect(folderIds.length).toBe(20); + expect(folderIds).toEqual(expect.not.arrayContaining([folder1.id])); }); }); From a781a8a36824175d0a51ab02a64bff7f6b529172 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Thu, 18 May 2023 09:39:28 +0200 Subject: [PATCH 5/8] fix: do not assign result to data folders --- api-tests/core/upload/admin/folder-file.test.api.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index 4b029b61d6a..8fafacf80f3 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -232,8 +232,8 @@ describe('Bulk actions for folders & files', () => { // Create folders const folder1 = await createFolder('folderToDelete', null); - data.folders = await Promise.all( - Array.from({ length: 20 }).map((_, i) => createFolder(`${i}`, null)) + await Promise.all( + Array.from({ length: 20 }).map((_, i) => createFolder(`folder-${i}`, null)) ); // Delete folder1 From 2ad193e1a39aa8d0d4fdb9e1fba179e89da67b85 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Fri, 19 May 2023 09:35:35 +0200 Subject: [PATCH 6/8] chore: logs to debug test --- api-tests/core/upload/admin/folder-file.test.api.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index 8fafacf80f3..c99fb6e04eb 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -20,6 +20,7 @@ const createFolder = async (name, parent = null) => { url: '/upload/folders', body: { name, parent }, }); + console.log('createFolder', res.body.data); return res.body.data; }; @@ -233,12 +234,15 @@ describe('Bulk actions for folders & files', () => { // Create folders const folder1 = await createFolder('folderToDelete', null); await Promise.all( - Array.from({ length: 20 }).map((_, i) => createFolder(`folder-${i}`, null)) + Array.from({ length: 20 }).map((_, i) => createFolder(`folderToKeep-${i}`, null)) ); // Delete folder1 - await rq.post('/upload/actions/bulk-delete', { body: { folderIds: [folder1.id] } }); + const res = await rq.post('/upload/actions/bulk-delete', { + body: { folderIds: [folder1.id] }, + }); + console.log('deleteFolders', JSON.stringify(res.body, null, 2)); const folderIds = await rq .get('/upload/folders') .then((res) => res.body.data.map((f) => f.id)); From c266835d04305526131eca3ce03654d8dbc62b68 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Fri, 19 May 2023 10:35:15 +0200 Subject: [PATCH 7/8] chore: more logs --- .../core/upload/admin/folder-file.test.api.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index c99fb6e04eb..483cf9338b5 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -15,12 +15,19 @@ const data = { }; const createFolder = async (name, parent = null) => { + const log = name.startsWith('folderToKeep'); + if (log) { + console.log('====================='); + console.log('createFolderBefore', name, parent); + } const res = await rq({ method: 'POST', url: '/upload/folders', body: { name, parent }, }); - console.log('createFolder', res.body.data); + if (log) { + console.log('createFolder', res.body.data); + } return res.body.data; }; @@ -233,10 +240,12 @@ describe('Bulk actions for folders & files', () => { // Create folders const folder1 = await createFolder('folderToDelete', null); - await Promise.all( - Array.from({ length: 20 }).map((_, i) => createFolder(`folderToKeep-${i}`, null)) - ); - + // await Promise.all( + // Array.from({ length: 20 }).map((_, i) => createFolder(`folderToKeep-${i}`, null)) + // ); + for (let i = 0; i < 20; i++) { + await createFolder(`folderToKeep-${i}`, null); + } // Delete folder1 const res = await rq.post('/upload/actions/bulk-delete', { body: { folderIds: [folder1.id] }, From 1b00e1d8e258c245776ab809e62d253b79230fa2 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Fri, 19 May 2023 11:22:17 +0200 Subject: [PATCH 8/8] remove logs --- .../core/upload/admin/folder-file.test.api.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/api-tests/core/upload/admin/folder-file.test.api.js b/api-tests/core/upload/admin/folder-file.test.api.js index 483cf9338b5..b299a88a1e5 100644 --- a/api-tests/core/upload/admin/folder-file.test.api.js +++ b/api-tests/core/upload/admin/folder-file.test.api.js @@ -15,19 +15,11 @@ const data = { }; const createFolder = async (name, parent = null) => { - const log = name.startsWith('folderToKeep'); - if (log) { - console.log('====================='); - console.log('createFolderBefore', name, parent); - } const res = await rq({ method: 'POST', url: '/upload/folders', body: { name, parent }, }); - if (log) { - console.log('createFolder', res.body.data); - } return res.body.data; }; @@ -240,18 +232,14 @@ describe('Bulk actions for folders & files', () => { // Create folders const folder1 = await createFolder('folderToDelete', null); - // await Promise.all( - // Array.from({ length: 20 }).map((_, i) => createFolder(`folderToKeep-${i}`, null)) - // ); for (let i = 0; i < 20; i++) { await createFolder(`folderToKeep-${i}`, null); } // Delete folder1 - const res = await rq.post('/upload/actions/bulk-delete', { + await rq.post('/upload/actions/bulk-delete', { body: { folderIds: [folder1.id] }, }); - console.log('deleteFolders', JSON.stringify(res.body, null, 2)); const folderIds = await rq .get('/upload/folders') .then((res) => res.body.data.map((f) => f.id));