From 93e53b3d24f6071f8ec98a916ca6d8aa0ae80e97 Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Wed, 27 Jan 2021 10:20:44 +0100 Subject: [PATCH] fix: Only require append permissions on POST requests --- .../permissions/MethodPermissionsExtractor.ts | 8 +++++--- test/integration/LdpHandlerWithAuth.test.ts | 20 +++++++++++++++++++ ....ts => MethodPermissionsExtractor.test.ts} | 4 ++-- 3 files changed, 27 insertions(+), 5 deletions(-) rename test/unit/ldp/permissions/{BasePermissionsExtractor.test.ts => MethodPermissionsExtractor.test.ts} (95%) diff --git a/src/ldp/permissions/MethodPermissionsExtractor.ts b/src/ldp/permissions/MethodPermissionsExtractor.ts index 2a06c3db8..7fad3d8c0 100644 --- a/src/ldp/permissions/MethodPermissionsExtractor.ts +++ b/src/ldp/permissions/MethodPermissionsExtractor.ts @@ -4,8 +4,9 @@ import type { PermissionSet } from './PermissionSet'; import { PermissionsExtractor } from './PermissionsExtractor'; const READ_METHODS = new Set([ 'GET', 'HEAD' ]); -const WRITE_METHODS = new Set([ 'POST', 'PUT', 'DELETE' ]); -const SUPPORTED_METHODS = new Set([ ...READ_METHODS, ...WRITE_METHODS ]); +const WRITE_METHODS = new Set([ 'PUT', 'DELETE' ]); +const APPEND_METHODS = new Set([ 'POST' ]); +const SUPPORTED_METHODS = new Set([ ...READ_METHODS, ...WRITE_METHODS, ...APPEND_METHODS ]); /** * Generates permissions for the base set of methods that always require the same permissions. @@ -21,6 +22,7 @@ export class MethodPermissionsExtractor extends PermissionsExtractor { public async handle({ method }: Operation): Promise { const read = READ_METHODS.has(method); const write = WRITE_METHODS.has(method); - return { read, write, append: write }; + const append = write || APPEND_METHODS.has(method); + return { read, write, append }; } } diff --git a/test/integration/LdpHandlerWithAuth.test.ts b/test/integration/LdpHandlerWithAuth.test.ts index 1e0b42313..661325bb7 100644 --- a/test/integration/LdpHandlerWithAuth.test.ts +++ b/test/integration/LdpHandlerWithAuth.test.ts @@ -117,4 +117,24 @@ describe.each(stores)('An LDP handler with auth using %s', (name, { storeUrn, se response = await resourceHelper.deleteResource('http://test.com/permanent.txt', true); expect(response.statusCode).toBe(401); }); + + it('can add files but not write to them if append is allowed.', async(): Promise => { + // Set acl + await aclHelper.setSimpleAcl({ read: true, write: false, append: true }, 'agent'); + + // Add a file + let response = await resourceHelper.createResource( + '../assets/testfile2.txt', 'testfile2.txt', 'text/plain', true, + ); + expect(response.statusCode).toBe(201); + + const id = response._getHeaders().location; + response = await resourceHelper.performRequestWithBody( + new URL(id), + 'PUT', + { 'content-type': 'text/plain', 'transfer-encoding': 'chunked' }, + Buffer.from('data'), + ); + expect(response.statusCode).toBe(401); + }); }); diff --git a/test/unit/ldp/permissions/BasePermissionsExtractor.test.ts b/test/unit/ldp/permissions/MethodPermissionsExtractor.test.ts similarity index 95% rename from test/unit/ldp/permissions/BasePermissionsExtractor.test.ts rename to test/unit/ldp/permissions/MethodPermissionsExtractor.test.ts index 4475df98b..0aa455218 100644 --- a/test/unit/ldp/permissions/BasePermissionsExtractor.test.ts +++ b/test/unit/ldp/permissions/MethodPermissionsExtractor.test.ts @@ -30,11 +30,11 @@ describe('A MethodPermissionsExtractor', (): void => { }); }); - it('requires write for POST operations.', async(): Promise => { + it('requires append for POST operations.', async(): Promise => { await expect(extractor.handle({ method: 'POST' } as Operation)).resolves.toEqual({ read: false, append: true, - write: true, + write: false, }); });