fix: Correctly handle acl behaviour for acl identifiers

This commit is contained in:
Joachim Van Herwegen
2020-11-18 16:48:12 +01:00
parent de16af2104
commit ee312910d7
7 changed files with 77 additions and 47 deletions

View File

@@ -3,18 +3,32 @@ import { UrlBasedAclManager } from '../../../src/authorization/UrlBasedAclManage
describe('An UrlBasedAclManager', (): void => {
const manager = new UrlBasedAclManager();
it('generates acl URLs by adding an .acl extension.', async(): Promise<void> => {
await expect(manager.getAcl({ path: '/foo/bar' })).resolves.toEqual({ path: '/foo/bar.acl' });
describe('#getAcl', (): void => {
it('generates acl URLs by adding an .acl extension.', async(): Promise<void> => {
await expect(manager.getAclDocument({ path: '/foo/bar' })).resolves.toEqual({ path: '/foo/bar.acl' });
});
it('returns the identifier if the input is already an acl resource.', async(): Promise<void> => {
await expect(manager.getAclDocument({ path: '/foo/bar.acl' })).resolves.toEqual({ path: '/foo/bar.acl' });
});
});
it('returns the identifier if the input is already an acl file.', async(): Promise<void> => {
await expect(manager.getAcl({ path: '/foo/bar.acl' })).resolves.toEqual({ path: '/foo/bar.acl' });
describe('#isAcl', (): void => {
it('checks if a resource is an acl resource by looking at the extension.', async(): Promise<void> => {
await expect(manager.isAclDocument({ path: '/foo/bar' })).resolves.toBeFalsy();
await expect(manager.isAclDocument({ path: '/foo/bar/' })).resolves.toBeFalsy();
await expect(manager.isAclDocument({ path: '/foo/bar.acl' })).resolves.toBeTruthy();
await expect(manager.isAclDocument({ path: '/foo/bar.acl/' })).resolves.toBeTruthy();
});
});
it('checks if a resource is an acl file by looking at the extension.', async(): Promise<void> => {
await expect(manager.isAcl({ path: '/foo/bar' })).resolves.toBeFalsy();
await expect(manager.isAcl({ path: '/foo/bar/' })).resolves.toBeFalsy();
await expect(manager.isAcl({ path: '/foo/bar.acl' })).resolves.toBeTruthy();
await expect(manager.isAcl({ path: '/foo/bar.acl/' })).resolves.toBeTruthy();
describe('#getResource', (): void => {
it('generates non-acl resource URLs by removing the .acl extension.', async(): Promise<void> => {
await expect(manager.getAclConstrainedResource({ path: '/foo/bar.acl' })).resolves.toEqual({ path: '/foo/bar' });
});
it('returns the identifier if the input is already a non-acl resource.', async(): Promise<void> => {
await expect(manager.getAclConstrainedResource({ path: '/foo/bar' })).resolves.toEqual({ path: '/foo/bar' });
});
});
});

View File

@@ -19,9 +19,11 @@ const acl = 'http://www.w3.org/ns/auth/acl#';
describe('A WebAclAuthorizer', (): void => {
let authorizer: WebAclAuthorizer;
const aclManager: AclManager = {
getAcl: async(id: ResourceIdentifier): Promise<ResourceIdentifier> =>
getAclDocument: async(id: ResourceIdentifier): Promise<ResourceIdentifier> =>
id.path.endsWith('.acl') ? id : { path: `${id.path}.acl` },
isAcl: async(id: ResourceIdentifier): Promise<boolean> => id.path.endsWith('.acl'),
isAclDocument: async(id: ResourceIdentifier): Promise<boolean> => id.path.endsWith('.acl'),
getAclConstrainedResource: async(id: ResourceIdentifier): Promise<ResourceIdentifier> =>
!id.path.endsWith('.acl') ? id : { path: id.path.slice(0, -4) },
};
let permissions: PermissionSet;
let credentials: Credentials;
@@ -134,9 +136,9 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Control`)),
]) } as Representation),
} as unknown as ResourceStore;
identifier = await aclManager.getAcl(identifier);
const aclIdentifier = await aclManager.getAclDocument(identifier);
authorizer = new WebAclAuthorizer(aclManager, store);
await expect(authorizer.handle({ identifier, permissions, credentials })).resolves.toBeUndefined();
await expect(authorizer.handle({ identifier: aclIdentifier, permissions, credentials })).resolves.toBeUndefined();
});
it('errors if an agent tries to edit the acl file without control permissions.', async(): Promise<void> => {
@@ -149,7 +151,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
]) } as Representation),
} as unknown as ResourceStore;
identifier = await aclManager.getAcl(identifier);
identifier = await aclManager.getAclDocument(identifier);
authorizer = new WebAclAuthorizer(aclManager, store);
await expect(authorizer.handle({ identifier, permissions, credentials })).rejects.toThrow(ForbiddenHttpError);
});

View File

@@ -1,3 +1,4 @@
import type { AclManager } from '../../../src/authorization/AclManager';
import { Setup } from '../../../src/init/Setup';
import type { ResourceIdentifier } from '../../../src/ldp/representation/ResourceIdentifier';
import { VoidLoggerFactory } from '../../../src/logging/VoidLoggerFactory';
@@ -5,15 +6,15 @@ import { VoidLoggerFactory } from '../../../src/logging/VoidLoggerFactory';
describe('Setup', (): void => {
let serverFactory: any;
let store: any;
let aclManager: any;
let aclManager: AclManager;
let setup: Setup;
beforeEach(async(): Promise<void> => {
store = {
setRepresentation: jest.fn(async(): Promise<void> => undefined),
};
aclManager = {
getAcl: jest.fn(async(): Promise<ResourceIdentifier> => ({ path: 'http://test.com/.acl' })),
};
getAclDocument: jest.fn(async(): Promise<ResourceIdentifier> => ({ path: 'http://test.com/.acl' })),
} as any;
serverFactory = {
startServer: jest.fn(),
};
@@ -27,7 +28,7 @@ describe('Setup', (): void => {
it('invokes ACL initialization.', async(): Promise<void> => {
await setup.setup();
expect(aclManager.getAcl).toHaveBeenCalledWith({ path: 'http://localhost:3000/' });
expect(aclManager.getAclDocument).toHaveBeenCalledWith({ path: 'http://localhost:3000/' });
expect(store.setRepresentation).toHaveBeenCalledTimes(1);
});
});