From f7e05ca31e718732540214bc3f4b9400e6564c11 Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Fri, 21 Apr 2023 10:40:36 +0200 Subject: [PATCH] feat: Restrict channels to 2 weeks by default --- .../http/notifications/webhooks/routes.json | 2 +- .../notifications/webhooks/subscription.json | 3 ++- .../websockets/subscription.json | 5 ++-- documentation/markdown/usage/notifications.md | 24 +++++++++++++++++++ .../notifications/ListeningActivityHandler.ts | 3 +-- .../notifications/NotificationSubscriber.ts | 3 ++- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/config/http/notifications/webhooks/routes.json b/config/http/notifications/webhooks/routes.json index 5e294c33a..603330a11 100644 --- a/config/http/notifications/webhooks/routes.json +++ b/config/http/notifications/webhooks/routes.json @@ -44,7 +44,7 @@ "@id": "urn:solid-server:default:NotificationTypeHandler", "@type": "WaterfallHandler", "handlers": [ - { "@id": "urn:solid-server:default:WebHookSubscriber" }, + { "@id": "urn:solid-server:default:WebHookRouter" }, { "@id": "urn:solid-server:default:WebHookUnsubscriber" }, { "@id": "urn:solid-server:default:WebHookWebId" } ] diff --git a/config/http/notifications/webhooks/subscription.json b/config/http/notifications/webhooks/subscription.json index 0f1b87d7e..fb969b4fe 100644 --- a/config/http/notifications/webhooks/subscription.json +++ b/config/http/notifications/webhooks/subscription.json @@ -3,12 +3,13 @@ "@graph": [ { "comment": "Handles the subscriptions targeting a WebHookSubscription2021.", - "@id": "urn:solid-server:default:WebHookSubscriber", + "@id": "urn:solid-server:default:WebHookRouter", "@type": "OperationRouterHandler", "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, "allowedMethods": [ "HEAD", "GET", "POST" ], "allowedPathNames": [ "/WebHookSubscription2021/$" ], "handler": { + "@id": "urn:solid-server:default:WebHookSubscriber", "@type": "NotificationSubscriber", "channelType": { "@id": "urn:solid-server:default:WebHookSubscription2021" }, "converter": { "@id": "urn:solid-server:default:RepresentationConverter" }, diff --git a/config/http/notifications/websockets/subscription.json b/config/http/notifications/websockets/subscription.json index 12f5dfed2..5b2094816 100644 --- a/config/http/notifications/websockets/subscription.json +++ b/config/http/notifications/websockets/subscription.json @@ -3,12 +3,13 @@ "@graph": [ { "comment": "Handles the subscriptions targeting a WebSocketChannel2023.", - "@id": "urn:solid-server:default:WebSocket2023Subscriber", + "@id": "urn:solid-server:default:WebSocket2023Router", "@type": "OperationRouterHandler", "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, "allowedMethods": [ "HEAD", "GET", "POST" ], "allowedPathNames": [ "/WebSocketChannel2023/$" ], "handler": { + "@id": "urn:solid-server:default:WebSocket2023Subscriber", "@type": "NotificationSubscriber", "channelType": { "@id": "urn:solid-server:default:WebSocketChannel2023Type" }, "converter": { "@id": "urn:solid-server:default:RepresentationConverter" }, @@ -35,7 +36,7 @@ "@id": "urn:solid-server:default:NotificationTypeHandler", "@type": "WaterfallHandler", "handlers": [ - { "@id": "urn:solid-server:default:WebSocket2023Subscriber" } + { "@id": "urn:solid-server:default:WebSocket2023Router" } ] }, diff --git a/documentation/markdown/usage/notifications.md b/documentation/markdown/usage/notifications.md index d3861c5e7..32d43dc6c 100644 --- a/documentation/markdown/usage/notifications.md +++ b/documentation/markdown/usage/notifications.md @@ -200,3 +200,27 @@ The available fields are: A new notification will only be sent out after this much time has passed since the previous notification. * **`accept`**: A description of the `content-type(s)` in which the client would want to receive the notifications. Expects the same values as an `Accept` HTTP header. + +## Important note for server owners + +There is not much restriction on who can create a new notification channel, +only `Read` permissions on the target resource are required. +It is therefore possible for the server to accumulate created channels. +As these channels still get used every time their corresponding resource changes, +this could degrade server performance. + +For this reason, the server is by default configured to always remove notification channels after 2 weeks. +You can modify this behaviour by adding the following block to your configuration: + +```json +{ + "@id": "urn:solid-server:default:WebSocket2023Subscriber", + "@type": "NotificationSubscriber", + "maxDuration": 20160 +} +``` + +`maxDuration` defines after how many minutes every channel will be removed. +Setting this value to 0 will allow channels to exist forever. +Similarly, for changing the maximum duration of webhook channels you can use the identifier +`urn:solid-server:default:WebHookSubscriber`. diff --git a/src/server/notifications/ListeningActivityHandler.ts b/src/server/notifications/ListeningActivityHandler.ts index c397dffab..19b63023d 100644 --- a/src/server/notifications/ListeningActivityHandler.ts +++ b/src/server/notifications/ListeningActivityHandler.ts @@ -60,13 +60,12 @@ export class ListeningActivityHandler extends StaticHandler { // No need to wait on this to resolve before going to the next channel. // Prevent failed notification from blocking other notifications. this.handler.handleSafe({ channel, activity, topic, metadata }) - .then((): Promise => { + .then(async(): Promise => { // Update the `lastEmit` value if the channel has a rate limit if (channel.rate) { channel.lastEmit = Date.now(); return this.storage.update(channel); } - return Promise.resolve(); }) .catch((error): void => { this.logger.error(`Error trying to handle notification for ${id}: ${createErrorMessage(error)}`); diff --git a/src/server/notifications/NotificationSubscriber.ts b/src/server/notifications/NotificationSubscriber.ts index 152c42274..d5720f06b 100644 --- a/src/server/notifications/NotificationSubscriber.ts +++ b/src/server/notifications/NotificationSubscriber.ts @@ -46,6 +46,7 @@ export interface NotificationSubscriberArgs { * Overrides the expiration feature of channels, by making sure they always expire after the `maxDuration` value. * If the expiration of the channel is shorter than `maxDuration`, the original value will be kept. * Value is set in minutes. 0 is infinite. + * Defaults to 20160 minutes, which is 2 weeks. */ maxDuration?: number; } @@ -76,7 +77,7 @@ export class NotificationSubscriber extends OperationHttpHandler { this.permissionReader = args.permissionReader; this.authorizer = args.authorizer; this.storage = args.storage; - this.maxDuration = (args.maxDuration ?? 0) * 60 * 1000; + this.maxDuration = (args.maxDuration ?? 20160) * 60 * 1000; } public async handle({ operation, request }: OperationHttpHandlerInput): Promise {