Skip to content

Commit

Permalink
refactor: Improve logging for access control.
Browse files Browse the repository at this point in the history
  • Loading branch information
RubenVerborgh committed Jan 15, 2021
1 parent c469df2 commit 7dcde1e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
27 changes: 14 additions & 13 deletions src/authorization/WebAclAuthorizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,21 @@ export class WebAclAuthorizer extends Authorizer {
* Will throw an error if this is not the case.
* @param input - Relevant data needed to check if access can be granted.
*/
public async handle(input: AuthorizerArgs): Promise<void> {
const store = await this.getAclRecursive(input.identifier);
if (await this.aclManager.isAclDocument(input.identifier)) {
// Solid, §4.3.3: "To discover, read, create, or modify an ACL auxiliary resource, an acl:agent MUST
// have acl:Control privileges per the ACL inheritance algorithm on the resource directly associated with it."
// https://solid.github.io/specification/protocol#auxiliary-resources-reserved
this.checkPermission(input.credentials, store, 'control');
} else {
(Object.keys(input.permissions) as (keyof PermissionSet)[]).forEach((key): void => {
if (input.permissions[key]) {
this.checkPermission(input.credentials, store, key);
}
});
public async handle({ identifier, permissions, credentials }: AuthorizerArgs): Promise<void> {
// Solid, §4.3.3: "To discover, read, create, or modify an ACL auxiliary resource, an acl:agent MUST
// have acl:Control privileges per the ACL inheritance algorithm on the resource directly associated with it."
// https://solid.github.io/specification/protocol#auxiliary-resources-reserved
const modes = await this.aclManager.isAclDocument(identifier) ?
[ 'control' ] :
(Object.keys(permissions) as (keyof PermissionSet)[]).filter((key): boolean => permissions[key]);

// Verify that all required modes are set for the given agent
this.logger.debug(`Checking if ${credentials.webId} has ${modes.join()} permissions for ${identifier.path}`);
const store = await this.getAclRecursive(identifier);
for (const mode of modes) {
this.checkPermission(credentials, store, mode);
}
this.logger.debug(`${credentials.webId} has ${modes.join()} permissions for ${identifier.path}`);
}

/**
Expand Down
9 changes: 8 additions & 1 deletion test/unit/authorization/WebAclAuthorizer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('A WebAclAuthorizer', (): void => {
permissions = {
read: true,
append: false,
write: false,
write: true,
};
credentials = {};
identifier = { path: 'http://test.com/foo' };
Expand All @@ -56,6 +56,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agentClass`), nn('http://xmlns.com/foaf/0.1/Agent')),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
await expect(authorizer.handle({ identifier, permissions, credentials })).resolves.toBeUndefined();
});
Expand All @@ -70,6 +71,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agentClass`), nn('http://xmlns.com/foaf/0.1/Agent')),
quad(nn('auth'), nn(`${acl}default`), nn(identifierStrategy.getParentContainer(identifier).path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]),
} as Representation;
};
Expand All @@ -81,6 +83,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agentClass`), nn('http://xmlns.com/foaf/0.1/AuthenticatedAgent')),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
credentials.webId = 'http://test.com/user';
await expect(authorizer.handle({ identifier, permissions, credentials })).resolves.toBeUndefined();
Expand All @@ -91,6 +94,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agentClass`), nn('http://xmlns.com/foaf/0.1/AuthenticatedAgent')),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
await expect(authorizer.handle({ identifier, permissions, credentials })).rejects.toThrow(UnauthorizedHttpError);
});
Expand All @@ -101,6 +105,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agent`), nn(credentials.webId!)),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
await expect(authorizer.handle({ identifier, permissions, credentials })).resolves.toBeUndefined();
});
Expand All @@ -111,6 +116,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agent`), nn('http://test.com/differentUser')),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
await expect(authorizer.handle({ identifier, permissions, credentials })).rejects.toThrow(ForbiddenHttpError);
});
Expand All @@ -134,6 +140,7 @@ describe('A WebAclAuthorizer', (): void => {
quad(nn('auth'), nn(`${acl}agent`), nn(credentials.webId!)),
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Write`)),
]) } as Representation);
identifier = await aclManager.getAclDocument(identifier);
await expect(authorizer.handle({ identifier, permissions, credentials })).rejects.toThrow(ForbiddenHttpError);
Expand Down

0 comments on commit 7dcde1e

Please sign in to comment.