mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
test: Update LdpHandlerWitAuth to use fetch for tests
The AclHelper class has been extended to be more flexible for future tests.
This commit is contained in:
parent
dd3fb63d18
commit
4083d24e4a
@ -1,8 +1,15 @@
|
|||||||
import { createReadStream } from 'fs';
|
import type { Server } from 'http';
|
||||||
import type { HttpHandler, Initializer, ResourceStore } from '../../src/';
|
import fetch from 'cross-fetch';
|
||||||
import { LDP, BasicRepresentation, joinFilePath } from '../../src/';
|
import type { Initializer, ResourceStore } from '../../src/';
|
||||||
import { AclHelper, ResourceHelper } from '../util/TestHelpers';
|
import { BasicRepresentation } from '../../src/';
|
||||||
import { BASE, getTestFolder, removeFolder, instantiateFromConfig } from './Config';
|
import type { HttpServerFactory } from '../../src/server/HttpServerFactory';
|
||||||
|
import { deleteResource, getResource, postResource, putResource } from '../util/FetchUtil';
|
||||||
|
import { AclHelper } from '../util/TestHelpers';
|
||||||
|
import { getPort } from '../util/Util';
|
||||||
|
import { getTestFolder, instantiateFromConfig, removeFolder } from './Config';
|
||||||
|
|
||||||
|
const port = getPort('LpdHandlerWithAuth');
|
||||||
|
const baseUrl = `http://localhost:${port}/`;
|
||||||
|
|
||||||
const rootFilePath = getTestFolder('full-config-acl');
|
const rootFilePath = getTestFolder('full-config-acl');
|
||||||
const stores: [string, any][] = [
|
const stores: [string, any][] = [
|
||||||
@ -17,13 +24,17 @@ const stores: [string, any][] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
describe.each(stores)('An LDP handler with auth using %s', (name, { storeUrn, teardown }): void => {
|
describe.each(stores)('An LDP handler with auth using %s', (name, { storeUrn, teardown }): void => {
|
||||||
let handler: HttpHandler;
|
let server: Server;
|
||||||
|
let initializer: Initializer;
|
||||||
|
let factory: HttpServerFactory;
|
||||||
|
let store: ResourceStore;
|
||||||
let aclHelper: AclHelper;
|
let aclHelper: AclHelper;
|
||||||
let resourceHelper: ResourceHelper;
|
const permanent = `${baseUrl}document.txt`;
|
||||||
|
|
||||||
beforeAll(async(): Promise<void> => {
|
beforeAll(async(): Promise<void> => {
|
||||||
const variables: Record<string, any> = {
|
const variables: Record<string, any> = {
|
||||||
'urn:solid-server:default:variable:baseUrl': BASE,
|
'urn:solid-server:default:variable:port': port,
|
||||||
|
'urn:solid-server:default:variable:baseUrl': baseUrl,
|
||||||
'urn:solid-server:default:variable:rootFilePath': rootFilePath,
|
'urn:solid-server:default:variable:rootFilePath': rootFilePath,
|
||||||
};
|
};
|
||||||
const internalStore = await instantiateFromConfig(
|
const internalStore = await instantiateFromConfig(
|
||||||
@ -33,128 +44,145 @@ describe.each(stores)('An LDP handler with auth using %s', (name, { storeUrn, te
|
|||||||
) as ResourceStore;
|
) as ResourceStore;
|
||||||
variables['urn:solid-server:default:variable:store'] = internalStore;
|
variables['urn:solid-server:default:variable:store'] = internalStore;
|
||||||
|
|
||||||
// Create and initialize the HTTP handler and related components
|
// Create and initialize the server
|
||||||
let initializer: Initializer;
|
|
||||||
let store: ResourceStore;
|
|
||||||
const instances = await instantiateFromConfig(
|
const instances = await instantiateFromConfig(
|
||||||
'urn:solid-server:test:Instances',
|
'urn:solid-server:test:Instances',
|
||||||
'ldp-with-auth.json',
|
'ldp-with-auth.json',
|
||||||
variables,
|
variables,
|
||||||
) as Record<string, any>;
|
) as Record<string, any>;
|
||||||
({ handler, store, initializer } = instances);
|
({ factory, initializer, store } = instances);
|
||||||
// Set up the internal store
|
|
||||||
await initializer.handleSafe();
|
await initializer.handleSafe();
|
||||||
|
server = factory.startServer(port);
|
||||||
|
|
||||||
// Create test helpers for manipulating the components
|
// Create test helper for manipulating acl
|
||||||
aclHelper = new AclHelper(store, BASE);
|
aclHelper = new AclHelper(store);
|
||||||
resourceHelper = new ResourceHelper(handler, BASE);
|
});
|
||||||
|
|
||||||
// Write test resource
|
beforeEach(async(): Promise<void> => {
|
||||||
await store.setRepresentation({ path: `${BASE}/permanent.txt` },
|
// Set the root acl file to allow everything and create a single document
|
||||||
new BasicRepresentation(createReadStream(joinFilePath(__dirname, '../assets/permanent.txt')), 'text/plain'));
|
await store.setRepresentation({ path: permanent }, new BasicRepresentation('PERMANENT', 'text/plain'));
|
||||||
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
|
permissions: { read: true, write: true, append: true, control: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async(): Promise<void> => {
|
afterAll(async(): Promise<void> => {
|
||||||
await teardown();
|
await teardown();
|
||||||
|
await new Promise((resolve, reject): void => {
|
||||||
|
server.close((error): void => error ? reject(error) : resolve());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can add a file to the store, read it and delete it if allowed.', async(): Promise<void> => {
|
it('can add a document, read it and delete it if allowed.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'agent');
|
permissions: { read: true, write: true, append: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Create file
|
// PUT
|
||||||
const filePath = 'testfile2.txt';
|
const document = `${baseUrl}test.txt`;
|
||||||
const fileUrl = `${BASE}/${filePath}`;
|
await putResource(document, { contentType: 'text/plain', body: 'TESTDATA' });
|
||||||
let response = await resourceHelper.createResource(
|
|
||||||
'../assets/testfile2.txt', filePath, 'text/plain',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get file
|
// GET
|
||||||
response = await resourceHelper.getResource(fileUrl);
|
const response = await getResource(document);
|
||||||
expect(response.statusCode).toBe(200);
|
await expect(response.text()).resolves.toBe('TESTDATA');
|
||||||
expect(response._getBuffer().toString()).toContain('TESTFILE2');
|
expect(response.headers.get('wac-allow')).toBe('user="read write append",public="read write append"');
|
||||||
expect(response.getHeaders().link).toContain(`<${LDP.Resource}>; rel="type"`);
|
|
||||||
expect(response.getHeaders().link).toContain(`<${fileUrl}.acl>; rel="acl"`);
|
|
||||||
expect(response.getHeaders()['wac-allow']).toBe('user="read write append",public="read write append"');
|
|
||||||
|
|
||||||
// DELETE file
|
// DELETE
|
||||||
await resourceHelper.deleteResource(fileUrl);
|
await deleteResource(document);
|
||||||
await resourceHelper.shouldNotExist(fileUrl);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can not add a file to the store if not allowed.', async(): Promise<void> => {
|
it('can not add a file to the store if not allowed.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'authenticated');
|
permissions: { read: true, write: true, append: true },
|
||||||
|
agentClass: 'authenticated',
|
||||||
|
accessTo: true,
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Try to create file
|
// PUT fail
|
||||||
const filePath = 'testfile2.txt';
|
const documentUrl = `${baseUrl}test.txt`;
|
||||||
const response = await resourceHelper.createResource(
|
const response = await fetch(documentUrl, { method: 'PUT' });
|
||||||
'../assets/testfile2.txt', filePath, 'text/plain', true,
|
expect(response.status).toBe(401);
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(401);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can not add/delete, but only read files if allowed.', async(): Promise<void> => {
|
it('can not add/delete if only read is allowed.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: false, append: false, control: false }, 'agent');
|
permissions: { read: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Try to create file
|
// PUT fail
|
||||||
const filePath = 'testfile2.txt';
|
const document = `${baseUrl}test.txt`;
|
||||||
let response = await resourceHelper.createResource(
|
let response = await fetch(document, { method: 'PUT' });
|
||||||
'../assets/testfile2.txt', filePath, 'text/plain', true,
|
expect(response.status).toBe(401);
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(401);
|
|
||||||
|
|
||||||
// GET permanent file
|
// GET permanent file
|
||||||
response = await resourceHelper.getResource('http://test.com/permanent.txt');
|
response = await getResource(permanent);
|
||||||
expect(response._getBuffer().toString()).toContain('TEST');
|
await expect(response.text()).resolves.toBe('PERMANENT');
|
||||||
expect(response.getHeaders().link).toContain(`<${LDP.Resource}>; rel="type"`);
|
expect(response.headers.get('wac-allow')).toBe('user="read",public="read"');
|
||||||
expect(response.getHeaders().link).toContain(`<http://test.com/permanent.txt.acl>; rel="acl"`);
|
|
||||||
expect(response.getHeaders()['wac-allow']).toBe('user="read",public="read"');
|
|
||||||
|
|
||||||
// Try to delete permanent file
|
// DELETE fail
|
||||||
response = await resourceHelper.deleteResource('http://test.com/permanent.txt', true);
|
response = await fetch(permanent, { method: 'DELETE' });
|
||||||
expect(response.statusCode).toBe(401);
|
expect(response.status).toBe(401);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can add files but not write to them if append is allowed.', async(): Promise<void> => {
|
it('can add files but not write to them if append is allowed.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: false, append: true, control: false }, 'agent');
|
permissions: { append: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Add a file
|
// POST
|
||||||
const filePath = 'testfile2.txt';
|
const slug = 'slug';
|
||||||
let response = await resourceHelper.performRequestWithBody(
|
let response = await postResource(baseUrl, { contentType: 'text/plain', slug, body: 'SLUGDATA' });
|
||||||
new URL(`${BASE}/`),
|
const document = response.headers.get('location')!;
|
||||||
'POST',
|
|
||||||
{
|
|
||||||
'content-type': 'text/plain',
|
|
||||||
'transfer-encoding': 'chunked',
|
|
||||||
slug: filePath,
|
|
||||||
},
|
|
||||||
Buffer.from('data'),
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(201);
|
|
||||||
|
|
||||||
response = await resourceHelper.createResource(
|
// PUT fail
|
||||||
'../assets/testfile2.txt', filePath, 'text/plain', true,
|
response = await fetch(document, { method: 'PUT' });
|
||||||
);
|
expect(response.status).toBe(401);
|
||||||
expect(response.statusCode).toBe(401);
|
|
||||||
|
// DELETE fail
|
||||||
|
response = await fetch(document, { method: 'DELETE' });
|
||||||
|
expect(response.status).toBe(401);
|
||||||
|
|
||||||
|
// Clean up resource
|
||||||
|
await store.deleteResource({ path: document });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can not access an acl file if no control rights are provided.', async(): Promise<void> => {
|
it('can not access an acl file if no control rights are provided.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'agent');
|
permissions: { read: true, write: true, append: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
});
|
||||||
|
|
||||||
const response = await resourceHelper.performRequest(new URL('http://test.com/.acl'), 'GET', { accept: '*/*' });
|
const response = await fetch(`${baseUrl}.acl`);
|
||||||
expect(response.statusCode).toBe(401);
|
expect(response.status).toBe(401);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can only access an acl file if control rights are provided.', async(): Promise<void> => {
|
it('can only access an acl file if control rights are provided.', async(): Promise<void> => {
|
||||||
// Set acl
|
await aclHelper.setSimpleAcl(baseUrl, {
|
||||||
await aclHelper.setSimpleAcl({ read: false, write: false, append: false, control: true }, 'agent');
|
permissions: { control: true },
|
||||||
|
agentClass: 'agent',
|
||||||
|
accessTo: true,
|
||||||
|
});
|
||||||
|
|
||||||
const response = await resourceHelper.performRequest(new URL('http://test.com/.acl'), 'GET', { accept: '*/*' });
|
const response = await fetch(`${baseUrl}.acl`);
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.status).toBe(200);
|
||||||
expect(response.getHeaders()['wac-allow']).toBe('user="control",public="control"');
|
expect(response.headers.get('wac-allow')).toBe('user="control",public="control"');
|
||||||
|
|
||||||
|
// Close response
|
||||||
|
await response.text();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -253,4 +253,22 @@ describe.each(stores)('An LDP handler allowing all request %s', (name, { storeUr
|
|||||||
// DELETE
|
// DELETE
|
||||||
expect(await deleteResource(containerUrl)).toBeUndefined();
|
expect(await deleteResource(containerUrl)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/solid/community-server/issues/498
|
||||||
|
it('accepts a GET with Content-Length: 0.', async(): Promise<void> => {
|
||||||
|
// PUT
|
||||||
|
const documentUrl = `${baseUrl}foo/bar`;
|
||||||
|
const response = await fetch(documentUrl, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'content-length': '0', 'content-type': 'text/turtle' },
|
||||||
|
body: '',
|
||||||
|
});
|
||||||
|
expect(response.status).toBe(205);
|
||||||
|
|
||||||
|
// GET
|
||||||
|
await getResource(documentUrl);
|
||||||
|
|
||||||
|
// DELETE
|
||||||
|
expect(await deleteResource(documentUrl)).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
import type { MockResponse } from 'node-mocks-http';
|
|
||||||
import type { HttpHandler, Initializer, ResourceStore } from '../../src/';
|
|
||||||
import { AclHelper } from '../util/TestHelpers';
|
|
||||||
import { performRequest } from '../util/Util';
|
|
||||||
import { BASE, instantiateFromConfig } from './Config';
|
|
||||||
|
|
||||||
describe('A server with authorization', (): void => {
|
|
||||||
let handler: HttpHandler;
|
|
||||||
let aclHelper: AclHelper;
|
|
||||||
|
|
||||||
beforeAll(async(): Promise<void> => {
|
|
||||||
// Set up the internal store
|
|
||||||
const variables: Record<string, any> = {
|
|
||||||
'urn:solid-server:default:variable:baseUrl': BASE,
|
|
||||||
};
|
|
||||||
const internalStore = await instantiateFromConfig(
|
|
||||||
'urn:solid-server:default:MemoryResourceStore',
|
|
||||||
'ldp-with-auth.json',
|
|
||||||
variables,
|
|
||||||
) as ResourceStore;
|
|
||||||
variables['urn:solid-server:default:variable:store'] = internalStore;
|
|
||||||
|
|
||||||
// Create and initialize the HTTP handler and related components
|
|
||||||
let initializer: Initializer;
|
|
||||||
let store: ResourceStore;
|
|
||||||
const instances = await instantiateFromConfig(
|
|
||||||
'urn:solid-server:test:Instances',
|
|
||||||
'ldp-with-auth.json',
|
|
||||||
variables,
|
|
||||||
) as Record<string, any>;
|
|
||||||
({ handler, store, initializer } = instances);
|
|
||||||
await initializer.handleSafe();
|
|
||||||
|
|
||||||
// Create test helpers for manipulating the components
|
|
||||||
aclHelper = new AclHelper(store, BASE);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can create new entries.', async(): Promise<void> => {
|
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'agent');
|
|
||||||
|
|
||||||
// POST
|
|
||||||
let requestUrl = new URL('http://test.com/');
|
|
||||||
let response: MockResponse<any> = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'POST',
|
|
||||||
{ 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' },
|
|
||||||
[ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(201);
|
|
||||||
|
|
||||||
// PUT
|
|
||||||
requestUrl = new URL('http://test.com/foo/bar');
|
|
||||||
response = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'PUT',
|
|
||||||
{ 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' },
|
|
||||||
[ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(205);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cannot create new entries if not allowed.', async(): Promise<void> => {
|
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'authenticated');
|
|
||||||
|
|
||||||
// POST
|
|
||||||
let requestUrl = new URL('http://test.com/');
|
|
||||||
let response: MockResponse<any> = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'POST',
|
|
||||||
{ 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' },
|
|
||||||
[ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(401);
|
|
||||||
|
|
||||||
// PUT
|
|
||||||
requestUrl = new URL('http://test.com/foo/bar');
|
|
||||||
response = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'PUT',
|
|
||||||
{ 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' },
|
|
||||||
[ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(401);
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://github.com/solid/community-server/issues/498
|
|
||||||
it('accepts a GET with Content-Length: 0.', async(): Promise<void> => {
|
|
||||||
await aclHelper.setSimpleAcl({ read: true, write: true, append: true, control: false }, 'agent');
|
|
||||||
|
|
||||||
// PUT
|
|
||||||
let requestUrl = new URL('http://test.com/foo/bar');
|
|
||||||
let response: MockResponse<any> = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'PUT',
|
|
||||||
{ 'content-length': '0', 'content-type': 'text/turtle' },
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(205);
|
|
||||||
|
|
||||||
// GET
|
|
||||||
requestUrl = new URL('http://test.com/foo/bar');
|
|
||||||
response = await performRequest(
|
|
||||||
handler,
|
|
||||||
requestUrl,
|
|
||||||
'GET',
|
|
||||||
{ 'content-length': '0' },
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toBe(200);
|
|
||||||
expect(response.getHeaders()['wac-allow']).toBe('user="read write append",public="read write append"');
|
|
||||||
});
|
|
||||||
});
|
|
@ -4,7 +4,6 @@
|
|||||||
"files-scs:config/presets/acl.json",
|
"files-scs:config/presets/acl.json",
|
||||||
"files-scs:config/presets/identifiers/suffix-identifiers.json",
|
"files-scs:config/presets/identifiers/suffix-identifiers.json",
|
||||||
"files-scs:config/presets/init.json",
|
"files-scs:config/presets/init.json",
|
||||||
"files-scs:config/presets/ldp.json",
|
|
||||||
"files-scs:config/presets/ldp/credentials-extractor.json",
|
"files-scs:config/presets/ldp/credentials-extractor.json",
|
||||||
"files-scs:config/presets/ldp/metadata-handler.json",
|
"files-scs:config/presets/ldp/metadata-handler.json",
|
||||||
"files-scs:config/presets/ldp/operation-handler.json",
|
"files-scs:config/presets/ldp/operation-handler.json",
|
||||||
@ -24,7 +23,7 @@
|
|||||||
"comment": "Sets up an HTTP server with only the LDP handler as HttpHandler.",
|
"comment": "Sets up an HTTP server with only the LDP handler as HttpHandler.",
|
||||||
"@id": "urn:solid-server:test:Instances",
|
"@id": "urn:solid-server:test:Instances",
|
||||||
"@type": "RecordObject",
|
"@type": "RecordObject",
|
||||||
"RecordObject:_record": [
|
"record": [
|
||||||
{
|
{
|
||||||
"RecordObject:_record_key": "initializer",
|
"RecordObject:_record_key": "initializer",
|
||||||
"RecordObject:_record_value": {
|
"RecordObject:_record_value": {
|
||||||
@ -35,10 +34,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"RecordObject:_record_key": "handler",
|
|
||||||
"RecordObject:_record_value": { "@id": "urn:solid-server:default:LdpHandler" }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"RecordObject:_record_key": "store",
|
"RecordObject:_record_key": "store",
|
||||||
"RecordObject:_record_value": { "@id": "urn:solid-server:default:ResourceStore" }
|
"RecordObject:_record_value": { "@id": "urn:solid-server:default:ResourceStore" }
|
||||||
@ -50,6 +45,38 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"comment": "The default LDP handler, but with an unsecure webId extractor.",
|
||||||
|
"@id": "urn:solid-server:default:LdpHandler",
|
||||||
|
"@type": "AuthenticatedLdpHandler",
|
||||||
|
"args_requestParser": {
|
||||||
|
"@id": "urn:solid-server:default:RequestParser"
|
||||||
|
},
|
||||||
|
"args_credentialsExtractor": {
|
||||||
|
"@type": "WaterfallHandler",
|
||||||
|
"WaterfallHandler:_handlers": [
|
||||||
|
{
|
||||||
|
"@type": "UnsecureWebIdExtractor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "EmptyCredentialsExtractor"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"args_permissionsExtractor": {
|
||||||
|
"@id": "urn:solid-server:default:PermissionsExtractor"
|
||||||
|
},
|
||||||
|
"args_authorizer": {
|
||||||
|
"@id": "urn:solid-server:default:AclBasedAuthorizer"
|
||||||
|
},
|
||||||
|
"args_operationHandler": {
|
||||||
|
"@id": "urn:solid-server:default:OperationHandler"
|
||||||
|
},
|
||||||
|
"args_responseWriter": {
|
||||||
|
"@id": "urn:solid-server:default:ResponseWriter"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"@id": "urn:solid-server:default:ServerFactory",
|
"@id": "urn:solid-server:default:ServerFactory",
|
||||||
"@type": "BaseHttpServerFactory",
|
"@type": "BaseHttpServerFactory",
|
||||||
@ -60,7 +87,7 @@
|
|||||||
{
|
{
|
||||||
"@id": "urn:solid-server:default:RoutingResourceStore",
|
"@id": "urn:solid-server:default:RoutingResourceStore",
|
||||||
"@type": "PassthroughStore",
|
"@type": "PassthroughStore",
|
||||||
"PassthroughStore:_source": {
|
"source": {
|
||||||
"@id": "urn:solid-server:default:variable:store"
|
"@id": "urn:solid-server:default:variable:store"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,23 +5,34 @@ import { Readable } from 'stream';
|
|||||||
import type { MockResponse } from 'node-mocks-http';
|
import type { MockResponse } from 'node-mocks-http';
|
||||||
import { createResponse } from 'node-mocks-http';
|
import { createResponse } from 'node-mocks-http';
|
||||||
import type { ResourceStore, PermissionSet, HttpHandler, HttpRequest } from '../../src/';
|
import type { ResourceStore, PermissionSet, HttpHandler, HttpRequest } from '../../src/';
|
||||||
import { BasicRepresentation, joinFilePath, ensureTrailingSlash } from '../../src/';
|
import { BasicRepresentation, joinFilePath } from '../../src/';
|
||||||
import { performRequest } from './Util';
|
import { performRequest } from './Util';
|
||||||
|
|
||||||
/* eslint-disable jest/no-standalone-expect */
|
/* eslint-disable jest/no-standalone-expect */
|
||||||
export class AclHelper {
|
export class AclHelper {
|
||||||
public readonly store: ResourceStore;
|
public readonly store: ResourceStore;
|
||||||
public id: string;
|
|
||||||
|
|
||||||
public constructor(store: ResourceStore, id: string) {
|
public constructor(store: ResourceStore) {
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.id = ensureTrailingSlash(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setSimpleAcl(
|
public async setSimpleAcl(
|
||||||
permissions: PermissionSet,
|
resource: string,
|
||||||
agentClass: 'agent' | 'authenticated',
|
options: {
|
||||||
|
permissions: Partial<PermissionSet>;
|
||||||
|
agentClass?: 'agent' | 'authenticated';
|
||||||
|
agent?: string;
|
||||||
|
accessTo?: boolean;
|
||||||
|
default?: boolean;
|
||||||
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
if (!options.agentClass && !options.agent) {
|
||||||
|
throw new Error('At least one of agentClass or agent have to be provided for this to make sense.');
|
||||||
|
}
|
||||||
|
if (!options.accessTo && !options.default) {
|
||||||
|
throw new Error('At least one of accessTo or default have to be true for this to make sense.');
|
||||||
|
}
|
||||||
|
|
||||||
const acl: string[] = [
|
const acl: string[] = [
|
||||||
'@prefix acl: <http://www.w3.org/ns/auth/acl#>.\n',
|
'@prefix acl: <http://www.w3.org/ns/auth/acl#>.\n',
|
||||||
'@prefix foaf: <http://xmlns.com/foaf/0.1/>.\n',
|
'@prefix foaf: <http://xmlns.com/foaf/0.1/>.\n',
|
||||||
@ -29,21 +40,30 @@ export class AclHelper {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (const perm of [ 'Read', 'Append', 'Write', 'Control' ]) {
|
for (const perm of [ 'Read', 'Append', 'Write', 'Control' ]) {
|
||||||
if (permissions[perm.toLowerCase() as keyof PermissionSet]) {
|
if (options.permissions[perm.toLowerCase() as keyof PermissionSet]) {
|
||||||
acl.push(`;\n acl:mode acl:${perm}`);
|
acl.push(`;\n acl:mode acl:${perm}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
acl.push(`;\n acl:accessTo <${this.id}>`);
|
if (options.accessTo) {
|
||||||
acl.push(`;\n acl:default <${this.id}>`);
|
acl.push(`;\n acl:accessTo <${resource}>`);
|
||||||
acl.push(
|
}
|
||||||
`;\n acl:agentClass ${
|
if (options.default) {
|
||||||
agentClass === 'agent' ? 'foaf:Agent' : 'foaf:AuthenticatedAgent'
|
acl.push(`;\n acl:default <${resource}>`);
|
||||||
}`,
|
}
|
||||||
);
|
if (options.agentClass) {
|
||||||
|
acl.push(
|
||||||
|
`;\n acl:agentClass ${
|
||||||
|
options.agentClass === 'agent' ? 'foaf:Agent' : 'foaf:AuthenticatedAgent'
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (options.agent) {
|
||||||
|
acl.push(`;\n acl:agent ${options.agent}`);
|
||||||
|
}
|
||||||
|
|
||||||
acl.push('.');
|
acl.push('.');
|
||||||
|
|
||||||
await this.store.setRepresentation({ path: `${this.id}.acl` }, new BasicRepresentation(acl, 'text/turtle'));
|
await this.store.setRepresentation({ path: `${resource}.acl` }, new BasicRepresentation(acl, 'text/turtle'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import type { SystemError } from '../../src/util/errors/SystemError';
|
|||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
const portNames = [
|
const portNames = [
|
||||||
'DynamicPods',
|
'DynamicPods',
|
||||||
|
'LpdHandlerWithAuth',
|
||||||
'LpdHandlerWithoutAuth',
|
'LpdHandlerWithoutAuth',
|
||||||
'Middleware',
|
'Middleware',
|
||||||
'PodCreation',
|
'PodCreation',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user