refactor: Rename WebHook to Webhook

This commit is contained in:
Joachim Van Herwegen 2023-10-05 16:19:43 +02:00
parent 1e3684bcf3
commit 531c299c7b
16 changed files with 77 additions and 73 deletions

View File

@ -31,6 +31,8 @@ The following changes are relevant for v6 custom configs that replaced certain f
- `/http/notifications/base/storage.json` - `/http/notifications/base/storage.json`
- `/identity/*` - `/identity/*`
- `/storage/keyvalue/storages/storages.json` - `/storage/keyvalue/storages/storages.json`
- All identifiers containing the string "WebHook" have been renamed to instead use "Webhook"
to be consistent with the notification type.
### Interface changes ### Interface changes
@ -41,6 +43,8 @@ These changes are relevant if you wrote custom modules for the server that depen
- `EncodingPathStorage` has been removed - `EncodingPathStorage` has been removed
and its functionality split up over `Base64EncodingStorage` and `ContainerPathStorage`. and its functionality split up over `Base64EncodingStorage` and `ContainerPathStorage`.
`HashEncodingPathStorage` has similarly been replaced by introducing `HashEncodingStorage`. `HashEncodingPathStorage` has similarly been replaced by introducing `HashEncodingStorage`.
- All classes with the name `WebHook*` have been renamed to `Webhook*`
to be consistent with the corresponding notification type.
## v6.1.0 ## v6.1.0

View File

