27 lines
1.4 KiB
JavaScript
27 lines
1.4 KiB
JavaScript
// Audit log: who signed in, who was added or changed, what was downloaded. One JSON line per event in /data/audit.log
|
|
// (rotated at about 1 MB, keeping one older file). Contains no passwords, codes or message text.
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, 'data');
|
|
const FILE = path.join(DATA_DIR, 'audit.log'), MAX = 1024 * 1024;
|
|
const ipOf = req => String((req && (req.headers['x-forwarded-for'] || (req.socket && req.socket.remoteAddress))) || '').split(',')[0].trim();
|
|
|
|
/** log('sign-in', { who: 'Nate', ip, detail: 'iPhone' }) */
|
|
function log(event, o = {}, req) {
|
|
try {
|
|
const line = JSON.stringify({ t: Date.now(), event, who: o.who || '', detail: o.detail || '', ip: o.ip || ipOf(req) }) + '\n';
|
|
try { if (fs.statSync(FILE).size > MAX) fs.renameSync(FILE, FILE + '.1'); } catch {}
|
|
fs.appendFileSync(FILE, line, { mode: 0o600 });
|
|
} catch (e) { console.error('[audit] could not write:', e.message); }
|
|
}
|
|
/** Newest first. */
|
|
function recent(n = 200) {
|
|
const rows = [];
|
|
for (const f of [FILE, FILE + '.1']) {
|
|
let text = ''; try { text = fs.readFileSync(f, 'utf8'); } catch { continue; }
|
|
for (const l of text.split('\n').reverse()) { if (!l) continue; try { rows.push(JSON.parse(l)); } catch {} if (rows.length >= n) return rows; }
|
|
}
|
|
return rows;
|
|
}
|
|
module.exports = { log, recent };
|