Audit log (admin Activity list) and passkey recovery codes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-22 07:53:41 -04:00
1 parent c8399ccaa7
commit 561b6181a0
8 files changed
+101 -14

No files matched your search

+5
View File
@@ -2,6 +2,7 @@
// sign them out everywhere, turn them off, or delete them and their data. Admin only (enforced by the caller).
const users = require('./users');
const auth = require('./auth');
const audit = require('./audit');
const readBody = req => new Promise((ok, no) => { const c = []; req.on('data', d => c.push(d)); req.on('end', () => ok(Buffer.concat(c).toString())); req.on('error', no); });
const json = (res, code, obj) => { res.writeHead(code, { 'content-type': 'application/json' }); res.end(JSON.stringify(obj)); };
@@ -15,18 +16,22 @@ async function handle(req, res, me) {
if (!id && req.method === 'POST') {
const b = JSON.parse(await readBody(req) || '{}');
const u = users.create({ name: b.name, role: 'user', tabs: b.tabs });
audit.log('person added', { who: me.name, detail: u.name }, req);
return json(res, 200, { user: row(u), code: auth.newInvite(u.id), minutes: auth.INVITE_MINUTES });
}
const u = users.get(id); if (!u) return json(res, 404, { error: 'Person not found' });
if (action === 'invite' && req.method === 'POST') audit.log('invite created', { who: me.name, detail: u.name }, req);
if (action === 'invite' && req.method === 'POST') return json(res, 200, { code: auth.newInvite(u.id), minutes: auth.INVITE_MINUTES }); // for a new device or to recover access
if (!action && req.method === 'PUT') {
const b = JSON.parse(await readBody(req) || '{}');
if (u.id === me.id && b.disabled) return json(res, 400, { error: 'You cannot turn off your own account' });
audit.log('person changed', { who: me.name, detail: u.name + (b.disabled !== undefined ? (b.disabled ? ' (turned off)' : ' (turned on)') : '') + (b.signOutEverywhere ? ' (signed out everywhere)' : '') + (b.tabs ? ' (tabs)' : '') + (b.role ? ' (role)' : '') }, req);
users.update(id, { name: b.name, tabs: b.tabs, role: b.role, disabled: b.disabled, signOutEverywhere: b.signOutEverywhere });
return json(res, 200, { user: row(users.get(id)) });
}
if (!action && req.method === 'DELETE') {
if (u.id === me.id) return json(res, 400, { error: 'You cannot delete your own account' });
audit.log('person removed', { who: me.name, detail: u.name }, req);
users.remove(id); auth.removeCredsOf(id);
return json(res, 200, { ok: true });
}