[feature] Allow preventing changes to the organization of specific models
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
Direzione di ricerca
Inizia con OrgMixin e ShareableOrgMixin, in particolare from_db(), refresh_from_db() e clean(), quindi esamina i punti di ingresso di Django admin e della REST API/Swagger descritti nell’issue. Esamina i casi correlati di Controller e i requisiti di audit dei modelli. Il lavoro è completato quando sono disponibili la validazione riutilizzabile, l’applicazione delle regole nell’admin e nell’API, la visibilità nello schema e l’identificazione dei modelli configurati senza query al database.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
⚠️ not suited to first time contributors (PRs will be closed without explanation!).
Is your feature request related to a problem? Please describe.
OpenWISP uses the organization field on many models, but it does not have a shared rule for whether that field can be changed after an object has been created.
Some objects must stay in their original organization. Changing the organization of a VPN server, certificate authority, certificate, VPN-client template, or certificate-generator template can leave credentials, configuration, or related records connected to the wrong organization.
This has led to related Controller work in #1050, #1334, and #1459. While reviewing certificate-template work in #1378, we found more cases that need the same kind of protection.
Adding a separate check every time a new case is discovered will create different behavior in different applications and will eventually miss important cases. We need one reusable rule that every OpenWISP module can use.
Describe the solution you'd like
Add this class attribute to OrgMixin and ShareableOrgMixin:
organization_change_allowed = True
A model that must not change organization after creation sets:
organization_change_allowed = False
When an object is loaded from the database, OrgMixin.from_db() stores its original organization ID in _initial_organization_id. OrgMixin.refresh_from_db() updates this snapshot when the organization field is refreshed.
In OrgMixin.clean():
- If
organization_change_allowedisFalseand the object already exists, compare_initial_organization_idwith the currentorganization_id. - Raise
ValidationErrorif they differ. - Treat changes between a specific organization and the shared organization (
organization=None) as organization changes. - Call
super().clean()so model-specific validation continues to run. - Support deferred fields and custom models which replace OpenWISP default models.
- Do not add database queries.
Django admin
For an existing object with organization_change_allowed = False, show the organization field as read-only on the Django admin change page.
The model validation remains the final protection, because admin UI restrictions can be bypassed.
REST API
REST API updates must reject organization changes with the model validation error.
Swagger documentation should make this rule visible:
- Creation requests show
organizationas writable. - Update requests show
organizationas read-only when the model setsorganization_change_allowed = False.
If the current schema generator cannot describe different create and update request fields, document the field clearly as: “Can be set when creating the resource. Cannot be changed afterwards.”
After adding the reusable mechanism, audit OpenWISP applications and set organization_change_allowed = False on models which must remain in their original organization.
The initial Controller audit should include:
- VPN servers
- Certificate authorities
- Certificates
- VPN-client templates
- Certificate-generator templates
- Other models discovered during the audit
Describe alternatives you've considered
Adding separate checks in each application can fix individual cases, but it duplicates logic and leads to inconsistent behavior.
Blocking organization changes for every model is too broad.
Database triggers would not work consistently with custom models and downstream OpenWISP applications.
Additional context
Related issues:
- Lingua principale
- Python
- Stelle
- 179
- Fork
- 97
- Merge medio
- 5h 41m
- PR unite (30g)
- 6
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di openwisp/openwisp-users
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
openwisp/openwisp-users#582 ·
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
openwisp/openwisp-users#559 ·
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
openwisp/openwisp-users#557 · 1 commento ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
openwisp/openwisp-users#552 ·
-
enhancement
Difficoltà 4/5 3-5 giorni Idoneità per principianti 30/100
openwisp/openwisp-users#546 ·
Tutte le issue di openwisp/openwisp-users
Issue simili
-
approved Good First Issue scope: docs
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
hiero-ledger/hiero-sdk-python#2730 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
wemake-services/wemake-django-template#3178 · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
md/asciidoc/csv: an explicit `encoding="utf-8"` keeps a leading BOM, the auto-detect path drops itAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
docling-project/docling#4846 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
neurostuff/NiMARE#1181 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
pytest-dev/pytest#15180 ·
I maintainer di solito rispondono entro 1 giorno