feat: Remove agent/user permission differentiation

This was only used for the WAC-Allow header and greatly simplifies how we use permissions.
This commit is contained in:
Joachim Van Herwegen
2022-11-18 14:01:06 +01:00
parent 6ad5c0c797
commit c46d01d3d7
28 changed files with 220 additions and 276 deletions

View File

@@ -2,7 +2,7 @@ import { DataFactory } from 'n3';
import type { Credentials } from '../../../src/authentication/Credentials';
import type { AccessChecker } from '../../../src/authorization/access/AccessChecker';
import type { PermissionReaderInput } from '../../../src/authorization/PermissionReader';
import { AclMode } from '../../../src/authorization/permissions/AclPermission';
import { AclMode } from '../../../src/authorization/permissions/AclPermissionSet';
import type { AccessMap, PermissionSet } from '../../../src/authorization/permissions/Permissions';
import { AccessMode } from '../../../src/authorization/permissions/Permissions';
import { WebAclReader } from '../../../src/authorization/WebAclReader';
@@ -77,10 +77,7 @@ describe('A WebAclReader', (): void => {
it('returns undefined permissions for undefined credentials.', async(): Promise<void> => {
input.credentials = {};
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: {},
agent: {},
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {}]]));
});
it('reads the accessTo value of the acl resource.', async(): Promise<void> => {
@@ -90,10 +87,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: { read: true },
agent: { read: true },
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, { read: true }]]));
});
it('ignores accessTo fields pointing to different resources.', async(): Promise<void> => {
@@ -103,10 +97,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth'), nn(`${acl}accessTo`), nn('somewhereElse')),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: {},
agent: {},
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {}]]));
});
it('handles all valid modes and ignores other ones.', async(): Promise<void> => {
@@ -117,10 +108,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}fakeMode1`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: { read: true },
agent: { read: true },
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, { read: true }]]));
});
it('reads the default value of a parent if there is no direct acl resource.', async(): Promise<void> => {
@@ -131,10 +119,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth'), nn(`${acl}default`), nn(identifierStrategy.getParentContainer(identifier).path)),
quad(nn('auth'), nn(`${acl}mode`), nn(`${acl}Read`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: { read: true },
agent: { read: true },
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, { read: true }]]));
});
it('does not use default authorizations for the resource itself.', async(): Promise<void> => {
@@ -148,10 +133,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth2'), nn(`${acl}accessTo`), nn(identifier.path)),
quad(nn('auth2'), nn(`${acl}mode`), nn(`${acl}Append`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, {
public: { append: true },
agent: { append: true },
}]]));
compareMaps(await reader.handle(input), new IdentifierMap([[ identifier, { append: true }]]));
});
it('re-throws ResourceStore errors as internal errors.', async(): Promise<void> => {
@@ -170,9 +152,7 @@ describe('A WebAclReader', (): void => {
it('ignores rules where no access is granted.', async(): Promise<void> => {
credentials.agent = { webId: 'http://test.com/user' };
// CredentialGroup.public gets true on auth1, CredentialGroup.agent on auth2
accessChecker.handleSafe.mockImplementation(async({ rule, credentials: cred }): Promise<boolean> =>
(rule.value === 'auth1') === !cred.agent?.webId);
accessChecker.handleSafe.mockImplementation(async({ rule }): Promise<boolean> => rule.value !== 'auth1');
store.getRepresentation.mockResolvedValue(new BasicRepresentation([
quad(nn('auth1'), nn(`${rdf}type`), nn(`${acl}Authorization`)),
@@ -183,10 +163,7 @@ describe('A WebAclReader', (): void => {
quad(nn('auth2'), nn(`${acl}mode`), nn(`${acl}Append`)),
], INTERNAL_QUADS));
compareMaps(await reader.handle(input), new IdentifierMap<PermissionSet>([[ identifier, {
public: { read: true },
agent: { append: true },
}]]));
compareMaps(await reader.handle(input), new IdentifierMap<PermissionSet>([[ identifier, { append: true }]]));
});
it('combines ACL representation requests for resources when possible.', async(): Promise<void> => {
@@ -224,9 +201,9 @@ describe('A WebAclReader', (): void => {
input.requestedModes.set(identifier3, new Set([ AccessMode.append ]));
compareMaps(await reader.handle(input), new IdentifierMap([
[ identifier, { public: { read: true }, agent: { read: true }}],
[ identifier2, { public: { read: true }, agent: { read: true }}],
[ identifier3, { public: { append: true }, agent: { append: true }}],
[ identifier, { read: true }],
[ identifier2, { read: true }],
[ identifier3, { append: true }],
]));
// http://example.com/.acl and http://example.com/bar/.acl
expect(store.getRepresentation).toHaveBeenCalledTimes(2);