diff --git a/backend/src/routes/admin.js b/backend/src/routes/admin.js index bba4075..dc5b94e 100644 --- a/backend/src/routes/admin.js +++ b/backend/src/routes/admin.js @@ -97,7 +97,7 @@ router.put('/users/:id/reset-password', authenticate, requireAdmin, (req, res) = const getSetting = k => db.prepare('SELECT value FROM admin_settings WHERE key=?').get(k)?.value; -// GET gesperrte Konten +// GET gesperrte Konten mit IPs router.get('/lockouts', authenticate, requireAdmin, (req, res) => { const locked = db.prepare(` SELECT id, username, failed_attempts, locked_until, last_failed_at @@ -105,11 +105,25 @@ router.get('/lockouts', authenticate, requireAdmin, (req, res) => { WHERE locked_until IS NOT NULL ORDER BY locked_until DESC `).all(); - res.json(locked); + + // IPs aus login_attempts hinzufügen + const result = locked.map(u => { + const ips = db.prepare(` + SELECT DISTINCT ip FROM login_attempts + WHERE username=? AND success=0 + ORDER BY created_at DESC LIMIT 10 + `).all(u.username).map(r => r.ip).filter(Boolean); + return { ...u, ips }; + }); + res.json(result); }); -// DELETE Sperre aufheben +// DELETE Sperre aufheben + Login-Versuche löschen router.delete('/lockouts/:userId', authenticate, requireAdmin, (req, res) => { + const user = db.prepare('SELECT username FROM users WHERE id=?').get(req.params.userId); + if (user) { + db.prepare('DELETE FROM login_attempts WHERE username=?').run(user.username); + } db.prepare('UPDATE users SET failed_attempts=0, locked_until=NULL, last_failed_at=NULL WHERE id=?') .run(req.params.userId); res.json({ ok: true }); diff --git a/backend/src/routes/auth.js b/backend/src/routes/auth.js index 6944a64..ea7c230 100644 --- a/backend/src/routes/auth.js +++ b/backend/src/routes/auth.js @@ -72,8 +72,9 @@ router.post('/login', (req, res) => { lockedUntil: until.toISOString(), }); } - // Abgelaufen + // Abgelaufen → zurücksetzen + Attempts löschen db.prepare('UPDATE users SET failed_attempts=0, locked_until=NULL, last_failed_at=NULL WHERE id=?').run(user.id); + db.prepare('DELETE FROM login_attempts WHERE username=?').run(username); } // Passwort prüfen @@ -96,8 +97,9 @@ router.post('/login', (req, res) => { }); } - // Erfolgreich → Zähler zurücksetzen + // Erfolgreich → Zähler zurücksetzen + Attempts löschen db.prepare('UPDATE users SET failed_attempts=0, locked_until=NULL, last_failed_at=NULL WHERE id=?').run(user.id); + db.prepare('DELETE FROM login_attempts WHERE username=?').run(username); const token = jwt.sign( { id: user.id, username: user.username, role: user.role }, diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e02edde..dd783df 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1068,6 +1068,15 @@ function SecuritySettingsAdmin({ toast }) { Letzter Versuch: {fmtDate(u.last_failed_at)} )} + {u.ips?.length > 0 && ( +