From 56a4b21401f1df35cef7fd8bd352a1ff53a1dc74 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 22 Oct 2024 11:39:47 +0800 Subject: [PATCH 01/40] remove forgotten console.log --- Server/tests/services/settingsService.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Server/tests/services/settingsService.test.js b/Server/tests/services/settingsService.test.js index 3060758f7..0835bcf00 100644 --- a/Server/tests/services/settingsService.test.js +++ b/Server/tests/services/settingsService.test.js @@ -84,7 +84,6 @@ describe("SettingsService", () => { try { await settingsService.loadSettings(); } catch (error) { - console.log(error); expect(error.message).to.equal("Test error"); expect(error.service).to.equal("OTHER_SERVICE"); expect(error.method).to.equal("otherMethod"); From 3f90bb1d0f5f4a59e545ab00fc50e08fb6d02ba5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 22 Oct 2024 15:26:38 +0800 Subject: [PATCH 02/40] Inject dependencies for JobQueue --- Server/index.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Server/index.js b/Server/index.js index 68a6c354a..3f4ef91ba 100644 --- a/Server/index.js +++ b/Server/index.js @@ -19,7 +19,10 @@ import { fileURLToPath } from "url"; import { connectDbAndRunServer } from "./configs/db.js"; import queueRouter from "./routes/queueRoute.js"; + +//JobQueue service and dependencies import JobQueue from "./service/jobQueue.js"; +import { Queue, Worker } from "bullmq"; //Network service and dependencies import NetworkService from "./service/networkService.js"; @@ -36,7 +39,7 @@ import mjml2html from "mjml"; // Settings Service and dependencies import SettingsService from "./service/settingsService.js"; -import AppSettings from "../db/models/AppSettings.js"; +import AppSettings from "./db/models/AppSettings.js"; import db from "./db/mongo/MongoDB.js"; const SERVICE_NAME = "Server"; @@ -157,7 +160,14 @@ const startApp = async () => { logger ); const networkService = new NetworkService(db, emailService, axios, ping, logger, http); - const jobQueue = await JobQueue.createJobQueue(db, networkService, settingsService); + const jobQueue = await JobQueue.createJobQueue( + db, + networkService, + settingsService, + logger, + Queue, + Worker + ); const cleanup = async () => { if (cleaningUp) { From fc85d2b794485d1d98811eb4b00134314520b140 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 22 Oct 2024 15:26:55 +0800 Subject: [PATCH 03/40] Minor refactor in worker loop for clarity --- Server/service/jobQueue.js | 64 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/Server/service/jobQueue.js b/Server/service/jobQueue.js index f8493911e..0eea10c49 100644 --- a/Server/service/jobQueue.js +++ b/Server/service/jobQueue.js @@ -1,8 +1,5 @@ -import { Queue, Worker, Job } from "bullmq"; const QUEUE_NAME = "monitors"; - const JOBS_PER_WORKER = 5; -import logger from "../utils/logger.js"; import { errorMessages, successMessages } from "../utils/messages.js"; const SERVICE_NAME = "JobQueue"; /** @@ -19,11 +16,13 @@ class JobQueue { * @param {SettingsService} settingsService - The settings service * @throws {Error} */ - constructor(settingsService) { - const { redisHost, redisPort } = settingsService.getSettings(); + constructor(settingsService, logger, Queue, Worker) { + const settings = settingsService.getSettings() || {}; + + const { redisHost = "127.0.0.1", redisPort = 6379 } = settings; const connection = { - host: redisHost || "127.0.0.1", - port: redisPort || 6379, + host: redisHost, + port: redisPort, }; this.connection = connection; this.queue = new Queue(QUEUE_NAME, { @@ -33,6 +32,8 @@ class JobQueue { this.db = null; this.networkService = null; this.settingsService = settingsService; + this.logger = logger; + this.Worker = Worker; } /** @@ -42,8 +43,15 @@ class JobQueue { * @returns {Promise} - Returns a new JobQueue * */ - static async createJobQueue(db, networkService, settingsService) { - const queue = new JobQueue(settingsService); + static async createJobQueue( + db, + networkService, + settingsService, + logger, + Queue, + Worker + ) { + const queue = new JobQueue(settingsService, logger, Queue, Worker); try { queue.db = db; queue.networkService = networkService; @@ -69,7 +77,7 @@ class JobQueue { * @returns {Worker} The newly created worker */ createWorker() { - const worker = new Worker( + const worker = new this.Worker( QUEUE_NAME, async (job) => { try { @@ -96,17 +104,16 @@ class JobQueue { } return acc; }, false); - if (!maintenanceWindowActive) { await this.networkService.getStatus(job); } else { - logger.info(`Monitor ${monitorId} is in maintenance window`, { + this.logger.info(`Monitor ${monitorId} is in maintenance window`, { service: SERVICE_NAME, monitorId, }); } } catch (error) { - logger.error(`Error processing job ${job.id}: ${error.message}`, { + this.logger.error(`Error processing job ${job.id}: ${error.message}`, { service: SERVICE_NAME, jobId: job.id, error: error, @@ -169,11 +176,9 @@ class JobQueue { } return true; } - if (workerStats.load > JOBS_PER_WORKER) { // Find out how many more jobs we have than current workers can handle const excessJobs = workerStats.jobs.length - this.workers.length * JOBS_PER_WORKER; - // Divide by jobs/worker to find out how many workers to add const workersToAdd = Math.ceil(excessJobs / JOBS_PER_WORKER); for (let i = 0; i < workersToAdd; i++) { @@ -188,18 +193,17 @@ class JobQueue { const workerCapacity = this.workers.length * JOBS_PER_WORKER; const excessCapacity = workerCapacity - workerStats.jobs.length; // Calculate how many workers to remove - const workersToRemove = Math.floor(excessCapacity / JOBS_PER_WORKER); - if (this.workers.length > 5) { - for (let i = 0; i < workersToRemove; i++) { - const worker = this.workers.pop(); - try { - await worker.close(); - } catch (error) { - // Catch the error instead of throwing it - logger.error(errorMessages.JOB_QUEUE_WORKER_CLOSE, { - service: SERVICE_NAME, - }); - } + let workersToRemove = Math.floor(excessCapacity / JOBS_PER_WORKER); // Make sure there are always at least 5 + while (workersToRemove > 0 && this.workers.length > 5) { + const worker = this.workers.pop(); + workersToRemove--; + try { + await worker.close(); + } catch (error) { + // Catch the error instead of throwing it + this.logger.error(errorMessages.JOB_QUEUE_WORKER_CLOSE, { + service: SERVICE_NAME, + }); } } return true; @@ -282,14 +286,14 @@ class JobQueue { every: monitor.interval, }); if (deleted) { - logger.info(successMessages.JOB_QUEUE_DELETE_JOB, { + this.logger.info(successMessages.JOB_QUEUE_DELETE_JOB, { service: SERVICE_NAME, jobId: monitor.id, }); const workerStats = await this.getWorkerStats(); await this.scaleWorkers(workerStats); } else { - logger.error(errorMessages.JOB_QUEUE_DELETE_JOB, { + this.logger.error(errorMessages.JOB_QUEUE_DELETE_JOB, { service: SERVICE_NAME, jobId: monitor.id, }); @@ -313,7 +317,7 @@ class JobQueue { }; return metrics; } catch (error) { - logger.error("Failed to retrieve job queue metrics", { + this.logger.error("Failed to retrieve job queue metrics", { service: SERVICE_NAME, errorMsg: error.message, }); From 0005b195b1c97d1a9c49a114465a4bdcb3b2da01 Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Tue, 22 Oct 2024 09:31:00 -0400 Subject: [PATCH 04/40] - update based review --- Client/src/Validation/validation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index a6ec7688c..8978f5ffa 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -152,8 +152,8 @@ const advancedSettingsValidation = joi.object({ "string.empty": "Redis host is required", }), redisPort: joi.string().allow('').custom((value, helpers) => { - if(value && isNaN(parseInt(value))){ - return helpers.message("Redit port must be a number") + if(value && Number.isNaN(parseInt(value))){ + return helpers.message("Redis port must be a number") } return value }), From 4966f3fd38e43960e2e6d3fbea78afb205c08883 Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Tue, 22 Oct 2024 14:15:11 -0400 Subject: [PATCH 05/40] - Update jwt ttl validation --- Client/src/Pages/AdvancedSettings/index.jsx | 26 ++++++++++- .../Maintenance/CreateMaintenance/index.jsx | 27 ++---------- Client/src/Validation/validation.js | 44 ++++++++++++------- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index ce1c89250..b71123ca7 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -12,6 +12,8 @@ import { useNavigate } from "react-router"; import { getAppSettings, updateAppSettings } from "../../Features/Settings/settingsSlice"; import { useState, useEffect } from "react"; import Select from "../../Components/Inputs/Select"; +import { advancedSettingsValidation } from "../../Validation/validation"; +import { buildErrors, hasValidationErrors } from "../../Validation/error"; const AdvancedSettings = ({ isAdmin }) => { const navigate = useNavigate(); @@ -21,7 +23,7 @@ const AdvancedSettings = ({ isAdmin }) => { navigate("/"); } }, [navigate, isAdmin]); - + const [errors, setErrors] = useState({}); const theme = useTheme(); const { authToken } = useSelector((state) => state.auth); const dispatch = useDispatch(); @@ -75,9 +77,20 @@ const AdvancedSettings = ({ isAdmin }) => { const handleChange = (event) => { const { value, id } = event.target; setLocalSettings({ ...localSettings, [id]: value }); + const { error } = advancedSettingsValidation.validate( + { [id]: value }, + { + abortEarly: false, + } + ); + setErrors((prev) => { + return buildErrors(prev, id, error); + }); }; const handleSave = async () => { + if (hasValidationErrors(localSettings, advancedSettingsValidation, setErrors)) + return; const action = await dispatch( updateAppSettings({ settings: localSettings, authToken }) ); @@ -118,6 +131,7 @@ const AdvancedSettings = ({ isAdmin }) => { label="API URL Host" value={localSettings.apiBaseUrl} onChange={handleChange} + error={errors.apiBaseUrl} /> { items={logItems} value={logItemLookup[localSettings.logLevel]} onChange={handleLogLevel} + onBlur={handleBlur} error={errors.logLevel} /> @@ -160,6 +167,7 @@ const AdvancedSettings = ({ isAdmin }) => { name="systemEmailHost" value={localSettings.systemEmailHost} onChange={handleChange} + onBlur={handleBlur} error={errors.systemEmailHost} /> { name="systemEmailPort" value={localSettings.systemEmailPort.toString()} onChange={handleChange} + onBlur={handleBlur} error={errors.systemEmailPort} /> { name="systemEmailPassword" value={localSettings.systemEmailPassword} onChange={handleChange} + onBlur={handleBlur} error={errors.systemEmailPassword} /> @@ -206,6 +216,7 @@ const AdvancedSettings = ({ isAdmin }) => { name="jwtTTL" value={localSettings.jwtTTL} onChange={handleChange} + onBlur={handleBlur} error={errors.jwtTTL} /> { name="dbType" value={localSettings.dbType} onChange={handleChange} + onBlur={handleBlur} error={errors.dbType} /> { name="redisHost" value={localSettings.redisHost} onChange={handleChange} + onBlur={handleBlur} error={errors.redisHost} /> { name="redisPort" value={localSettings.redisPort.toString()} onChange={handleChange} + onBlur={handleBlur} error={errors.redisPort} /> { name="pagespeedApiKey" value={localSettings.pagespeedApiKey} onChange={handleChange} + onBlur={handleBlur} error={errors.pagespeedApiKey} /> diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index a5c0e029f..83f94db4e 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -147,7 +147,7 @@ const advancedSettingsValidation = joi.object({ .custom((value, helpers) => { // test against regx start with a number followed by number or ., //ends with d or h - const regex = /^[1-9]+\d*(.)*(d|h)$/; + const regex = /^[1-9]+\d*(d|h)$/; const found = value.match(regex); if (!found) { return helpers.message( From a4344b89a23692d4d7cb2a534b90d99044d5ae24 Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Wed, 23 Oct 2024 21:03:40 -0400 Subject: [PATCH 17/40] - Add select dropdown for jwt ttl units --- Client/src/Pages/AdvancedSettings/index.jsx | 43 +++++++++++++++++---- Client/src/Validation/validation.js | 20 ++++------ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index d5ac22b26..836722db6 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -36,6 +36,7 @@ const AdvancedSettings = ({ isAdmin }) => { systemEmailAddress: "", systemEmailPassword: "", jwtTTL: "", + jwtTTLUnits: "days", dbType: "", redisHost: "", redisPort: "", @@ -68,12 +69,30 @@ const AdvancedSettings = ({ isAdmin }) => { warn: 4, }; + const unitItems = [ + { _id: 1, name: "days" }, + { _id: 2, name: "weeks" }, + { _id: 3, name: "months" } + ]; + + const unitItemLookup = { + days: 1, + weeks: 2, + months: 3, + }; + const handleLogLevel = (e) => { const id = e.target.value; const newLogLevel = logItems.find((item) => item._id === id).name; setLocalSettings({ ...localSettings, logLevel: newLogLevel }); }; + const handleJWTTTLUnits = (e) => { + const id = e.target.value; + const newUnits = unitItems.find((item) => item._id === id).name; + setLocalSettings({ ...localSettings, jwtTTLUnits: newUnits }); + }; + const handleBlur = (event) => { const { value, id } = event.target; const { error } = advancedSettingsValidation.validate( @@ -82,11 +101,9 @@ const AdvancedSettings = ({ isAdmin }) => { abortEarly: false, } ); - if (error) { - setErrors((prev) => { - return buildErrors(prev, id, error); - }); - } + setErrors((prev) => { + return buildErrors(prev, id, error); + }); }; const handleChange = (event) => { const { value, id } = event.target; @@ -209,8 +226,8 @@ const AdvancedSettings = ({ isAdmin }) => { - { onBlur={handleBlur} error={errors.jwtTTL} /> + { value={unitItemLookup[localSettings.jwtTTLUnits]} onChange={handleJWTTTLUnits} onBlur={handleBlur} - error={errors.jwtttlUnits} + error={errors.jwtTTLUnits} /> { if (error) { const newErrors = {}; error.details.forEach((err) => { - newErrors[err.path[0]] = err.message?? "Validation error"; + if ( + ![ + "clientHost", + "refreshTokenSecret", + "dbConnectionString", + "refreshTokenTTL", + "jwtTTL", + ].includes(err.path[0]) + ) { + newErrors[err.path[0]] = err.message ?? "Validation error"; + } }); - setErrors(newErrors); - return true; + if (Object.keys(newErrors).length > 0) { + setErrors(newErrors); + return true; + } else return false; } return false; }; diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index 43f3904b9..dfdacd3b1 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -138,18 +138,20 @@ const advancedSettingsValidation = joi.object({ systemEmailPort: joi.string().allow(""), systemEmailAddress: joi.string().allow(""), systemEmailPassword: joi.string().allow(""), - jwtTTL: joi.string().trim().messages({ - "string.empty": "JWT TTL is required.", - }), + jwtTTLNum: joi + .number() + .messages({ + "any.required": "JWT TTL is required.", + }), jwtTTLUnits: joi .string() .trim() .custom((value, helpers) => { - if (value == 0) { + if( !["days", "hours"].includes(value)) { return helpers.message("JWT TTL unit is required."); } return value; - }), + }), dbType: joi.string().trim().messages({ "string.empty": "DB type is required.", }), From 410f3b7ab1e8abf8bb01f723f6dfcf45b8383c8c Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Thu, 24 Oct 2024 13:33:05 -0400 Subject: [PATCH 27/40] - updated js doc --- guides/users-guide/server-settings.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/guides/users-guide/server-settings.md b/guides/users-guide/server-settings.md index 6276f3c42..ae1380dff 100644 --- a/guides/users-guide/server-settings.md +++ b/guides/users-guide/server-settings.md @@ -26,10 +26,12 @@ Here you can setup the following: **Email settings:** Set your host email settings here. These settings are used for sending system emails. -Server settings: Several server settings can be done here. Alternatively, you can add a pagespeed API key to bypass Google's limitations (albeit they are generous about it) +**Server settings:** Several server settings can be done here. Alternatively, you can add a pagespeed API key to bypass Google's limitations (albeit they are generous about it) + +Select a number for jwt TTL and a unit for it (days or hours), the combined result +would be in vercel/ms time format, e.g "99d", this will be sent to server to persist -\ From 67f158a5173697af32f6dbba497613299c3e2662 Mon Sep 17 00:00:00 2001 From: Khadeeja Date: Thu, 24 Oct 2024 21:52:04 +0400 Subject: [PATCH 28/40] Add link to logo --- Client/src/Components/Sidebar/index.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Client/src/Components/Sidebar/index.jsx b/Client/src/Components/Sidebar/index.jsx index d4e7c9fd2..9135dcefa 100644 --- a/Client/src/Components/Sidebar/index.jsx +++ b/Client/src/Components/Sidebar/index.jsx @@ -181,6 +181,8 @@ function Sidebar() { direction="row" alignItems="center" gap={theme.spacing(4)} + onClick={() => window.open("https://github.com/bluewave-labs/bluewave-uptime", "_blank", "noreferrer")} + sx={{ cursor: "pointer" }} > Date: Thu, 24 Oct 2024 14:13:07 -0400 Subject: [PATCH 29/40] - update number validation --- Client/src/Validation/validation.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index dfdacd3b1..71495cfa1 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -138,20 +138,18 @@ const advancedSettingsValidation = joi.object({ systemEmailPort: joi.string().allow(""), systemEmailAddress: joi.string().allow(""), systemEmailPassword: joi.string().allow(""), - jwtTTLNum: joi - .number() - .messages({ - "any.required": "JWT TTL is required.", - }), + jwtTTLNum: joi.number().messages({ + "number.base": "JWT TTL is required.", + }), jwtTTLUnits: joi .string() .trim() .custom((value, helpers) => { - if( !["days", "hours"].includes(value)) { + if (!["days", "hours"].includes(value)) { return helpers.message("JWT TTL unit is required."); } return value; - }), + }), dbType: joi.string().trim().messages({ "string.empty": "DB type is required.", }), From 1526b50fd2044ca2df035c6f0a41eaab0e3c56c2 Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Thu, 24 Oct 2024 14:40:04 -0400 Subject: [PATCH 30/40] - update unitItems with lookup --- Client/src/Pages/AdvancedSettings/index.jsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index 853817544..3f04653cb 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -81,15 +81,14 @@ const AdvancedSettings = ({ isAdmin }) => { warn: 4, }; - const unitItems = [ - { _id: "d", name: "days" }, - { _id: "h", name: "hours" } - ]; - const unitItemLookup = { days: "d", hours: "h", }; + const unitItems = Object.keys(unitItemLookup).map((key) => ({ + _id: unitItemLookup[key], + name: key, + })); const handleLogLevel = (e) => { const id = e.target.value; From 9f190c540b3c4b85a1666f4c29f7ce122a820542 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 24 Oct 2024 22:46:29 +0000 Subject: [PATCH 31/40] chore(deps): update dependency eslint-plugin-react-refresh to v0.4.14 --- Client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Client/package-lock.json b/Client/package-lock.json index 40e2c8be6..29d019536 100644 --- a/Client/package-lock.json +++ b/Client/package-lock.json @@ -3568,9 +3568,9 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.13.tgz", - "integrity": "sha512-f1EppwrpJRWmqDTyvAyomFVDYRtrS7iTEqv3nokETnMiMzs2SSTmKRTACce4O2p4jYyowiSMvpdwC/RLcMFhuQ==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.14.tgz", + "integrity": "sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==", "dev": true, "license": "MIT", "peerDependencies": { From 5d9b8bf0515fecc68d04ada8dc8ee3a24121a085 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 25 Oct 2024 09:58:11 +0800 Subject: [PATCH 32/40] remove some testing code accidentally committed --- Client/src/App.jsx | 15 --------------- Client/src/Features/Settings/settingsSlice.js | 1 - Client/src/Utils/NetworkService.js | 1 - 3 files changed, 17 deletions(-) diff --git a/Client/src/App.jsx b/Client/src/App.jsx index ed97b67f9..001758713 100644 --- a/Client/src/App.jsx +++ b/Client/src/App.jsx @@ -66,21 +66,6 @@ function App() { }; }, []); - useEffect(() => { - const thing = async () => { - const action = await dispatch( - updateAppSettings({ authToken, settings: { apiBaseUrl: "test" } }) - ); - - if (action.payload.success) { - console.log(action.payload.data); - } else { - console.log(action); - } - }; - thing(); - }, [dispatch, authToken]); - return ( diff --git a/Client/src/Features/Settings/settingsSlice.js b/Client/src/Features/Settings/settingsSlice.js index e5cd6e8b8..283a8502d 100644 --- a/Client/src/Features/Settings/settingsSlice.js +++ b/Client/src/Features/Settings/settingsSlice.js @@ -49,7 +49,6 @@ export const updateAppSettings = createAsyncThunk( systemEmailAddress: settings.systemEmailAddress, systemEmailPassword: settings.systemEmailPassword, }; - console.log(parsedSettings); const res = await networkService.updateAppSettings({ settings: parsedSettings, authToken, diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js index 287cba4b4..71cbe9670 100644 --- a/Client/src/Utils/NetworkService.js +++ b/Client/src/Utils/NetworkService.js @@ -13,7 +13,6 @@ class NetworkService { this.setBaseUrl(baseURL); this.unsubscribe = store.subscribe(() => { const state = store.getState(); - console.log(state.settings.apiBaseUrl); if (BASE_URL !== undefined) { baseURL = BASE_URL; } else if (state?.settings?.apiBaseUrl ?? null) { From 70872c368d2739a56f2b08ca33ebfc0fe5088310 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 25 Oct 2024 10:48:37 +0800 Subject: [PATCH 33/40] Add status to hardware check model --- Server/db/models/HardwareCheck.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/db/models/HardwareCheck.js b/Server/db/models/HardwareCheck.js index 8ff615ec6..5e7f53329 100644 --- a/Server/db/models/HardwareCheck.js +++ b/Server/db/models/HardwareCheck.js @@ -37,6 +37,10 @@ const HardwareCheckSchema = mongoose.Schema( ref: "Monitor", immutable: true, }, + status: { + type: Boolean, + index: true, + }, cpu: { type: cpuSchema, default: () => ({}), From 50c6e32d6e1b6130f70e35fbbf01adf3b3b8bb03 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 25 Oct 2024 10:49:08 +0800 Subject: [PATCH 34/40] Fix variable assignment in --- Server/service/networkService.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Server/service/networkService.js b/Server/service/networkService.js index 2fa470df1..157a29006 100644 --- a/Server/service/networkService.js +++ b/Server/service/networkService.js @@ -104,8 +104,7 @@ class NetworkService { monitor: monitor, template: isAlive === true ? "serverIsUpTemplate" : "serverIsDownTemplate", context: { monitorName: monitor.name, monitorUrl: monitor.url }, - subject: - (subject = `Monitor ${monitor.name} is ${isAlive === true ? "up" : "down"}`), + subject: `Monitor ${monitor.name} is ${isAlive === true ? "up" : "down"}`, }; this.handleNotification(config); } From 2427bdb78804732071a288e4d69c54f43bae804f Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Fri, 25 Oct 2024 10:00:10 -0400 Subject: [PATCH 35/40] - Fix the wrong label --- Client/src/Pages/AdvancedSettings/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index 3f04653cb..bfcc66a8b 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -202,7 +202,7 @@ const AdvancedSettings = ({ isAdmin }) => { Date: Fri, 25 Oct 2024 15:52:32 +0000 Subject: [PATCH 36/40] fix(deps): update material-ui monorepo to v7.22.0 --- Client/package-lock.json | 22 +++++++++++----------- Client/package.json | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Client/package-lock.json b/Client/package-lock.json index 29d019536..c2790af71 100644 --- a/Client/package-lock.json +++ b/Client/package-lock.json @@ -15,8 +15,8 @@ "@mui/lab": "^5.0.0-alpha.170", "@mui/material": "^5.15.16", "@mui/x-charts": "^7.5.1", - "@mui/x-data-grid": "7.21.0", - "@mui/x-date-pickers": "7.21.0", + "@mui/x-data-grid": "7.22.0", + "@mui/x-date-pickers": "7.22.0", "@reduxjs/toolkit": "2.3.0", "axios": "^1.7.4", "chart.js": "^4.4.3", @@ -1400,9 +1400,9 @@ } }, "node_modules/@mui/x-charts": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.21.0.tgz", - "integrity": "sha512-Qv7U1Koo7hxinn1ncbn+Yfcwd8h3bSJDVCpjyKKgO0247kGIAK4ecrBlFHwVLol4bNTY36Ir1prEaA0G1MmUrg==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.22.0.tgz", + "integrity": "sha512-B70ix8keyww9CpfdwbsHygQGsgEySCXuHhGrDRiVyFgK+Be4edBWNswbL3ngIp37CHBbWegaYkPp/Q9GDas0AA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.7", @@ -1458,9 +1458,9 @@ } }, "node_modules/@mui/x-data-grid": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.21.0.tgz", - "integrity": "sha512-0JAiwb2yRuVAd4idzfA64Bs1yn6KfC8VPBH7Njba0ySQB0+Ix+hvkzWQySD96hl7tK5heXbvbJ48pYLvhqS4Vw==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.22.0.tgz", + "integrity": "sha512-gXl7+hG0YRNU3YODlPvz6Q/9+EeUsPAWn/u2YMQmYTgwAxeY5QE3lY224VRnwM5v9SfTFheo1kzAKmXPdjb9tQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.7", @@ -1495,9 +1495,9 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.21.0.tgz", - "integrity": "sha512-WLpuTu3PvhYwd7IAJSuDWr1Zd8c5C8Cc7rpAYCaV5+tGBoEP0C2UKqClMR4F1wTiU2a7x3dzgQzkcgK72yyqDw==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.22.0.tgz", + "integrity": "sha512-hopYo3ORP7ddYKnyBsqAtO2txEe2Zf6cehdikS5b1cqMTGOSL+18b11jfGVod9oipjb9L2JcT/WWkjoifs9Iww==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.7", diff --git a/Client/package.json b/Client/package.json index 2aa5fb463..44d796143 100644 --- a/Client/package.json +++ b/Client/package.json @@ -17,8 +17,8 @@ "@mui/lab": "^5.0.0-alpha.170", "@mui/material": "^5.15.16", "@mui/x-charts": "^7.5.1", - "@mui/x-data-grid": "7.21.0", - "@mui/x-date-pickers": "7.21.0", + "@mui/x-data-grid": "7.22.0", + "@mui/x-date-pickers": "7.22.0", "@reduxjs/toolkit": "2.3.0", "axios": "^1.7.4", "chart.js": "^4.4.3", From a823bd9372167532602dca84cdd738277bcd0083 Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Fri, 25 Oct 2024 14:27:11 -0400 Subject: [PATCH 37/40] - change joi to be optional number for redis port and email port --- Client/src/Validation/validation.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index 71495cfa1..08b1632c3 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -135,7 +135,7 @@ const advancedSettingsValidation = joi.object({ }), logLevel: joi.string().valid("debug", "none", "error", "warn").allow(""), systemEmailHost: joi.string().allow(""), - systemEmailPort: joi.string().allow(""), + systemEmailPort: joi.number().allow(null, ""), systemEmailAddress: joi.string().allow(""), systemEmailPassword: joi.string().allow(""), jwtTTLNum: joi.number().messages({ @@ -156,15 +156,7 @@ const advancedSettingsValidation = joi.object({ redisHost: joi.string().trim().messages({ "string.empty": "Redis host is required.", }), - redisPort: joi - .string() - .allow("") - .custom((value, helpers) => { - if (value && Number.isNaN(parseInt(value))) { - return helpers.message("Redis port must be a number."); - } - return value; - }), + redisPort: joi.number().allow(null, ""), pagespeedApiKey: joi.string().allow(""), }); From 39e8ad4308ce37a74c3424b20da5f631b2f0dedc Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Fri, 25 Oct 2024 14:37:43 -0400 Subject: [PATCH 38/40] - Fix empty port number case --- Client/src/Pages/AdvancedSettings/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index bfcc66a8b..bc9affad6 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -204,7 +204,7 @@ const AdvancedSettings = ({ isAdmin }) => { id="systemEmailPort" label="System email port" name="systemEmailPort" - value={localSettings.systemEmailPort.toString()} + value={localSettings.systemEmailPort?.toString()} onChange={handleChange} onBlur={handleBlur} error={errors.systemEmailPort} @@ -285,7 +285,7 @@ const AdvancedSettings = ({ isAdmin }) => { id="redisPort" label="Redis port" name="redisPort" - value={localSettings.redisPort.toString()} + value={localSettings.redisPort?.toString()} onChange={handleChange} onBlur={handleBlur} error={errors.redisPort} From f3e33d1ebd9796c1a2ebb1710af4e909059a8fd7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 18:43:47 +0000 Subject: [PATCH 39/40] fix(deps): update dependency mongoose to v8.7.3 --- Server/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/package-lock.json b/Server/package-lock.json index 46faaa3e0..73f2316c8 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -4369,9 +4369,9 @@ } }, "node_modules/mongoose": { - "version": "8.7.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.2.tgz", - "integrity": "sha512-Ok4VzMds9p5G3ZSUhmvBm1GdxanbzhS29jpSn02SPj+IXEVFnIdfwAlHHXWkyNscZKlcn8GuMi68FH++jo0flg==", + "version": "8.7.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.3.tgz", + "integrity": "sha512-Xl6+dzU5ZpEcDoJ8/AyrIdAwTY099QwpolvV73PIytpK13XqwllLq/9XeVzzLEQgmyvwBVGVgjmMrKbuezxrIA==", "license": "MIT", "dependencies": { "bson": "^6.7.0", From f61cb275ffd2a3c2f2897be7ef620c1762e325f7 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Sat, 26 Oct 2024 09:36:15 +0800 Subject: [PATCH 40/40] email host -> System email host --- Client/src/Pages/AdvancedSettings/index.jsx | 61 +++++++++++---------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/Client/src/Pages/AdvancedSettings/index.jsx b/Client/src/Pages/AdvancedSettings/index.jsx index bc9affad6..a830159b8 100644 --- a/Client/src/Pages/AdvancedSettings/index.jsx +++ b/Client/src/Pages/AdvancedSettings/index.jsx @@ -58,7 +58,7 @@ const AdvancedSettings = ({ isAdmin }) => { const getSettings = async () => { const action = await dispatch(getAppSettings({ authToken })); if (action.payload.success) { - parseJWTTTL(action.payload.data) + parseJWTTTL(action.payload.data); setLocalSettings(action.payload.data); } else { createToast({ body: "Failed to get settings" }); @@ -100,7 +100,7 @@ const AdvancedSettings = ({ isAdmin }) => { const id = e.target.value; const newUnits = unitItems.find((item) => item._id === id).name; setLocalSettings({ ...localSettings, jwtTTLUnits: newUnits }); - }; + }; const handleBlur = (event) => { const { value, id } = event.target; @@ -116,7 +116,7 @@ const AdvancedSettings = ({ isAdmin }) => { }; const handleChange = (event) => { const { value, id } = event.target; - setLocalSettings({ ...localSettings, [id]: value }); + setLocalSettings({ ...localSettings, [id]: value }); }; const handleSave = async () => { @@ -125,12 +125,12 @@ const AdvancedSettings = ({ isAdmin }) => { if (hasValidationErrors(localSettings, advancedSettingsValidation, setErrors)) { return; } - const action = await dispatch( + const action = await dispatch( updateAppSettings({ settings: localSettings, authToken }) ); let body = ""; if (action.payload.success) { - parseJWTTTL(action.payload.data) + parseJWTTTL(action.payload.data); setLocalSettings(action.payload.data); body = "Settings saved successfully"; } else { @@ -192,7 +192,7 @@ const AdvancedSettings = ({ isAdmin }) => { { - - +