Standardbrowser je Workspace-Version (Migration 0058)
Vorgabe im Entwurf setzen (Firefox oder ein im Entwurf enthaltener Browser), wird mit kopiert, faellt beim Entfernen des Browsers zurueck und steht in der Wirkungsvorschau. Der Check-in liefert sie als eigenen Auftrag "standardbrowser" (kein Katalog-Merkmal); dessen Rueckmeldung erzeugt keine Ereigniszeile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
381e0e55c1
commit
26e26e1b3b
2 files changed
+131
-2
No files matched your search
@@ -1033,6 +1033,49 @@ WEBAPP_XDG_CATEGORIES_DEFAULT = "Network;WebBrowser;"
|
||||
KIOSK_BROWSER_PRIORITAET = ["google-chrome", "chromium"]
|
||||
|
||||
|
||||
# Standardbrowser je Workspace-Version (13.10.2026, Migration 0058): Firefox
|
||||
# ist auf den Images vorinstalliert, die übrigen sind Merkmale und nur
|
||||
# wählbar, wenn sie in derselben Version enthalten sind. Der Server gibt die
|
||||
# Vorgabe als eigenen Auftrag an den Agenten weiter (Rolle "standardbrowser",
|
||||
# Option "browser"); es gibt dafür bewusst kein Katalog-Merkmal, damit die
|
||||
# Vorgabe nicht zusätzlich in der Merkmal-Auswahl auftaucht.
|
||||
STANDARDBROWSER_AUFTRAG = "standardbrowser"
|
||||
STANDARDBROWSER_FIREFOX = "firefox"
|
||||
STANDARDBROWSER_MERKMALE = ["google-chrome", "chromium", "browser-brave", "microsoft-edge"]
|
||||
|
||||
|
||||
def standardbrowser_auswahl(cur, version_id) -> list[dict]:
|
||||
"""Was in dieser Version als Standardbrowser wählbar ist."""
|
||||
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT m.key, m.name
|
||||
FROM workspace_version_merkmale vm
|
||||
JOIN merkmale m ON m.id = vm.merkmal_id
|
||||
WHERE vm.workspace_version_id = %s AND m.key = ANY(%s)
|
||||
ORDER BY m.name
|
||||
""",
|
||||
(version_id, STANDARDBROWSER_MERKMALE),
|
||||
)
|
||||
return [{"key": STANDARDBROWSER_FIREFOX, "name": "Firefox (vorinstalliert)"}] + [
|
||||
{"key": key, "name": name} for key, name in cur.fetchall()
|
||||
]
|
||||
|
||||
|
||||
def set_workspace_standardbrowser(workspace_id: str, browser: str | None):
|
||||
"""Setzt die Vorgabe im Entwurf. Rückgabe: None oder Fehlermeldung."""
|
||||
|
||||
with get_database_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
vid = entwurf_id(cur, workspace_id)
|
||||
if vid is None:
|
||||
return "Änderungen gehen nur in einem Entwurf - bitte zuerst einen Entwurf anlegen."
|
||||
if browser is not None and browser not in {b["key"] for b in standardbrowser_auswahl(cur, vid)}:
|
||||
return "Dieser Browser ist im Workspace nicht enthalten."
|
||||
cur.execute("UPDATE workspace_versionen SET standardbrowser = %s WHERE id = %s", (browser, vid))
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_kiosk_browser(version_id) -> str | None:
|
||||
with get_database_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -1513,6 +1556,10 @@ def fetch_auftragskatalog_state(device_id: str):
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
|
||||
cur.execute("SELECT standardbrowser FROM workspace_versionen WHERE id = %s", (version_id,))
|
||||
standardbrowser_row = cur.fetchone()
|
||||
standardbrowser = standardbrowser_row[0] if standardbrowser_row else None
|
||||
|
||||
overrides = resolve_katalog_overrides(device_id)
|
||||
|
||||
ergebnis = []
|
||||
@@ -1530,6 +1577,16 @@ def fetch_auftragskatalog_state(device_id: str):
|
||||
"optionen": decrypt_sensitive_optionen(optionen),
|
||||
})
|
||||
|
||||
# Standardbrowser der Workspace-Version: immer mitschicken, auch als
|
||||
# "absent" - sonst liefe die Rolle nach dem Zurücknehmen der Vorgabe nie
|
||||
# wieder und der alte Eintrag bliebe stehen.
|
||||
ergebnis.append({
|
||||
"merkmal": STANDARDBROWSER_AUFTRAG,
|
||||
"ansible_role": STANDARDBROWSER_AUFTRAG,
|
||||
"state": "present" if standardbrowser else "absent",
|
||||
"optionen": {"browser": standardbrowser} if standardbrowser else {},
|
||||
})
|
||||
|
||||
return ergebnis
|
||||
|
||||
def fetch_auftragskatalog_listing(device_id: str):
|
||||
@@ -3663,6 +3720,15 @@ def _version_kopieren(cur, quelle_version_id, ziel_version_id, ziel_workspace_id
|
||||
"INSERT INTO workspace_version_merkmale (workspace_version_id, merkmal_id) VALUES (%s, %s)",
|
||||
(ziel_version_id, merkmal_id),
|
||||
)
|
||||
# Standardbrowser mitnehmen, sofern der Browser im Ziel noch enthalten ist
|
||||
# (merkmal_filter kann ihn beim Kopieren auf eine andere Distro entfernen).
|
||||
cur.execute("SELECT standardbrowser FROM workspace_versionen WHERE id = %s", (quelle_version_id,))
|
||||
quelle_row = cur.fetchone()
|
||||
if quelle_row and quelle_row[0] in {b["key"] for b in standardbrowser_auswahl(cur, ziel_version_id)}:
|
||||
cur.execute(
|
||||
"UPDATE workspace_versionen SET standardbrowser = %s WHERE id = %s",
|
||||
(quelle_row[0], ziel_version_id),
|
||||
)
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO workspace_webapps (id, workspace_id, workspace_version_id, name, url, icon_filename,
|
||||
@@ -3892,8 +3958,16 @@ def workspace_wirkung(workspace_id: str) -> dict | None:
|
||||
cur.execute("SELECT name, url FROM workspace_webapps WHERE workspace_version_id = %s", (vid,))
|
||||
return set(cur.fetchall())
|
||||
|
||||
def standardbrowser(vid):
|
||||
if vid is None:
|
||||
return None
|
||||
cur.execute("SELECT standardbrowser FROM workspace_versionen WHERE id = %s", (vid,))
|
||||
key = cur.fetchone()[0]
|
||||
return next((b["name"] for b in standardbrowser_auswahl(cur, vid) if b["key"] == key), key)
|
||||
|
||||
m_alt, m_neu = merkmale(alt), merkmale(neu)
|
||||
w_alt, w_neu = webapps(alt), webapps(neu)
|
||||
sb_alt, sb_neu = standardbrowser(alt), standardbrowser(neu)
|
||||
|
||||
def namen(ids, quelle, art):
|
||||
return sorted(quelle[i][0] for i in ids if quelle[i][1] == art)
|
||||
@@ -3906,7 +3980,10 @@ def workspace_wirkung(workspace_id: str) -> dict | None:
|
||||
"richtlinien_weg": namen(weg, m_alt, "richtlinie"),
|
||||
"webapps_neu": sorted(n for n, _u in w_neu - w_alt),
|
||||
"webapps_weg": sorted(n for n, _u in w_alt - w_neu),
|
||||
"unveraendert": not (hinzu or weg or w_neu != w_alt),
|
||||
"standardbrowser_geaendert": sb_alt != sb_neu,
|
||||
"standardbrowser_alt": sb_alt,
|
||||
"standardbrowser_neu": sb_neu,
|
||||
"unveraendert": not (hinzu or weg or w_neu != w_alt or sb_alt != sb_neu),
|
||||
"nutzung": workspace_nutzung(workspace_id),
|
||||
}
|
||||
|
||||
@@ -4143,6 +4220,10 @@ def fetch_workspace_detail(workspace_id: str):
|
||||
)
|
||||
version_row = cur.fetchone()
|
||||
|
||||
cur.execute("SELECT standardbrowser FROM workspace_versionen WHERE id = %s", (version_id,))
|
||||
standardbrowser_row = cur.fetchone()
|
||||
browser_auswahl = standardbrowser_auswahl(cur, version_id)
|
||||
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT m.id, m.key, m.name
|
||||
@@ -4173,6 +4254,8 @@ def fetch_workspace_detail(workspace_id: str):
|
||||
if version_row else None
|
||||
),
|
||||
"merkmale": merkmale,
|
||||
"standardbrowser": standardbrowser_row[0] if standardbrowser_row else None,
|
||||
"standardbrowser_auswahl": browser_auswahl,
|
||||
}
|
||||
|
||||
def add_merkmal_to_workspace(workspace_id: str, merkmal_id: str):
|
||||
@@ -4553,9 +4636,18 @@ def activate_webapp_template(workspace_id: str, template_id: str):
|
||||
def remove_merkmal_from_workspace(workspace_id: str, merkmal_id: str):
|
||||
with get_database_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
version_id = arbeitsversion_id(cur, workspace_id)
|
||||
cur.execute(
|
||||
"DELETE FROM workspace_version_merkmale WHERE workspace_version_id = %s AND merkmal_id = %s",
|
||||
(arbeitsversion_id(cur, workspace_id), merkmal_id),
|
||||
(version_id, merkmal_id),
|
||||
)
|
||||
# War das der Standardbrowser, gilt wieder "keine Vorgabe".
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE workspace_versionen SET standardbrowser = NULL
|
||||
WHERE id = %s AND standardbrowser = (SELECT key FROM merkmale WHERE id = %s)
|
||||
""",
|
||||
(version_id, merkmal_id),
|
||||
)
|
||||
|
||||
def fetch_backends():
|
||||
@@ -5596,6 +5688,10 @@ def agent_report(
|
||||
with conn.cursor() as cur:
|
||||
merkmal_ids = {}
|
||||
|
||||
# Der Standardbrowser-Auftrag ist kein Merkmal und hat keine
|
||||
# Ereigniszeile (siehe STANDARDBROWSER_AUFTRAG).
|
||||
payload.results = [e for e in payload.results if e.merkmal != STANDARDBROWSER_AUFTRAG]
|
||||
|
||||
for entry in payload.results:
|
||||
if entry.merkmal in merkmal_ids:
|
||||
continue
|
||||
@@ -6353,6 +6449,25 @@ def remove_workspace_merkmal(workspace_id: str, merkmal_id: str, authorization:
|
||||
return {"success": True}
|
||||
|
||||
|
||||
class SetStandardbrowserRequest(BaseModel):
|
||||
browser: str | None = None
|
||||
|
||||
|
||||
@app.put("/api/v1/workspaces/{workspace_id}/standardbrowser")
|
||||
def put_workspace_standardbrowser(
|
||||
workspace_id: str,
|
||||
payload: SetStandardbrowserRequest,
|
||||
authorization: str | None = Header(default=None),
|
||||
):
|
||||
if not require_service_token(authorization):
|
||||
return {"success": False, "error": "unauthorized", "message": "Fehlendes oder ungültiges Service-Token."}
|
||||
|
||||
if fehler := set_workspace_standardbrowser(workspace_id, payload.browser or None):
|
||||
return {"success": False, "error": "invalid_request", "message": fehler}
|
||||
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@app.get("/api/v1/workspaces/{workspace_id}/webapps")
|
||||
def list_workspace_webapps(workspace_id: str, authorization: str | None = Header(default=None)):
|
||||
if not require_service_token(authorization):
|
||||
|
||||
Reference in new issue
Block a user