mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
test: Add ACP integration tests
This commit is contained in:
121
test/integration/AcpServer.test.ts
Normal file
121
test/integration/AcpServer.test.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import fetch from 'cross-fetch';
|
||||
import { BasicRepresentation } from '../../src/http/representation/BasicRepresentation';
|
||||
import type { App } from '../../src/init/App';
|
||||
import type { ResourceStore } from '../../src/storage/ResourceStore';
|
||||
import { joinUrl } from '../../src/util/PathUtil';
|
||||
import { AcpHelper } from '../util/AcpHelper';
|
||||
import { getPort } from '../util/Util';
|
||||
import {
|
||||
getDefaultVariables,
|
||||
getPresetConfigPath,
|
||||
getTestConfigPath,
|
||||
getTestFolder,
|
||||
instantiateFromConfig, removeFolder,
|
||||
} from './Config';
|
||||
|
||||
const port = getPort('AcpServer');
|
||||
const baseUrl = `http://localhost:${port}/`;
|
||||
|
||||
const rootFilePath = getTestFolder('full-config-acp');
|
||||
const stores: [string, any][] = [
|
||||
[ 'in-memory storage', {
|
||||
storeConfig: 'storage/backend/memory.json',
|
||||
teardown: jest.fn(),
|
||||
}],
|
||||
[ 'on-disk storage', {
|
||||
storeConfig: 'storage/backend/file.json',
|
||||
teardown: async(): Promise<void> => removeFolder(rootFilePath),
|
||||
}],
|
||||
];
|
||||
|
||||
describe.each(stores)('An LDP handler with ACP using %s', (name, { storeConfig, teardown }): void => {
|
||||
let app: App;
|
||||
let store: ResourceStore;
|
||||
let acpHelper: AcpHelper;
|
||||
|
||||
beforeAll(async(): Promise<void> => {
|
||||
const variables = {
|
||||
...getDefaultVariables(port, baseUrl),
|
||||
'urn:solid-server:default:variable:rootFilePath': rootFilePath,
|
||||
};
|
||||
|
||||
// Create and start the server
|
||||
const instances = await instantiateFromConfig(
|
||||
'urn:solid-server:test:Instances',
|
||||
[
|
||||
getPresetConfigPath(storeConfig),
|
||||
getTestConfigPath('ldp-with-acp.json'),
|
||||
],
|
||||
variables,
|
||||
) as Record<string, any>;
|
||||
({ app, store } = instances);
|
||||
|
||||
await app.start();
|
||||
|
||||
// Create test helper for manipulating acl
|
||||
acpHelper = new AcpHelper(store);
|
||||
});
|
||||
|
||||
afterAll(async(): Promise<void> => {
|
||||
await teardown();
|
||||
await app.stop();
|
||||
});
|
||||
|
||||
it('provides no access if no ACRs are defined.', async(): Promise<void> => {
|
||||
const response = await fetch(baseUrl);
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('provides access if the correct ACRs are defined.', async(): Promise<void> => {
|
||||
await acpHelper.setAcp(baseUrl, acpHelper.createAcr({ resource: baseUrl,
|
||||
policies: [ acpHelper.createPolicy({
|
||||
allow: [ 'read' ],
|
||||
anyOf: [ acpHelper.createMatcher({ publicAgent: true }) ],
|
||||
}) ]}));
|
||||
const response = await fetch(baseUrl);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('uses ACP inheritance.', async(): Promise<void> => {
|
||||
const target = joinUrl(baseUrl, 'foo');
|
||||
await store.setRepresentation({ path: target }, new BasicRepresentation('test', 'text/plain'));
|
||||
await acpHelper.setAcp(baseUrl, acpHelper.createAcr({ resource: baseUrl,
|
||||
memberPolicies: [ acpHelper.createPolicy({
|
||||
allow: [ 'read' ],
|
||||
anyOf: [ acpHelper.createMatcher({ publicAgent: true }) ],
|
||||
}) ]}));
|
||||
await acpHelper.setAcp(target, acpHelper.createAcr({ resource: baseUrl,
|
||||
policies: [ acpHelper.createPolicy({
|
||||
allow: [ 'write' ],
|
||||
anyOf: [ acpHelper.createMatcher({ publicAgent: true }) ],
|
||||
}) ]}));
|
||||
const response = await fetch(target);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('requires control permissions to access ACRs.', async(): Promise<void> => {
|
||||
const baseAcr = joinUrl(baseUrl, '.acr');
|
||||
const turtle = acpHelper.toTurtle(acpHelper.createAcr({ resource: baseUrl,
|
||||
policies: [ acpHelper.createPolicy({
|
||||
allow: [ 'read' ],
|
||||
anyOf: [ acpHelper.createMatcher({ publicAgent: true }) ],
|
||||
}) ]}));
|
||||
let response = await fetch(baseAcr);
|
||||
expect(response.status).toBe(401);
|
||||
response = await fetch(baseAcr, { method: 'PUT', headers: { 'content-type': 'text/turtle' }, body: turtle });
|
||||
expect(response.status).toBe(401);
|
||||
|
||||
await acpHelper.setAcp(baseUrl, acpHelper.createAcr({ resource: baseUrl,
|
||||
policies: [ acpHelper.createPolicy({
|
||||
allow: [ 'control' ],
|
||||
anyOf: [ acpHelper.createMatcher({ publicAgent: true }) ],
|
||||
}) ]}));
|
||||
response = await fetch(baseAcr);
|
||||
expect(response.status).toBe(200);
|
||||
response = await fetch(baseAcr, { method: 'PUT', headers: { 'content-type': 'text/turtle' }, body: turtle });
|
||||
expect(response.status).toBe(205);
|
||||
// Can now also read root container due to updated permissions
|
||||
response = await fetch(baseUrl);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
});
|
||||
48
test/integration/config/ldp-with-acp.json
Normal file
48
test/integration/config/ldp-with-acp.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^5.0.0/components/context.jsonld",
|
||||
"import": [
|
||||
"css:config/app/main/default.json",
|
||||
"css:config/app/init/default.json",
|
||||
"css:config/app/setup/disabled.json",
|
||||
"css:config/http/handler/simple.json",
|
||||
"css:config/http/middleware/no-websockets.json",
|
||||
"css:config/http/server-factory/no-websockets.json",
|
||||
"css:config/http/static/default.json",
|
||||
"css:config/identity/access/public.json",
|
||||
"css:config/identity/handler/default.json",
|
||||
"css:config/identity/ownership/token.json",
|
||||
"css:config/identity/pod/static.json",
|
||||
"css:config/ldp/authentication/debug-auth-header.json",
|
||||
"css:config/ldp/authorization/acp.json",
|
||||
"css:config/ldp/handler/default.json",
|
||||
"css:config/ldp/metadata-parser/default.json",
|
||||
"css:config/ldp/metadata-writer/default.json",
|
||||
"css:config/ldp/modes/default.json",
|
||||
"css:config/storage/key-value/memory.json",
|
||||
"css:config/storage/middleware/default.json",
|
||||
"css:config/util/auxiliary/acr.json",
|
||||
"css:config/util/identifiers/suffix.json",
|
||||
"css:config/util/index/default.json",
|
||||
"css:config/util/logging/winston.json",
|
||||
"css:config/util/representation-conversion/default.json",
|
||||
"css:config/util/resource-locker/memory.json",
|
||||
"css:config/util/variables/default.json"
|
||||
],
|
||||
"@graph": [
|
||||
{
|
||||
"comment": "An HTTP server with only the LDP handler as HttpHandler and an unsecure authenticator.",
|
||||
"@id": "urn:solid-server:test:Instances",
|
||||
"@type": "RecordObject",
|
||||
"record": [
|
||||
{
|
||||
"RecordObject:_record_key": "app",
|
||||
"RecordObject:_record_value": { "@id": "urn:solid-server:default:App" }
|
||||
},
|
||||
{
|
||||
"RecordObject:_record_key": "store",
|
||||
"RecordObject:_record_value": { "@id": "urn:solid-server:default:ResourceStore" }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user