mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-07 09:09:48 -05:00
266 lines
7.1 KiB
JavaScript
266 lines
7.1 KiB
JavaScript
import { createMonitorsBodyValidation } from "../../validation/joi.js";
|
|
import { createServerError } from "../../utils/errorUtils.js";
|
|
import logger from "../../utils/logger.js";
|
|
|
|
const SERVICE_NAME = "MonitorService";
|
|
class MonitorService {
|
|
SERVICE_NAME = SERVICE_NAME;
|
|
|
|
constructor({ db, settingsService, jobQueue, stringService, emailService, papaparse }) {
|
|
this.db = db;
|
|
this.settingsService = settingsService;
|
|
this.jobQueue = jobQueue;
|
|
this.stringService = stringService;
|
|
this.emailService = emailService;
|
|
this.papaparse = papaparse;
|
|
this.logger = logger;
|
|
}
|
|
|
|
verifyTeamAccess = async ({ teamId, monitorId }) => {
|
|
const monitor = await this.db.getMonitorById(monitorId);
|
|
if (!monitor?.teamId?.equals(teamId)) {
|
|
const error = new Error("Unauthorized");
|
|
error.status = 403;
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
getAllMonitors = async () => {
|
|
const monitors = await this.db.getAllMonitors();
|
|
return monitors;
|
|
};
|
|
|
|
getUptimeDetailsById = async ({ teamId, monitorId, dateRange, normalize }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const data = await this.db.getUptimeDetailsById({
|
|
monitorId,
|
|
dateRange,
|
|
normalize,
|
|
});
|
|
|
|
return data;
|
|
};
|
|
|
|
getMonitorStatsById = async ({ teamId, monitorId, limit, sortOrder, dateRange, numToDisplay, normalize }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const monitorStats = await this.db.getMonitorStatsById({
|
|
monitorId,
|
|
limit,
|
|
sortOrder,
|
|
dateRange,
|
|
numToDisplay,
|
|
normalize,
|
|
});
|
|
|
|
return monitorStats;
|
|
};
|
|
|
|
getHardwareDetailsById = async ({ teamId, monitorId, dateRange }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const monitor = await this.db.getHardwareDetailsById({ monitorId, dateRange });
|
|
|
|
return monitor;
|
|
};
|
|
|
|
getMonitorById = async ({ teamId, monitorId }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const monitor = await this.db.getMonitorById(monitorId);
|
|
|
|
return monitor;
|
|
};
|
|
|
|
createMonitor = async ({ teamId, userId, body }) => {
|
|
const monitor = await this.db.createMonitor({
|
|
body,
|
|
teamId,
|
|
userId,
|
|
});
|
|
|
|
this.jobQueue.addJob(monitor._id, monitor);
|
|
};
|
|
|
|
createBulkMonitors = async ({ fileData, userId, teamId }) => {
|
|
const { parse } = this.papaparse;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
parse(fileData, {
|
|
header: true,
|
|
skipEmptyLines: true,
|
|
transform: (value, header) => {
|
|
if (value === "") return undefined; // Empty fields become undefined
|
|
|
|
// Handle 'port' and 'interval' fields, check if they're valid numbers
|
|
if (["port", "interval"].includes(header)) {
|
|
const num = parseInt(value, 10);
|
|
if (isNaN(num)) {
|
|
throw new Error(`${header} should be a valid number, got: ${value}`);
|
|
}
|
|
return num;
|
|
}
|
|
|
|
return value;
|
|
},
|
|
complete: async ({ data, errors }) => {
|
|
try {
|
|
if (errors.length > 0) {
|
|
throw createServerError("Error parsing CSV");
|
|
}
|
|
|
|
if (!data || data.length === 0) {
|
|
throw createServerError("CSV file contains no data rows");
|
|
}
|
|
|
|
const enrichedData = data.map((monitor) => ({
|
|
userId,
|
|
teamId,
|
|
...monitor,
|
|
description: monitor.description || monitor.name || monitor.url,
|
|
name: monitor.name || monitor.url,
|
|
type: monitor.type || "http",
|
|
}));
|
|
|
|
await createMonitorsBodyValidation.validateAsync(enrichedData);
|
|
|
|
const monitors = await this.db.createBulkMonitors(enrichedData);
|
|
|
|
await Promise.all(
|
|
monitors.map(async (monitor) => {
|
|
this.jobQueue.addJob(monitor._id, monitor);
|
|
})
|
|
);
|
|
|
|
resolve(monitors);
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
},
|
|
});
|
|
});
|
|
};
|
|
|
|
deleteMonitor = async ({ teamId, monitorId }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const monitor = await this.db.deleteMonitor({ teamId, monitorId });
|
|
await this.jobQueue.deleteJob(monitor);
|
|
await this.db.deleteStatusPagesByMonitorId(monitor._id);
|
|
return monitor;
|
|
};
|
|
|
|
deleteAllMonitors = async ({ teamId }) => {
|
|
const { monitors, deletedCount } = await this.db.deleteAllMonitors(teamId);
|
|
await Promise.all(
|
|
monitors.map(async (monitor) => {
|
|
try {
|
|
await this.jobQueue.deleteJob(monitor);
|
|
await this.db.deleteChecks(monitor._id);
|
|
await this.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
|
await this.db.deleteNotificationsByMonitorId(monitor._id);
|
|
} catch (error) {
|
|
logger.warn({
|
|
message: `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
|
service: SERVICE_NAME,
|
|
method: "deleteAllMonitors",
|
|
stack: error.stack,
|
|
});
|
|
}
|
|
})
|
|
);
|
|
return deletedCount;
|
|
};
|
|
|
|
editMonitor = async ({ teamId, monitorId, body }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const editedMonitor = await this.db.editMonitor({ monitorId, body });
|
|
await this.jobQueue.updateJob(editedMonitor);
|
|
};
|
|
|
|
pauseMonitor = async ({ teamId, monitorId }) => {
|
|
await this.verifyTeamAccess({ teamId, monitorId });
|
|
const monitor = await this.db.pauseMonitor({ monitorId });
|
|
monitor.isActive === true ? await this.jobQueue.resumeJob(monitor._id, monitor) : await this.jobQueue.pauseJob(monitor);
|
|
return monitor;
|
|
};
|
|
|
|
addDemoMonitors = async ({ userId, teamId }) => {
|
|
const demoMonitors = await this.db.addDemoMonitors(userId, teamId);
|
|
await Promise.all(demoMonitors.map((monitor) => this.jobQueue.addJob(monitor._id, monitor)));
|
|
return demoMonitors;
|
|
};
|
|
|
|
sendTestEmail = async ({ to }) => {
|
|
const subject = this.stringService.testEmailSubject;
|
|
const context = { testName: "Monitoring System" };
|
|
|
|
const html = await this.emailService.buildEmail("testEmailTemplate", context);
|
|
const messageId = await this.emailService.sendEmail(to, subject, html);
|
|
|
|
if (!messageId) {
|
|
throw createServerError("Failed to send test email.");
|
|
}
|
|
|
|
return messageId;
|
|
};
|
|
|
|
getMonitorsByTeamId = async ({ teamId, limit, type, page, rowsPerPage, filter, field, order }) => {
|
|
const monitors = await this.db.getMonitorsByTeamId({
|
|
limit,
|
|
type,
|
|
page,
|
|
rowsPerPage,
|
|
filter,
|
|
field,
|
|
order,
|
|
teamId,
|
|
});
|
|
return monitors;
|
|
};
|
|
|
|
getMonitorsAndSummaryByTeamId = async ({ teamId, type, explain }) => {
|
|
const result = await this.db.getMonitorsAndSummaryByTeamId({
|
|
type,
|
|
explain,
|
|
teamId,
|
|
});
|
|
return result;
|
|
};
|
|
|
|
getMonitorsWithChecksByTeamId = async ({ teamId, limit, type, page, rowsPerPage, filter, field, order, explain }) => {
|
|
const result = await this.db.getMonitorsWithChecksByTeamId({
|
|
limit,
|
|
type,
|
|
page,
|
|
rowsPerPage,
|
|
filter,
|
|
field,
|
|
order,
|
|
teamId,
|
|
explain,
|
|
});
|
|
return result;
|
|
};
|
|
|
|
exportMonitorsToCSV = async ({ teamId }) => {
|
|
const monitors = await this.monitorService.getMonitorsByTeamId({ teamId });
|
|
|
|
if (!monitors || monitors.length === 0) {
|
|
throw new Error("No monitors to export");
|
|
}
|
|
|
|
const csvData = monitors?.filteredMonitors?.map((monitor) => ({
|
|
name: monitor.name,
|
|
description: monitor.description,
|
|
type: monitor.type,
|
|
url: monitor.url,
|
|
interval: monitor.interval,
|
|
port: monitor.port,
|
|
ignoreTlsErrors: monitor.ignoreTlsErrors,
|
|
isActive: monitor.isActive,
|
|
}));
|
|
|
|
const csv = this.papaparse.unparse(csvData);
|
|
return csv;
|
|
};
|
|
}
|
|
|
|
export default MonitorService;
|