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.
71 Zeilen
3.3 KiB
Python
71 Zeilen
3.3 KiB
Python
"""HTML-E-Mail-Vorlagen fuer das Verwaltungsportal."""
|
|
|
|
|
|
def invite_email(username: str, org_name: str, code: str, link: str) -> tuple[str, str]:
|
|
"""Erzeugt Einladungs-E-Mail fuer neue OSINT-Monitor-Nutzer.
|
|
|
|
Returns:
|
|
(subject, html_body)
|
|
"""
|
|
subject = f"Einladung zum AegisSight OSINT Monitor - {org_name}"
|
|
html = f"""<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="UTF-8"></head>
|
|
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f172a; color: #e2e8f0; padding: 40px 20px;">
|
|
<div style="max-width: 480px; margin: 0 auto; background: #1e293b; border-radius: 12px; padding: 32px; border: 1px solid #334155;">
|
|
<h1 style="color: #f0b429; font-size: 20px; margin: 0 0 24px 0;">AegisSight OSINT Monitor</h1>
|
|
|
|
<p style="margin: 0 0 16px 0;">Hallo {username},</p>
|
|
|
|
<p style="margin: 0 0 16px 0;">Sie wurden zur Organisation <strong>{org_name}</strong> im AegisSight OSINT Monitor eingeladen.</p>
|
|
|
|
<p style="margin: 0 0 24px 0;">Klicken Sie auf den Link, um Ihren Zugang zu aktivieren:</p>
|
|
|
|
<div style="background: #0f172a; border-radius: 8px; padding: 20px; text-align: center; margin: 0 0 24px 0;">
|
|
<div style="font-size: 32px; font-weight: 700; letter-spacing: 8px; color: #f0b429; font-family: monospace;">{code}</div>
|
|
</div>
|
|
|
|
<div style="text-align: center; margin: 0 0 24px 0;">
|
|
<a href="{link}" style="display: inline-block; background: #f0b429; color: #0f172a; padding: 12px 32px; border-radius: 6px; text-decoration: none; font-weight: 600;">Einladung annehmen</a>
|
|
</div>
|
|
|
|
<p style="color: #94a3b8; font-size: 13px; margin: 0;">Dieser Link ist 10 Minuten gültig.</p>
|
|
</div>
|
|
</body>
|
|
</html>"""
|
|
return subject, html
|
|
|
|
|
|
def portal_magic_link_email(link: str, expire_minutes: int) -> tuple[str, str]:
|
|
"""Erzeugt Login-E-Mail mit Magic-Link für das Verwaltungsportal.
|
|
|
|
Args:
|
|
link: Login-URL inkl. Token
|
|
expire_minutes: Gültigkeitsdauer in Minuten
|
|
|
|
Returns:
|
|
(subject, html_body)
|
|
"""
|
|
subject = "AegisSight Verwaltung - Anmeldung"
|
|
html = f"""<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="UTF-8"></head>
|
|
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f172a; color: #e2e8f0; padding: 40px 20px;">
|
|
<div style="max-width: 480px; margin: 0 auto; background: #1e293b; border-radius: 12px; padding: 32px; border: 1px solid #334155;">
|
|
<h1 style="color: #f0b429; font-size: 20px; margin: 0 0 24px 0;">AegisSight Verwaltung</h1>
|
|
|
|
<p style="margin: 0 0 24px 0;">Klicken Sie auf den Button, um sich am Verwaltungsportal anzumelden:</p>
|
|
|
|
<div style="text-align: center; margin: 0 0 24px 0;">
|
|
<a href="{link}" style="display: inline-block; background: #f0b429; color: #0f172a; padding: 14px 40px; border-radius: 6px; text-decoration: none; font-weight: 600; font-size: 16px;">Jetzt anmelden</a>
|
|
</div>
|
|
|
|
<p style="color: #94a3b8; font-size: 13px; margin: 0 0 12px 0;">Oder kopieren Sie diesen Link in Ihren Browser:</p>
|
|
<p style="color: #64748b; font-size: 11px; word-break: break-all; margin: 0 0 24px 0;">{link}</p>
|
|
|
|
<p style="color: #94a3b8; font-size: 13px; margin: 0;">Dieser Link ist {expire_minutes} Minuten gültig. Falls Sie diese Anmeldung nicht angefordert haben, ignorieren Sie diese E-Mail.</p>
|
|
</div>
|
|
</body>
|
|
</html>"""
|
|
return subject, html
|