Add configurable custom notification webhooks (#5742) - #8580
Open
joshi-rushikesh wants to merge 4 commits into
Open
Add configurable custom notification webhooks (#5742)#8580joshi-rushikesh wants to merge 4 commits into
joshi-rushikesh wants to merge 4 commits into
Conversation
Nightscout notifications could only be delivered to IFTTT Maker. The destination host is hardcoded in maker.makeKeyRequest and the whole path returns null without a MAKER_KEY, so operators could not send events to their own endpoint (issue nightscout#5742). Add a sibling delivery path for operator-configured destinations: - CUSTOM_WEBHOOK_URL_1..4 / CUSTOM_WEBHOOK_EVENT_1..4 declared in lib/settings.js, following the existing numbered frameUrl/frameName pattern so nameFromKey maps them without changes to env.js - lib/server/customwebhook.js normalizes the pairs, skipping unused and incomplete slots and rejecting anything that is not a valid http or https URL, so bad configuration warns instead of failing startup - matching reuses the ns-event / ns-<level> / ns-<level>-<name> names documented for Maker, but sends one request per destination rather than Maker's three, which exist only to work around IFTTT filtering - delivery is POST JSON over http or https with an explicit timeout, any 2xx treated as success, and network errors reported through the callback so a failed webhook cannot break the notification path Custom delivery is not gated on ctx.maker, so it works with no MAKER_KEY, and it does not touch the recentlySent TTL. lib/plugins/maker.js is unchanged, so existing MAKER_KEY and MAKER_ANNOUNCEMENT_KEY behavior is identical. The SGV-oriented lib/plugins/webhook.js is also unchanged. Webhook URLs are added to secureSettings because /api/v1/status publishes env.settings, and these URLs commonly embed per-destination tokens. Logs record the origin only, never the full URL or notification content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tests/customwebhook.test.js covers configuration parsing, event matching and transport, replacing customwebhook.sendRequest so no test performs a real network request, following the seam tests/webhook.test.js already uses for the SGV webhook plugin. Configuration: no config, absent settings, url without event, event without url, malformed url, non http(s) scheme, one invalid entry not discarding the valid ones, sparse indexes and whitespace trimming. Matching: the generated ns-event / ns-<level> / ns-<level>-<name> names, a match delivering exactly one request to the configured destination, a non-match delivering nothing, several destinations matching one notification, a single destination being sent once even when two of its configured event names match, missing name and level rejection, and allclear reaching only the destinations configured for it. Payload and transport: payload fields, announcement flag, parsed http and https targets including port, path and query, a network failure surfaced through the callback rather than thrown, and a partial failure that still counts the successful send while keeping the secret bearing path out of the error text. tests/settings.test.js adds coverage for the numbered CUSTOM_WEBHOOK_URL_n and CUSTOM_WEBHOOK_EVENT_n env var mapping, including a sparse index, and asserts filteredSettings does not publish the URLs in status.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add a "Custom Notification WebHooks" section to the README next to the IFTTT Maker section, covering what the feature does and why it exists, the numbered CUSTOM_WEBHOOK_URL_n and CUSTOM_WEBHOOK_EVENT_n variables, a worked two destination example, the event matching rules including the one request per destination guarantee, the JSON request body, and the operational notes on sparse numbering, skipped invalid entries, timeout and 2xx handling. State explicitly that the feature is independent of the IFTTT Maker integration and needs no MAKER_KEY, and that it is separate from the SGV webhook plugin, so operators are not left guessing which one they want. Document the security posture: URLs are secure settings and are not published in /api/v1/status, logs contain the destination host only, and these variables let the server reach any address it can route to. Add the corresponding TOC entry and commented examples in docs/example-template.env. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The event matching documentation used ns-urgent-simplealarms as its example of the ns-<level>-<name> form, but that name is never generated. simplealarms sets eventName to low or high on every alarm branch, and pushnotify uses notify.eventName in preference to the plugin name, so the plugin name fallback never applies to BG alarms. Use ns-urgent-low as the example instead and spell out that low and high BG alarms are level qualified: ns-urgent-low for BG_LOW, ns-warning-low for BG_TARGET_BOTTOM, and the matching high variants. Also state that there is no bare ns-low event, since issue nightscout#5742 illustrates the feature with that name, and point at the existing maker setup event list for the full vocabulary. Documentation only, no behavior change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author
|
Hi @AndyLow91 — this is my first contribution to Nightscout. I implemented #5742 by adding configurable notification-event webhooks as an independent delivery path while preserving the existing Maker/IFTTT behavior. I also added focused tests and documentation. Since you reviewed the related server-webhook contribution #8427, I’d really appreciate a review when you have time. Thank you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5742
Why
Issue #5742 describes delays caused by routing Nightscout notification events through IFTTT Maker. Today, the Maker notification path is tied to an IFTTT key and a hardcoded IFTTT destination, so operators cannot route those same notification events directly to their own endpoints.
This PR adds an independent custom notification-webhook path while preserving the existing Maker/IFTTT behavior.
What changed
Operators can configure up to four URL/event pairs:
Matching notifications are delivered directly to the configured endpoint as JSON
POSTrequests.The implementation:
lib/server/customwebhook.jssenderpushnotifysecureSettingslib/plugins/maker.jsandlib/plugins/webhook.jsunchangedDesign notes
Independent from Maker / IFTTT
lib/plugins/maker.jsis intentionally not modified.Maker's existing three-event fan-out (
ns-event,ns-<level>,ns-<level>-<name>) is an IFTTT-specific compatibility behavior that dates back to the original implementation. Extending the Maker sender directly would also inherit the requirement for aMAKER_KEY.Instead, this PR adds a sibling delivery path from the notification dispatcher. Custom webhooks therefore work even when
ctx.maker === null, while existing Maker behavior remains unchanged.Configuration naming
The issue illustrates names such as
CUSTOM_WEBHOOK_1_URL, but Nightscout's current numbered-setting convention maps naturally to:This matches existing settings such as
FRAME_URL_1and avoids changing the global settings-name parser.Event matching
Custom webhook event matching follows Nightscout's existing Maker event vocabulary:
ns-eventns-<level>ns-<level>-<name>ns-allclearFor low blood glucose alarms, the level-qualified forms are used, for example:
There is no bare
ns-lowevent in the current event vocabulary.Delivery behavior
A single configured destination is sent at most one request for a notification, even if more than one generated event name would match that same destination.
The JSON payload includes the notification fields needed by the receiving endpoint, and the transport uses Node's built-in
http,https, andURLAPIs. No new dependencies were added.Security considerations
Webhook URLs may contain credentials or tokens, so the new URL settings are included in
secureSettingsand are not exposed through normal serialized settings output.The implementation also:
http:andhttps:schemesCustom webhook URLs are operator-controlled configuration. They can point to private-network hosts, which is intentional for this use case and consistent with Nightscout's existing server webhook functionality. This is documented because it creates the expected SSRF surface of an operator-configurable outbound webhook feature.
Backward compatibility
The default configuration contains no custom webhook destinations, so the new module initializes to
nulland produces no additional outbound traffic unless explicitly configured.Existing behavior is preserved:
lib/plugins/maker.jsis unchangedlib/plugins/webhook.jsis unchangedMAKER_KEYrecentlySentTTL or Pushover receipt handlingTesting
Focused feature tests
Result:
Related regression suites
Relevant results:
The existing Maker and SGV-webhook test files were not modified.
Broader unit suite
The broader local unit suite produced:
The six failures are MongoDB-dependent local-environment failures in the existing security/authentication tests. To verify they were not introduced by this change, I temporarily removed the custom-webhook source changes and re-ran the failing suites; the same four
verifyauthtimeouts and twosecurityfailures remained.Lint
npm run lintreports the same 32 pre-existing problems with or without the custom-webhook source changes.Running ESLint against the new/modified source and test files produces no new lint problems.
Manual transport verification
Because automated tests stub the outbound request seam, I also exercised the real transport against a local HTTP listener:
Acceptance criteria
devCloses #5742Before / after verification evidence
Before implementation, reproducing an urgent-low notification through the existing path generated three requests to the hardcoded IFTTT Maker endpoint and zero requests to the configured custom endpoint:
After implementation:
The existing Maker and SGV-webhook implementations remain unchanged.
Documentation
This PR updates:
README.mdwith a new Custom Notification WebHooks sectiondocs/example-template.envwith commented configuration examplesThe README documents the configuration variables, event matching behavior, JSON delivery behavior, low/high alarm event naming, and security considerations.