From 8409571d57b4824a60a9edf069ec6396cd5e5b94 Mon Sep 17 00:00:00 2001 From: Skorpios Date: Sun, 16 Feb 2025 19:32:52 -0800 Subject: [PATCH] Defined new schema for the config object. --- Server/controllers/notificationController.js | 19 +++++---- Server/db/models/Notification.js | 15 ++++--- Server/service/notificationService.js | 28 ++++++------- Server/validation/joi.js | 44 +++++++++++++------- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/Server/controllers/notificationController.js b/Server/controllers/notificationController.js index 362b5b381..cdb49b90d 100644 --- a/Server/controllers/notificationController.js +++ b/Server/controllers/notificationController.js @@ -1,13 +1,12 @@ - class NotificationController { constructor(notificationService) { this.notificationService = notificationService; this.triggerNotification = this.triggerNotification.bind(this); } - async triggerNotification(req, res, next) { + async triggerNotification(req, res, next) { try { - const { monitorId, type, config } = req.body; + const { monitorId, type, platform, config } = req.body; const networkResponse = { monitor: { _id: monitorId, name: "Test Monitor", url: "http://www.google.com" }, @@ -15,18 +14,24 @@ class NotificationController { statusChanged: true, prevStatus: true, }; - + if (type === "webhook") { + const notification = { + type, + platform, + config + }; + await this.notificationService.sendWebhookNotification( networkResponse, - config + notification ); } - + return res.success({ msg: "Notification sent successfully" }); - + } catch (error) { error.service = "NotificationController"; error.method = "triggerNotification"; diff --git a/Server/db/models/Notification.js b/Server/db/models/Notification.js index 7d684bbc1..53d9eb4a2 100644 --- a/Server/db/models/Notification.js +++ b/Server/db/models/Notification.js @@ -1,4 +1,11 @@ import mongoose from "mongoose"; + +const configSchema = mongoose.Schema({ + webhookUrl: { type: String }, + botToken: { type: String }, + chatId: { type: String } +}, { _id: false }); + const NotificationSchema = mongoose.Schema( { monitorId: { @@ -11,11 +18,9 @@ const NotificationSchema = mongoose.Schema( enum: ["email", "sms", "webhook"], }, config: { - type: String, - webhookUrl: String, - botToken: String, - chatId: String - }, + type: configSchema, + default: () => ({}) + }, address: { type: String, }, diff --git a/Server/service/notificationService.js b/Server/service/notificationService.js index 1e0202d39..b182e273a 100644 --- a/Server/service/notificationService.js +++ b/Server/service/notificationService.js @@ -33,23 +33,24 @@ class NotificationService { return null; } - async sendWebhookNotification(networkResponse, config) { + async sendWebhookNotification(networkResponse, notification) { const { monitor, status } = networkResponse; - const { type, webhookUrl, botToken, chatId } = config; + const { platform } = notification; // Use platform instead of type for webhook formatting + const { webhookUrl, botToken, chatId } = notification.config; let url = webhookUrl; - const message = this.formatNotificationMessage(monitor, status, type, chatId); + const message = this.formatNotificationMessage(monitor, status, platform, chatId); if (message === null) { this.logger.warn({ - message: `Unsupported webhook type: ${type}`, + message: `Unsupported webhook platform: ${platform}`, service: this.SERVICE_NAME, method: 'sendWebhookNotification', - type + platform }); return false; } - if (type === 'telegram') { + if (platform === 'telegram') { if (!botToken || !chatId) { return false; } @@ -57,17 +58,17 @@ class NotificationService { } try { - const response = await this.networkService.requestWebhook(type, url, message); + const response = await this.networkService.requestWebhook(platform, url, message); return response.status; } catch (error) { this.logger.error({ - message: `Error sending ${type} notification`, + message: `Error sending ${platform} notification`, service: this.SERVICE_NAME, method: 'sendWebhookNotification', error: error.message, stack: error.stack, url, - type, + platform, requestPayload: message }); return false; @@ -115,7 +116,7 @@ class NotificationService { async handleStatusNotifications(networkResponse) { try { - //If status hasn't changed, we're done + // If status hasn't changed, we're done if (networkResponse.statusChanged === false) return false; // if prevStatus is undefined, monitor is resuming, we're done if (networkResponse.prevStatus === undefined) return false; @@ -124,13 +125,12 @@ class NotificationService { for (const notification of notifications) { if (notification.type === "email") { - this.sendEmail(networkResponse, notification.address); + await this.sendEmail(networkResponse, notification.address); } else if (notification.type === "webhook") { - this.sendWebhookNotification(networkResponse, notification.address, notification.type); - + await this.sendWebhookNotification(networkResponse, notification); + } // Handle other types of notifications here } - } return true; } catch (error) { this.logger.warn({ diff --git a/Server/validation/joi.js b/Server/validation/joi.js index 565b62d26..1b285b0a5 100644 --- a/Server/validation/joi.js +++ b/Server/validation/joi.js @@ -476,7 +476,7 @@ const imageValidation = joi }); const telegramWebhookConfigValidation = joi.object({ - type: joi.string().valid('telegram').required(), + webhookUrl: joi.string().uri().optional(), botToken: joi.string().required().messages({ 'string.empty': 'Telegram bot token is required', 'any.required': 'Telegram bot token is required' @@ -488,21 +488,23 @@ const imageValidation = joi }); const discordWebhookConfigValidation = joi.object({ - type: joi.string().valid('discord').required(), webhookUrl: joi.string().uri().required().messages({ 'string.empty': 'Discord webhook URL is required', 'string.uri': 'Discord webhook URL must be a valid URL', 'any.required': 'Discord webhook URL is required' - }) + }), + botToken: joi.string().optional(), + chatId: joi.string().optional() }); const slackWebhookConfigValidation = joi.object({ - type: joi.string().valid('slack').required(), webhookUrl: joi.string().uri().required().messages({ 'string.empty': 'Slack webhook URL is required', 'string.uri': 'Slack webhook URL must be a valid URL', 'any.required': 'Slack webhook URL is required' - }) + }), + botToken: joi.string().optional(), + chatId: joi.string().optional() }); const triggerNotificationBodyValidation = joi.object({ @@ -515,16 +517,30 @@ const imageValidation = joi 'any.required': 'Notification type is required', 'any.only': 'Notification type must be webhook' }), + + platform: joi.string().valid('telegram', 'discord', 'slack').required().messages({ + 'string.empty': 'Platform type is required', + 'any.required': 'Platform type is required', + 'any.only': 'Platform must be telegram, discord, or slack' + }), config: joi.alternatives() - .conditional('type', { - is: 'webhook', - then: joi.alternatives().try( - telegramWebhookConfigValidation, - discordWebhookConfigValidation, - slackWebhookConfigValidation - ).required().messages({ - 'any.required': 'Webhook configuration is required' - }) + .conditional('platform', [ + { + is: 'telegram', + then: telegramWebhookConfigValidation + }, + { + is: 'discord', + then: discordWebhookConfigValidation + }, + { + is: 'slack', + then: slackWebhookConfigValidation + } + ]) + .required() + .messages({ + 'any.required': 'Webhook configuration is required' }) });