Audit activité utilisateurs
This commit is contained in:
1 parent
f54d352b7f
commit
a5b4f3e721
10 files changed
+528
-21
No files matched your search
@@ -10,6 +10,7 @@ import { createRequire } from 'node:module';
|
||||
const _require = createRequire(import.meta.url);
|
||||
const QRCode = _require('qrcode');
|
||||
import { generateSecret as totpGenerateSecret, generateURI as totpGenerateURI, verifySync as totpVerifySync } from 'otplib';
|
||||
import { audit } from '../utils/audit.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -82,9 +83,11 @@ router.post('/register', async (req, res, next) => {
|
||||
// Ne pas faire échouer l'inscription si le mail échoue
|
||||
}
|
||||
|
||||
audit(req, { action: 'user_registered', category: 'account', targetUserId: userId, details: { email: body.email, role, auto_verified: false } });
|
||||
return res.status(201).json({ requiresVerification: true, email: body.email });
|
||||
}
|
||||
|
||||
audit(req, { action: 'user_registered', category: 'account', targetUserId: userId, details: { email: body.email, role, auto_verified: true } });
|
||||
const token = signToken({ sub: userId, email: body.email });
|
||||
res.status(201).json({
|
||||
token,
|
||||
@@ -103,10 +106,16 @@ router.post('/login', async (req, res, next) => {
|
||||
const user = db
|
||||
.prepare('SELECT id, email, password_hash, display_name, role, email_verified, totp_enabled, status FROM users WHERE email = ?')
|
||||
.get(body.email);
|
||||
if (!user) throw new HttpError(401, 'Invalid credentials');
|
||||
if (!user) {
|
||||
audit(req, { action: 'login_failed', category: 'auth', details: { email: body.email, reason: 'user_not_found' } });
|
||||
throw new HttpError(401, 'Invalid credentials');
|
||||
}
|
||||
|
||||
const ok = bcrypt.compareSync(body.password, user.password_hash);
|
||||
if (!ok) throw new HttpError(401, 'Invalid credentials');
|
||||
if (!ok) {
|
||||
audit(req, { action: 'login_failed', category: 'auth', targetUserId: user.id, details: { email: body.email, reason: 'wrong_password' } });
|
||||
throw new HttpError(401, 'Invalid credentials');
|
||||
}
|
||||
|
||||
if (user.status === 'deactivated') {
|
||||
return res.status(403).json({ error: 'Ce compte a été désactivé. Contactez un administrateur.', code: 'ACCOUNT_DEACTIVATED' });
|
||||
@@ -152,6 +161,7 @@ router.post('/login', async (req, res, next) => {
|
||||
});
|
||||
}
|
||||
|
||||
audit(req, { action: 'login_success', category: 'auth', actorId: user.id, targetUserId: user.id, details: { email: user.email } });
|
||||
const token = signToken({ sub: user.id, email: user.email });
|
||||
res.json({
|
||||
token,
|
||||
@@ -405,6 +415,7 @@ router.post('/2fa/confirm-setup', requireAuth, async (req, res, next) => {
|
||||
if (!valid) throw new HttpError(400, 'Code invalide. Réessayez.');
|
||||
|
||||
db.prepare("UPDATE users SET totp_enabled=1 WHERE id=?").run(req.user.id);
|
||||
audit(req, { action: '2fa_enabled', category: '2fa', actorId: req.user.id, targetUserId: req.user.id });
|
||||
res.json({ ok: true });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
@@ -423,6 +434,7 @@ router.post('/2fa/disable', requireAuth, async (req, res, next) => {
|
||||
db.prepare("UPDATE users SET totp_enabled=0, totp_secret=NULL WHERE id=?").run(req.user.id);
|
||||
// Supprimer tous les appareils de confiance
|
||||
db.prepare('DELETE FROM two_fa_trusted_devices WHERE user_id=?').run(req.user.id);
|
||||
audit(req, { action: '2fa_disabled', category: '2fa', actorId: req.user.id, targetUserId: req.user.id });
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) { next(e); }
|
||||
@@ -513,6 +525,7 @@ router.post('/2fa/verify', async (req, res, next) => {
|
||||
db.prepare('INSERT INTO two_fa_trusted_devices (user_id, token, expires_at, user_agent, ip_address) VALUES (?,?,?,?,?)').run(user.id, deviceToken, devExpires, ua, ip);
|
||||
}
|
||||
|
||||
audit(req, { action: 'login_2fa_success', category: 'auth', actorId: user.id, targetUserId: user.id, details: { method, trustDevice: !!trustDevice } });
|
||||
const token = signToken({ sub: user.id, email: user.email });
|
||||
res.json({
|
||||
token,
|
||||
@@ -555,7 +568,7 @@ router.delete('/trusted-devices/:id', requireAuth, (req, res, next) => {
|
||||
const id = parseInt(req.params.id, 10);
|
||||
const dev = db.prepare('SELECT id FROM two_fa_trusted_devices WHERE id=? AND user_id=?').get(id, req.user.id);
|
||||
if (!dev) throw new HttpError(404, 'Appareil introuvable.');
|
||||
db.prepare('DELETE FROM two_fa_trusted_devices WHERE id=?').run(id);
|
||||
db.prepare('DELETE FROM two_fa_trusted_devices WHERE id=?').run(id); db.prepare('DELETE FROM two_fa_trusted_devices WHERE id=?').run(id);
|
||||
res.json({ ok: true });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user