Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
- **Übernehmen: mit vorhandenem zentralem Objekt verknüpfen:** Dieselbe von Hand angelegte Regel, derselbe Alias oder dieselbe NAT-Regel auf mehreren Firewalls (z. B. beide HA-Knoten) wird nicht mehr als zweites Objekt übernommen. Im Dialog „Von Firewall übernehmen“ erscheint bei exakter Übereinstimmung (nach Einsetzen der Host-Variablen, bei Aliasen inkl. Verweisen) die Aktion **Verknüpfen**: die Firewall wird weiteres Ziel des vorhandenen Objekts, die Vorschau zeigt „keine Änderung“, und der nächste Rollout aktualisiert alle Firewalls an einem Objekt. Auf der Firewall wird dabei nichts geändert. Unterscheidet sich ein gleichnamiges Objekt, zeigt der Dialog die abweichenden Felder; verknüpft wird dann nie. „Alle übernehmbaren“ fragt vorher nach („3 verknüpfen, 2 neu übernehmen, 1 nicht übernehmbar“). Aliase, die bisher wegen „Name existiert“ abgelehnt wurden, lassen sich so übernehmen. Wartet das vorhandene Objekt gerade auf eine Bestätigung, wird nicht verknüpft; „Alle übernehmbaren“ lässt den Eintrag dann aus. Verknüpfen macht ein gerade geöffnetes Bearbeiten-Formular des Objekts ungültig, damit die neue Firewall nicht versehentlich wieder aus den Zielen fällt. - **Tooltips überarbeitet:** Der deaktivierte Button „Oberfläche öffnen“ nennt jetzt den Grund im Klartext samt nächstem Schritt (statt nur einer Variablen wie `GUI_GATEWAY_TOKEN`); dasselbe gilt für ausgeschaltete Funktion, deaktivierte Firewall, Nicht-HTTPS-Adresse und ausgeschaltete Zertifikatsprüfung. Texte durchgehend in Du-Form, kürzere VPN-Einleitungen, verständlichere Hinweise bei gesperrten Buttons (Zertifikate, Benutzer, Dienste). Icon-Buttons (Bearbeiten, Löschen, Schließen, Reihenfolge) zeigen beim Darüberfahren ihren Namen.
64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
"""Small pieces shared by every "take over what was made by hand on a firewall" feature
|
|
(rule_adopt_service.py for filter rules, object_adopt_service.py for aliases and NAT)."""
|
|
|
|
|
|
class NotAdoptable(Exception):
|
|
"""The object exists on the host but cannot be described without distortion.
|
|
|
|
`reasons` are machine-readable codes (the UI translates them); `details` maps a code to
|
|
extra text the translation can show (e.g. the alias names a reference points to)."""
|
|
|
|
def __init__(self, reasons: list[str], details: dict[str, str] | None = None):
|
|
super().__init__(", ".join(reasons))
|
|
self.reasons = reasons
|
|
self.details = details or {}
|
|
|
|
|
|
class NotFoundOnHost(Exception):
|
|
"""The UUID is not (or no longer) present in the host's live configuration."""
|
|
|
|
|
|
def on(value) -> bool:
|
|
"""OPNsense booleans arrive as "1"/"0" strings, sometimes as real booleans."""
|
|
return value in ("1", 1, True)
|
|
|
|
|
|
def clean(value) -> str:
|
|
return "" if value is None else str(value).strip()
|
|
|
|
|
|
class LinkTargetNotFound(Exception):
|
|
"""The central object chosen to link to was deleted in the meantime."""
|
|
|
|
|
|
class LinkTargetChanged(Exception):
|
|
"""The central object no longer equals what is live on the host. `diff` lists the differing fields."""
|
|
|
|
def __init__(self, diff: list[dict]):
|
|
super().__init__(", ".join(d["field"] for d in diff))
|
|
self.diff = diff
|
|
|
|
|
|
class HostAlreadyHasObject(Exception):
|
|
"""The central object is already deployed to / managed on this host under another UUID."""
|
|
|
|
|
|
class LinkTargetBusy(Exception):
|
|
"""The central object has an unconfirmed deployment or a failed rollback; linking waits until it is settled."""
|
|
|
|
|
|
LINK_ERRORS = (LinkTargetNotFound, LinkTargetChanged, HostAlreadyHasObject, LinkTargetBusy)
|
|
|
|
|
|
def link_api_error(exc: Exception):
|
|
"""The HTTP error for a failed link (shared by the rule and the object endpoints)."""
|
|
from app.errors import ErrorCode, api_error
|
|
|
|
if isinstance(exc, LinkTargetNotFound):
|
|
return api_error(404, ErrorCode.ADOPT_LINK_TARGET_NOT_FOUND)
|
|
if isinstance(exc, LinkTargetChanged):
|
|
return api_error(409, ErrorCode.ADOPT_LINK_TARGET_CHANGED, fields=", ".join(d["field"] for d in exc.diff))
|
|
if isinstance(exc, HostAlreadyHasObject):
|
|
return api_error(409, ErrorCode.ADOPT_LINK_HOST_HAS_OBJECT)
|
|
return api_error(409, ErrorCode.ADOPT_LINK_BUSY)
|