Skip to content

[feature] Emit a signal when an object changes organization #559

Description

@nemesifier

⚠️ not suited to first time contributors (PRs will be closed without explanation!).

Is your feature request related to a problem? Please describe.

Organization-owned models currently have no shared, public lifecycle hook for reacting to a change to their organization field. Integrations must implement their own change detection and cannot consistently receive both the previous and new organization in the same transaction.

This is needed by related Controller work: #1050, #1334, and #1459. Reviewing #1378 also showed that different objects need different organization-change rules. Some objects must reject organization changes. Others need to update their related records when the organization changes. A shared signal is needed for the second case.

Describe the solution you would like

Add an organization_changed signal to openwisp_users.signals, emitted by OrgMixin and inherited by ShareableOrgMixin.

When an object is loaded from the database, OrgMixin.from_db() should store its original organization ID in _initial_organization_id. OrgMixin.refresh_from_db() should update the snapshot when the organization field is refreshed. This lets clean() and save() detect organization changes without extra database queries.

The signal should emit only for existing objects whose persisted organization_id actually changed. It should use the concrete model as sender and provide instance, old_organization_id, and organization_id. It must respect update_fields, including relation names and attnames, and support deferred fields and swappable models.

After a successful save(), when the values differ, emit the signal synchronously inside the current transaction, then update _initial_organization_id. Do not use transaction.on_commit(): receivers must be able to update related records in the same transaction.

Describe alternatives you have considered

Application-specific pre-save and post-save receivers duplicate organization-change detection and cannot provide a consistent public integration point. Querying the database from clean() adds unnecessary queries. Deferring the signal to transaction.on_commit() is unsuitable for receivers which must reconcile related state atomically.

Additional context

A related follow-up will define a reusable way for models which must not change organization to reject that change during clean(). The same _initial_organization_id snapshot should support both behaviors.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions