Dateien
AegisSight-Globe/static/login.html
Claude Dev af08fa6b4d Auth: Nur noch Magic Link, Code-Verifizierung entfernt
- /api/auth/verify-code Endpoint entfernt
- generate_magic_code() entfernt
- E-Mail: Nur noch Anmelde-Link, kein 6-stelliger Code
- Login-Seite: Zeigt nach E-Mail-Eingabe Hinweis statt Code-Feld
- Magic Link Token-Verifikation via URL bleibt bestehen
2026-03-25 00:01:21 +01:00

122 Zeilen
5.7 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AegisSight Globe — Login</title>
<style>
:root { --bg: #0b1121; --accent: #00ff88; --border: rgba(0,255,136,0.15); --text: #e8eaf0; --text-dim: rgba(255,255,255,0.5); --mono: 'JetBrains Mono','Courier New',monospace; }
* { margin:0; padding:0; box-sizing:border-box; }
body { min-height:100vh; background:var(--bg); color:var(--text); font-family:var(--mono); display:flex; align-items:center; justify-content:center; }
.login-box { width:380px; background:rgba(11,17,33,0.95); border:1px solid var(--border); border-radius:12px; padding:40px 32px; box-shadow:0 16px 64px rgba(0,0,0,0.5); }
.logo { text-align:center; margin-bottom:32px; }
.logo svg { width:40px; height:40px; }
.logo h1 { font-size:14px; letter-spacing:3px; color:var(--accent); margin-top:12px; }
.logo p { font-size:11px; color:var(--text-dim); margin-top:4px; }
.form-group { margin-bottom:20px; }
label { display:block; font-size:10px; letter-spacing:1.5px; color:var(--text-dim); margin-bottom:6px; text-transform:uppercase; }
input[type="email"] {
width:100%; padding:12px 14px; background:rgba(255,255,255,0.05); border:1px solid var(--border);
border-radius:6px; color:var(--text); font-family:var(--mono); font-size:14px; outline:none; transition:border-color 0.2s;
}
input:focus { border-color:var(--accent); }
.btn {
width:100%; padding:12px; background:rgba(0,255,136,0.1); border:1px solid var(--accent);
border-radius:6px; color:var(--accent); font-family:var(--mono); font-size:13px; font-weight:700;
letter-spacing:1px; cursor:pointer; transition:all 0.2s;
}
.btn:hover { background:rgba(0,255,136,0.2); }
.btn:disabled { opacity:0.4; cursor:not-allowed; }
.btn-secondary { background:none; border-color:var(--border); color:var(--text-dim); }
.btn-secondary:hover { border-color:var(--accent); color:var(--accent); }
.error { color:#ff4444; font-size:12px; margin-top:8px; display:none; }
.step { display:none; }
.step.active { display:block; }
</style>
</head>
<body>
<div class="login-box">
<div class="logo">
<svg viewBox="0 0 24 24" fill="none" stroke="#00ff88" stroke-width="1.5">
<circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10A15.3 15.3 0 0 1 12 2z"/>
</svg>
<h1>AEGISSIGHT GLOBE</h1>
<p>Geospatial Intelligence Dashboard</p>
</div>
<!-- Step 1: E-Mail -->
<div id="step-email" class="step active">
<div class="form-group">
<label>E-Mail-Adresse</label>
<input type="email" id="input-email" placeholder="name@beispiel.de" autofocus>
</div>
<button class="btn" id="btn-send" onclick="requestLink()">Anmelde-Link anfordern</button>
<div class="error" id="error-email"></div>
</div>
<!-- Step 2: Link gesendet -->
<div id="step-sent" class="step">
<div style="text-align:center; padding: 16px 0;">
<div style="font-size: 36px; margin-bottom: 16px;">&#9993;</div>
<p style="color:var(--text-dim); font-size:13px; margin-bottom:8px;">Anmelde-Link wurde gesendet an</p>
<p style="color:var(--accent); font-size:14px; font-weight:700; margin-bottom:16px;" id="sent-email"></p>
<p style="color:var(--text-dim); font-size:12px; line-height:1.6;">
Bitte prüfe dein Postfach und klicke auf den Link in der E-Mail.
</p>
</div>
<button class="btn btn-secondary" style="margin-top:20px;" onclick="showStep('email')">Andere E-Mail verwenden</button>
</div>
</div>
<script>
// Check if already logged in
if (localStorage.getItem('globe_token')) {
window.location.href = '/';
}
function showStep(step) {
document.querySelectorAll('.step').forEach(function(el) { el.classList.remove('active'); });
document.getElementById('step-' + step).classList.add('active');
document.querySelectorAll('.error').forEach(function(el) { el.style.display = 'none'; });
}
function showError(id, msg) {
var el = document.getElementById(id);
el.textContent = msg;
el.style.display = 'block';
}
async function requestLink() {
var email = document.getElementById('input-email').value.trim();
if (!email) return;
var btn = document.getElementById('btn-send');
btn.disabled = true;
btn.textContent = 'Sende...';
document.getElementById('error-email').style.display = 'none';
try {
var resp = await fetch('/api/auth/request-link', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email }),
});
var data = await resp.json();
if (!resp.ok) {
showError('error-email', data.detail || 'Fehler');
} else {
document.getElementById('sent-email').textContent = email;
showStep('sent');
}
} catch (e) {
showError('error-email', 'Verbindungsfehler');
}
btn.disabled = false;
btn.textContent = 'Anmelde-Link anfordern';
}
// Enter-Taste
document.getElementById('input-email').addEventListener('keydown', function(e) { if (e.key === 'Enter') requestLink(); });
</script>
</body>
</html>