// services/auditLogger.js /** * Audit Logging Service * * Logs all API requests with user context, action, route, status, and timestamp * Logs both success and failure cases */ // In-memory log store (for development/testing) // In production, you should integrate with a logging service (e.g., Winston, Bunyan, CloudWatch, etc.) const auditLogs = []; /** * Audit Logger Class */ class AuditLogger { constructor(req) { this.req = req; this.userId = req.user?.userId || null; this.clientIp = req.clientIp || 'unknown'; this.userAgent = req.userAgent || 'unknown'; this.requestId = req.requestId; this.route = req.path; this.method = req.method; } /** * Log an audit event * * @param {Object} params * @param {string} params.action - Action being performed * @param {string} params.status - Status ('success', 'failed', 'forbidden', etc.) * @param {Object} params.meta - Additional metadata */ log({ action, status = 'success', meta = {} }) { const auditEntry = { timestamp: new Date().toISOString(), requestId: this.requestId, userId: this.userId, action, route: this.route, method: this.method, status, clientIp: this.clientIp, userAgent: this.userAgent, meta, }; // In production, send to logging service (e.g., CloudWatch, Elasticsearch, etc.) // For now, log to console and store in memory console.log('[AUDIT]', JSON.stringify(auditEntry)); auditLogs.push(auditEntry); // Keep only last 1000 logs in memory if (auditLogs.length > 1000) { auditLogs.shift(); } // TODO: Integrate with external logging service // Example: // if (process.env.LOGGING_SERVICE_URL) { // axios.post(process.env.LOGGING_SERVICE_URL + '/audit', auditEntry).catch(err => { // console.error('Failed to send audit log:', err); // }); // } } /** * Log successful request */ logSuccess(action, meta = {}) { this.log({ action, status: 'success', meta }); } /** * Log failed request */ logFailure(action, reason, meta = {}) { this.log({ action, status: 'failed', meta: { ...meta, reason } }); } /** * Log forbidden access */ logForbidden(action, reason, meta = {}) { this.log({ action, status: 'forbidden', meta: { ...meta, reason } }); } } /** * Middleware to attach audit logger to request */ export function auditLoggerMiddleware(req, res, next) { req.auditLogger = new AuditLogger(req); next(); } /** * Get audit logs (for debugging/admin purposes) */ export function getAuditLogs(limit = 100) { return auditLogs.slice(-limit); } export default AuditLogger;