From 5b91a5bf8471d6bb33e73c072aed1022156dac76 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 19 Aug 2026 19:13:22 +0200 Subject: [PATCH] Admin-Login lokal: 2FA-PIN ohne Mailversand (Dev) + Mailer-Fehler abfangen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: lokal konnte man sich nicht als Admin anmelden — der 2FA-PIN kam nie an (kein SMTP), und Mailer::sendAdminPin() warf sogar eine Exception, die den Login komplett abbrach (leere Antwort → „MFA fehlt"). - admin.php: Mailversand nur auf Prod + in try/catch (Mail-Fehler darf den Login NIE blocken). Lokal (!IS_PRODUCTION) wird der PIN als `devPin` in der Login-Antwort zurückgegeben — auf Prod NIEMALS (2FA bleibt Pflicht). - admin.html: devPin wird lokal automatisch ins PIN-Feld vorausgefüllt + als Hinweis angezeigt. Verifiziert (temp Test-Admin): login → devPin → verify → authenticated:true, admin-weltkueche.html erreichbar. Prod unberührt (IS_PRODUCTION-Gate). Co-Authored-By: Claude Opus 4.8 --- App/admin.html | 8 ++++++++ App/php/api/admin.php | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/App/admin.html b/App/admin.html index 24c1fc1..dcbc606 100644 --- a/App/admin.html +++ b/App/admin.html @@ -83,6 +83,14 @@ async function doLogin() { document.getElementById('step-login').classList.add('hidden'); document.getElementById('step-pin').classList.remove('hidden'); document.getElementById('msg').className = 'msg'; + // Dev-Umgebung (localhost): PIN kommt in der Antwort mit → direkt vorausfüllen, + // damit man sich ohne Mailversand anmelden kann. Auf Prod gibt es kein devPin. + if (r.devPin) { + document.getElementById('a-pin').value = r.devPin; + document.getElementById('pin-email').textContent = 'Dev-Umgebung'; + var hint = document.querySelector('#step-pin .step-hint'); + if (hint) hint.innerHTML = '🔧 Dev: kein Mailversand — PIN ' + r.devPin + ' ist vorausgefüllt. Auf „Bestätigen".'; + } document.getElementById('a-pin').focus(); } diff --git a/App/php/api/admin.php b/App/php/api/admin.php index 88b8747..02666e9 100644 --- a/App/php/api/admin.php +++ b/App/php/api/admin.php @@ -32,9 +32,12 @@ if ($action === 'login') { [$admin['id'], $pin] ); - // PIN per E-Mail senden - if (class_exists('Mailer')) { - Mailer::sendAdminPin($admin['email_2fa'], $pin); + // PIN per E-Mail senden — Fehler dürfen den Login NIE abbrechen (lokal geht + // kein SMTP raus; früher warf das hier und die Anmeldung schlug fehl → „MFA + // fehlt"). Lokal ohnehin überspringen, da wir den PIN als devPin zurückgeben. + if (IS_PRODUCTION && class_exists('Mailer') && !empty($admin['email_2fa'])) { + try { Mailer::sendAdminPin($admin['email_2fa'], $pin); } + catch (\Throwable $e) { error_log('[admin] Mailer::sendAdminPin fehlgeschlagen: ' . $e->getMessage()); } } // Admin-ID in Session speichern (aber noch nicht authentifiziert) @@ -42,7 +45,14 @@ if ($action === 'login') { $_SESSION['admin_pending'] = (int)$admin['id']; unset($_SESSION['admin_id']); // Sicherstellen dass nicht schon eingeloggt - Response::ok(['message' => 'PIN wurde an Ihre E-Mail gesendet.', 'email' => maskEmail($admin['email_2fa'])]); + $resp = ['message' => 'PIN wurde an Ihre E-Mail gesendet.', 'email' => maskEmail($admin['email_2fa'])]; + // Dev-Umgebung (localhost): es geht keine Mail raus → PIN direkt zurückgeben, + // damit man sich lokal anmelden kann. Auf Prod (IS_PRODUCTION) NIEMALS. + if (!IS_PRODUCTION) { + $resp['devPin'] = $pin; + $resp['message'] = 'Dev-Umgebung – kein Mailversand. PIN steht unten.'; + } + Response::ok($resp); } // === VERIFY PIN (Schritt 2: PIN eingeben → Admin-Session) ===