This commit is contained in:
2026-06-14 22:35:27 +02:00
parent 6f3dc0c05a
commit a6fc9f445f
6 changed files with 55 additions and 154 deletions
+21
View File
@@ -490,6 +490,22 @@ function SecurityForm() {
/* ── Appareils connectés ─────────────────────────────────────── */
function fmtRelative(isoStr) {
if (!isoStr) return null;
// SQLite datetime() returns UTC without Z — force UTC parsing
const d = new Date(isoStr.endsWith('Z') ? isoStr : isoStr + 'Z');
const diff = Date.now() - d.getTime();
const secs = Math.floor(diff / 1000);
const mins = Math.floor(secs / 60);
const hours = Math.floor(mins / 60);
const days = Math.floor(hours / 24);
if (secs < 60) return `à l'instant`;
if (mins < 60) return `il y a ${mins} min`;
if (hours < 24) return `il y a ${hours} h`;
if (days < 30) return `il y a ${days} j`;
return d.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' });
}
function parseUA(ua) {
if (!ua) return { device: 'Inconnu', browser: '', icon: 'desktop' };
const isMobile = /mobile|android|iphone|ipad/i.test(ua);
@@ -625,6 +641,11 @@ function TrustedDevicesSection() {
<div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 3 }}>
{dev.ip_address && <span>{dev.ip_address} · </span>}
<span>Connecté le {connDate}</span>
{fmtRelative(dev.last_seen_at) && (
<span style={{ marginLeft: 8, color: 'var(--text-muted)', opacity: 0.75 }}>
· Vu {fmtRelative(dev.last_seen_at)}
</span>
)}
</div>
</div>
<button
@@ -82,6 +82,7 @@ export default function UsersSection({ currentUserId }) {
<th>Nom</th>
<th>Email</th>
<th>Email vérifié</th>
<th>2FA</th>
<th>Rôle</th>
<th>Créé le</th>
<th>Actions</th>
@@ -99,6 +100,12 @@ export default function UsersSection({ currentUserId }) {
: <span style={{ fontSize: 11, fontWeight: 600, padding: '2px 8px', borderRadius: 10, background: 'var(--warning-bg, #fffbeb)', color: 'var(--warning-text, #92400e)', border: '1px solid #fcd34d' }}>En attente</span>
}
</td>
<td>
{u.totp_enabled
? <span style={{ fontSize: 11, fontWeight: 600, padding: '2px 8px', borderRadius: 10, background: 'var(--primary-bg, #eff6ff)', color: 'var(--primary, #1e40af)', border: '1px solid #bfdbfe' }}>🔐 Activé</span>
: <span style={{ fontSize: 11, color: 'var(--text-muted)' }}></span>
}
</td>
<td><Badge role={u.role} /></td>
<td style={{ color: 'var(--text-muted)', fontSize: 12 }}>{fmt(u.created_at)}</td>
<td>