Release 2.8.0
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
const AUDIT_EVENT_CATEGORIES = Object.freeze({
|
||||
AUTHENTICATION: 'authentication',
|
||||
SECURITY: 'security',
|
||||
SESSIONS: 'sessions',
|
||||
USERS: 'users',
|
||||
ROLES: 'roles',
|
||||
SETTINGS: 'system-settings',
|
||||
SLIDES: 'slides',
|
||||
TEMPLATES: 'templates',
|
||||
PLAYLISTS: 'playlists',
|
||||
SCREENS: 'screens',
|
||||
ANNOUNCEMENTS: 'announcements',
|
||||
CANVAS_SIZES: 'canvas-sizes',
|
||||
API_SOURCES: 'api-sources',
|
||||
RSS_FEEDS: 'rss-feeds',
|
||||
TIMETABLES: 'timetables'
|
||||
});
|
||||
const AUDIT_CATEGORY_KEYS = Object.freeze(Object.values(AUDIT_EVENT_CATEGORIES));
|
||||
const AUDIT_CATEGORY_LABELS = Object.freeze({
|
||||
authentication: 'Authentication',
|
||||
security: 'Security',
|
||||
sessions: 'Sessions',
|
||||
users: 'Users',
|
||||
roles: 'Roles',
|
||||
'system-settings': 'System Settings',
|
||||
slides: 'Slides',
|
||||
templates: 'Templates',
|
||||
playlists: 'Playlists',
|
||||
screens: 'Screens',
|
||||
announcements: 'Announcements',
|
||||
'canvas-sizes': 'Canvas Sizes',
|
||||
'api-sources': 'API Sources',
|
||||
'rss-feeds': 'RSS Feeds',
|
||||
timetables: 'Timetables'
|
||||
});
|
||||
const { fetchAppSettings } = require('./app-settings');
|
||||
|
||||
function normalizeDetails(details) {
|
||||
if (details === undefined || details === null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.stringify(details);
|
||||
}
|
||||
|
||||
function getRequestMetadata(req) {
|
||||
const forwardedAddress = String(req && req.headers && req.headers['x-forwarded-for'] || '').split(',')[0].trim();
|
||||
return {
|
||||
ipAddress: forwardedAddress || String(req && req.ip || req && req.socket && req.socket.remoteAddress || '').trim() || null,
|
||||
userAgent: String(req && req.headers && req.headers['user-agent'] || '').trim() || null
|
||||
};
|
||||
}
|
||||
|
||||
async function recordAuditEvent(pool, event) {
|
||||
const input = event && typeof event === 'object' ? event : {};
|
||||
const category = String(input.category || '').trim().toLowerCase();
|
||||
const eventType = String(input.eventType || '').trim().toLowerCase();
|
||||
if (!category || !eventType) {
|
||||
throw new Error('Audit events require a category and event type.');
|
||||
}
|
||||
|
||||
await pool.query(
|
||||
`INSERT INTO o_audit_events
|
||||
(category, event_type, actor_user_id, target_type, target_id, target_label, ip_address, user_agent, details_json)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
category,
|
||||
eventType,
|
||||
Number.isInteger(Number(input.actorUserId)) && Number(input.actorUserId) > 0 ? Number(input.actorUserId) : null,
|
||||
String(input.targetType || '').trim() || null,
|
||||
String(input.targetId || '').trim() || null,
|
||||
String(input.targetLabel || '').trim() || null,
|
||||
String(input.ipAddress || '').trim() || null,
|
||||
String(input.userAgent || '').trim() || null,
|
||||
normalizeDetails(input.details)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
async function recordRequestAuditEvent(pool, req, event) {
|
||||
try {
|
||||
const settings = await fetchAppSettings(pool);
|
||||
const category = String(event && event.category || '').trim().toLowerCase();
|
||||
const enabledCategories = Array.isArray(settings['audit.categories']) ? settings['audit.categories'] : AUDIT_CATEGORY_KEYS;
|
||||
if (!settings['audit.enabled'] || !enabledCategories.includes(category)) {
|
||||
return;
|
||||
}
|
||||
const metadata = settings['audit.include_request_metadata'] ? getRequestMetadata(req) : {};
|
||||
await recordAuditEvent(pool, Object.assign({}, event, metadata));
|
||||
} catch (error) {
|
||||
// Auditing must not turn a successful login or administration action into a failed request.
|
||||
console.error('Unable to record audit event:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
AUDIT_EVENT_CATEGORIES,
|
||||
AUDIT_CATEGORY_KEYS,
|
||||
AUDIT_CATEGORY_LABELS,
|
||||
getRequestMetadata,
|
||||
recordAuditEvent,
|
||||
recordRequestAuditEvent
|
||||
};
|
||||
Reference in New Issue
Block a user