From c3be74c450ba7d57ccfc9f6c0463478e579682a0 Mon Sep 17 00:00:00 2001 From: Jonathan Jogenfors Date: Sun, 22 Dec 2024 23:22:16 +0100 Subject: [PATCH] fix(server): support import paths with special chars (#14856) --- e2e/src/api/specs/library.e2e-spec.ts | 61 +++++++++++++++++++ server/src/repositories/storage.repository.ts | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/e2e/src/api/specs/library.e2e-spec.ts b/e2e/src/api/specs/library.e2e-spec.ts index dde2cf79eb..23cdf092cf 100644 --- a/e2e/src/api/specs/library.e2e-spec.ts +++ b/e2e/src/api/specs/library.e2e-spec.ts @@ -403,6 +403,67 @@ describe('/libraries', () => { utils.removeImageFile(`${testAssetDir}/temp/folder} b/assetB.png`); }); + const annoyingChars = [ + "'", + '"', + '`', + '*', + '{', + '}', + ',', + '(', + ')', + '[', + ']', + '?', + '!', + '@', + '#', + '$', + '%', + '^', + '&', + '=', + '+', + '~', + '|', + '<', + '>', + ';', + ':', + '/', // We never got backslashes to work + ]; + + it.each(annoyingChars)('should scan multiple import paths with %s', async (char) => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/folder${char}1`, `${testAssetDirInternal}/temp/folder${char}2`], + }); + + utils.createImageFile(`${testAssetDir}/temp/folder${char}1/asset1.png`); + utils.createImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`); + + const { status } = await request(app) + .post(`/libraries/${library.id}/scan`) + .set('Authorization', `Bearer ${admin.accessToken}`) + .send(); + expect(status).toBe(204); + + await utils.waitForQueueFinish(admin.accessToken, 'library'); + + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(assets.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ originalPath: expect.stringContaining(`folder${char}1/asset1.png`) }), + expect.objectContaining({ originalPath: expect.stringContaining(`folder${char}2/asset2.png`) }), + ]), + ); + + utils.removeImageFile(`${testAssetDir}/temp/folder${char}1/asset1.png`); + utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`); + }); + it('should reimport a modified file', async () => { const library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, diff --git a/server/src/repositories/storage.repository.ts b/server/src/repositories/storage.repository.ts index e4c0c68451..a8d3db15d8 100644 --- a/server/src/repositories/storage.repository.ts +++ b/server/src/repositories/storage.repository.ts @@ -214,7 +214,7 @@ export class StorageRepository implements IStorageRepository { } private asGlob(pathToCrawl: string): string { - const escapedPath = escapePath(pathToCrawl); + const escapedPath = escapePath(pathToCrawl).replaceAll('"', '["]').replaceAll("'", "[']").replaceAll('`', '[`]'); const extensions = `*{${mimeTypes.getSupportedFileExtensions().join(',')}}`; return `${escapedPath}/**/${extensions}`; }