Auth: Magic Link Login + Globe-Zugangssteuerung

- Magic Link Login (E-Mail + 6-stelliger Code)
- JWT-basierte Session (24h)
- Prueft: is_active=1 UND globe_access=1
- Akzeptiert auch Monitor-JWT-Tokens (Kompatibilitaet)
- Globe-spezifisches E-Mail-Template (Dark Theme)
- Alle Daten-APIs hinter Auth-Middleware
- Login-Seite mit taktischem Design
- Auto-Redirect bei fehlendem/abgelaufenem Token
- Fetch-Wrapper injiziert Authorization Header automatisch
Dieser Commit ist enthalten in:
Claude Dev
2026-03-24 11:57:00 +01:00
Ursprung a22a4e70d1
Commit 338e082467
9 geänderte Dateien mit 487 neuen und 9 gelöschten Zeilen

50
src/email_utils.py Normale Datei
Datei anzeigen

@@ -0,0 +1,50 @@
"""E-Mail-Versand fuer Globe Magic Links."""
import logging
import aiosmtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from config import SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM_EMAIL, SMTP_FROM_NAME
logger = logging.getLogger("globe.email")
async def send_magic_link_email(to_email: str, code: str, link: str):
"""Sendet Magic Link + Code per E-Mail."""
html = f"""
<div style="font-family: 'Courier New', monospace; max-width: 500px; margin: 0 auto; padding: 30px; background: #0b1121; color: #e8eaf0; border-radius: 12px;">
<h2 style="color: #00ff88; font-size: 16px; letter-spacing: 2px; margin-bottom: 24px;">AEGISSIGHT GLOBE</h2>
<p style="font-size: 14px; line-height: 1.6;">Dein Zugangscode:</p>
<div style="background: rgba(0,255,136,0.08); border: 1px solid rgba(0,255,136,0.2); border-radius: 8px; padding: 20px; text-align: center; margin: 20px 0;">
<span style="font-size: 32px; font-weight: 700; letter-spacing: 8px; color: #00ff88;">{code}</span>
</div>
<p style="font-size: 13px; color: rgba(255,255,255,0.6); line-height: 1.6;">
Oder klicke auf diesen Link:<br>
<a href="{link}" style="color: #00ff88; word-break: break-all;">{link}</a>
</p>
<p style="font-size: 11px; color: rgba(255,255,255,0.3); margin-top: 24px;">
Dieser Code ist 10 Minuten gueltig. Falls du diese Anfrage nicht gesendet hast, ignoriere diese E-Mail.
</p>
</div>
"""
msg = MIMEMultipart("alternative")
msg["From"] = f"{SMTP_FROM_NAME} <{SMTP_FROM_EMAIL}>"
msg["To"] = to_email
msg["Subject"] = "AegisSight Globe — Zugangscode"
msg.attach(MIMEText(f"Dein Globe-Zugangscode: {code}\n\nLink: {link}\n\nGueltig fuer 10 Minuten.", "plain"))
msg.attach(MIMEText(html, "html"))
try:
await aiosmtplib.send(
msg,
hostname=SMTP_HOST,
port=SMTP_PORT,
username=SMTP_USER,
password=SMTP_PASSWORD,
start_tls=True,
)
logger.info(f"Magic Link E-Mail gesendet an {to_email}")
except Exception as e:
logger.error(f"E-Mail-Versand fehlgeschlagen: {e}")
raise