@ -22,13 +22,13 @@ Determines how notifications should be sent out from the server when resources c
* *all*: Supports all available notification types of the Solid Notifications protocol * *all*: Supports all available notification types of the Solid Notifications protocol
[specification](https://solidproject.org/TR/notifications-protocol). [specification](https://solidproject.org/TR/notifications-protocol).
Currently, this includes WebHookChannel2023 and WebSocketChannel2023. Currently, this includes WebhookChannel2023 and WebSocketChannel2023.
* *disabled*: No notifications are sent out. * *disabled*: No notifications are sent out.
* *legacy-websocket*: Follows the legacy Solid WebSocket * *legacy-websocket*: Follows the legacy Solid WebSocket
[specification](https://github.com/solid/solid-spec/blob/master/api-websockets.md). [specification](https://github.com/solid/solid-spec/blob/master/api-websockets.md).
Will be removed in future versions. Will be removed in future versions.
* *new-old-websockets.json*: Support for both the legacy Solid Websockets and the new WebSocketChannel2023. * *new-old-websockets.json*: Support for both the legacy Solid Websockets and the new WebSocketChannel2023.
* *webhooks*: Follows the WebHookChannel2023 * *webhooks*: Follows the WebhookChannel2023
[specification](https://solid.github.io/notifications/webhook-channel-2023) draft. [specification](https://solid.github.io/notifications/webhook-channel-2023) draft.
* *websockets*: Follows the WebSocketChannel2023 * *websockets*: Follows the WebSocketChannel2023
[specification](https://solid.github.io/notifications/websocket-channel-2023). [specification](https://solid.github.io/notifications/websocket-channel-2023).

View File

@ -3,23 +3,23 @@
"@graph": [ "@graph": [
{ {
"comment": "Handles the generation and serialization of notifications for WebhookChannel2023.", "comment": "Handles the generation and serialization of notifications for WebhookChannel2023.",
"@id": "urn:solid-server:default:WebHookNotificationHandler", "@id": "urn:solid-server:default:WebhookNotificationHandler",
"@type": "TypedNotificationHandler", "@type": "TypedNotificationHandler",
"type": "http://www.w3.org/ns/solid/notifications#WebhookChannel2023", "type": "http://www.w3.org/ns/solid/notifications#WebhookChannel2023",
"source": { "source": {
"@type": "ComposedNotificationHandler", "@type": "ComposedNotificationHandler",
"generator": { "@id": "urn:solid-server:default:BaseNotificationGenerator" }, "generator": { "@id": "urn:solid-server:default:BaseNotificationGenerator" },
"serializer": { "@id": "urn:solid-server:default:BaseNotificationSerializer" }, "serializer": { "@id": "urn:solid-server:default:BaseNotificationSerializer" },
"emitter": { "@id": "urn:solid-server:default:WebHookEmitter" }, "emitter": { "@id": "urn:solid-server:default:WebhookEmitter" },
"eTagHandler": { "@id": "urn:solid-server:default:ETagHandler" } "eTagHandler": { "@id": "urn:solid-server:default:ETagHandler" }
} }
}, },
{ {
"comment": "Emits serialized notifications through HTTP requests to the Webhook.", "comment": "Emits serialized notifications through HTTP requests to the Webhook.",
"@id": "urn:solid-server:default:WebHookEmitter", "@id": "urn:solid-server:default:WebhookEmitter",
"@type": "WebHookEmitter", "@type": "WebhookEmitter",
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
"webIdRoute": { "@id": "urn:solid-server:default:WebHookWebIdRoute" }, "webIdRoute": { "@id": "urn:solid-server:default:WebhookWebIdRoute" },
"jwkGenerator": { "@id": "urn:solid-server:default:JwkGenerator" } "jwkGenerator": { "@id": "urn:solid-server:default:JwkGenerator" }
}, },
@ -27,7 +27,7 @@
"@id": "urn:solid-server:default:NotificationHandler", "@id": "urn:solid-server:default:NotificationHandler",
"@type": "WaterfallHandler", "@type": "WaterfallHandler",
"handlers": [ "handlers": [
{ "@id": "urn:solid-server:default:WebHookNotificationHandler" } { "@id": "urn:solid-server:default:WebhookNotificationHandler" }
] ]
} }
] ]

View File

@ -2,26 +2,26 @@
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld", "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
"@graph": [ "@graph": [
{ {
"@id": "urn:solid-server:default:WebHookRoute", "@id": "urn:solid-server:default:WebhookRoute",
"@type": "RelativePathInteractionRoute", "@type": "RelativePathInteractionRoute",
"base": { "@id": "urn:solid-server:default:NotificationRoute" }, "base": { "@id": "urn:solid-server:default:NotificationRoute" },
"relativePath": "/WebhookChannel2023/" "relativePath": "/WebhookChannel2023/"
}, },
{ {
"@id": "urn:solid-server:default:WebHookWebIdRoute", "@id": "urn:solid-server:default:WebhookWebIdRoute",
"@type": "RelativePathInteractionRoute", "@type": "RelativePathInteractionRoute",
"base": { "@id": "urn:solid-server:default:WebHookRoute" }, "base": { "@id": "urn:solid-server:default:WebhookRoute" },
"relativePath": "/webId" "relativePath": "/webId"
}, },
{ {
"comment": "Handles the WebhookChannel2023 WebID.", "comment": "Handles the WebhookChannel2023 WebID.",
"@id": "urn:solid-server:default:WebHookWebId", "@id": "urn:solid-server:default:WebhookWebId",
"@type": "OperationRouterHandler", "@type": "OperationRouterHandler",
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
"allowedPathNames": [ "/WebhookChannel2023/webId$" ], "allowedPathNames": [ "/WebhookChannel2023/webId$" ],
"handler": { "handler": {
"@type": "WebHookWebId", "@type": "WebhookWebId",
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" } "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }
} }
}, },
@ -30,8 +30,8 @@
"@id": "urn:solid-server:default:NotificationTypeHandler", "@id": "urn:solid-server:default:NotificationTypeHandler",
"@type": "WaterfallHandler", "@type": "WaterfallHandler",
"handlers": [ "handlers": [
{ "@id": "urn:solid-server:default:WebHookRouter" }, { "@id": "urn:solid-server:default:WebhookRouter" },
{ "@id": "urn:solid-server:default:WebHookWebId" } { "@id": "urn:solid-server:default:WebhookWebId" }
] ]
} }
] ]

View File

