feat: Add required ACP headers

This commit is contained in:
Joachim Van Herwegen
2022-08-19 15:24:53 +02:00
parent f3e7a20800
commit fa1dee573e
8 changed files with 147 additions and 3 deletions

View File

@@ -118,4 +118,21 @@ describe.each(stores)('An LDP handler with ACP using %s', (name, { storeConfig,
response = await fetch(baseUrl);
expect(response.status).toBe(200);
});
it('returns the required Link headers.', async(): Promise<void> => {
const baseAcr = joinUrl(baseUrl, '.acr');
const response = await fetch(baseAcr, { method: 'OPTIONS' });
const linkHeaders = response.headers.get('link');
expect(linkHeaders).toContain('<http://www.w3.org/ns/solid/acp#AccessControlResource>; rel="type"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/auth/acl#Read>; rel="http://www.w3.org/ns/solid/acp#grant"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/auth/acl#Append>; rel="http://www.w3.org/ns/solid/acp#grant"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/auth/acl#Write>; rel="http://www.w3.org/ns/solid/acp#grant"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/auth/acl#Control>; rel="http://www.w3.org/ns/solid/acp#grant"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/solid/acp#target>; rel="http://www.w3.org/ns/solid/acp#attribute"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/solid/acp#agent>; rel="http://www.w3.org/ns/solid/acp#attribute"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/solid/acp#client>; rel="http://www.w3.org/ns/solid/acp#attribute"');
expect(linkHeaders).toContain('<http://www.w3.org/ns/solid/acp#issuer>; rel="http://www.w3.org/ns/solid/acp#attribute"');
});
});

View File

@@ -4,20 +4,24 @@
"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",
@@ -30,7 +34,7 @@
],
"@graph": [
{
"comment": "An HTTP server with only the LDP handler as HttpHandler and an unsecure authenticator.",
"comment": "An HTTP server with only the LDP handler as HttpHandler and an unsecure authenticator using ACP.",
"@id": "urn:solid-server:test:Instances",
"@type": "RecordObject",
"record": [

View File

@@ -0,0 +1,47 @@
import { ACP } from '@solid/access-control-policy/dist/constant/acp';
import { createResponse } from 'node-mocks-http';
import type { AuxiliaryIdentifierStrategy } from '../../../../src/http/auxiliary/AuxiliaryIdentifierStrategy';
import type { TargetExtractor } from '../../../../src/http/input/identifier/TargetExtractor';
import type { HttpRequest } from '../../../../src/server/HttpRequest';
import type { HttpResponse } from '../../../../src/server/HttpResponse';
import { AcpHeaderHandler } from '../../../../src/server/middleware/AcpHeaderHandler';
import { ACL } from '../../../../src/util/Vocabularies';
import { SimpleSuffixStrategy } from '../../../util/SimpleSuffixStrategy';
describe('an AcpHeaderHandler', (): void => {
const request: HttpRequest = {} as any;
let response: HttpResponse;
const modes = [ ACL.Read, ACL.Write ];
const attributes = [ ACP.agent, ACP.client ];
let targetExtractor: jest.Mocked<TargetExtractor>;
let strategy: AuxiliaryIdentifierStrategy;
let handler: AcpHeaderHandler;
beforeEach(async(): Promise<void> => {
response = createResponse() as HttpResponse;
targetExtractor = {
handleSafe: jest.fn().mockResolvedValue({ path: 'http://example.org/foo/bar' }),
} as any;
strategy = new SimpleSuffixStrategy('.acr');
handler = new AcpHeaderHandler(targetExtractor, strategy, modes, attributes);
});
it('adds no headers if the target is not an ACR.', async(): Promise<void> => {
await expect(handler.handle({ request, response })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({});
});
it('adds all the required headers.', async(): Promise<void> => {
targetExtractor.handleSafe.mockResolvedValueOnce({ path: 'http://example.org/foo/bar.acr' });
await expect(handler.handle({ request, response })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({ link: [
'<http://www.w3.org/ns/solid/acp#AccessControlResource>; rel="type"',
'<http://www.w3.org/ns/auth/acl#Read>; rel="http://www.w3.org/ns/solid/acp#grant"',
'<http://www.w3.org/ns/auth/acl#Write>; rel="http://www.w3.org/ns/solid/acp#grant"',
'<http://www.w3.org/ns/solid/acp#agent>; rel="http://www.w3.org/ns/solid/acp#attribute"',
'<http://www.w3.org/ns/solid/acp#client>; rel="http://www.w3.org/ns/solid/acp#attribute"',
]});
});
});