Auth: Verwaltung auf Magic-Link umstellen (Passwort-Login entfernt)

Backend:
- src/routers/auth.py NEU: POST /api/auth/magic-link + POST /api/auth/verify
- src/auth.py: verify_password/hash_password raus, generate_magic_token rein
- src/main.py: alter Login-Endpoint + Brute-Force-Logik raus, neuer auth-Router eingebunden
- src/config.py: ALLOWED_EMAIL + PORTAL_MAGIC_LINK_* hinzu
- src/models.py: LoginRequest raus, MagicLinkRequest etc. rein
- src/email_utils/templates.py: portal_magic_link_email Template

Frontend:
- src/static/index.html: Email-Eingabe statt Passwort, Token-Verify-Logik fuer ?token= aus URL

Datenbank-Migration (migrations/2026-05-09_portal_magic_link.py):
- portal_magic_links + portal_magic_link_attempts neu
- portal_login_attempts gedroppt
- portal_admins.email Spalte hinzu, password_hash geleert

Whitelist info@aegis-sight.de, Rate-Limit 5/15 Min, Anti-Enumeration generische Antwort.
Dieser Commit ist enthalten in:
claude-dev
2026-05-09 02:21:40 +00:00
Ursprung e6fdc5cfa0
Commit 7c741062a9
9 geänderte Dateien mit 482 neuen und 151 gelöschten Zeilen

Datei anzeigen

@@ -27,10 +27,20 @@ SMTP_FROM_EMAIL = os.environ.get("SMTP_FROM_EMAIL", "noreply@aegis-sight.de")
SMTP_FROM_NAME = os.environ.get("SMTP_FROM_NAME", "AegisSight Verwaltung")
SMTP_USE_TLS = os.environ.get("SMTP_USE_TLS", "true").lower() == "true"
# Magic Link Base URL (fuer OSINT-Monitor Einladungen)
# Magic Link Base URL (fuer Einladungen Richtung OSINT-Monitor, NICHT Portal-Login)
MAGIC_LINK_BASE_URL = os.environ.get("MAGIC_LINK_BASE_URL", "https://monitor.aegis-sight.de")
MAGIC_LINK_EXPIRE_MINUTES = 10
# Magic-Link-Auth fuer das Verwaltungsportal SELBST
# (frueher Passwort-Login, ab 2026-05-09 nur noch Magic-Link)
ALLOWED_EMAIL = os.environ.get("PORTAL_ALLOWED_EMAIL", "info@aegis-sight.de")
PORTAL_MAGIC_LINK_BASE_URL = os.environ.get(
"PORTAL_MAGIC_LINK_BASE_URL", "https://monitor-verwaltung.aegis-sight.de"
)
PORTAL_MAGIC_LINK_EXPIRE_MINUTES = int(
os.environ.get("PORTAL_MAGIC_LINK_EXPIRE_MINUTES", "10")
)
# Source Discovery (geteilte Config mit OSINT-Monitor)
CLAUDE_PATH = os.environ.get("CLAUDE_PATH", "/home/claude-dev/.claude/local/claude")
CLAUDE_TIMEOUT = 300