All notable changes to this project will be documented in this file.
The format follows Keep a Changelog, and this project adheres to Semantic Versioning.
notifications.jsno longer emits a useless?extraChannels=query param when there are no channels to subscribe to.normalizeExtraChannelsnow returnsnull(→ param omitted) for an empty array, the already-JSON strings"[]",'""'and"null", and whitespace-only input. The'""'case is the common Django footgun where{{ extraChannels|json_script }}on an undefined context variable rendersjson.dumps('') === '""', which used to leak as?extraChannels=%22%22. Non-empty arrays and non-JSON strings are unchanged (the latter still pass through verbatim).
- Renamed Python package
channels_notifications→channels_broadcast. All imports, the Django app label, and the settings prefixCHANNELS_NOTIFICATIONS_*→CHANNELS_BROADCAST_*change in lockstep. TheAppConfigclass is nowChannelsBroadcastConfig. UpdateINSTALLED_APPS, everyfrom channels_notifications import …, and anyCHANNELS_NOTIFICATIONS_*settings keys in your project.
- Initial extraction from BPP (Bibliografia Publikacji Pracowników) monolith
at commit
75f3c70f7. - Public audience-routing API:
send_to_all,send_to_authenticated,send_to_anonymous,send_to_user,send_to_object, plussend_to_channelfor raw channel names. - Redirect API:
redirect_user,redirect_object,redirect_channel— tell the receiving page to navigate to a URL. - Progress API:
progress_user,progress_object,progress_channel— push a percent to a progress bar. - Subscription authorization: settings-pluggable callable
CHANNELS_BROADCAST_SUBSCRIPTION_AUTHORIZERruns once per channel in?extraChannels=. Default: deny everything (secure by default). - Signed subscription tokens:
issue_subscription_token(user, channels, ttl)binds a user to a channel list for N seconds, no Redis required — uses Django'sTimestampSigner. Browser sends as?subscription_token=; consumer verifies signature + user match + TTL. - Settings contract for individual audience gates:
CHANNELS_BROADCAST_ENABLE_{ALL,AUTHENTICATED,ANONYMOUS,PAGE_CHANNELS}. - Anonymous visitors get no websocket connection at all when
ENABLE_ANONYMOUS=False(default). send_notificationmanagement command with--audienceflag.- 80 unit + ASGI integration tests covering audience routing, flag enforcement, redirect/progress payloads, authorizer hook, and signed-token subscription including tampered/expired/cross-user cases.
- 22 QUnit + sinon frontend tests run via Node (
npm test) using jsdom — covering the default Mustache renderer, redirect / progress payload handling, ACK behaviour, the chime hook, and the Toastify integration with stubbed Toastify. - Optional opt-in JS plugins:
notifications-toastify.js(right-side toast popups via Toastify, ~3KB) andnotifications-chime.js(four-note arpeggio via Tone.js, user-gesture deferred). - Example project demonstrates all five audience modes plus the authorizer (owner-only) and signed-token UID flows.
- JS global renamed from
bppNotificationstochannelsBroadcastfor the public package. Existing payload shapes ({text, cssClass, ...},{url},{progress, percent}) and Mustache template contract unchanged. - Tone.js audio code extracted out of
notifications.jsinto an optional siblingnotifications-chime.js. Corenotifications.jsno longer depends on Tone.js being loaded. send_notificationmanagement command rewritten:- Now reaches every function in
channels_broadcast.api— messages, redirects, progress, across all six audience targets (all,authenticated,anonymous,user,object,channel). - New
--kind=,--object=app.Model:pk,--channel=flags. - Interactive wizard mode: run with no arguments (or just some flags) from a TTY and the command prompts for kind → audience → target → level → payload. Non-TTY (cron, systemd) keeps the fail-fast "X is required" behaviour.
--kind={redirect,progress}is rejected for broadcast audiences (all/authenticated/anonymous) — those require a specific recipient.- When the relevant
ENABLE_*flag is False, exits 0 with aNo-op: ...stdout warning rather than silently swallowing.
- Now reaches every function in
NotificationsMiddleware(BPP-specificmessages_extendscoupling).send_messagemanagement command (BPP-specificmessages_extendscoupling).- Legacy migrations 0002/0003 squashed into a single
0001_initial.