espid2sensor: Passwort ändern + Admin-Passwort-Reset

- POST /api/changePassword: jeder eingeloggte User kann sein eigenes
  Passwort ändern (erfordert aktuelles Passwort), neuer Profil-Tab
- POST /api/resetPassword: Admin kann das Passwort eines Users per
  Email zuruecksetzen, neue Karte im bestehenden User-Tab
- Login-Seite: Hinweis fuer "Passwort vergessen" (Kontakt zum Admin,
  da keine Mail-Infrastruktur im Projekt existiert)
- Bugfix beim Umsetzen: express-session's MemoryStore serialisiert
  Sessions per JSON, wodurch die ObjectId aus req.session.userId zu
  einem String wird - vor der Mongo-Query per ObjectId(...) casten

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 10:07:52 +00:00
parent 47d27148ca
commit cd4d7ba25d
5 changed files with 130 additions and 2 deletions
+35
View File
@@ -92,4 +92,39 @@ export function registerApiRoutes(app, requireLogin) {
res.status(500).json({ error: 'Fehler beim Anlegen' });
}
});
app.post('/api/changePassword', requireLogin, async (req, res) => {
const { currentPassword, newPassword } = req.body;
if (!currentPassword || !newPassword) {
return res.status(400).json({ error: 'Aktuelles und neues Passwort erforderlich' });
}
try {
const user = await usersCollection.findOne({ _id: new ObjectId(req.session.userId) });
if (!user) return res.status(404).json({ error: 'User nicht gefunden' });
const match = await bcrypt.compare(currentPassword, user.passwordHash);
if (!match) return res.status(403).json({ error: 'Aktuelles Passwort ist falsch' });
const hash = await bcrypt.hash(newPassword, 10);
await usersCollection.updateOne({ _id: user._id }, { $set: { passwordHash: hash } });
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: 'Fehler beim Ändern des Passworts' });
}
});
app.post('/api/resetPassword', requireLogin, async (req, res) => {
if (!req.session.isAdmin) return res.status(403).json({ error: 'Nur Admins erlaubt' });
const { email, newPassword } = req.body;
if (!email || !newPassword) return res.status(400).json({ error: 'Email und neues Passwort erforderlich' });
try {
const hash = await bcrypt.hash(newPassword, 10);
const result = await usersCollection.updateOne(
{ email: email.toLowerCase() },
{ $set: { passwordHash: hash } }
);
if (result.matchedCount === 0) return res.status(404).json({ error: 'User nicht gefunden' });
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: 'Fehler beim Zurücksetzen' });
}
});
}