Frontend-Dateien auf Zustand vor i18n zurückgesetzt. lang.js entfernt, CSP bereinigt. Backend-Umlaut-Fix bleibt erhalten. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
213 Zeilen
9.6 KiB
HTML
213 Zeilen
9.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<script>(function(){var t=localStorage.getItem('osint_theme');if(t)document.documentElement.setAttribute('data-theme',t);try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
|
<link rel="shortcut icon" href="/static/favicon.ico">
|
|
<title>AegisSight Monitor - Login</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/css/style.css?v=20260304a">
|
|
</head>
|
|
<body>
|
|
<a href="#login-form" class="skip-link">Zum Anmeldeformular springen</a>
|
|
<main class="login-container">
|
|
<div class="login-box">
|
|
<div class="login-logo">
|
|
<h1>Aegis<span style="color: var(--accent)">Sight</span></h1>
|
|
<div class="subtitle">Lagemonitor</div>
|
|
</div>
|
|
|
|
<div id="login-error" class="login-error" role="alert" aria-live="assertive"></div>
|
|
<div id="login-success" class="login-success" role="status" aria-live="polite" style="display:none;"></div>
|
|
|
|
<!-- Schritt 1: E-Mail eingeben -->
|
|
<form id="email-form">
|
|
<div class="form-group">
|
|
<label for="email">E-Mail-Adresse</label>
|
|
<input type="email" id="email" name="email" autocomplete="email" required aria-required="true" placeholder="name@organisation.de">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-full" id="email-btn">Anmelden</button>
|
|
</form>
|
|
|
|
<!-- Schritt 2: Code eingeben -->
|
|
<form id="code-form" style="display:none;">
|
|
<p style="color: var(--text-secondary); margin: 0 0 16px 0; font-size: 14px;">
|
|
Ein 6-stelliger Code wurde an <strong id="sent-email"></strong> gesendet.
|
|
</p>
|
|
<div class="form-group">
|
|
<label for="code">Code eingeben</label>
|
|
<input type="text" id="code" name="code" autocomplete="one-time-code" required aria-required="true"
|
|
placeholder="000000" maxlength="6" pattern="[0-9]{6}"
|
|
style="text-align:center; font-size:24px; letter-spacing:8px; font-family:monospace;">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-full" id="code-btn">Verifizieren</button>
|
|
<button type="button" class="btn btn-secondary btn-full" id="back-btn" style="margin-top:8px;">Zurück</button>
|
|
</form>
|
|
|
|
<div style="text-align:center;margin-top:16px;">
|
|
<button class="btn btn-secondary btn-small theme-toggle-btn" id="theme-toggle" onclick="ThemeManager.toggle()" title="Theme wechseln" aria-label="Theme wechseln">☼</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<script>
|
|
const ThemeManager = {
|
|
_key: 'osint_theme',
|
|
init() {
|
|
const saved = localStorage.getItem(this._key);
|
|
const theme = saved || 'dark';
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
this._updateIcon(theme);
|
|
},
|
|
toggle() {
|
|
const current = document.documentElement.getAttribute('data-theme') || 'dark';
|
|
const next = current === 'dark' ? 'light' : 'dark';
|
|
document.documentElement.setAttribute('data-theme', next);
|
|
localStorage.setItem(this._key, next);
|
|
this._updateIcon(next);
|
|
},
|
|
_updateIcon(theme) {
|
|
const btn = document.getElementById('theme-toggle');
|
|
if (btn) btn.textContent = theme === 'dark' ? '\u2600' : '\u263D';
|
|
}
|
|
};
|
|
ThemeManager.init();
|
|
</script>
|
|
<script>
|
|
// Pruefen ob bereits eingeloggt
|
|
const token = localStorage.getItem('osint_token');
|
|
if (token) {
|
|
fetch('/api/auth/me', {
|
|
headers: { 'Authorization': 'Bearer ' + token }
|
|
}).then(r => {
|
|
if (r.ok) window.location.href = '/dashboard';
|
|
});
|
|
}
|
|
|
|
// URL-Parameter pruefen (Magic Link Token)
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const verifyToken = urlParams.get('token');
|
|
|
|
if (verifyToken) {
|
|
// Direkte Token-Verifikation
|
|
(async () => {
|
|
try {
|
|
const response = await fetch('/api/auth/verify', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ token: verifyToken }),
|
|
});
|
|
if (!response.ok) {
|
|
const data = await response.json();
|
|
throw new Error(data.detail || 'Verifikation fehlgeschlagen');
|
|
}
|
|
const data = await response.json();
|
|
localStorage.setItem('osint_token', data.access_token);
|
|
localStorage.setItem('osint_username', data.username);
|
|
window.location.href = '/dashboard';
|
|
} catch (err) {
|
|
const errorEl = document.getElementById('login-error');
|
|
errorEl.textContent = err.message;
|
|
errorEl.style.display = 'block';
|
|
// URL bereinigen
|
|
window.history.replaceState({}, '', '/');
|
|
}
|
|
})();
|
|
}
|
|
|
|
let currentEmail = '';
|
|
|
|
// Schritt 1: E-Mail senden
|
|
document.getElementById('email-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const errorEl = document.getElementById('login-error');
|
|
const successEl = document.getElementById('login-success');
|
|
const btn = document.getElementById('email-btn');
|
|
errorEl.style.display = 'none';
|
|
successEl.style.display = 'none';
|
|
btn.disabled = true;
|
|
btn.textContent = 'Wird gesendet...';
|
|
|
|
currentEmail = document.getElementById('email').value.trim();
|
|
|
|
try {
|
|
const response = await fetch('/api/auth/magic-link', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: currentEmail }),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const data = await response.json();
|
|
throw new Error(data.detail || 'Anfrage fehlgeschlagen');
|
|
}
|
|
|
|
// Zu Code-Eingabe wechseln
|
|
document.getElementById('email-form').style.display = 'none';
|
|
document.getElementById('code-form').style.display = 'block';
|
|
document.getElementById('sent-email').textContent = currentEmail;
|
|
document.getElementById('code').focus();
|
|
|
|
} catch (err) {
|
|
errorEl.textContent = err.message;
|
|
errorEl.style.display = 'block';
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Anmelden';
|
|
}
|
|
});
|
|
|
|
// Schritt 2: Code verifizieren
|
|
document.getElementById('code-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const errorEl = document.getElementById('login-error');
|
|
const btn = document.getElementById('code-btn');
|
|
errorEl.style.display = 'none';
|
|
btn.disabled = true;
|
|
btn.textContent = 'Wird geprüft...';
|
|
|
|
try {
|
|
const response = await fetch('/api/auth/verify-code', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
email: currentEmail,
|
|
code: document.getElementById('code').value.trim(),
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const data = await response.json();
|
|
throw new Error(data.detail || 'Verifizierung fehlgeschlagen');
|
|
}
|
|
|
|
const data = await response.json();
|
|
localStorage.setItem('osint_token', data.access_token);
|
|
localStorage.setItem('osint_username', data.username);
|
|
window.location.href = '/dashboard';
|
|
} catch (err) {
|
|
errorEl.textContent = err.message;
|
|
errorEl.style.display = 'block';
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Verifizieren';
|
|
}
|
|
});
|
|
|
|
// Zurück-Button
|
|
document.getElementById('back-btn').addEventListener('click', () => {
|
|
document.getElementById('code-form').style.display = 'none';
|
|
document.getElementById('email-form').style.display = 'block';
|
|
document.getElementById('login-error').style.display = 'none';
|
|
document.getElementById('code').value = '';
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|