Skip to content

feat: allow disabling and dismissing the open source message banner#15089

Open
devGregA wants to merge 3 commits into
DefectDojo:devfrom
devGregA:devgrega/os-message-opt-out
Open

feat: allow disabling and dismissing the open source message banner#15089
devGregA wants to merge 3 commits into
DefectDojo:devfrom
devGregA:devgrega/os-message-opt-out

Conversation

@devGregA

Copy link
Copy Markdown
Contributor

The open source message banner (the "Upgrade to Pro" promo fetched from the
GCS bucket) currently can't be turned off. This adds two ways to do that.

  1. DD_OS_MESSAGE_ENABLED (default True) — an instance-wide switch.
    When it's off, get_os_banner() returns early, so we don't fetch the
    message or render the banner at all.

  2. A dismiss (×) button on the banner. Dismissing it is remembered per user
    by storing a hash of the current message on UserContactInfo. If the
    message later changes, the hash no longer matches and the banner shows
    again. This follows the same pattern as the existing announcement
    dismissal, minus the confirmation page.

Default behavior is unchanged: leave the env var unset and don't click ×,
and the banner behaves exactly as it does today.

Notes:

  • New os_message_dismissed_hash field on UserContactInfo (migration 0270).
  • The × posts to a small dismiss_os_message view (CSRF handled by the form);
    JS hides the banner immediately and falls back to a normal POST if JS is off.
    Handled in both the classic and v3 base templates.
  • Settings doc / template-env updated and a note added to the 3.1 upgrade page.

Testing: extended unittests/test_os_message.py (env gate, dismiss-token,
context-processor gating, and the dismiss view). All passing locally.

…r the OS promo banner

DD_OS_MESSAGE_ENABLED (bool, default True) is a global admin opt-out: when False, get_os_banner() returns None before any network call, so no request is made to the GCS bucket. Default behavior is unchanged.

Authenticated users can also dismiss the banner via a close (x) button. The dismissal is stored as a hash of the current message on UserContactInfo (mirroring the ui_use_tailwind preference), so the banner reappears only when the promo text changes. The button posts to a new dismiss_os_message endpoint (form-based CSRF) and hides the banner instantly via JS, degrading to a normal POST when JS is disabled.

Includes migration 0270, docs and template-env updates, and unit tests (36 passing in unittests/test_os_message.py).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR docs unittests ui labels Jun 26, 2026
…utton

Moves the dismiss (x) to lead the banner, before the headline, so it is clearly separated from the expand caret and avoids misclicks. Replaces the reused Bootstrap '.close' class (which collided with auto-generated v3 UI styles) with a dedicated 'os-message-dismiss' class styled as a small bordered button.

Lays out the OS banner as a centered flex row scoped to [data-source="os"], so the styling applies only to this banner; other banners and the messages notifications are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@devGregA devGregA marked this pull request as ready for review June 26, 2026 03:45
@devGregA

Copy link
Copy Markdown
Contributor Author

@DryRunSecurity fp drs_d57257ef This isn't user input. banner.message is fetched from our own GCS bucket and already runs through bleach.clean() in parse_os_message() (allowlist of strong/em/a, strip=True) before it hits the template. The |safe also predates this PR; I just moved the line when I reordered the dismiss button.

@devGregA

Copy link
Copy Markdown
Contributor Author

@DryRunSecurity fp drs_f11c06a6 Same deal, this is the classic-UI copy of that same line.

@dryrunsecurity

Copy link
Copy Markdown

Finding d57257ef has been successfully dismissed and marked as False Positive.

@dryrunsecurity

Copy link
Copy Markdown

Finding f11c06a6 has been successfully dismissed and marked as False Positive.

…URE_LOCATIONS

TestDismissOsMessageView loaded dojo_testdata.json directly, which raises NotImplementedError under V3_FEATURE_LOCATIONS=True (the fixture contains deprecated Endpoint records). Adding the @versioned_fixtures decorator swaps it to dojo_testdata_locations.json under V3, matching the convention used by the rest of the suite. Test-only change; verified passing locally under both V3=True and V3=False.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR ui unittests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant