Grotti 3.1.0: Bedarf-UI, Zeitfenster, HT/NT, Theme, Chrome-Fixes.

Bedarf in Sidebar/Material, Drucker-Zeitfenster und Tarif in Einstellungen, helles Theme; Legacy-Token und /api/drucker entfernt; SSE/SW-Fixes gegen hängende Navigation in Chrome.
This commit is contained in:
Dominic Gundel committed 2026-10-18 02:20:12 +02:00
1 parent 8e88efc094
commit 6e59df22e5
23 files changed
+741 -171

No files matched your search

+24 -11
View File
@@ -103,6 +103,7 @@ def create_app(cfg):
)
ADMIN_API_EXACT = {
"/api/v1/telegram/test",
"/api/v1/ntfy/test",
}
ADMIN_METHODS_ON = {
# Drucker anlegen/ändern/löschen nur Admin
@@ -135,14 +136,6 @@ def create_app(cfg):
return user
def resolve_bearer(presented):
legacy = cfg.get("token") or ""
if legacy and secrets.compare_digest(presented, legacy):
return {
"id": None,
"username": "legacy-token",
"role": "admin",
"auth": "legacy",
}
if not presented.startswith(grotti_auth.TOKEN_PREFIX):
return None
row = store.get_api_token_by_hash(conn(), grotti_auth.hash_token(presented))
@@ -821,8 +814,17 @@ def create_app(cfg):
)
return jsonify({"ok": True})
@app.post("/api/v1/ntfy/test")
def ntfy_test():
ok = notify.send_ntfy(cfg, "Grotti-Test: ntfy ist verbunden.")
if not ok:
raise GrottiError(
"ntfy nicht erreichbar. Server, Topic und „aktiv“ prüfen.",
"ntfy",
)
return jsonify({"ok": True})
@app.get("/api/v1/drucker")
@app.get("/api/drucker") # veraltet — Alias zu /api/v1/drucker
def printers():
rows = store.list_printers(conn())
clears = store.bed_clear_map(conn())
@@ -908,7 +910,18 @@ def create_app(cfg):
if other and str(other["id"]) != str(printer_id):
raise GrottiError("Diesen Host gibt es schon.", "host")
locked = data.get("locked") if "locked" in data else current.get("locked")
row = store.update_printer(conn(), printer_id, name, host, family, locked=bool(locked))
start_window = data.get("start_window") if "start_window" in data else None
if start_window is not None and not isinstance(start_window, dict):
raise GrottiError("Zeitfenster muss ein Objekt sein.", "start_window")
row = store.update_printer(
conn(),
printer_id,
name,
host,
family,
locked=bool(locked),
start_window=start_window,
)
return jsonify(row)
@app.delete("/api/v1/drucker/id/<printer_id>")
@@ -2388,12 +2401,12 @@ def create_app(cfg):
finally:
events_bus.unsubscribe(q)
# Kein Connection-Header: waitress verbietet Hop-by-Hop-Header (PEP 3333).
return Response(
stream_with_context(generate()),
mimetype="text/event-stream; charset=utf-8",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no",
},
)