diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index 59ba2e243..665cfbaee 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -1,25 +1,28 @@ import { - getMonitorByIdParamValidation, - getMonitorByIdQueryValidation, - getMonitorsByTeamIdValidation, - createMonitorBodyValidation, - editMonitorBodyValidation, - getMonitorsAndSummaryByTeamIdParamValidation, - getMonitorsAndSummaryByTeamIdQueryValidation, - getMonitorsByTeamIdQueryValidation, - pauseMonitorParamValidation, - getMonitorStatsByIdParamValidation, - getMonitorStatsByIdQueryValidation, - getCertificateParamValidation, + getMonitorByIdParamValidation, + getMonitorByIdQueryValidation, + getMonitorsByTeamIdValidation, + createMonitorBodyValidation, + editMonitorBodyValidation, + getMonitorsAndSummaryByTeamIdParamValidation, + getMonitorsAndSummaryByTeamIdQueryValidation, + getMonitorsByTeamIdQueryValidation, + pauseMonitorParamValidation, + getMonitorStatsByIdParamValidation, + getMonitorStatsByIdQueryValidation, + getCertificateParamValidation, } from "../validation/joi.js"; -import sslChecker from "ssl-checker"; const SERVICE_NAME = "monitorController"; import { errorMessages, successMessages } from "../utils/messages.js"; import jwt from "jsonwebtoken"; import { getTokenFromHeaders } from "../utils/utils.js"; import logger from "../utils/logger.js"; -import { handleError, handleValidationError } from "./controllerUtils.js"; +import { + handleError, + handleValidationError, + fetchMonitorCertificate, +} from "./controllerUtils.js"; /** * Returns all monitors @@ -31,16 +34,16 @@ import { handleError, handleValidationError } from "./controllerUtils.js"; * @throws {Error} */ const getAllMonitors = async (req, res, next) => { - try { - const monitors = await req.db.getAllMonitors(); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_GET_ALL, - data: monitors, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getAllMonitors")); - } + try { + const monitors = await req.db.getAllMonitors(); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_GET_ALL, + data: monitors, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getAllMonitors")); + } }; /** @@ -53,56 +56,55 @@ const getAllMonitors = async (req, res, next) => { * @throws {Error} */ const getMonitorStatsById = async (req, res, next) => { - try { - await getMonitorStatsByIdParamValidation.validateAsync(req.params); - await getMonitorStatsByIdQueryValidation.validateAsync(req.query); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorStatsByIdParamValidation.validateAsync(req.params); + await getMonitorStatsByIdQueryValidation.validateAsync(req.query); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const monitorStats = await req.db.getMonitorStatsById(req); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_STATS_BY_ID, - data: monitorStats, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getMonitorStatsById")); - } + try { + const monitorStats = await req.db.getMonitorStatsById(req); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_STATS_BY_ID, + data: monitorStats, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMonitorStatsById")); + } }; const getMonitorCertificate = async (req, res, next) => { - try { - await getCertificateParamValidation.validateAsync(req.params); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - } + try { + await getCertificateParamValidation.validateAsync(req.params); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + } - try { - const { monitorId } = req.params; - const monitor = await req.db.getMonitorById(monitorId); - const monitorUrl = new URL(monitor.url); - const certificate = await sslChecker(monitorUrl.hostname); - if (certificate && certificate.validTo) { - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_CERTIFICATE, - data: { - certificateDate: new Date(certificate.validTo).toLocaleDateString(), - }, - }); - } else { - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_CERTIFICATE, - data: { certificateDate: "N/A" }, - }); - } - } catch (error) { - next(handleError(error, SERVICE_NAME, "getMonitorCertificate")); - } + try { + const { monitorId } = req.params; + const monitor = await req.db.getMonitorById(monitorId); + const certificate = await fetchMonitorCertificate(monitor); + if (certificate && certificate.validTo) { + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_CERTIFICATE, + data: { + certificateDate: new Date(certificate.validTo), + }, + }); + } else { + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_CERTIFICATE, + data: { certificateDate: "N/A" }, + }); + } + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMonitorCertificate")); + } }; /** @@ -117,30 +119,30 @@ const getMonitorCertificate = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if the monitor is not found (404) or if there is a validation error (422). */ const getMonitorById = async (req, res, next) => { - try { - await getMonitorByIdParamValidation.validateAsync(req.params); - await getMonitorByIdQueryValidation.validateAsync(req.query); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorByIdParamValidation.validateAsync(req.params); + await getMonitorByIdQueryValidation.validateAsync(req.query); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const monitor = await req.db.getMonitorById(req.params.monitorId); - if (!monitor) { - const error = new Error(errorMessages.MONITOR_GET_BY_ID); - error.status = 404; - throw error; - } + try { + const monitor = await req.db.getMonitorById(req.params.monitorId); + if (!monitor) { + const error = new Error(errorMessages.MONITOR_GET_BY_ID); + error.status = 404; + throw error; + } - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_GET_BY_ID, - data: monitor, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getMonitorById")); - } + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_GET_BY_ID, + data: monitor, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMonitorById")); + } }; /** @@ -157,31 +159,26 @@ const getMonitorById = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const getMonitorsAndSummaryByTeamId = async (req, res, next) => { - try { - await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync( - req.params - ); - await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync(req.params); + await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const { teamId } = req.params; - const { type } = req.query; - const monitorsSummary = await req.db.getMonitorsAndSummaryByTeamId( - teamId, - type - ); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_GET_BY_USER_ID(teamId), - data: monitorsSummary, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getMonitorsAndSummaryByTeamId")); - } + try { + const { teamId } = req.params; + const { type } = req.query; + const monitorsSummary = await req.db.getMonitorsAndSummaryByTeamId(teamId, type); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(teamId), + data: monitorsSummary, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMonitorsAndSummaryByTeamId")); + } }; /** @@ -197,26 +194,26 @@ const getMonitorsAndSummaryByTeamId = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const getMonitorsByTeamId = async (req, res, next) => { - try { - await getMonitorsByTeamIdValidation.validateAsync(req.params); - await getMonitorsByTeamIdQueryValidation.validateAsync(req.query); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorsByTeamIdValidation.validateAsync(req.params); + await getMonitorsByTeamIdQueryValidation.validateAsync(req.query); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const teamId = req.params.teamId; - const monitors = await req.db.getMonitorsByTeamId(req, res); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_GET_BY_USER_ID(teamId), - data: monitors, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getMonitorsByTeamId")); - next(error); - } + try { + const teamId = req.params.teamId; + const monitors = await req.db.getMonitorsByTeamId(req, res); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(teamId), + data: monitors, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMonitorsByTeamId")); + next(error); + } }; /** @@ -231,36 +228,36 @@ const getMonitorsByTeamId = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const createMonitor = async (req, res, next) => { - try { - await createMonitorBodyValidation.validateAsync(req.body); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await createMonitorBodyValidation.validateAsync(req.body); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const notifications = req.body.notifications; - const monitor = await req.db.createMonitor(req, res); + try { + const notifications = req.body.notifications; + const monitor = await req.db.createMonitor(req, res); - if (notifications && notifications.length !== 0) { - monitor.notifications = await Promise.all( - notifications.map(async (notification) => { - notification.monitorId = monitor._id; - await req.db.createNotification(notification); - }) - ); - await monitor.save(); - } - // Add monitor to job queue - req.jobQueue.addJob(monitor._id, monitor); - return res.status(201).json({ - success: true, - msg: successMessages.MONITOR_CREATE, - data: monitor, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "createMonitor")); - } + if (notifications && notifications.length !== 0) { + monitor.notifications = await Promise.all( + notifications.map(async (notification) => { + notification.monitorId = monitor._id; + await req.db.createNotification(notification); + }) + ); + await monitor.save(); + } + // Add monitor to job queue + req.jobQueue.addJob(monitor._id, monitor); + return res.status(201).json({ + success: true, + msg: successMessages.MONITOR_CREATE, + data: monitor, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "createMonitor")); + } }; /** @@ -275,37 +272,35 @@ const createMonitor = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422) or an error in deleting associated records. */ const deleteMonitor = async (req, res, next) => { - try { - await getMonitorByIdParamValidation.validateAsync(req.params); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorByIdParamValidation.validateAsync(req.params); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const monitor = await req.db.deleteMonitor(req, res, next); - // Delete associated checks,alerts,and notifications - try { - await req.jobQueue.deleteJob(monitor); - await req.db.deleteChecks(monitor._id); - await req.db.deletePageSpeedChecksByMonitorId(monitor._id); - await req.db.deleteNotificationsByMonitorId(monitor._id); - } catch (error) { - logger.error( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`, - { - method: "deleteMonitor", - service: SERVICE_NAME, - error: error.message, - } - ); - } - return res - .status(200) - .json({ success: true, msg: successMessages.MONITOR_DELETE }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "deleteMonitor")); - } + try { + const monitor = await req.db.deleteMonitor(req, res, next); + // Delete associated checks,alerts,and notifications + try { + await req.jobQueue.deleteJob(monitor); + await req.db.deleteChecks(monitor._id); + await req.db.deletePageSpeedChecksByMonitorId(monitor._id); + await req.db.deleteNotificationsByMonitorId(monitor._id); + } catch (error) { + logger.error( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`, + { + method: "deleteMonitor", + service: SERVICE_NAME, + error: error.message, + } + ); + } + return res.status(200).json({ success: true, msg: successMessages.MONITOR_DELETE }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "deleteMonitor")); + } }; /** @@ -320,34 +315,34 @@ const deleteMonitor = async (req, res, next) => { * @throws {Error} If there is an error during the deletion process. */ const deleteAllMonitors = async (req, res, next) => { - try { - const token = getTokenFromHeaders(req.headers); - const { jwtSecret } = req.settingsService.getSettings(); - const { teamId } = jwt.verify(token, jwtSecret); - const { monitors, deletedCount } = await req.db.deleteAllMonitors(teamId); - await Promise.all( - monitors.map(async (monitor) => { - try { - await req.jobQueue.deleteJob(monitor); - await req.db.deleteChecks(monitor._id); - await req.db.deletePageSpeedChecksByMonitorId(monitor._id); - await req.db.deleteNotificationsByMonitorId(monitor._id); - } catch (error) { - logger.error( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`, - { - method: "deleteAllMonitors", - } - ); - } - }) - ); - return res - .status(200) - .json({ success: true, msg: `Deleted ${deletedCount} monitors` }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "deleteAllMonitors")); - } + try { + const token = getTokenFromHeaders(req.headers); + const { jwtSecret } = req.settingsService.getSettings(); + const { teamId } = jwt.verify(token, jwtSecret); + const { monitors, deletedCount } = await req.db.deleteAllMonitors(teamId); + await Promise.all( + monitors.map(async (monitor) => { + try { + await req.jobQueue.deleteJob(monitor); + await req.db.deleteChecks(monitor._id); + await req.db.deletePageSpeedChecksByMonitorId(monitor._id); + await req.db.deleteNotificationsByMonitorId(monitor._id); + } catch (error) { + logger.error( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`, + { + method: "deleteAllMonitors", + } + ); + } + }) + ); + return res + .status(200) + .json({ success: true, msg: `Deleted ${deletedCount} monitors` }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "deleteAllMonitors")); + } }; /** @@ -364,46 +359,46 @@ const deleteAllMonitors = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const editMonitor = async (req, res, next) => { - try { - await getMonitorByIdParamValidation.validateAsync(req.params); - await editMonitorBodyValidation.validateAsync(req.body); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + try { + await getMonitorByIdParamValidation.validateAsync(req.params); + await editMonitorBodyValidation.validateAsync(req.body); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const { monitorId } = req.params; - const monitorBeforeEdit = await req.db.getMonitorById(monitorId); + try { + const { monitorId } = req.params; + const monitorBeforeEdit = await req.db.getMonitorById(monitorId); - // Get notifications from the request body - const notifications = req.body.notifications; + // Get notifications from the request body + const notifications = req.body.notifications; - const editedMonitor = await req.db.editMonitor(monitorId, req.body); + const editedMonitor = await req.db.editMonitor(monitorId, req.body); - await req.db.deleteNotificationsByMonitorId(editedMonitor._id); + await req.db.deleteNotificationsByMonitorId(editedMonitor._id); - if (notifications && notifications.length !== 0) { - await Promise.all( - notifications.map(async (notification) => { - notification.monitorId = editedMonitor._id; - await req.db.createNotification(notification); - }) - ); - } + if (notifications && notifications.length !== 0) { + await Promise.all( + notifications.map(async (notification) => { + notification.monitorId = editedMonitor._id; + await req.db.createNotification(notification); + }) + ); + } - // Delete the old job(editedMonitor has the same ID as the old monitor) - await req.jobQueue.deleteJob(monitorBeforeEdit); - // Add the new job back to the queue - await req.jobQueue.addJob(editedMonitor._id, editedMonitor); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_EDIT, - data: editedMonitor, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "editMonitor")); - } + // Delete the old job(editedMonitor has the same ID as the old monitor) + await req.jobQueue.deleteJob(monitorBeforeEdit); + // Add the new job back to the queue + await req.jobQueue.addJob(editedMonitor._id, editedMonitor); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_EDIT, + data: editedMonitor, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "editMonitor")); + } }; /** @@ -418,32 +413,32 @@ const editMonitor = async (req, res, next) => { * @throws {Error} If there is an error during the process. */ const pauseMonitor = async (req, res, next) => { - try { - await pauseMonitorParamValidation.validateAsync(req.params); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - } + try { + await pauseMonitorParamValidation.validateAsync(req.params); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + } - try { - const monitor = await req.db.getMonitorById(req.params.monitorId); - if (monitor.isActive) { - await req.jobQueue.deleteJob(monitor); - } else { - await req.jobQueue.addJob(monitor._id, monitor); - } - monitor.isActive = !monitor.isActive; - monitor.status = undefined; - monitor.save(); - return res.status(200).json({ - success: true, - msg: monitor.isActive - ? successMessages.MONITOR_RESUME - : successMessages.MONITOR_PAUSE, - data: monitor, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "pauseMonitor")); - } + try { + const monitor = await req.db.getMonitorById(req.params.monitorId); + if (monitor.isActive) { + await req.jobQueue.deleteJob(monitor); + } else { + await req.jobQueue.addJob(monitor._id, monitor); + } + monitor.isActive = !monitor.isActive; + monitor.status = undefined; + monitor.save(); + return res.status(200).json({ + success: true, + msg: monitor.isActive + ? successMessages.MONITOR_RESUME + : successMessages.MONITOR_PAUSE, + data: monitor, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "pauseMonitor")); + } }; /** @@ -458,36 +453,36 @@ const pauseMonitor = async (req, res, next) => { * @throws {Error} If there is an error during the process. */ const addDemoMonitors = async (req, res, next) => { - try { - const token = getTokenFromHeaders(req.headers); - const { jwtSecret } = req.settingsService.getSettings(); - const { _id, teamId } = jwt.verify(token, jwtSecret); - const demoMonitors = await req.db.addDemoMonitors(_id, teamId); - await Promise.all( - demoMonitors.map((monitor) => req.jobQueue.addJob(monitor._id, monitor)) - ); + try { + const token = getTokenFromHeaders(req.headers); + const { jwtSecret } = req.settingsService.getSettings(); + const { _id, teamId } = jwt.verify(token, jwtSecret); + const demoMonitors = await req.db.addDemoMonitors(_id, teamId); + await Promise.all( + demoMonitors.map((monitor) => req.jobQueue.addJob(monitor._id, monitor)) + ); - return res.status(200).json({ - success: true, - msg: successMessages.MONITOR_DEMO_ADDED, - data: demoMonitors.length, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "addDemoMonitors")); - } + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_DEMO_ADDED, + data: demoMonitors.length, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "addDemoMonitors")); + } }; export { - getAllMonitors, - getMonitorStatsById, - getMonitorCertificate, - getMonitorById, - getMonitorsAndSummaryByTeamId, - getMonitorsByTeamId, - createMonitor, - deleteMonitor, - deleteAllMonitors, - editMonitor, - pauseMonitor, - addDemoMonitors, + getAllMonitors, + getMonitorStatsById, + getMonitorCertificate, + getMonitorById, + getMonitorsAndSummaryByTeamId, + getMonitorsByTeamId, + createMonitor, + deleteMonitor, + deleteAllMonitors, + editMonitor, + pauseMonitor, + addDemoMonitors, };