Skip to content

[change] Do not generate notifications for disabled organizations #472

Description

@pandafy
Image

openwisp-notifications does not fully honor an organization's is_active flag.

When an organization is disabled (Organization.is_active=False), notifications can still be generated, persisted, emailed, and delivered over WebSocket for that organization. Additionally, some notification preference-management endpoints still allow updates against disabled organizations.

This is inconsistent with the organization-disablement policy being introduced in openwisp-users, where objects belonging to disabled organizations remain readable and deletable but are blocked from creation and update operations.

For openwisp-notifications, this means:

  • Notifications should not be created for disabled organizations.
  • Notification-setting updates should not be allowed for disabled organizations.

Blocked by

This issue depends on:

That issue establishes the cross-project policy for disabled organizations and provides reusable Django admin and DRF mixins that can be adopted by OpenWISP modules to enforce it consistently.

Background

In OpenWISP, disabling an organization is represented by:

Organization.is_active = False

The policy introduced in openwisp-users#522 defines that:

  • Existing objects belonging to disabled organizations remain accessible for read and delete operations.
  • Creation and update operations involving disabled organizations are blocked.
  • The rule applies consistently across Django Admin, REST API, background tasks, signals, and other system operations.

openwisp-notifications currently does not enforce this policy consistently.

Current behavior

Notification generation starts in:

openwisp_notifications.handlers.notify_handler

The handler resolves the target organization from the notification target but never validates whether the organization is active.

As a result:

  • Notification records are still created.
  • Emails are still sent.
  • WebSocket notifications are still delivered.

for disabled organizations.

Additionally, notification-setting updates can still occur through some write paths even when the related organization is disabled.

Proposed change

flowchart TD

    A["Organization Disabled<br/>is_active = False"]

    A --> B["Notification Event"]

    B --> C{"Organization<br/>Active?"}

    C -->|No| D["Abort"]

    D --> D1["No notification record"]
    D1 --> D2["No email delivery"]
    D2 --> D3["No WebSocket delivery"]

    C -->|Yes| E["Create Notification"]

    E --> E1["Persist"]
    E --> E2["Email"]
    E --> E3["WebSocket"]

    A --> F["Notification Settings"]

    F --> G{"Write Operation?"}

    G -->|Yes| H["BLOCK"]

    H --> H1["API updates"]
    H --> H2["Admin updates"]

    G -->|No| I["ALLOW"]

    I --> I1["Read"]
    I --> I2["Delete"]

    A --> J["Global Notifications"]

    J --> K["ALLOW"]
Loading

P1: Block notification generation for disabled organizations

Add a guard in notify_handler which aborts notification creation when the target belongs to a disabled organization.

Example:

target_org = getattr(target, "organization_id", None)

if target_org and not Organization.objects.filter(
    pk=target_org,
    is_active=True,
).exists():
    return

This validation should happen before recipients are resolved and before any notification records are created.

Blocking notification creation at the source automatically prevents:

  • notification persistence;
  • email delivery;
  • batched email delivery;
  • WebSocket delivery.

Global notifications which are not associated with an organization should continue to work normally.

P2: Prevent notification-setting updates for disabled organizations

Adopt the reusable protections introduced by openwisp-users#522 for standard Django Admin and DRF write paths.

Affected areas include:

  • UserOrgNotificationSettingView;
  • OrganizationNotificationSettingsInline.

These write operations should be blocked when the related organization is disabled, while read and delete operations remain allowed.

Out of scope

The following items are intentionally excluded from this issue:

  • Notifications that were created before an organization was disabled
    should remain unchanged. This issue only concerns preventing the
    creation of new notifications for disabled organizations.
  • Existing notifications belonging to disabled organizations should not
    be automatically deleted or cleaned up. Read and delete operations on
    those notifications should continue to work as defined by the
    organization-disablement policy.
  • No changes are required to notification-setting population tasks.
    These tasks may continue to create or maintain
    NotificationSetting objects for disabled organizations. Preserving
    these records avoids introducing additional synchronization and
    backfill logic when an organization is re-enabled, while notification
    generation is independently blocked by this change.

Acceptance criteria

  • No notification is created when the target belongs to a disabled organization.
  • No email delivery occurs for blocked notifications.
  • No WebSocket delivery occurs for blocked notifications.
  • Global notifications (notifications without target object) continue to work normally.
  • Notification-setting updates are blocked for disabled organizations.
  • Read and delete operations continue to work for disabled organizations, in accordance with openwisp-users#522.
  • Automated tests cover disabled and active organization scenarios.

Reference: OpenWISP Device Operation Analysis

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    Fields

    No fields configured for Task.

    Projects

    Status
    Backlog
    Status
    To do (general)
    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions