From a1c3633a25d09633cac46a77b85f05a31b1a28b7 Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Mon, 13 Sep 2021 15:25:43 +0200 Subject: [PATCH] fix: Only check DataAccessor canHandle call for Documents --- src/storage/DataAccessorBasedStore.ts | 21 ++++++++++++------- .../storage/DataAccessorBasedStore.test.ts | 12 +++++------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/storage/DataAccessorBasedStore.ts b/src/storage/DataAccessorBasedStore.ts index 3ab8c3ef4..fca95564f 100644 --- a/src/storage/DataAccessorBasedStore.ts +++ b/src/storage/DataAccessorBasedStore.ts @@ -141,9 +141,6 @@ export class DataAccessorBasedStore implements ResourceStore { Promise { this.validateIdentifier(container); - // Ensure the representation is supported by the accessor - await this.accessor.canHandle(representation); - const parentMetadata = await this.getSafeNormalizedMetadata(container); // Solid, ยง5.3: "When a POST method request targets a resource without an existing representation, @@ -168,9 +165,16 @@ export class DataAccessorBasedStore implements ResourceStore { // Clients who want the server to assign a URI of a resource, MUST use the POST request." // https://solid.github.io/specification/protocol#resource-type-heuristics const newID = await this.createSafeUri(container, representation.metadata); + const isContainer = isContainerIdentifier(newID); + + // Ensure the representation is supported by the accessor + // Containers are not checked because uploaded representations are treated as metadata + if (!isContainer) { + await this.accessor.canHandle(representation); + } // Write the data. New containers should never be made for a POST request. - await this.writeData(newID, representation, isContainerIdentifier(newID), false, false); + await this.writeData(newID, representation, isContainer, false, false); return newID; } @@ -179,9 +183,6 @@ export class DataAccessorBasedStore implements ResourceStore { conditions?: Conditions): Promise { this.validateIdentifier(identifier); - // Ensure the representation is supported by the accessor - await this.accessor.canHandle(representation); - // Check if the resource already exists const oldMetadata = await this.getSafeNormalizedMetadata(identifier); @@ -202,6 +203,12 @@ export class DataAccessorBasedStore implements ResourceStore { throw new BadRequestHttpError('Containers should have a `/` at the end of their path, resources should not.'); } + // Ensure the representation is supported by the accessor + // Containers are not checked because uploaded representations are treated as metadata + if (!isContainer) { + await this.accessor.canHandle(representation); + } + this.validateConditions(conditions, oldMetadata); // Potentially have to create containers if it didn't exist yet diff --git a/test/unit/storage/DataAccessorBasedStore.test.ts b/test/unit/storage/DataAccessorBasedStore.test.ts index a3ffcd5c9..517ccf76b 100644 --- a/test/unit/storage/DataAccessorBasedStore.test.ts +++ b/test/unit/storage/DataAccessorBasedStore.test.ts @@ -214,12 +214,6 @@ describe('A DataAccessorBasedStore', (): void => { .rejects.toThrow(NotFoundHttpError); }); - it('checks if the DataAccessor supports the data.', async(): Promise => { - const resourceID = { path: `${root}container/` }; - representation.binary = false; - await expect(store.addResource(resourceID, representation)).rejects.toThrow(BadRequestHttpError); - }); - it('will 404 if the target does not exist.', async(): Promise => { const resourceID = { path: `${root}container/` }; await expect(store.addResource(resourceID, representation)).rejects.toThrow(NotFoundHttpError); @@ -241,6 +235,12 @@ describe('A DataAccessorBasedStore', (): void => { await expect(result).rejects.toThrow('The given path is not a container.'); }); + it('checks if the DataAccessor supports the data.', async(): Promise => { + const resourceID = { path: root }; + representation.binary = false; + await expect(store.addResource(resourceID, representation)).rejects.toThrow(BadRequestHttpError); + }); + it('throws a 412 if the conditions are not matched.', async(): Promise => { const resourceID = { path: root }; const conditions = new BasicConditions({ notMatchesETag: [ '*' ]});