fix: Mandant vor erstem Speichern importierter Ordner setzen

This commit is contained in:
2026-09-02 10:49:03 +02:00
parent 1e670b1148
commit 90787fd360
4 changed files with 43 additions and 12 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ Ein in NetBox integriertes Markdown-Wiki für Betriebsdokumentationen und Anleit
## Kompatibilität ## Kompatibilität
Die Version `0.9.2` zielt auf NetBox 4.x (mindestens 4.0). Vor einem produktiven Rollout sollte das Plugin gegen die konkret eingesetzte NetBox-Minor-Version in einer Testinstanz geprüft werden. Die Version `0.9.3` zielt auf NetBox 4.x (mindestens 4.0). Vor einem produktiven Rollout sollte das Plugin gegen die konkret eingesetzte NetBox-Minor-Version in einer Testinstanz geprüft werden.
## Installation ## Installation
+1 -1
View File
@@ -5,7 +5,7 @@ class DocumentationConfig(PluginConfig):
name = "netbox_documentation" name = "netbox_documentation"
verbose_name = "NetBox Dokumentation" verbose_name = "NetBox Dokumentation"
description = "Wiki und Office-Dokumentation direkt in NetBox" description = "Wiki und Office-Dokumentation direkt in NetBox"
version = "0.9.2" version = "0.9.3"
author = "LKE" author = "LKE"
base_url = "documentation" base_url = "documentation"
min_version = "4.0.0" min_version = "4.0.0"
+40 -9
View File
@@ -5,6 +5,7 @@ from zipfile import ZIP_DEFLATED, BadZipFile, ZipFile
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import transaction from django.db import transaction
from django.utils.text import slugify from django.utils.text import slugify
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
@@ -21,6 +22,14 @@ class ArchiveFailure(ValueError):
pass pass
def _save_imported_object(instance, context, **save_kwargs):
try:
instance.save(**save_kwargs)
except ValidationError as exc:
messages = getattr(exc, "messages", None) or [str(exc)]
raise ArchiveFailure(f"{context}: {'; '.join(messages)}") from exc
def documents_for_categories(categories, include_subfolders=True, user=None): def documents_for_categories(categories, include_subfolders=True, user=None):
"""Return distinct permitted documents contained in the selected category trees.""" """Return distinct permitted documents contained in the selected category trees."""
category_ids = set(categories.values_list("pk", flat=True)) category_ids = set(categories.values_list("pk", flat=True))
@@ -173,15 +182,32 @@ def _category_from_path(names, tenancy_path=None):
if not name: if not name:
continue continue
slug = slugify(name)[:100] or "ordner" slug = slugify(name)[:100] or "ordner"
tenancy = tenancy_path[index] if index < len(tenancy_path) and isinstance(tenancy_path[index], dict) else {}
context = f"Ordner „{name}“"
tenant_group = _resolve_tenant_group(tenancy.get("tenant_group"), context)
tenant = _resolve_tenant(tenancy.get("tenant"), context)
if tenant and tenant_group and tenant.group_id != tenant_group.pk:
raise ArchiveFailure(
f"{context}: Der Mandant „{tenant.slug}“ gehört nicht zur "
f"Mandantengruppe „{tenant_group.slug}“ auf dieser Instanz."
)
category = DocumentCategory.objects.filter(parent=parent, slug=slug).first() category = DocumentCategory.objects.filter(parent=parent, slug=slug).first()
if not category: if not category:
category = DocumentCategory.objects.create(name=name, slug=slug, parent=parent) # Set tenancy before the first save. NetBox installations may
tenancy = tenancy_path[index] if index < len(tenancy_path) and isinstance(tenancy_path[index], dict) else {} # enforce a tenant via custom validation rules, so creating the
if tenancy: # category first and assigning its tenant in a second save fails.
context = f"Ordner „{name}“" category = DocumentCategory(
category.tenant_group = _resolve_tenant_group(tenancy.get("tenant_group"), context) name=name, slug=slug, parent=parent,
category.tenant = _resolve_tenant(tenancy.get("tenant"), context) tenant_group=tenant_group, tenant=tenant,
category.save(update_fields=("tenant_group", "tenant", "last_updated")) )
_save_imported_object(category, context)
elif tenancy:
category.tenant_group = tenant_group
category.tenant = tenant
_save_imported_object(
category, context,
update_fields=("tenant_group", "tenant", "last_updated"),
)
parent = category parent = category
return parent return parent
@@ -237,7 +263,12 @@ def import_archive(upload, update_existing=False):
context = f"Dokument „{document.title}“" context = f"Dokument „{document.title}“"
document.tenant_group = _resolve_tenant_group(record.get("tenant_group"), context) document.tenant_group = _resolve_tenant_group(record.get("tenant_group"), context)
document.tenant = _resolve_tenant(record.get("tenant"), context) document.tenant = _resolve_tenant(record.get("tenant"), context)
document.save() if document.tenant and document.tenant_group and document.tenant.group_id != document.tenant_group_id:
raise ArchiveFailure(
f"{context}: Der Mandant „{document.tenant.slug}“ gehört nicht zur "
f"Mandantengruppe „{document.tenant_group.slug}“ auf dieser Instanz."
)
_save_imported_object(document, context)
for assignment in record.get("assignments") or []: for assignment in record.get("assignments") or []:
label = f"{assignment.get('app_label')}.{assignment.get('model')}" label = f"{assignment.get('app_label')}.{assignment.get('model')}"
if label not in allowed: if label not in allowed:
@@ -280,4 +311,4 @@ def import_archive(upload, update_existing=False):
if item.get("source_url"): if item.get("source_url"):
document.body = document.body.replace(str(item["source_url"]), attachment.file.url) document.body = document.body.replace(str(item["source_url"]), attachment.file.url)
document.save(update_fields=("body", "last_updated")) document.save(update_fields=("body", "last_updated"))
return {"created": created, "updated": updated, "skipped_assignments": skipped_assignments} return {"created": created, "updated": updated, "skipped_assignments": skipped_assignments}
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "netbox-documentation" name = "netbox-documentation"
version = "0.9.2" version = "0.9.3"
description = "Integrated Markdown wiki and office document importer for NetBox" description = "Integrated Markdown wiki and office document importer for NetBox"
readme = "README.md" readme = "README.md"
requires-python = ">=3.10" requires-python = ">=3.10"