From c83a89d308f19085d9efa8df1ed7a6a52578224e Mon Sep 17 00:00:00 2001 From: nmemmert <67961292+nmemmert@users.noreply.github.com> Date: Wed, 10 Dec 2025 11:03:40 -0500 Subject: [PATCH] Keep notification settings in sync without restart --- server/index.js | 27 ++++++++++++++++++ server/notificationService.js | 53 ++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/server/index.js b/server/index.js index 29a339c..218e24d 100644 --- a/server/index.js +++ b/server/index.js @@ -6,6 +6,7 @@ require('dotenv').config(); const db = require('./database'); const scheduler = require('./scheduler'); const monitorService = require('./monitorService'); +const notificationService = require('./notificationService'); const app = express(); const PORT = process.env.PORT || 3001; @@ -181,6 +182,32 @@ TIMEOUT=${timeout} try { fs.writeFileSync(envPath, envContent); + + // Keep runtime config in sync without requiring a restart + process.env.EMAIL_ENABLED = String(email_enabled); + process.env.EMAIL_HOST = email_host; + process.env.EMAIL_PORT = String(email_port); + process.env.EMAIL_USER = email_user; + process.env.EMAIL_PASS = email_pass || process.env.EMAIL_PASS || ''; + process.env.EMAIL_FROM = email_from; + process.env.EMAIL_TO = email_to; + process.env.WEBHOOK_ENABLED = String(webhook_enabled); + process.env.WEBHOOK_URL = webhook_url; + process.env.CHECK_INTERVAL = String(check_interval); + process.env.TIMEOUT = String(timeout); + + notificationService.setConfig({ + email_enabled: email_enabled === true || email_enabled === 'true', + email_host, + email_port, + email_user, + email_pass: email_pass || process.env.EMAIL_PASS || '', + email_from, + email_to, + webhook_enabled: webhook_enabled === true || webhook_enabled === 'true', + webhook_url, + }); + res.json({ message: 'Settings saved successfully' }); } catch (error) { console.error('Error saving settings:', error); diff --git a/server/notificationService.js b/server/notificationService.js index 81a38e7..4a3a0b4 100644 --- a/server/notificationService.js +++ b/server/notificationService.js @@ -4,19 +4,47 @@ require('dotenv').config(); class NotificationService { constructor() { - this.emailEnabled = process.env.EMAIL_ENABLED === 'true'; - this.webhookEnabled = process.env.WEBHOOK_ENABLED === 'true'; + this.applyConfigFromEnv(); + } - if (this.emailEnabled) { + applyConfigFromEnv() { + this.setConfig({ + email_enabled: process.env.EMAIL_ENABLED === 'true', + email_host: process.env.EMAIL_HOST, + email_port: parseInt(process.env.EMAIL_PORT), + email_user: process.env.EMAIL_USER, + email_pass: process.env.EMAIL_PASS, + email_from: process.env.EMAIL_FROM, + email_to: process.env.EMAIL_TO, + webhook_enabled: process.env.WEBHOOK_ENABLED === 'true', + webhook_url: process.env.WEBHOOK_URL, + }); + } + + setConfig(config) { + this.emailEnabled = !!config.email_enabled; + this.webhookEnabled = !!config.webhook_enabled; + this.config = config; + + // Recreate transporter when email config changes; skip if incomplete + if ( + this.emailEnabled && + config.email_host && + config.email_port && + config.email_user && + config.email_pass + ) { this.transporter = nodemailer.createTransport({ - host: process.env.EMAIL_HOST, - port: parseInt(process.env.EMAIL_PORT), + host: config.email_host, + port: parseInt(config.email_port), secure: false, auth: { - user: process.env.EMAIL_USER, - pass: process.env.EMAIL_PASS, + user: config.email_user, + pass: config.email_pass, }, }); + } else { + this.transporter = null; } } @@ -39,10 +67,15 @@ class NotificationService { } async sendEmail(resource, message, type) { + if (!this.transporter) { + console.error('Email config incomplete; skipping email'); + return; + } + try { await this.transporter.sendMail({ - from: process.env.EMAIL_FROM, - to: process.env.EMAIL_TO, + from: this.config.email_from, + to: this.config.email_to, subject: `Alert: ${resource.name} is ${type === 'started' ? 'DOWN' : 'UP'}`, text: message, }); @@ -54,7 +87,7 @@ class NotificationService { async sendWebhook(resource, message, type) { try { - await axios.post(process.env.WEBHOOK_URL, { + await axios.post(this.config.webhook_url || process.env.WEBHOOK_URL, { resource: resource.name, url: resource.url, status: type === 'started' ? 'down' : 'up',