CommunitySolidServer/test/unit/authorization/WebAclAuxiliaryReader.test.ts
2022-07-11 14:07:43 +02:00

73 lines
3.7 KiB
TypeScript

import type { CredentialSet } from '../../../src/authentication/Credentials';
import type { PermissionReader } from '../../../src/authorization/PermissionReader';
import { AclMode } from '../../../src/authorization/permissions/AclPermission';
import type { AccessMap, PermissionMap, PermissionSet } from '../../../src/authorization/permissions/Permissions';
import { AccessMode } from '../../../src/authorization/permissions/Permissions';
import { WebAclAuxiliaryReader } from '../../../src/authorization/WebAclAuxiliaryReader';
import type { AuxiliaryStrategy } from '../../../src/http/auxiliary/AuxiliaryStrategy';
import type { ResourceIdentifier } from '../../../src/http/representation/ResourceIdentifier';
import { IdentifierMap, IdentifierSetMultiMap } from '../../../src/util/map/IdentifierMap';
import { joinUrl } from '../../../src/util/PathUtil';
import { compareMaps } from '../../util/Util';
describe('A WebAclAuxiliaryReader', (): void => {
const baseUrl = 'http://example.com/';
const subject1 = { path: joinUrl(baseUrl, 'foo/') };
const acl1 = { path: joinUrl(subject1.path, '.acl') };
const subject2 = { path: joinUrl(baseUrl, 'bar/') };
const acl2 = { path: joinUrl(subject2.path, '.acl') };
const credentials: CredentialSet = { public: {}};
let requestedModes: AccessMap;
let sourceResult: PermissionMap;
let aclStrategy: jest.Mocked<AuxiliaryStrategy>;
let source: jest.Mocked<PermissionReader>;
let reader: WebAclAuxiliaryReader;
beforeEach(async(): Promise<void> => {
requestedModes = new IdentifierSetMultiMap();
sourceResult = new IdentifierMap();
aclStrategy = {
isAuxiliaryIdentifier: jest.fn((identifier): boolean => identifier.path.endsWith('.acl')),
getSubjectIdentifier: jest.fn((identifier): ResourceIdentifier => ({ path: identifier.path.slice(0, -4) })),
} as any;
source = { handleSafe: jest.fn().mockResolvedValue(sourceResult) } as any;
reader = new WebAclAuxiliaryReader(source, aclStrategy);
});
it('requires control permissions on the subject resource to do everything.', async(): Promise<void> => {
requestedModes.set(acl1, AccessMode.read);
requestedModes.set(acl2, AccessMode.read);
sourceResult.set(subject1, { public: { control: true }} as PermissionSet);
const result = await reader.handle({ requestedModes, credentials });
expect(result.get(acl1)).toEqual({ public: { read: true, append: true, write: true, control: true }});
expect(result.get(acl2)).toEqual({ });
const updatedMap = new IdentifierMap();
updatedMap.set(subject1, new Set([ AclMode.control ]));
updatedMap.set(subject2, new Set([ AclMode.control ]));
expect(source.handleSafe).toHaveBeenCalledTimes(1);
expect(source.handleSafe.mock.calls[0][0].credentials).toBe(credentials);
compareMaps(source.handleSafe.mock.calls[0][0].requestedModes, updatedMap);
expect(source.handleSafe.mock.calls[0][0].requestedModes).not.toEqual(requestedModes);
});
it('combines the modes with the subject resource if it is also being requested.', async(): Promise<void> => {
requestedModes.set(acl1, AccessMode.read);
requestedModes.set(subject1, AccessMode.write);
const resultSet = { public: { read: true, write: true, control: true }} as PermissionSet;
sourceResult.set(subject1, resultSet);
const resultMap: PermissionMap = new IdentifierMap([
[ acl1, { public: { read: true, write: true, control: true, append: true }} as PermissionSet ],
[ subject1, resultSet ],
]);
compareMaps(await reader.handle({ credentials, requestedModes }), resultMap);
expect(source.handleSafe.mock.calls[0][0].requestedModes.get(subject1))
.toEqual(new Set([ AccessMode.write, AclMode.control ]));
});
});