Summary
When a device is moved from one organization to another, shared templates with default=True are removed and not re-assigned when the device is moved back. Only templates with required=True survive the roundtrip.
Steps to reproduce
- Create a shared template (no organization) with
default=True, required=False (e.g. "SSH Keys")
- Create a shared template with
default=True, required=True (e.g. "default-management-vpn")
- Create an org-specific template with
default=True in Org A (e.g. "Provision-OrgA")
- Register a device in Org A — it gets all 3 templates automatically ✅
- Move the device to Org B via the admin UI or API
- Observed: Only the
required=True template remains. The shared default=True template and the org-specific template are both removed.
- Move the device back to Org A
- Observed: The org-specific template is re-assigned (because
default=True in Org A), but the shared default=True template is NOT re-assigned.
Expected behavior
After moving a device to a new organization, all applicable default=True templates (both shared and org-specific) should be automatically assigned, just as they would be for a newly registered device in that organization.
Actual behavior
Shared templates with default=True but required=False are removed during the org change and never re-applied, even when moving back to the original organization. The device ends up with fewer templates than a freshly registered device in the same org.
Workaround
Setting the shared template to required=True prevents it from being removed during organization changes. However, this prevents users from ever unassigning the template, which may not be desirable.
Environment
- openwisp-controller version: latest (as of April 2026)
- Tested via REST API (
PATCH /api/v1/controller/device/{id}/ with {"organization": "<new-org-id>"})
- Also reproducible via the admin UI
Analysis
The issue appears to be in the organization-change handler: it correctly removes org-specific templates that don't belong to the new organization, but it also removes shared default=True templates (which are valid in any organization). When the device arrives in the new org, only org-specific default=True templates are auto-assigned — the shared ones are not reconsidered.
The required=True flag acts as a "never remove" guard, which is why those templates survive. But default=True should mean "always assign to new devices in this context", and an organization change is effectively a "new device in this org" scenario.
Summary
When a device is moved from one organization to another, shared templates with
default=Trueare removed and not re-assigned when the device is moved back. Only templates withrequired=Truesurvive the roundtrip.Steps to reproduce
default=True,required=False(e.g. "SSH Keys")default=True,required=True(e.g. "default-management-vpn")default=Truein Org A (e.g. "Provision-OrgA")required=Truetemplate remains. The shareddefault=Truetemplate and the org-specific template are both removed.default=Truein Org A), but the shareddefault=Truetemplate is NOT re-assigned.Expected behavior
After moving a device to a new organization, all applicable
default=Truetemplates (both shared and org-specific) should be automatically assigned, just as they would be for a newly registered device in that organization.Actual behavior
Shared templates with
default=Truebutrequired=Falseare removed during the org change and never re-applied, even when moving back to the original organization. The device ends up with fewer templates than a freshly registered device in the same org.Workaround
Setting the shared template to
required=Trueprevents it from being removed during organization changes. However, this prevents users from ever unassigning the template, which may not be desirable.Environment
PATCH /api/v1/controller/device/{id}/with{"organization": "<new-org-id>"})Analysis
The issue appears to be in the organization-change handler: it correctly removes org-specific templates that don't belong to the new organization, but it also removes shared
default=Truetemplates (which are valid in any organization). When the device arrives in the new org, only org-specificdefault=Truetemplates are auto-assigned — the shared ones are not reconsidered.The
required=Trueflag acts as a "never remove" guard, which is why those templates survive. Butdefault=Trueshould mean "always assign to new devices in this context", and an organization change is effectively a "new device in this org" scenario.