diff --git a/server/.github/pull_request_template.md b/server/.github/pull_request_template.md index ed81cc04b..4f4da5d80 100755 --- a/server/.github/pull_request_template.md +++ b/server/.github/pull_request_template.md @@ -1,23 +1,25 @@ -**(Please remove this line only before submitting your PR. Ensure that all relevant items are checked before submission.)** +**(Please remove this line only before submitting your PR. Ensure that all relevant items are checked before submission.)** ## Describe your changes -Briefly describe the changes you made and their purpose. +Briefly describe the changes you made and their purpose. ## Write your issue number after "Fixes " -Fixes #123 +Fixes #123 ## Please ensure all items are checked off before requesting a review. "Checked off" means you need to add an "x" character between brackets so they turn into checkmarks. - [ ] (Do not skip this or your PR will be closed) I deployed the application locally. - [ ] (Do not skip this or your PR will be closed) I have performed a self-review and testing of my code. - [ ] I have included the issue # in the PR. -- [ ] I have added i18n support to visible strings (instead of `
Add
`, use): +- [ ] I have added i18n support to visible strings (instead of `
Add
`, use): + ```Javascript const { t } = useTranslation();
{t('add')}
``` + - [ ] The issue I am working on is assigned to me. - [ ] I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application). - [ ] My PR is granular and targeted to one specific feature. diff --git a/server/README.md b/server/README.md index 03f1b1629..db609cb02 100755 --- a/server/README.md +++ b/server/README.md @@ -2,7 +2,7 @@

The backend service for Checkmate, an open source uptime and infrastructure monitoring application

-This directory contains the **backend** of Checkmate, which handles data processing, storage, and API services for the Checkmate monitoring tool. The backend is responsible for managing uptime checks, handling real-time alerts, and storing historical monitoring data. +This directory contains the **backend** of Checkmate, which handles data processing, storage, and API services for the Checkmate monitoring tool. The backend is responsible for managing uptime checks, handling real-time alerts, and storing historical monitoring data. Checkmate's backend is designed to be lightweight and scalable, ensuring reliable performance even with a high number of active monitors. diff --git a/server/controllers/notificationController.js b/server/controllers/notificationController.js index 3682821eb..3164a111b 100755 --- a/server/controllers/notificationController.js +++ b/server/controllers/notificationController.js @@ -4,171 +4,171 @@ import { handleError, handleValidationError } from "./controllerUtils.js"; const SERVICE_NAME = "NotificationController"; const NOTIFICATION_TYPES = { - WEBHOOK: 'webhook', - TELEGRAM: 'telegram' + WEBHOOK: "webhook", + TELEGRAM: "telegram", }; const PLATFORMS = { - SLACK: 'slack', - DISCORD: 'discord', - TELEGRAM: 'telegram' + SLACK: "slack", + DISCORD: "discord", + TELEGRAM: "telegram", }; class NotificationController { - constructor(notificationService, stringService, statusService) { - this.notificationService = notificationService; - this.stringService = stringService; - this.statusService = statusService; - this.triggerNotification = this.triggerNotification.bind(this); - this.testWebhook = this.testWebhook.bind(this); - } + constructor(notificationService, stringService, statusService) { + this.notificationService = notificationService; + this.stringService = stringService; + this.statusService = statusService; + this.triggerNotification = this.triggerNotification.bind(this); + this.testWebhook = this.testWebhook.bind(this); + } - async triggerNotification(req, res, next) { - try { - await triggerNotificationBodyValidation.validateAsync(req.body, { - abortEarly: false, - stripUnknown: true, - }); - } catch (error) { - next(handleValidationError(error, SERVICE_NAME)); - return; - } + async triggerNotification(req, res, next) { + try { + await triggerNotificationBodyValidation.validateAsync(req.body, { + abortEarly: false, + stripUnknown: true, + }); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } - try { - const { monitorId, type, platform, config, status = false } = req.body; + try { + const { monitorId, type, platform, config, status = false } = req.body; - // Create a simplified networkResponse similar to what would come from monitoring - const networkResponse = { - monitorId, - status - }; - - // Use the statusService to get monitor details and handle status change logic - // This returns { monitor, statusChanged, prevStatus } exactly like your job queue uses - const statusResult = await this.statusService.updateStatus(networkResponse); - - if (type === NOTIFICATION_TYPES.WEBHOOK) { - const notification = { - type, - platform, - config, - }; + // Create a simplified networkResponse similar to what would come from monitoring + const networkResponse = { + monitorId, + status, + }; - await this.notificationService.sendWebhookNotification( - statusResult, // Contains monitor, statusChanged, and prevStatus - notification - ); - } + // Use the statusService to get monitor details and handle status change logic + // This returns { monitor, statusChanged, prevStatus } exactly like your job queue uses + const statusResult = await this.statusService.updateStatus(networkResponse); - return res.success({ - msg: this.stringService.webhookSendSuccess, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "triggerNotification")); - } - } + if (type === NOTIFICATION_TYPES.WEBHOOK) { + const notification = { + type, + platform, + config, + }; - createTestNetworkResponse() { - return { - monitor: { - _id: "test-monitor-id", - name: "Test Monitor", - url: "https://example.com" - }, - status: true, - statusChanged: true, - prevStatus: false, - }; - } + await this.notificationService.sendWebhookNotification( + statusResult, // Contains monitor, statusChanged, and prevStatus + notification + ); + } - handleTelegramTest(botToken, chatId) { - if (!botToken || !chatId) { - return { - isValid: false, - error: { - msg: this.stringService.telegramRequiresBotTokenAndChatId, - status: 400 - } - }; - } + return res.success({ + msg: this.stringService.webhookSendSuccess, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "triggerNotification")); + } + } - return { - isValid: true, - notification: { - type: NOTIFICATION_TYPES.WEBHOOK, - platform: PLATFORMS.TELEGRAM, - config: { botToken, chatId } - } - }; - } + createTestNetworkResponse() { + return { + monitor: { + _id: "test-monitor-id", + name: "Test Monitor", + url: "https://example.com", + }, + status: true, + statusChanged: true, + prevStatus: false, + }; + } - handleWebhookTest(webhookUrl, platform) { - if (webhookUrl === null) { - return { - isValid: false, - error: { - msg: this.stringService.webhookUrlRequired, - status: 400 - } - }; - } + handleTelegramTest(botToken, chatId) { + if (!botToken || !chatId) { + return { + isValid: false, + error: { + msg: this.stringService.telegramRequiresBotTokenAndChatId, + status: 400, + }, + }; + } - return { - isValid: true, - notification: { - type: NOTIFICATION_TYPES.WEBHOOK, - platform: platform, - config: { webhookUrl } - } - }; - } + return { + isValid: true, + notification: { + type: NOTIFICATION_TYPES.WEBHOOK, + platform: PLATFORMS.TELEGRAM, + config: { botToken, chatId }, + }, + }; + } - async testWebhook(req, res, next) { - try { - const { webhookUrl, platform, botToken, chatId } = req.body; + handleWebhookTest(webhookUrl, platform) { + if (webhookUrl === null) { + return { + isValid: false, + error: { + msg: this.stringService.webhookUrlRequired, + status: 400, + }, + }; + } - if (platform === null) { - return res.error({ - msg: this.stringService.platformRequired, - status: 400 - }); - } - - // Platform-specific handling - const platformHandlers = { - [PLATFORMS.TELEGRAM]: () => this.handleTelegramTest(botToken, chatId), - // Default handler for webhook-based platforms (Slack, Discord, etc.) - default: () => this.handleWebhookTest(webhookUrl, platform) - }; - - const handler = platformHandlers[platform] || platformHandlers.default; - const handlerResult = handler(); - - if (!handlerResult.isValid) { - return res.error(handlerResult.error); - } - - const networkResponse = this.createTestNetworkResponse(); - - const result = await this.notificationService.sendWebhookNotification( - networkResponse, - handlerResult.notification - ); - - if (result && result !== false) { - return res.success({ - msg: this.stringService.webhookSendSuccess, - }); - } else { - return res.error({ - msg: this.stringService.testNotificationFailed, - status: 400 - }); - } - } catch (error) { - next(handleError(error, SERVICE_NAME, "testWebhook")); - } - } + return { + isValid: true, + notification: { + type: NOTIFICATION_TYPES.WEBHOOK, + platform: platform, + config: { webhookUrl }, + }, + }; + } + + async testWebhook(req, res, next) { + try { + const { webhookUrl, platform, botToken, chatId } = req.body; + + if (platform === null) { + return res.error({ + msg: this.stringService.platformRequired, + status: 400, + }); + } + + // Platform-specific handling + const platformHandlers = { + [PLATFORMS.TELEGRAM]: () => this.handleTelegramTest(botToken, chatId), + // Default handler for webhook-based platforms (Slack, Discord, etc.) + default: () => this.handleWebhookTest(webhookUrl, platform), + }; + + const handler = platformHandlers[platform] || platformHandlers.default; + const handlerResult = handler(); + + if (!handlerResult.isValid) { + return res.error(handlerResult.error); + } + + const networkResponse = this.createTestNetworkResponse(); + + const result = await this.notificationService.sendWebhookNotification( + networkResponse, + handlerResult.notification + ); + + if (result && result !== false) { + return res.success({ + msg: this.stringService.webhookSendSuccess, + }); + } else { + return res.error({ + msg: this.stringService.testNotificationFailed, + status: 400, + }); + } + } catch (error) { + next(handleError(error, SERVICE_NAME, "testWebhook")); + } + } } -export default NotificationController; \ No newline at end of file +export default NotificationController; diff --git a/server/db/models/Notification.js b/server/db/models/Notification.js index 43eb73c93..ab51e0617 100755 --- a/server/db/models/Notification.js +++ b/server/db/models/Notification.js @@ -20,9 +20,9 @@ const NotificationSchema = mongoose.Schema( type: String, enum: ["email", "sms", "webhook"], }, - platform: { + platform: { type: String, - }, + }, config: { type: configSchema, default: () => ({}), diff --git a/server/db/mongo/modules/statusPageModule.js b/server/db/mongo/modules/statusPageModule.js index e5c88eecb..e06e50a5d 100755 --- a/server/db/mongo/modules/statusPageModule.js +++ b/server/db/mongo/modules/statusPageModule.js @@ -38,7 +38,7 @@ const updateStatusPage = async (statusPageData, image) => { data: image.buffer, contentType: image.mimetype, }; - }else{ + } else { statusPageData.logo = null; } diff --git a/server/routes/notificationRoute.js b/server/routes/notificationRoute.js index 7ea94843e..2c0bbf5b7 100755 --- a/server/routes/notificationRoute.js +++ b/server/routes/notificationRoute.js @@ -2,29 +2,23 @@ import { Router } from "express"; import { verifyJWT } from "../middleware/verifyJWT.js"; class NotificationRoutes { - constructor(notificationController) { - this.router = Router(); - this.notificationController = notificationController; - this.initializeRoutes(); - } + constructor(notificationController) { + this.router = Router(); + this.notificationController = notificationController; + this.initializeRoutes(); + } - initializeRoutes() { - this.router.use(verifyJWT); - - this.router.post( - "/trigger", - this.notificationController.triggerNotification - ); - - this.router.post( - "/test-webhook", - this.notificationController.testWebhook - ); - } + initializeRoutes() { + this.router.use(verifyJWT); - getRouter() { - return this.router; - } + this.router.post("/trigger", this.notificationController.triggerNotification); + + this.router.post("/test-webhook", this.notificationController.testWebhook); + } + + getRouter() { + return this.router; + } } -export default NotificationRoutes; \ No newline at end of file +export default NotificationRoutes; diff --git a/server/templates/testEmailTemplate.mjml b/server/templates/testEmailTemplate.mjml index e9fd3221e..4f8fd7644 100644 --- a/server/templates/testEmailTemplate.mjml +++ b/server/templates/testEmailTemplate.mjml @@ -1,17 +1,26 @@ - - - - - Hello! - - - This is a test email from the Monitoring System. - - - If you're receiving this, your email configuration is working correctly. - - - - + + + + + Hello! + + + This is a test email from the Monitoring System. + + + If you're receiving this, your email configuration is working correctly. + + + +