Files
Checkmate/server/controllers/monitorController.js
T

441 lines
12 KiB
JavaScript
Raw Normal View History

2025-04-20 11:29:53 -07:00
import {
getMonitorByIdParamValidation,
getMonitorByIdQueryValidation,
getMonitorsByTeamIdParamValidation,
getMonitorsByTeamIdQueryValidation,
createMonitorBodyValidation,
editMonitorBodyValidation,
pauseMonitorParamValidation,
getMonitorStatsByIdParamValidation,
getMonitorStatsByIdQueryValidation,
getCertificateParamValidation,
getHardwareDetailsByIdParamValidation,
getHardwareDetailsByIdQueryValidation,
} from "../validation/joi.js";
import sslChecker from "ssl-checker";
2025-07-21 13:58:01 -07:00
import { fetchMonitorCertificate } from "./controllerUtils.js";
2025-07-24 15:06:46 -07:00
import BaseController from "./baseController.js";
2025-04-20 11:29:53 -07:00
const SERVICE_NAME = "monitorController";
2025-07-24 15:06:46 -07:00
class MonitorController extends BaseController {
2025-07-25 10:16:29 -07:00
constructor(commonDependencies, { settingsService, jobQueue, emailService, monitorService }) {
super(commonDependencies);
2025-04-20 11:29:53 -07:00
this.settingsService = settingsService;
this.jobQueue = jobQueue;
2025-05-06 00:08:11 +05:30
this.emailService = emailService;
2025-07-24 13:50:21 -07:00
this.monitorService = monitorService;
2025-04-20 11:29:53 -07:00
}
2025-07-21 13:58:01 -07:00
async verifyTeamAccess(teamId, monitorId) {
const monitor = await this.db.getMonitorById(monitorId);
if (!monitor.teamId.equals(teamId)) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createAuthorizationError();
2025-07-21 13:58:01 -07:00
}
}
2025-07-24 15:06:46 -07:00
getAllMonitors = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
const monitors = await this.monitorService.getAllMonitors();
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorGetAll,
data: monitors,
});
},
SERVICE_NAME,
"getAllMonitors"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getUptimeDetailsById = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
const monitorId = req?.params?.monitorId;
const dateRange = req?.query?.dateRange;
const normalize = req?.query?.normalize;
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
2025-07-24 13:50:21 -07:00
2025-07-21 13:58:01 -07:00
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const data = await this.monitorService.getUptimeDetailsById({
teamId,
monitorId,
dateRange,
normalize,
});
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorGetByIdSuccess,
2025-07-24 13:50:21 -07:00
data: data,
2025-04-20 11:29:53 -07:00
});
},
SERVICE_NAME,
"getUptimeDetailsById"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getMonitorStatsById = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorStatsByIdParamValidation.validateAsync(req.params);
await getMonitorStatsByIdQueryValidation.validateAsync(req.query);
let { limit, sortOrder, dateRange, numToDisplay, normalize } = req.query;
2025-07-24 13:50:21 -07:00
const monitorId = req?.params?.monitorId;
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const monitorStats = await this.monitorService.getMonitorStatsById({
teamId,
monitorId,
limit,
sortOrder,
dateRange,
numToDisplay,
normalize,
});
2025-07-24 13:50:21 -07:00
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorStatsById,
data: monitorStats,
});
},
SERVICE_NAME,
"getMonitorStatsById"
);
2025-04-20 11:29:53 -07:00
/**
* Get hardware details for a specific monitor by ID
* @async
* @param {Express.Request} req - Express request object containing monitorId in params
* @param {Express.Response} res - Express response object
* @param {Express.NextFunction} next - Express next middleware function
* @returns {Promise<Express.Response>}
* @throws {Error} - Throws error if monitor not found or other database errors
*/
2025-07-24 15:06:46 -07:00
getHardwareDetailsById = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getHardwareDetailsByIdParamValidation.validateAsync(req.params);
await getHardwareDetailsByIdQueryValidation.validateAsync(req.query);
2025-07-21 13:58:01 -07:00
const monitorId = req?.params?.monitorId;
const dateRange = req?.query?.dateRange;
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const monitor = await this.monitorService.getHardwareDetailsById({
teamId,
monitorId,
dateRange,
});
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorGetByIdSuccess,
data: monitor,
});
},
SERVICE_NAME,
"getHardwareDetailsById"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getMonitorCertificate = this.asyncHandler(
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getCertificateParamValidation.validateAsync(req.params);
const { monitorId } = req.params;
const monitor = await this.db.getMonitorById(monitorId);
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
return res.success({
msg: this.stringService.monitorCertificate,
data: {
certificateDate: new Date(certificate.validTo),
},
});
},
SERVICE_NAME,
"getMonitorCertificate"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getMonitorById = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorByIdParamValidation.validateAsync(req.params);
await getMonitorByIdQueryValidation.validateAsync(req.query);
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const monitor = await this.monitorService.getMonitorById({ teamId, monitorId: req?.params?.monitorId });
2025-07-21 13:58:01 -07:00
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorGetByIdSuccess,
data: monitor,
});
},
SERVICE_NAME,
"getMonitorById"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
createMonitor = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await createMonitorBodyValidation.validateAsync(req.body);
2025-07-24 13:50:21 -07:00
const userId = req?.user?._id;
const teamId = req?.user?.teamId;
const monitor = await this.monitorService.createMonitor({ teamId, userId, body: req.body });
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorCreate,
data: monitor,
});
},
SERVICE_NAME,
"createMonitor"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
createBulkMonitors = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
if (!req.file) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("No file uploaded");
}
if (!req.file.mimetype.includes("csv")) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("File is not a CSV");
}
if (req.file.size === 0) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("File is empty");
}
2025-07-24 13:50:21 -07:00
const userId = req?.user?._id;
const teamId = req?.user?.teamId;
2025-07-24 13:50:21 -07:00
if (!userId || !teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Missing userId or teamId");
}
2025-07-24 13:50:21 -07:00
const fileData = req?.file?.buffer?.toString("utf-8");
if (!fileData) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Cannot get file from buffer");
2025-07-24 13:50:21 -07:00
}
const monitors = await this.monitorService.createBulkMonitors({ fileData, userId, teamId });
2025-04-20 11:29:53 -07:00
return res.success({
2025-07-24 13:50:21 -07:00
msg: this.stringService.bulkMonitorsCreate,
data: monitors,
2025-04-20 11:29:53 -07:00
});
},
SERVICE_NAME,
2025-07-24 13:50:21 -07:00
"createBulkMonitors"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
deleteMonitor = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorByIdParamValidation.validateAsync(req.params);
const monitorId = req.params.monitorId;
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const deletedMonitor = await this.monitorService.deleteMonitor({ teamId, monitorId });
2025-07-21 13:58:01 -07:00
2025-07-24 13:50:21 -07:00
return res.success({ msg: this.stringService.monitorDelete, data: deletedMonitor });
},
SERVICE_NAME,
"deleteMonitor"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
deleteAllMonitors = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
2025-07-24 13:50:21 -07:00
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-24 13:50:21 -07:00
}
const deletedCount = await this.monitorService.deleteAllMonitors({ teamId });
2025-04-20 11:29:53 -07:00
return res.success({ msg: `Deleted ${deletedCount} monitors` });
},
SERVICE_NAME,
"deleteAllMonitors"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
editMonitor = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorByIdParamValidation.validateAsync(req.params);
await editMonitorBodyValidation.validateAsync(req.body);
2025-07-21 13:58:01 -07:00
const monitorId = req?.params?.monitorId;
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const editedMonitor = await this.monitorService.editMonitor({ teamId, monitorId, body: req.body });
2025-06-08 08:41:42 +08:00
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorEdit,
data: editedMonitor,
});
},
SERVICE_NAME,
"editMonitor"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
pauseMonitor = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await pauseMonitorParamValidation.validateAsync(req.params);
const monitorId = req.params.monitorId;
2025-07-21 13:58:01 -07:00
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-21 13:58:01 -07:00
}
2025-07-24 13:50:21 -07:00
const monitor = await this.monitorService.pauseMonitor({ teamId, monitorId });
2025-04-20 11:29:53 -07:00
return res.success({
2025-07-21 10:34:16 -07:00
msg: monitor.isActive ? this.stringService.monitorResume : this.stringService.monitorPause,
2025-04-20 11:29:53 -07:00
data: monitor,
});
},
SERVICE_NAME,
"pauseMonitor"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
addDemoMonitors = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
const { _id, teamId } = req.user;
2025-07-24 13:50:21 -07:00
const demoMonitors = await this.monitorService.addDemoMonitors({ userId: _id, teamId });
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorDemoAdded,
2025-07-24 13:50:21 -07:00
data: demoMonitors?.length ?? 0,
2025-04-20 11:29:53 -07:00
});
},
SERVICE_NAME,
"addDemoMonitors"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
sendTestEmail = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-05-06 00:08:11 +05:30
const { to } = req.body;
if (!to || typeof to !== "string") {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError(this.stringService.errorForValidEmailAddress);
2025-05-06 00:08:11 +05:30
}
2025-07-24 13:50:21 -07:00
const messageId = await this.monitorService.sendTestEmail({ to });
2025-05-06 00:08:11 +05:30
return res.success({
2025-05-06 00:27:27 +05:30
msg: this.stringService.sendTestEmail,
2025-05-06 00:08:11 +05:30
data: { messageId },
});
},
SERVICE_NAME,
"sendTestEmail"
);
2025-05-06 00:08:11 +05:30
2025-07-24 15:06:46 -07:00
getMonitorsByTeamId = this.asyncHandler(
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorsByTeamIdParamValidation.validateAsync(req.params);
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
let { limit, type, page, rowsPerPage, filter, field, order } = req.query;
2025-07-24 13:50:21 -07:00
const teamId = req?.user?.teamId;
const monitors = await this.monitorService.getMonitorsByTeamId({ teamId, limit, type, page, rowsPerPage, filter, field, order });
2025-04-20 11:29:53 -07:00
return res.success({
msg: this.stringService.monitorGetByTeamId,
data: monitors,
});
},
SERVICE_NAME,
"getMonitorsByTeamId"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getMonitorsAndSummaryByTeamId = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorsByTeamIdParamValidation.validateAsync(req.params);
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
2025-07-24 13:50:21 -07:00
const explain = req?.query?.explain;
const type = req?.query?.type;
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-24 13:50:21 -07:00
}
const result = await this.monitorService.getMonitorsAndSummaryByTeamId({ teamId, type, explain });
2025-04-20 11:29:53 -07:00
return res.success({
msg: "OK", // TODO
data: result,
});
},
SERVICE_NAME,
"getMonitorsAndSummaryByTeamId"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
getMonitorsWithChecksByTeamId = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
2025-04-20 11:29:53 -07:00
await getMonitorsByTeamIdParamValidation.validateAsync(req.params);
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
2025-07-24 13:50:21 -07:00
const explain = req?.query?.explain;
let { limit, type, page, rowsPerPage, filter, field, order } = req.query;
2025-07-24 13:50:21 -07:00
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-07-24 13:50:21 -07:00
}
2025-07-24 13:50:21 -07:00
const monitors = await this.monitorService.getMonitorsWithChecksByTeamId({
teamId,
limit,
type,
page,
rowsPerPage,
filter,
field,
order,
explain,
});
2025-07-24 13:50:21 -07:00
2025-04-20 11:29:53 -07:00
return res.success({
2025-06-18 01:07:22 +05:30
msg: "OK",
2025-07-24 13:50:21 -07:00
data: monitors,
2025-04-20 11:29:53 -07:00
});
},
SERVICE_NAME,
"getMonitorsWithChecksByTeamId"
);
2025-04-20 11:29:53 -07:00
2025-07-24 15:06:46 -07:00
exportMonitorsToCSV = this.asyncHandler(
2025-07-24 13:50:21 -07:00
async (req, res) => {
const teamId = req?.user?.teamId;
if (!teamId) {
2025-07-24 15:06:46 -07:00
throw this.errorService.createBadRequestError("Team ID is required");
2025-06-18 01:07:22 +05:30
}
2025-07-24 13:50:21 -07:00
const csv = await this.monitorService.exportMonitorsToCSV({ teamId });
2025-06-17 00:11:33 +05:30
return res.file({
2025-06-18 01:07:22 +05:30
data: csv,
headers: {
"Content-Type": "text/csv",
"Content-Disposition": "attachment; filename=monitors.csv",
},
});
},
SERVICE_NAME,
"exportMonitorsToCSV"
);
2025-04-20 11:29:53 -07:00
}
export default MonitorController;