Dateien
AegisSight-Monitor/src/middleware/license_check.py
Claude Code 6293cef91e Banner-Text + AI-Disclaimer-Modal + Translator-Robustheit
#28 Banner-Text bei Token-Budget aufgebraucht:
- middleware/license_check.py + static/js/app.js: Statt "Bitte Verwaltung
  kontaktieren" jetzt konkreter Upgrade-Pfad mit info@aegis-sight.de.

#29 AI-Hallucination-Disclaimer:
- Neue static/js/ai-disclaimer.js (analog zu update-system.js):
  IIFE-Modul, localStorage-versioniert (aegis_ai_disclaimer_seen=v1),
  inline-CSS mit Theme-Variablen, Modal mit Lucide-Info-Icon.
- Wird beim ersten Login einmalig gezeigt; ueber Header-User-Dropdown
  Eintrag "Ueber KI-Inhalte" jederzeit erneut oeffenbar.
- dashboard.html: Script-Tag + Dropdown-Button mit Lucide-SVG.
- style.css: kleiner Stil-Block fuer .header-dropdown-action.

Translator-Robustheit (Bonus):
- agents/translator.py: Parser akzeptiert jetzt auch von Claude wrapped
  Antworten ({{translations: [...]}}, {{items: [...]}}, einzelnes
  Object). Behebt Wrapper-Bug der gestern beim Backfill 75% der Calls
  fehlschlagen liess.
- Prompt deutlicher: "flaches JSON-Array, kein Wrapper".
2026-05-03 13:29:19 +00:00

65 Zeilen
2.4 KiB
Python

"""FastAPI Dependency: Lizenzpruefung vor mutiernden Endpoints."""
from fastapi import Depends, HTTPException, status
from auth import get_current_user
from database import db_dependency
from services.license_service import check_license
import aiosqlite
async def require_active_license(
current_user: dict = Depends(get_current_user),
db: aiosqlite.Connection = Depends(db_dependency),
) -> dict:
"""Dependency die sicherstellt, dass die Lizenz der Org aktiv ist.
Blockiert mutierende Operationen bei abgelaufener/widerrufener Lizenz.
Gibt den current_user zurueck (angereichert mit Lizenz-Info).
"""
tenant_id = current_user.get("tenant_id")
if not tenant_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Keine Organisation zugeordnet",
)
lic = await check_license(db, tenant_id)
if not lic["valid"]:
if lic["status"] == "org_disabled":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Organisation deaktiviert. Bitte kontaktieren Sie den Support.",
)
current_user["license"] = lic
return current_user
async def require_writable_license(
current_user: dict = Depends(require_active_license),
) -> dict:
"""Dependency die sicherstellt, dass die Lizenz Schreibzugriff erlaubt.
Blockiert neue Lagen/Refreshes bei abgelaufener Lizenz, deaktivierter Org
oder aufgebrauchtem Token-Budget (Hard-Stop).
"""
lic = current_user.get("license", {})
if lic.get("read_only"):
reason = lic.get("read_only_reason") or "expired"
if reason == "budget_exceeded":
detail = "Token-Budget aufgebraucht. Für Aufstockung oder Upgrade bitte info@aegis-sight.de kontaktieren."
elif reason == "expired":
detail = "Lizenz abgelaufen. Nur Lesezugriff moeglich."
elif reason == "no_license":
detail = "Keine aktive Lizenz. Bitte Verwaltung kontaktieren."
elif reason == "org_disabled":
detail = "Organisation deaktiviert. Bitte Support kontaktieren."
else:
detail = lic.get("message") or "Nur Lesezugriff moeglich."
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=detail,
headers={"X-License-Status": reason},
)
return current_user