Files
kundenplattform/ressourcen_formular.py
adminandClaude Opus 5.5 ccf7b547a7 Org-Ressourcen: Seite Organisation > Ressourcen und Admin-Reiter
Kunden-Admins pflegen Mail, Nextcloud, ownCloud, WebDAV, SMB und Web-Proxy
ihrer Organisation (Formulare aus den Typ-Definitionen des Servers, keine
Zugangsdaten), Wirkung fuer die ganze Org, OEs oder Gruppen. Unterseite
erscheint nur fuer freigeschaltete Organisationen; root pflegt immer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:02:51 +02:00

91 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Org-Ressourcen (15.10.2026, platform-docs roadmap/org-ressourcen-konzept.md):
# gemeinsamer Teil von Kunden-Seite (/organisation/ressourcen) und Admin-
# Reiter (/admin/kunden/<org>/ressourcen). Die Typen und ihre Felder
# definiert allein der Server (ORG_RESSOURCEN_TYPEN in provisioning-server),
# das Formular wird daraus erzeugt.
from urllib.parse import urlencode
from anode_client import anode_request
def lade_ressourcen_kontext(organization_id: str) -> dict:
"""Alles, was templates/_ressourcen.html braucht."""
typen = anode_request("GET", "/api/v1/org-ressourcen/typen").get("typen", {})
liste = anode_request("GET", f"/api/v1/organizations/{organization_id}/ressourcen")
oes_result = anode_request("GET", f"/api/v1/organizations/{organization_id}/organisationseinheiten")
oes = oes_result.get("organisationseinheiten", []) if oes_result.get("success") else []
gruppen_result = anode_request("GET", f"/api/v1/organizations/{organization_id}/gruppen")
gruppen = gruppen_result.get("gruppen", []) if gruppen_result.get("success") else []
# OE-Pfad statt nur Name ("Schule › Haus A"), sortiert wie der Baum.
by_id = {oe["id"]: oe for oe in oes}
def pfad(oe):
teile, current, gesehen = [], oe, set()
while current is not None and current["id"] not in gesehen:
gesehen.add(current["id"])
teile.append(current["name"])
current = by_id.get(current.get("parent_id"))
return " › ".join(reversed(teile))
oe_auswahl = sorted(({"id": oe["id"], "name": pfad(oe)} for oe in oes), key=lambda o: o["name"].lower())
return {
"ressourcen_typen": typen,
"ressourcen": liste.get("ressourcen", []) if liste.get("success") else [],
"ressourcen_freigeschaltet": bool(liste.get("freigeschaltet")),
"ressourcen_oes": oe_auswahl,
"ressourcen_gruppen": gruppen,
}
def ressourcen_freigeschaltet(organization_id: str) -> bool:
liste = anode_request("GET", f"/api/v1/organizations/{organization_id}/ressourcen")
return bool(liste.get("success") and liste.get("freigeschaltet"))
def payload_aus_formular(form, typen: dict) -> dict:
"""Formularfelder (typ, name, daten.<key>, ganze_organisation,
oe_ids, gruppe_ids) in die Server-Anfrage übersetzen. Nur Felder, die der
Typ kennt; prüfen tut der Server."""
typ = form.get("typ", "")
felder = typen.get(typ, {}).get("felder", [])
daten = {f["key"]: form.get(f"daten.{f['key']}", "") for f in felder}
ganze_organisation = form.get("ganze_organisation") == "on"
return {
"typ": typ,
"name": form.get("name", ""),
"daten": daten,
"ganze_organisation": ganze_organisation,
"oe_ids": [] if ganze_organisation else form.getlist("oe_ids"),
"gruppe_ids": [] if ganze_organisation else form.getlist("gruppe_ids"),
}
def speichern(organization_id: str, ressource_id: str | None, form, ziel: str) -> str:
"""Anlegen oder ändern, liefert die Weiterleitungs-URL (mit ?fehler=…
bei einer Ablehnung durch den Server)."""
typen = anode_request("GET", "/api/v1/org-ressourcen/typen").get("typen", {})
payload = payload_aus_formular(form, typen)
if ressource_id is None:
result = anode_request("POST", f"/api/v1/organizations/{organization_id}/ressourcen", json=payload)
else:
result = anode_request("PUT", f"/api/v1/organizations/{organization_id}/ressourcen/{ressource_id}", json=payload)
if not result.get("success"):
return ziel + "?" + urlencode({"fehler": result.get("message", "Die Ressource konnte nicht gespeichert werden.")})
return ziel
def loeschen(organization_id: str, ressource_id: str, ziel: str) -> str:
result = anode_request("DELETE", f"/api/v1/organizations/{organization_id}/ressourcen/{ressource_id}")
if not result.get("success"):
return ziel + "?" + urlencode({"fehler": result.get("message", "Die Ressource konnte nicht gelöscht werden.")})
return ziel