94 lines
2.9 KiB
JavaScript
94 lines
2.9 KiB
JavaScript
const AuditLog = require('../models/AuditLog');
|
|
|
|
/**
|
|
* Middleware to log data changes to audit_logs table
|
|
*
|
|
* Usage:
|
|
* const { captureAuditLog } = require('../middleware/auditLogger');
|
|
*
|
|
* router.put('/endpoint/:id', async (req, res) => {
|
|
* const oldData = await Model.getById(id); // Fetch current data before update
|
|
*
|
|
* // Perform update
|
|
* const newData = await Model.update(id, req.body);
|
|
*
|
|
* // Log the change
|
|
* await captureAuditLog('table_name', id, 'UPDATE', oldData, newData);
|
|
*
|
|
* res.json({ success: true, data: newData });
|
|
* });
|
|
*/
|
|
|
|
/**
|
|
* Capture audit log for a data change
|
|
* @param {string} tableName - Name of the table being modified
|
|
* @param {string|number} recordId - ID of the record being modified
|
|
* @param {string} action - Action type: CREATE, UPDATE, DELETE
|
|
* @param {Object} oldValues - Previous values (null for CREATE)
|
|
* @param {Object} newValues - New values (null for DELETE)
|
|
* @returns {Promise<Object>} Created audit log entry
|
|
*/
|
|
async function captureAuditLog(tableName, recordId, action, oldValues = null, newValues = null) {
|
|
try {
|
|
// Determine which fields changed
|
|
const changedFields = [];
|
|
|
|
if (action === 'UPDATE' && oldValues && newValues) {
|
|
// Compare old and new values to find changed fields
|
|
for (const key in newValues) {
|
|
if (oldValues.hasOwnProperty(key)) {
|
|
// Handle different types of values
|
|
const oldVal = oldValues[key];
|
|
const newVal = newValues[key];
|
|
|
|
// Deep comparison for objects/arrays, simple comparison otherwise
|
|
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
changedFields.push(key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Only log if there are actual changes (for UPDATE) or always for CREATE/DELETE
|
|
if (action !== 'UPDATE' || changedFields.length > 0) {
|
|
return await AuditLog.create(
|
|
tableName,
|
|
recordId,
|
|
action,
|
|
oldValues,
|
|
newValues,
|
|
changedFields
|
|
);
|
|
}
|
|
|
|
return null; // No changes to log
|
|
} catch (error) {
|
|
// Log error but don't fail the main operation
|
|
console.error('Error capturing audit log:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper to extract only relevant fields for logging
|
|
* (excludes timestamps and internal fields)
|
|
* @param {Object} data - Data object
|
|
* @param {string[]} excludeFields - Fields to exclude (default: created_at, updated_at)
|
|
* @returns {Object} Filtered data object
|
|
*/
|
|
function filterAuditFields(data, excludeFields = ['created_at', 'updated_at']) {
|
|
if (!data) return null;
|
|
|
|
const filtered = { ...data };
|
|
excludeFields.forEach(field => {
|
|
delete filtered[field];
|
|
});
|
|
|
|
return filtered;
|
|
}
|
|
|
|
module.exports = {
|
|
captureAuditLog,
|
|
filterAuditFields
|
|
};
|