Skip to content

Commit

Permalink
feat: Integrate acl with rest of server
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimvh committed Aug 7, 2020
1 parent 43750bb commit 6d29afe
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 43 deletions.
56 changes: 51 additions & 5 deletions bin/server.ts
@@ -1,3 +1,6 @@
#!/usr/bin/env node
import { DATA_TYPE_BINARY } from '../src/util/ContentTypes';
import streamifyArray from 'streamify-array';
import yargs from 'yargs';
import {
AcceptPreferenceParser,
Expand All @@ -11,14 +14,16 @@ import {
Representation,
RepresentationConvertingStore,
ResponseDescription,
SimpleAuthorizer,
SimpleAclAuthorizer,
SimpleBodyParser,
SimpleCredentialsExtractor,
SimpleDeleteOperationHandler,
SimpleExtensionAclManager,
SimpleGetOperationHandler,
SimplePatchOperationHandler,
SimplePermissionsExtractor,
SimplePostOperationHandler,
SimplePutOperationHandler,
SimpleRequestParser,
SimpleResourceStore,
SimpleResponseWriter,
Expand All @@ -27,6 +32,7 @@ import {
SimpleTargetExtractor,
SimpleTurtleQuadConverter,
SingleThreadedResourceLocker,
UrlContainerManager,
} from '..';

const { argv } = yargs
Expand All @@ -38,6 +44,8 @@ const { argv } = yargs

const { port } = argv;

const base = `http://localhost:${port}/`;

// This is instead of the dependency injection that still needs to be added
const bodyParser: BodyParser = new CompositeAsyncHandler<HttpRequest, Representation | undefined>([
new SimpleSparqlUpdateBodyParser(),
Expand All @@ -51,21 +59,25 @@ const requestParser = new SimpleRequestParser({

const credentialsExtractor = new SimpleCredentialsExtractor();
const permissionsExtractor = new SimplePermissionsExtractor();
const authorizer = new SimpleAuthorizer();

// Will have to see how to best handle this
const store = new SimpleResourceStore(`http://localhost:${port}/`);
const store = new SimpleResourceStore(base);
const converter = new SimpleTurtleQuadConverter();
const convertingStore = new RepresentationConvertingStore(store, converter);
const locker = new SingleThreadedResourceLocker();
const patcher = new SimpleSparqlUpdatePatchHandler(convertingStore, locker);
const patchingStore = new PatchingStore(convertingStore, patcher);

const aclManager = new SimpleExtensionAclManager();
const containerManager = new UrlContainerManager(base);
const authorizer = new SimpleAclAuthorizer(aclManager, containerManager, patchingStore);

const operationHandler = new CompositeAsyncHandler<Operation, ResponseDescription>([
new SimpleDeleteOperationHandler(patchingStore),
new SimpleGetOperationHandler(patchingStore),
new SimplePatchOperationHandler(patchingStore),
new SimplePostOperationHandler(patchingStore),
new SimplePutOperationHandler(patchingStore),
]);

const responseWriter = new SimpleResponseWriter();
Expand All @@ -81,6 +93,40 @@ const httpHandler = new AuthenticatedLdpHandler({

const httpServer = new ExpressHttpServer(httpHandler);

httpServer.listen(port);
// Set up acl so everything can still be done by default
// Note that this will need to be adapted to go through all the correct channels later on
const aclSetup = async(): Promise<void> => {
const acl = `@prefix acl: <http://www.w3.org/ns/auth/acl#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
process.stdout.write(`Running at http://localhost:${port}/\n`);
<#authorization>
a acl:Authorization;
acl:agentClass foaf:Agent;
acl:mode acl:Read;
acl:mode acl:Write;
acl:mode acl:Append;
acl:mode acl:Delete;
acl:mode acl:Control;
acl:accessTo <${base}>;
acl:default <${base}>.`;
await store.setRepresentation(
await aclManager.getAcl({ path: base }),
{
dataType: DATA_TYPE_BINARY,
data: streamifyArray([ acl ]),
metadata: {
raw: [],
profiles: [],
contentType: 'text/turtle',
},
},
);
};
aclSetup().then((): void => {
httpServer.listen(port);

process.stdout.write(`Running at ${base}\n`);
}).catch((error): void => {
process.stderr.write(`${error}\n`);
process.exit(1);
});
8 changes: 8 additions & 0 deletions index.ts
Expand Up @@ -4,8 +4,11 @@ export * from './src/authentication/CredentialsExtractor';
export * from './src/authentication/SimpleCredentialsExtractor';

// Authorization
export * from './src/authorization/AclManager';
export * from './src/authorization/Authorizer';
export * from './src/authorization/SimpleAclAuthorizer';
export * from './src/authorization/SimpleAuthorizer';
export * from './src/authorization/SimpleExtensionAclManager';

// LDP/HTTP
export * from './src/ldp/http/AcceptPreferenceParser';
Expand All @@ -30,6 +33,7 @@ export * from './src/ldp/operations/SimpleDeleteOperationHandler';
export * from './src/ldp/operations/SimpleGetOperationHandler';
export * from './src/ldp/operations/SimplePatchOperationHandler';
export * from './src/ldp/operations/SimplePostOperationHandler';
export * from './src/ldp/operations/SimplePutOperationHandler';

// LDP/Permissions
export * from './src/ldp/permissions/PermissionSet';
Expand Down Expand Up @@ -66,6 +70,7 @@ export * from './src/storage/patch/SimpleSparqlUpdatePatchHandler';
// Storage
export * from './src/storage/AtomicResourceStore';
export * from './src/storage/Conditions';
export * from './src/storage/ContainerManager';
export * from './src/storage/Lock';
export * from './src/storage/LockingResourceStore';
export * from './src/storage/PassthroughStore';
Expand All @@ -76,10 +81,13 @@ export * from './src/storage/ResourceMapper';
export * from './src/storage/ResourceStore';
export * from './src/storage/SingleThreadedResourceLocker';
export * from './src/storage/SimpleResourceStore';
export * from './src/storage/UrlContainerManager';

// Util/Errors
export * from './src/util/errors/ForbiddenHttpError';
export * from './src/util/errors/HttpError';
export * from './src/util/errors/NotFoundHttpError';
export * from './src/util/errors/UnauthorizedHttpError';
export * from './src/util/errors/UnsupportedHttpError';
export * from './src/util/errors/UnsupportedMediaTypeHttpError';

Expand Down
5 changes: 0 additions & 5 deletions test/index.ts

This file was deleted.

41 changes: 8 additions & 33 deletions test/integration/AuthenticatedLdpHandler.test.ts
@@ -1,11 +1,10 @@
import { AcceptPreferenceParser } from '../../src/ldp/http/AcceptPreferenceParser';
import { AuthenticatedLdpHandler } from '../../src/ldp/AuthenticatedLdpHandler';
import { BodyParser } from '../../src/ldp/http/BodyParser';
import { call } from '../util/Util';
import { CompositeAsyncHandler } from '../../src/util/CompositeAsyncHandler';
import { EventEmitter } from 'events';
import { HttpHandler } from '../../src/server/HttpHandler';
import { HttpRequest } from '../../src/server/HttpRequest';
import { IncomingHttpHeaders } from 'http';
import { MockResponse } from 'node-mocks-http';
import { Operation } from '../../src/ldp/operations/Operation';
import { Parser } from 'n3';
import { PatchingStore } from '../../src/storage/PatchingStore';
Expand All @@ -28,34 +27,10 @@ import { SimpleSparqlUpdatePatchHandler } from '../../src/storage/patch/SimpleSp
import { SimpleTargetExtractor } from '../../src/ldp/http/SimpleTargetExtractor';
import { SimpleTurtleQuadConverter } from '../../src/storage/conversion/SimpleTurtleQuadConverter';
import { SingleThreadedResourceLocker } from '../../src/storage/SingleThreadedResourceLocker';
import streamifyArray from 'streamify-array';
import { createResponse, MockResponse } from 'node-mocks-http';
import { namedNode, quad } from '@rdfjs/data-model';
import * as url from 'url';

const call = async(handler: HttpHandler, requestUrl: url.URL, method: string,
headers: IncomingHttpHeaders, data: string[]): Promise<MockResponse<any>> => {
const request = streamifyArray(data) as HttpRequest;
request.url = requestUrl.pathname;
request.method = method;
request.headers = headers;
request.headers.host = requestUrl.host;
const response: MockResponse<any> = createResponse({ eventEmitter: EventEmitter });

const endPromise = new Promise((resolve): void => {
response.on('end', (): void => {
expect(response._isEndCalled()).toBeTruthy();
resolve();
});
});

await handler.handleSafe({ request, response });
await endPromise;

return response;
};

describe('An AuthenticatedLdpHandler', (): void => {
describe('An integrated AuthenticatedLdpHandler', (): void => {
describe('with simple handlers', (): void => {
const requestParser = new SimpleRequestParser({
targetExtractor: new SimpleTargetExtractor(),
Expand Down Expand Up @@ -87,7 +62,7 @@ describe('An AuthenticatedLdpHandler', (): void => {

it('can add, read and delete data based on incoming requests.', async(): Promise<void> => {
// POST
let requestUrl = new url.URL('http://test.com/');
let requestUrl = new URL('http://test.com/');
let response: MockResponse<any> = await call(
handler,
requestUrl,
Expand All @@ -101,7 +76,7 @@ describe('An AuthenticatedLdpHandler', (): void => {
expect(id).toContain(url.format(requestUrl));

// GET
requestUrl = new url.URL(id);
requestUrl = new URL(id);
response = await call(handler, requestUrl, 'GET', { accept: 'text/turtle' }, []);
expect(response.statusCode).toBe(200);
expect(response._getData()).toContain('<http://test.com/s> <http://test.com/p> <http://test.com/o>.');
Expand Down Expand Up @@ -162,7 +137,7 @@ describe('An AuthenticatedLdpHandler', (): void => {

it('can handle simple SPARQL updates.', async(): Promise<void> => {
// POST
let requestUrl = new url.URL('http://test.com/');
let requestUrl = new URL('http://test.com/');
let response: MockResponse<any> = await call(
handler,
requestUrl,
Expand All @@ -177,7 +152,7 @@ describe('An AuthenticatedLdpHandler', (): void => {
expect(id).toContain(url.format(requestUrl));

// PATCH
requestUrl = new url.URL(id);
requestUrl = new URL(id);
response = await call(
handler,
requestUrl,
Expand All @@ -192,7 +167,7 @@ describe('An AuthenticatedLdpHandler', (): void => {
expect(response._getHeaders().location).toBe(id);

// GET
requestUrl = new url.URL(id);
requestUrl = new URL(id);
response = await call(handler, requestUrl, 'GET', { accept: 'text/turtle' }, []);
expect(response.statusCode).toBe(200);
expect(response._getData()).toContain('<http://test.com/s2> <http://test.com/p2> <http://test.com/o2>.');
Expand Down

0 comments on commit 6d29afe

Please sign in to comment.