Files
stiftung-management-system/app/mcp_server/auth.py
SysAdmin Agent e0b377014c
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy (push) Has been cancelled
Code Quality / quality (push) Has been cancelled
v4.1.0: DMS email documents, category-specific Nachweis linking, version system
- Save cover email body as DMS document with new 'email' context type
- Show email body separately from attachments in email detail view
- Add per-category DMS document assignment in quarterly confirmation
  (Studiennachweis, Einkommenssituation, Vermögenssituation)
- Add VERSION file and context processor for automatic version display
- Add MCP server, agent system, import/export, and new migrations
- Update compose files and production environment template

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:48:52 +00:00

71 lines
2.0 KiB
Python
Raw 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.

"""
MCP-Authentifizierung Token-basierte Authentifizierung mit 3 Rollen.
Tokens werden über Umgebungsvariablen konfiguriert:
MCP_TOKEN_READONLY Nur-Lese-Zugriff (alle Daten, PII maskiert)
MCP_TOKEN_EDITOR Lesen + Schreiben (PII maskiert)
MCP_TOKEN_ADMIN Voll-Zugriff (keine PII-Maskierung, alle Schreib-Ops)
Das aktive Token wird per MCP_AUTH_TOKEN übergeben (wird vom MCP-Client gesetzt).
"""
import os
ROLE_READONLY = "readonly"
ROLE_EDITOR = "editor"
ROLE_ADMIN = "admin"
# Rollenrangfolge (höher = mehr Rechte)
ROLE_RANK = {ROLE_READONLY: 1, ROLE_EDITOR: 2, ROLE_ADMIN: 3}
def _token_map() -> dict[str, str]:
"""Erstellt Mapping token → Rolle aus Umgebungsvariablen."""
mapping: dict[str, str] = {}
for role, env_var in [
(ROLE_READONLY, "MCP_TOKEN_READONLY"),
(ROLE_EDITOR, "MCP_TOKEN_EDITOR"),
(ROLE_ADMIN, "MCP_TOKEN_ADMIN"),
]:
token = os.environ.get(env_var, "").strip()
if token:
mapping[token] = role
return mapping
def get_role_for_token(token: str) -> str | None:
"""
Gibt die Rolle für einen Token zurück oder None bei ungültigem Token.
"""
if not token:
return None
return _token_map().get(token)
def get_current_role() -> str | None:
"""
Gibt die Rolle des aktuell gesetzten MCP_AUTH_TOKEN zurück.
Wird vom Server beim Start einmalig ausgewertet.
"""
token = os.environ.get("MCP_AUTH_TOKEN", "").strip()
return get_role_for_token(token)
def can_write(role: str | None) -> bool:
"""Darf die Rolle Schreiboperationen ausführen?"""
return role in (ROLE_EDITOR, ROLE_ADMIN)
def can_read_unmasked(role: str | None) -> bool:
"""Darf die Rolle ungemaskierte PII-Daten lesen?"""
return role == ROLE_ADMIN
def require_role(role: str | None) -> None:
"""Wirft ValueError wenn keine gültige Rolle vorhanden."""
if not role:
raise ValueError(
"Ungültiger oder fehlender MCP_AUTH_TOKEN. "
"Bitte MCP_AUTH_TOKEN-Umgebungsvariable setzen."
)