Repository navigation
Notification template links are dropped or lose the path prefix #27432
Description
Several system notifications offer the user a link to the page where the reported
problem can be fixed. That link is missing entirely in the System Notifications
table, and on installations served under a path prefix one of them points to the
wrong place.
| What the user sees | "You can click here to solve this" with no link behind it, or a link that lands on a 404 |
| Where | System > Notifications, for 4 notification types that are raised today |
| Since | 7.2, not yet released, with the new paginated notifications table. The path prefix half is older |
| Blocked by | #27310, which adds the mechanism needed to fix it |
Risk
Risk level: low. Nothing is lost, corrupted or exposed. The user has to navigate
to the page by hand instead of clicking through.
| Severity | Low. Convenience only, and the notification text still names the page |
| Reach | 4 of the 9 affected notification types are ever raised in practice, and the missing link half has not shipped yet. The path prefix half needs both a prefixed install and a rare migration |
| Risk of fixing | Low. Template changes plus deletion of frontend code that is now unused |
| Risk of not fixing | Low and static. Mild support noise, no escalation path |
| One thing to get right | The link must stay origin relative. Making it absolute regresses installs reached directly rather than through a proxy, see the discussion on #27310 |
Details
Group A: the link is dropped (8 templates)
Eight templates take their href from a placeholder that is not part of the
notification. Seven are supplied by the web interface with the render request. One is
supplied by nobody at all.
| Template | Placeholder | Supplied by the web interface |
|---|---|---|
HTML/input_failing.ftl:12 |
${SYSTEM_INPUTS} |
no |
HTML/input_failed_to_start.ftl:12 |
${SYSTEM_INPUTS} |
yes |
HTML/input_failure_shutdown.ftl:12 |
${SYSTEM_INPUTS} |
yes |
HTML/no_input_running.ftl:11 |
${SYSTEM_INPUTS} |
yes |
HTML/data_node_needs_provisioning.ftl:15 |
${DATA_NODE_CONFIGURATION} |
yes |
HTML/remote_reindex_running.ftl:6 |
${DATA_NODE_MIGRATION_WIZARD} |
yes |
HTML/remote_reindex_finished.ftl:6 |
${DATA_NODE_MIGRATION_WIZARD} |
yes |
HTML/legacy_ldap_config_migration.ftl:6,10 |
${AUTHENTICATION_BACKEND} |
yes |
input_failing has no case in
graylog2-web-interface/src/components/notifications/NotificationsFactory.ts, so its
link never renders on any path, the Security app welcome modal included. It is a live
type, raised from InputStateListener.java:75.
The other seven placeholders are supplied by NotificationsFactory.ts, and their
values come from Routes, which is already prefix qualified (routing/Routes.ts:440).
So those links are correct wherever that mechanism is used.
The problem is that it is not used everywhere. NotificationsResource.renderHtmlById
(/system/notifications/{id}/message/html) passes no values at all
(NotificationsResource.java:274). That is the endpoint the System Notifications
table calls, via components/notifications/hooks/useNotificationBody.ts and
SystemNotificationsTable/expandedSections.tsx. Every <#if X?has_content> guard
evaluates false, so the link is omitted with no error and no log line.
legacy_ldap_config_migration.ftl is the one exception in shape: it has an <#else>
branch, so it degrades to a link free sentence rather than a truncated one.
Result: the same notification shows a "click here" link in the Security app welcome
modal (which uses useNotificationMessage and does pass the values) and shows no
link at all in the System Notifications table.
Introduced by #26062, which added the paginated notifications resource. Before it the
notifications list rendered through useNotificationMessage.
The PLAINTEXT templates have the same problem
Seven PLAINTEXT twins carry the same placeholders: all of the above except the two
remote_reindex_*, which carry no link in PLAINTEXT. These are rendered server side
with no values at all by NotificationPaginationService.java:144, where
render(notification) defaults to PLAINTEXT with values == null, and that output is
the title and description of every row in the paginated table.
NotificationSystemEventPublisher renders the same way. No client can pass values
into those paths, so the placeholders are always dropped there and need the same
server side fix.
Group B: the link loses the path prefix (1 template)
HTML/generic_with_link.ftl:11 uses ${GENERIC_URL}. This one is not supplied by
the client. It is written into the notification details in MongoDB at creation time
by V20230629140000_RenameFieldTypeOfEventDefinitionSeries.java:142-150, as
"/alerts/definitions/" + id (the path literal itself is built at :131). That is
the only producer in either repository, and NotificationsFactory.ts has no case
for it.
Because it comes from notification.getDetails(), it is merged into the template
model on both render paths (SystemNotificationRenderService.java:90-92), so the
link does appear. But it is root relative. On an install with a /graylog path
prefix it points at /alerts/definitions/<id> instead of
/graylog/alerts/definitions/<id>, which is outside the prefix, so the user gets a
404 or the start page depending on the proxy. This is exactly
Graylog2/graylog-plugin-enterprise#13940 in a second place.
It is also persisted, so a value written before a prefix was configured stays wrong
in the database.
Reach is small in practice: one migration, guarded by publishIfFirst, and only for
event definitions missing a field name.
Which of these notifications are actually raised
Four of the eight Group A types have no producer anywhere in graylog2-server or the
plugin repositories: REMOTE_REINDEX_RUNNING, REMOTE_REINDEX_FINISHED,
DATA_NODE_NEEDS_PROVISIONING and INPUT_FAILURE_SHUTDOWN appear only as enum
constants plus web interface types. Only input_failing, input_failed_to_start,
no_input_running and legacy_ldap_config_migration are raised today.
Steps to reproduce
Group A:
- Have an input that fails to start so an
input_failed_to_startnotification is
raised. - Open System > Notifications and expand the notification row.
- The "You can click here to solve this" sentence is missing its link.
- Open the same notification in the Security app welcome modal. The link is there.
- For
input_failingthe link is missing in both places, because that placeholder
has no producer at all.
Group B:
- Configure a path prefix, for example
/graylog. - Trigger the
V20230629140000migration notification, or insert a
generic_with_linknotification with aGENERIC_URLdetail. - Click the link. It goes to
/alerts/definitions/<id>, which is outside the
prefix.
Suggested fix
Both groups want the same thing: build the href server side at render time from the
request scoped uri_helper that #27310 adds, rather than depending on the caller to
pass a value in or on a path stored earlier.
- Group A: replace each placeholder with a
uri_helperexpression in the template,
in both the HTML and the PLAINTEXT variant, then remove the now unused keys from
NotificationsFactory.ts. The<#else>fallback in
legacy_ldap_config_migration.ftlcan go once the link is unconditional. - Group B: build the href from
uri_helperin the template and store only the event
definition ID in the notification details, not a path.
Whether the resolved link should be absolute or origin relative is being discussed on
#27310. Whichever shape lands there should be used here too, so the templates stay
consistent.
While touching legacy_ldap_config_migration.ftl: both of its anchors are malformed
today (<a href="${AUTHENTICATION_BACKEND}" authentication service</a>, missing the
closing >), and line 14 has a stray service<.. Worth fixing in the same pass.
Out of scope: templates that link to docs.graylog.org or to Elastic documentation.
Those are external absolute URLs and are correct as they are.
Activity