UNPKG

@openade/fe

Version:

Fatturazione Elettronica - Electronic Invoicing for Sistema di Interscambio (SDI)

275 lines 9.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuditTrailManager = void 0; exports.createAuditTrailManager = createAuditTrailManager; exports.logAuditEvent = logAuditEvent; exports.queryAuditEvents = queryAuditEvents; const fs_1 = require("fs"); const path_1 = require("path"); class AuditTrailManager { constructor(config) { this.currentLogFile = null; this.config = { maxLogSize: 10 * 1024 * 1024, retentionDays: 2555, detailedLogging: true, includeSensitiveData: false, format: 'json', compression: true, ...config, }; this.ensureLogDirectory(); } async logEvent(event) { const auditEvent = { id: this.generateEventId(), timestamp: new Date().toISOString(), ...event, }; if (!this.config.includeSensitiveData) { auditEvent.details = this.sanitizeSensitiveData(auditEvent.details); } await this.writeToLog(auditEvent); await this.rotateLogIfNeeded(); } async queryEvents(query = {}) { try { const logFiles = this.getLogFiles(); const events = []; for (const logFile of logFiles) { const fileEvents = await this.readLogFile(logFile); events.push(...fileEvents); } return this.filterEvents(events, query); } catch { return []; } } async getAuditStats(query = {}) { const events = await this.queryEvents(query); return this.calculateStats(events); } async exportEvents(query = {}, format = 'json') { const events = await this.queryEvents(query); if (format === 'csv') { return this.exportToCSV(events); } else { return JSON.stringify(events, null, 2); } } async cleanupOldLogs() { try { const logFiles = this.getLogFiles(); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - this.config.retentionDays); let deletedCount = 0; for (const logFile of logFiles) { const filePath = (0, path_1.join)(this.config.logDir, logFile); const stats = (0, fs_1.statSync)(filePath); if (stats.mtime < cutoffDate) { (0, fs_1.unlinkSync)(filePath); deletedCount++; } } return deletedCount; } catch { return 0; } } generateEventId() { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 8); return `EVT_${timestamp}_${random}`; } ensureLogDirectory() { if (!(0, fs_1.existsSync)(this.config.logDir)) { (0, fs_1.mkdirSync)(this.config.logDir, { recursive: true }); } } getCurrentLogFile() { if (!this.currentLogFile) { const date = new Date().toISOString().split('T')[0]; this.currentLogFile = (0, path_1.join)(this.config.logDir, `audit_${date}.log`); } return this.currentLogFile; } async writeToLog(event) { const logFile = this.getCurrentLogFile(); const logEntry = this.formatLogEntry(event); (0, fs_1.writeFileSync)(logFile, logEntry + '\n', { flag: 'a' }); } formatLogEntry(event) { if (this.config.format === 'json') { return JSON.stringify(event); } else { return `${event.timestamp} [${event.type}] ${event.description} - ${event.success ? 'SUCCESS' : 'FAILED'}`; } } async rotateLogIfNeeded() { const logFile = this.getCurrentLogFile(); if ((0, fs_1.existsSync)(logFile)) { const stats = (0, fs_1.statSync)(logFile); if (stats.size >= this.config.maxLogSize) { this.currentLogFile = null; } } } getLogFiles() { try { if (!(0, fs_1.existsSync)(this.config.logDir)) { return []; } return (0, fs_1.readdirSync)(this.config.logDir) .filter((file) => file.startsWith('audit_') && file.endsWith('.log')) .sort(); } catch { return []; } } async readLogFile(filename) { try { const filePath = (0, path_1.join)(this.config.logDir, filename); const content = (0, fs_1.readFileSync)(filePath, 'utf8'); const lines = content.trim().split('\n'); return lines .map((line) => { try { return JSON.parse(line); } catch { return null; } }) .filter((event) => event !== null); } catch { return []; } } filterEvents(events, query) { let filtered = events; if (query.types && query.types.length > 0) { filtered = filtered.filter((event) => query.types.includes(event.type)); } if (query.startDate) { filtered = filtered.filter((event) => event.timestamp >= query.startDate); } if (query.endDate) { filtered = filtered.filter((event) => event.timestamp <= query.endDate); } if (query.userId) { filtered = filtered.filter((event) => event.userId === query.userId); } if (query.success !== undefined) { filtered = filtered.filter((event) => event.success === query.success); } if (query.invoiceId) { filtered = filtered.filter((event) => event.invoiceId === query.invoiceId); } filtered.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()); if (query.offset) { filtered = filtered.slice(query.offset); } if (query.limit) { filtered = filtered.slice(0, query.limit); } return filtered; } calculateStats(events) { const eventsByType = {}; const eventsByUser = {}; const errors = {}; let totalDuration = 0; let durationCount = 0; for (const event of events) { eventsByType[event.type] = (eventsByType[event.type] || 0) + 1; if (event.userId) { eventsByUser[event.userId] = (eventsByUser[event.userId] || 0) + 1; } if (!event.success && event.error) { errors[event.error] = (errors[event.error] || 0) + 1; } if (event.duration) { totalDuration += event.duration; durationCount++; } } const commonErrors = Object.entries(errors) .map(([error, count]) => ({ error, count })) .sort((a, b) => b.count - a.count) .slice(0, 10); const successCount = events.filter((e) => e.success).length; const successRate = events.length > 0 ? (successCount / events.length) * 100 : 0; const averageDuration = durationCount > 0 ? totalDuration / durationCount : 0; const timestamps = events.map((e) => e.timestamp).sort(); const timeRange = { start: timestamps[0] || '', end: timestamps[timestamps.length - 1] || '', }; return { totalEvents: events.length, eventsByType, eventsByUser, successRate, averageDuration, commonErrors, timeRange, }; } exportToCSV(events) { if (events.length === 0) { return ''; } const headers = [ 'ID', 'Type', 'Timestamp', 'User ID', 'Description', 'Success', 'Error', 'Duration', 'Invoice ID', ]; const rows = events.map((event) => [ event.id, event.type, event.timestamp, event.userId || '', event.description, event.success ? 'TRUE' : 'FALSE', event.error || '', event.duration || '', event.invoiceId || '', ]); return [headers, ...rows].map((row) => row.join(',')).join('\n'); } sanitizeSensitiveData(details) { const sensitiveKeys = ['password', 'token', 'key', 'secret', 'certificate', 'privateKey']; const sanitized = { ...details }; for (const key of Object.keys(sanitized)) { if (sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive))) { sanitized[key] = '[REDACTED]'; } } return sanitized; } } exports.AuditTrailManager = AuditTrailManager; function createAuditTrailManager(config) { return new AuditTrailManager(config); } async function logAuditEvent(event, config) { const manager = createAuditTrailManager(config); await manager.logEvent(event); } async function queryAuditEvents(query = {}, config) { const manager = createAuditTrailManager(config); return await manager.queryEvents(query); } //# sourceMappingURL=audit.manager.js.map