@ -3,15 +3,15 @@
"@graph": [ "@graph": [
{ {
"comment": "Handles the subscriptions targeting a WebhookChannel2023.", "comment": "Handles the subscriptions targeting a WebhookChannel2023.",
"@id": "urn:solid-server:default:WebHookRouter", "@id": "urn:solid-server:default:WebhookRouter",
"@type": "OperationRouterHandler", "@type": "OperationRouterHandler",
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
"allowedMethods": [ "HEAD", "GET", "POST" ], "allowedMethods": [ "HEAD", "GET", "POST" ],
"allowedPathNames": [ "/WebhookChannel2023/$" ], "allowedPathNames": [ "/WebhookChannel2023/$" ],
"handler": { "handler": {
"@id": "urn:solid-server:default:WebHookSubscriber", "@id": "urn:solid-server:default:WebhookSubscriber",
"@type": "NotificationSubscriber", "@type": "NotificationSubscriber",
"channelType": { "@id": "urn:solid-server:default:WebHookChannel2023Type" }, "channelType": { "@id": "urn:solid-server:default:WebhookChannel2023Type" },
"converter": { "@id": "urn:solid-server:default:RepresentationConverter" }, "converter": { "@id": "urn:solid-server:default:RepresentationConverter" },
"credentialsExtractor": { "@id": "urn:solid-server:default:CredentialsExtractor" }, "credentialsExtractor": { "@id": "urn:solid-server:default:CredentialsExtractor" },
"permissionReader": { "@id": "urn:solid-server:default:PermissionReader" }, "permissionReader": { "@id": "urn:solid-server:default:PermissionReader" },
@ -21,13 +21,13 @@
}, },
{ {
"comment": "Contains all the metadata relevant for a WebhookChannel2023.", "comment": "Contains all the metadata relevant for a WebhookChannel2023.",
"@id": "urn:solid-server:default:WebHookChannel2023Type", "@id": "urn:solid-server:default:WebhookChannel2023Type",
"@type": "WebhookChannel2023Type", "@type": "WebhookChannel2023Type",
"route": { "@id": "urn:solid-server:default:WebHookRoute" }, "route": { "@id": "urn:solid-server:default:WebhookRoute" },
"webIdRoute": { "@id": "urn:solid-server:default:WebHookWebIdRoute" }, "webIdRoute": { "@id": "urn:solid-server:default:WebhookWebIdRoute" },
"stateHandler": { "stateHandler": {
"@type": "BaseStateHandler", "@type": "BaseStateHandler",
"handler": { "@id": "urn:solid-server:default:WebHookNotificationHandler" }, "handler": { "@id": "urn:solid-server:default:WebhookNotificationHandler" },
"storage": { "@id": "urn:solid-server:default:SubscriptionStorage" } "storage": { "@id": "urn:solid-server:default:SubscriptionStorage" }
} }
}, },
@ -37,7 +37,7 @@
"@type": "NotificationDescriber", "@type": "NotificationDescriber",
"subscriptions": [ "subscriptions": [
{ {
"@id": "urn:solid-server:default:WebHookChannel2023Type" "@id": "urn:solid-server:default:WebhookChannel2023Type"
} }
] ]
} }

View File

@ -174,13 +174,13 @@ so that class can emit events later on, as mentioned above.
The state handler will make sure that a notification gets sent out if the subscription has a `state` feature request, The state handler will make sure that a notification gets sent out if the subscription has a `state` feature request,
as defined in the notification specification. as defined in the notification specification.
## WebHookChannel2023 ## WebhookChannel2023
The additions required to support The additions required to support
[WebHookChannel2023](https://solid.github.io/notifications/webhook-channel-2023) [WebhookChannel2023](https://solid.github.io/notifications/webhook-channel-2023)
are quite similar to those needed for WebSocketChannel2023: are quite similar to those needed for WebSocketChannel2023:
* For discovery, there is a `WebHookDescriber`, which is an extension of a `NotificationDescriber`. * For discovery, there is a `WebhookDescriber`, which is an extension of a `NotificationDescriber`.
* The `WebHookChannel2023Type` class contains all the necessary typing information. * The `WebhookChannel2023Type` class contains all the necessary typing information.
* `WebHookEmitter` is the `NotificationEmitter` that sends the request. * `WebhookEmitter` is the `NotificationEmitter` that sends the request.
* `WebHookUnsubscriber` and `WebHookWebId` are additional utility classes to support the spec requirements. * `WebhookUnsubscriber` and `WebhookWebId` are additional utility classes to support the spec requirements.

View File

@ -228,4 +228,4 @@ You can modify this behaviour by adding the following block to your configuratio
`maxDuration` defines after how many minutes every channel will be removed. `maxDuration` defines after how many minutes every channel will be removed.
Setting this value to 0 will allow channels to exist forever. Setting this value to 0 will allow channels to exist forever.
Similarly, to change the maximum duration of webhook channels you can use the identifier Similarly, to change the maximum duration of webhook channels you can use the identifier
`urn:solid-server:default:WebHookSubscriber`. `urn:solid-server:default:WebhookSubscriber`.

View File

@ -325,10 +325,10 @@ export * from './server/notifications/serialize/ConvertingNotificationSerializer
export * from './server/notifications/serialize/JsonLdNotificationSerializer'; export * from './server/notifications/serialize/JsonLdNotificationSerializer';
export * from './server/notifications/serialize/NotificationSerializer'; export * from './server/notifications/serialize/NotificationSerializer';
// Server/Notifications/WebHookChannel2023 // Server/Notifications/WebhookChannel2023
export * from './server/notifications/WebHookChannel2023/WebhookChannel2023Type'; export * from './server/notifications/WebhookChannel2023/WebhookChannel2023Type';
export * from './server/notifications/WebHookChannel2023/WebHookEmitter'; export * from './server/notifications/WebhookChannel2023/WebhookEmitter';
export * from './server/notifications/WebHookChannel2023/WebHookWebId'; export * from './server/notifications/WebhookChannel2023/WebhookWebId';
// Server/Notifications/WebSocketChannel2023 // Server/Notifications/WebSocketChannel2023
export * from './server/notifications/WebSocketChannel2023/WebSocket2023Emitter'; export * from './server/notifications/WebSocketChannel2023/WebSocket2023Emitter';

View File

@ -8,11 +8,11 @@ import type { NotificationChannel } from '../NotificationChannel';
import type { StateHandler } from '../StateHandler'; import type { StateHandler } from '../StateHandler';
/** /**
* A {@link NotificationChannel} containing the necessary fields for a WebHookChannel2023 channel. * A {@link NotificationChannel} containing the necessary fields for a WebhookChannel2023 channel.
*/ */
export interface WebhookChannel2023 extends NotificationChannel { export interface WebhookChannel2023 extends NotificationChannel {
/** /**
* The "WebHookChannel2023" type. * The "WebhookChannel2023" type.
*/ */
type: typeof NOTIFY.WebhookChannel2023; type: typeof NOTIFY.WebhookChannel2023;
/** /**
@ -21,12 +21,12 @@ export interface WebhookChannel2023 extends NotificationChannel {
sendTo: string; sendTo: string;
} }
export function isWebHook2023Channel(channel: NotificationChannel): channel is WebhookChannel2023 { export function isWebhook2023Channel(channel: NotificationChannel): channel is WebhookChannel2023 {
return channel.type === NOTIFY.WebhookChannel2023; return channel.type === NOTIFY.WebhookChannel2023;
} }
/** /**
* The notification channel type WebHookChannel2023 as described in * The notification channel type WebhookChannel2023 as described in
* https://solid.github.io/notifications/webhook-channel-2023 * https://solid.github.io/notifications/webhook-channel-2023
* *
* Requires read permissions on a resource to be able to receive notifications. * Requires read permissions on a resource to be able to receive notifications.

View File

@ -10,10 +10,10 @@ import { readableToString } from '../../../util/StreamUtil';
import type { NotificationEmitterInput } from '../NotificationEmitter'; import type { NotificationEmitterInput } from '../NotificationEmitter';
import { NotificationEmitter } from '../NotificationEmitter'; import { NotificationEmitter } from '../NotificationEmitter';
import type { WebhookChannel2023 } from './WebhookChannel2023Type'; import type { WebhookChannel2023 } from './WebhookChannel2023Type';
import { isWebHook2023Channel } from './WebhookChannel2023Type'; import { isWebhook2023Channel } from './WebhookChannel2023Type';
/** /**
* Emits a notification representation using the WebHookChannel2023 specification. * Emits a notification representation using the WebhookChannel2023 specification.
* *
* At the time of writing it is not specified how exactly a notification sender should make its requests verifiable, * At the time of writing it is not specified how exactly a notification sender should make its requests verifiable,
* so for now we use a token similar to those from Solid-OIDC, signed by the server itself. * so for now we use a token similar to those from Solid-OIDC, signed by the server itself.
@ -23,7 +23,7 @@ import { isWebHook2023Channel } from './WebhookChannel2023Type';
* The `expiration` input parameter is how long the generated token should be valid in minutes. * The `expiration` input parameter is how long the generated token should be valid in minutes.
* Default is 20. * Default is 20.
*/ */
export class WebHookEmitter extends NotificationEmitter { export class WebhookEmitter extends NotificationEmitter {
protected readonly logger = getLoggerFor(this); protected readonly logger = getLoggerFor(this);
private readonly issuer: string; private readonly issuer: string;
@ -40,15 +40,15 @@ export class WebHookEmitter extends NotificationEmitter {
} }
public async canHandle({ channel }: NotificationEmitterInput): Promise<void> { public async canHandle({ channel }: NotificationEmitterInput): Promise<void> {
if (!isWebHook2023Channel(channel)) { if (!isWebhook2023Channel(channel)) {
throw new NotImplementedHttpError(`${channel.id} is not a WebHookChannel2023 channel.`); throw new NotImplementedHttpError(`${channel.id} is not a WebhookChannel2023 channel.`);
} }
} }
public async handle({ channel, representation }: NotificationEmitterInput): Promise<void> { public async handle({ channel, representation }: NotificationEmitterInput): Promise<void> {
// Cast was checked in `canHandle` // Cast was checked in `canHandle`
const webHookChannel = channel as WebhookChannel2023; const webhookChannel = channel as WebhookChannel2023;
this.logger.debug(`Emitting WebHook notification with target ${webHookChannel.sendTo}`); this.logger.debug(`Emitting Webhook notification with target ${webhookChannel.sendTo}`);
const privateKey = await this.jwkGenerator.getPrivateKey(); const privateKey = await this.jwkGenerator.getPrivateKey();
const publicKey = await this.jwkGenerator.getPublicKey(); const publicKey = await this.jwkGenerator.getPublicKey();
@ -78,14 +78,14 @@ export class WebHookEmitter extends NotificationEmitter {
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-4.2 // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-4.2
const dpopProof = await new SignJWT({ const dpopProof = await new SignJWT({
htu: webHookChannel.sendTo, htu: webhookChannel.sendTo,
htm: 'POST', htm: 'POST',
}).setProtectedHeader({ alg: privateKey.alg, jwk: publicKey, typ: 'dpop+jwt' }) }).setProtectedHeader({ alg: privateKey.alg, jwk: publicKey, typ: 'dpop+jwt' })
.setIssuedAt(time) .setIssuedAt(time)
.setJti(v4()) .setJti(v4())
.sign(privateKeyObject); .sign(privateKeyObject);
const response = await fetch(webHookChannel.sendTo, { const response = await fetch(webhookChannel.sendTo, {
method: 'POST', method: 'POST',
headers: { headers: {
'content-type': representation.metadata.contentType!, 'content-type': representation.metadata.contentType!,
@ -95,7 +95,7 @@ export class WebHookEmitter extends NotificationEmitter {
body: await readableToString(representation.data), body: await readableToString(representation.data),
}); });
if (response.status >= 400) { if (response.status >= 400) {
this.logger.error(`There was an issue emitting a WebHook notification with target ${webHookChannel.sendTo}: ${ this.logger.error(`There was an issue emitting a Webhook notification with target ${webhookChannel.sendTo}: ${
await response.text()}`); await response.text()}`);
} }
} }

View File

@ -9,11 +9,11 @@ import type { OperationHttpHandlerInput } from '../../OperationHttpHandler';
import { OperationHttpHandler } from '../../OperationHttpHandler'; import { OperationHttpHandler } from '../../OperationHttpHandler';
/** /**
* Generates a fixed WebID that we use to identify the server for notifications sent using a WebHookChannel2023. * Generates a fixed WebID that we use to identify the server for notifications sent using a WebhookChannel2023.
* This is used in tandem with the tokens generated by the {@link WebHookEmitter}. * This is used in tandem with the tokens generated by the {@link WebhookEmitter}.
* This is a minimal WebID with only the `solid:oidcIssuer` triple. * This is a minimal WebID with only the `solid:oidcIssuer` triple.
*/ */
export class WebHookWebId extends OperationHttpHandler { export class WebhookWebId extends OperationHttpHandler {
private readonly turtle: string; private readonly turtle: string;
public constructor(baseUrl: string) { public constructor(baseUrl: string) {

View File

@ -21,14 +21,14 @@ import {
} from './Config'; } from './Config';
import quad = DataFactory.quad; import quad = DataFactory.quad;
const port = getPort('WebHookChannel2023'); const port = getPort('WebhookChannel2023');
const baseUrl = `http://localhost:${port}/`; const baseUrl = `http://localhost:${port}/`;
const clientPort = getPort('WebHookChannel2023-client'); const clientPort = getPort('WebhookChannel2023-client');
const target = `http://localhost:${clientPort}/`; const target = `http://localhost:${clientPort}/`;
const webId = 'http://example.com/card/#me'; const webId = 'http://example.com/card/#me';
const notificationType = NOTIFY.WebhookChannel2023; const notificationType = NOTIFY.WebhookChannel2023;
const rootFilePath = getTestFolder('WebHookChannel2023'); const rootFilePath = getTestFolder('WebhookChannel2023');
const stores: [string, any][] = [ const stores: [string, any][] = [
[ 'in-memory storage', { [ 'in-memory storage', {
configs: [ 'storage/backend/memory.json', 'util/resource-locker/memory.json' ], configs: [ 'storage/backend/memory.json', 'util/resource-locker/memory.json' ],
@ -40,7 +40,7 @@ const stores: [string, any][] = [
}], }],
]; ];
describe.each(stores)('A server supporting WebHookChannel2023 using %s', (name, { configs, teardown }): void => { describe.each(stores)('A server supporting WebhookChannel2023 using %s', (name, { configs, teardown }): void => {
let app: App; let app: App;
const topic = joinUrl(baseUrl, '/foo'); const topic = joinUrl(baseUrl, '/foo');
let storageDescriptionUrl: string; let storageDescriptionUrl: string;

View File

@ -12,11 +12,11 @@ import type { NotificationChannel } from '../../../../../src/server/notification
import type { StateHandler } from '../../../../../src/server/notifications/StateHandler'; import type { StateHandler } from '../../../../../src/server/notifications/StateHandler';
import type { import type {
WebhookChannel2023, WebhookChannel2023,
} from '../../../../../src/server/notifications/WebHookChannel2023/WebhookChannel2023Type'; } from '../../../../../src/server/notifications/WebhookChannel2023/WebhookChannel2023Type';
import { import {
isWebHook2023Channel, isWebhook2023Channel,
WebhookChannel2023Type, WebhookChannel2023Type,
} from '../../../../../src/server/notifications/WebHookChannel2023/WebhookChannel2023Type'; } from '../../../../../src/server/notifications/WebhookChannel2023/WebhookChannel2023Type';
import { NOTIFY, RDF } from '../../../../../src/util/Vocabularies'; import { NOTIFY, RDF } from '../../../../../src/util/Vocabularies';
import quad = DataFactory.quad; import quad = DataFactory.quad;
import blankNode = DataFactory.blankNode; import blankNode = DataFactory.blankNode;
@ -63,10 +63,10 @@ describe('A WebhookChannel2023Type', (): void => {
}); });
it('exposes a utility function to verify if a channel is a webhook channel.', async(): Promise<void> => { it('exposes a utility function to verify if a channel is a webhook channel.', async(): Promise<void> => {
expect(isWebHook2023Channel(channel)).toBe(true); expect(isWebhook2023Channel(channel)).toBe(true);
(channel as NotificationChannel).type = 'something else'; (channel as NotificationChannel).type = 'something else';
expect(isWebHook2023Channel(channel)).toBe(false); expect(isWebhook2023Channel(channel)).toBe(false);
}); });
it('correctly parses notification channel bodies.', async(): Promise<void> => { it('correctly parses notification channel bodies.', async(): Promise<void> => {

View File

@ -11,8 +11,8 @@ import { getLoggerFor } from '../../../../../src/logging/LogUtil';
import type { Notification } from '../../../../../src/server/notifications/Notification'; import type { Notification } from '../../../../../src/server/notifications/Notification';
import type { import type {
WebhookChannel2023, WebhookChannel2023,
} from '../../../../../src/server/notifications/WebHookChannel2023/WebhookChannel2023Type'; } from '../../../../../src/server/notifications/WebhookChannel2023/WebhookChannel2023Type';
import { WebHookEmitter } from '../../../../../src/server/notifications/WebHookChannel2023/WebHookEmitter'; import { WebhookEmitter } from '../../../../../src/server/notifications/WebhookChannel2023/WebhookEmitter';
import { NotImplementedHttpError } from '../../../../../src/util/errors/NotImplementedHttpError'; import { NotImplementedHttpError } from '../../../../../src/util/errors/NotImplementedHttpError';
import { matchesAuthorizationScheme } from '../../../../../src/util/HeaderUtil'; import { matchesAuthorizationScheme } from '../../../../../src/util/HeaderUtil';
import { trimTrailingSlashes } from '../../../../../src/util/PathUtil'; import { trimTrailingSlashes } from '../../../../../src/util/PathUtil';
@ -26,7 +26,7 @@ jest.mock('../../../../../src/logging/LogUtil', (): any => {
return { getLoggerFor: (): Logger => logger }; return { getLoggerFor: (): Logger => logger };
}); });
describe('A WebHookEmitter', (): void => { describe('A WebhookEmitter', (): void => {
const fetchMock: jest.Mock = fetch as any; const fetchMock: jest.Mock = fetch as any;
const baseUrl = 'http://example.com/'; const baseUrl = 'http://example.com/';
const serverWebId = 'http://example.com/.notifcations/webhooks/webid'; const serverWebId = 'http://example.com/.notifcations/webhooks/webid';
@ -52,7 +52,7 @@ describe('A WebHookEmitter', (): void => {
let privateJwk: AlgJwk; let privateJwk: AlgJwk;
let publicJwk: AlgJwk; let publicJwk: AlgJwk;
let jwkGenerator: jest.Mocked<JwkGenerator>; let jwkGenerator: jest.Mocked<JwkGenerator>;
let emitter: WebHookEmitter; let emitter: WebhookEmitter;
beforeEach(async(): Promise<void> => { beforeEach(async(): Promise<void> => {
fetchMock.mockResolvedValue({ status: 200 }); fetchMock.mockResolvedValue({ status: 200 });
@ -70,7 +70,7 @@ describe('A WebHookEmitter', (): void => {
getPublicKey: jest.fn().mockResolvedValue(publicJwk), getPublicKey: jest.fn().mockResolvedValue(publicJwk),
}; };
emitter = new WebHookEmitter(baseUrl, webIdRoute, jwkGenerator); emitter = new WebhookEmitter(baseUrl, webIdRoute, jwkGenerator);
}); });
it('errors if the channel type is wrong.', async(): Promise<void> => { it('errors if the channel type is wrong.', async(): Promise<void> => {
@ -139,7 +139,7 @@ describe('A WebHookEmitter', (): void => {
expect(logger.error).toHaveBeenCalledTimes(1); expect(logger.error).toHaveBeenCalledTimes(1);
expect(logger.error).toHaveBeenLastCalledWith( expect(logger.error).toHaveBeenLastCalledWith(
`There was an issue emitting a WebHook notification with target ${channel.sendTo}: invalid request`, `There was an issue emitting a Webhook notification with target ${channel.sendTo}: invalid request`,
); );
}); });
}); });

View File

@ -3,17 +3,17 @@ import type { Operation } from '../../../../../src/http/Operation';
import { BasicRepresentation } from '../../../../../src/http/representation/BasicRepresentation'; import { BasicRepresentation } from '../../../../../src/http/representation/BasicRepresentation';
import type { HttpRequest } from '../../../../../src/server/HttpRequest'; import type { HttpRequest } from '../../../../../src/server/HttpRequest';
import type { HttpResponse } from '../../../../../src/server/HttpResponse'; import type { HttpResponse } from '../../../../../src/server/HttpResponse';
import { WebHookWebId } from '../../../../../src/server/notifications/WebHookChannel2023/WebHookWebId'; import { WebhookWebId } from '../../../../../src/server/notifications/WebhookChannel2023/WebhookWebId';
import { readableToString } from '../../../../../src/util/StreamUtil'; import { readableToString } from '../../../../../src/util/StreamUtil';
import { SOLID } from '../../../../../src/util/Vocabularies'; import { SOLID } from '../../../../../src/util/Vocabularies';
const { namedNode, quad } = DataFactory; const { namedNode, quad } = DataFactory;
describe('A WebHookWebId', (): void => { describe('A WebhookWebId', (): void => {
const request: HttpRequest = {} as any; const request: HttpRequest = {} as any;
const response: HttpResponse = {} as any; const response: HttpResponse = {} as any;
let operation: Operation; let operation: Operation;
const baseUrl = 'http://example.com/'; const baseUrl = 'http://example.com/';
let webIdHandler: WebHookWebId; let webIdHandler: WebhookWebId;
beforeEach(async(): Promise<void> => { beforeEach(async(): Promise<void> => {
operation = { operation = {
@ -23,7 +23,7 @@ describe('A WebHookWebId', (): void => {
body: new BasicRepresentation(), body: new BasicRepresentation(),
}; };
webIdHandler = new WebHookWebId(baseUrl); webIdHandler = new WebhookWebId(baseUrl);
}); });
it('returns a solid:oidcIssuer triple.', async(): Promise<void> => { it('returns a solid:oidcIssuer triple.', async(): Promise<void> => {
@ -41,7 +41,7 @@ describe('A WebHookWebId', (): void => {
}); });
it('errors if the base URL is invalid.', async(): Promise<void> => { it('errors if the base URL is invalid.', async(): Promise<void> => {
expect((): any => new WebHookWebId('very invalid URL')) expect((): any => new WebhookWebId('very invalid URL'))
.toThrow('Invalid issuer URL: Unexpected "<very" on line 2.'); .toThrow('Invalid issuer URL: Unexpected "<very" on line 2.');
}); });
}); });

View File

@ -29,8 +29,8 @@ const portNames = [
'SetupMemory', 'SetupMemory',
'SparqlStorage', 'SparqlStorage',
'Subdomains', 'Subdomains',
'WebHookChannel2023', 'WebhookChannel2023',
'WebHookChannel2023-client', 'WebhookChannel2023-client',
'WebSocketChannel2023', 'WebSocketChannel2023',
// Unit // Unit