forked from UKSOURCE/cms.hailearning.edu.vn
feat: implement comprehensive audit logging system
This commit is contained in:
178
controllers/auditLogController.js
Normal file
178
controllers/auditLogController.js
Normal file
@@ -0,0 +1,178 @@
|
||||
const AuditLog = require("../models/auditLog");
|
||||
const User = require("../models/User");
|
||||
|
||||
// Display audit logs with pagination and filtering
|
||||
exports.index = async (req, res) => {
|
||||
try {
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = parseInt(req.query.limit) || 8; // Default to 8, but allow override
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
// Build filter query
|
||||
const filter = {};
|
||||
|
||||
if (req.query.model) {
|
||||
filter.model = req.query.model;
|
||||
}
|
||||
|
||||
if (req.query.action) {
|
||||
filter.action = req.query.action;
|
||||
}
|
||||
|
||||
if (req.query.user) {
|
||||
filter.performedBy = req.query.user;
|
||||
}
|
||||
|
||||
if (req.query.dateFrom || req.query.dateTo) {
|
||||
filter.createdAt = {};
|
||||
if (req.query.dateFrom) {
|
||||
filter.createdAt.$gte = new Date(req.query.dateFrom);
|
||||
}
|
||||
if (req.query.dateTo) {
|
||||
const dateTo = new Date(req.query.dateTo);
|
||||
dateTo.setHours(23, 59, 59, 999); // End of day
|
||||
filter.createdAt.$lte = dateTo;
|
||||
}
|
||||
}
|
||||
|
||||
// Get audit logs with user population
|
||||
const auditLogs = await AuditLog.find(filter)
|
||||
.populate("performedBy", "username email")
|
||||
.sort({ createdAt: -1 })
|
||||
.skip(skip)
|
||||
.limit(limit);
|
||||
|
||||
// Get total count for pagination
|
||||
const totalCount = await AuditLog.countDocuments(filter);
|
||||
const totalPages = Math.ceil(totalCount / limit);
|
||||
|
||||
// Get unique models and actions for filter dropdowns
|
||||
const uniqueModels = await AuditLog.distinct("model");
|
||||
const uniqueActions = await AuditLog.distinct("action");
|
||||
const users = await User.find({}, "username email").sort({ username: 1 });
|
||||
|
||||
res.render("admin/audit-log/index", {
|
||||
title: "Audit Logs",
|
||||
layout: "layouts/main",
|
||||
auditLogs,
|
||||
pagination: {
|
||||
current: page,
|
||||
total: totalPages,
|
||||
limit,
|
||||
totalCount,
|
||||
},
|
||||
query: req.query,
|
||||
uniqueModels,
|
||||
uniqueActions,
|
||||
users,
|
||||
currentPath: req.path,
|
||||
user: req.session.user,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error loading audit logs:", err);
|
||||
req.flash("error_msg", "Error loading audit logs");
|
||||
res.redirect("/admin/dashboard");
|
||||
}
|
||||
};
|
||||
|
||||
// Display single audit log details
|
||||
exports.show = async (req, res) => {
|
||||
try {
|
||||
const auditLog = await AuditLog.findById(req.params.id).populate(
|
||||
"performedBy",
|
||||
"username email",
|
||||
);
|
||||
|
||||
if (!auditLog) {
|
||||
req.flash("error_msg", "Audit log not found");
|
||||
return res.redirect("/admin/audit-logs");
|
||||
}
|
||||
|
||||
res.render("admin/audit-log/show", {
|
||||
title: "Audit Log Details",
|
||||
layout: "layouts/main",
|
||||
auditLog,
|
||||
currentPath: req.path,
|
||||
user: req.session.user,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error loading audit log:", err);
|
||||
req.flash("error_msg", "Error loading audit log");
|
||||
res.redirect("/admin/audit-logs");
|
||||
}
|
||||
};
|
||||
|
||||
// API endpoint to get audit logs (for AJAX requests)
|
||||
exports.api = async (req, res) => {
|
||||
try {
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = parseInt(req.query.limit) || 7; // Default to 7, but allow override
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const filter = {};
|
||||
|
||||
if (req.query.model) filter.model = req.query.model;
|
||||
if (req.query.action) filter.action = req.query.action;
|
||||
if (req.query.user) filter.performedBy = req.query.user;
|
||||
|
||||
if (req.query.dateFrom || req.query.dateTo) {
|
||||
filter.createdAt = {};
|
||||
if (req.query.dateFrom) {
|
||||
filter.createdAt.$gte = new Date(req.query.dateFrom);
|
||||
}
|
||||
if (req.query.dateTo) {
|
||||
const dateTo = new Date(req.query.dateTo);
|
||||
dateTo.setHours(23, 59, 59, 999);
|
||||
filter.createdAt.$lte = dateTo;
|
||||
}
|
||||
}
|
||||
|
||||
const auditLogs = await AuditLog.find(filter)
|
||||
.populate("performedBy", "username email")
|
||||
.sort({ createdAt: -1 })
|
||||
.skip(skip)
|
||||
.limit(limit);
|
||||
|
||||
const totalCount = await AuditLog.countDocuments(filter);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: auditLogs,
|
||||
pagination: {
|
||||
current: page,
|
||||
total: Math.ceil(totalCount / limit),
|
||||
limit,
|
||||
totalCount,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("API Error:", err);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: "Error loading audit logs",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Delete old audit logs (cleanup)
|
||||
exports.cleanup = async (req, res) => {
|
||||
try {
|
||||
const daysToKeep = parseInt(req.body.days) || 90;
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
|
||||
|
||||
const result = await AuditLog.deleteMany({
|
||||
createdAt: { $lt: cutoffDate },
|
||||
});
|
||||
|
||||
req.flash(
|
||||
"success_msg",
|
||||
`Deleted ${result.deletedCount} old audit logs (older than ${daysToKeep} days)`,
|
||||
);
|
||||
res.redirect("/admin/audit-logs");
|
||||
} catch (err) {
|
||||
console.error("Error cleaning up audit logs:", err);
|
||||
req.flash("error_msg", "Error cleaning up audit logs");
|
||||
res.redirect("/admin/audit-logs");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user