From b85c760397c0235f853c099ad6564207834a70ff Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 01:21:09 +0200 Subject: [PATCH 01/23] Updated the client package.json --- client/package-lock.json | 4 ++-- client/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 1769b551..dab74278 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "client", - "version": "1.0.6", + "version": "1.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "client", - "version": "1.0.6", + "version": "1.0.7", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", diff --git a/client/package.json b/client/package.json index 795e8693..c995175c 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "client", - "version": "1.0.6", + "version": "1.0.7", "scripts": { "dev": "vite", "build": "vite build", From 6bd1ece523da10433ed82a57ee8792ebbea22cdb Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 01:21:24 +0200 Subject: [PATCH 02/23] Updated the server package.json --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b198c899..174905bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "myspeed", - "version": "1.0.6", + "version": "1.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "myspeed", - "version": "1.0.6", + "version": "1.0.7", "dependencies": { "axios": "^1.3.4", "bcrypt": "^5.1.0", diff --git a/package.json b/package.json index a7bfd9f9..bda240ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "myspeed", - "version": "1.0.6", + "version": "1.0.7", "scripts": { "client": "cd client && npm run dev", "server": "nodemon server", From 6f787e31a0010f137d6cdc4b81c1a212bd5ad76d Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 01:54:30 +0200 Subject: [PATCH 03/23] Fixed a bug in the export.js route --- server/routes/export.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/routes/export.js b/server/routes/export.js index beacbea3..32268e6b 100644 --- a/server/routes/export.js +++ b/server/routes/export.js @@ -10,6 +10,8 @@ app.get("/json", password(false), async (req, res) => { app.get("/csv", password(false), async (req, res) => { res.set({"Content-Disposition": "attachment; filename=\"speedtests.csv\""}); let list = await tests.list(); + + if (list.length === 0) return res.send(""); let fields = Object.keys(list[0]); let replacer = (key, value) => value === null ? '' : value; From 7c2c269e0148bc1c829332d6d9dfda4ff468023c Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 02:00:39 +0200 Subject: [PATCH 04/23] Added a check to the LatestTestComponent.jsx --- .../pages/Home/components/LatestTest/LatestTestComponent.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx b/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx index edfa9867..16d59617 100644 --- a/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx +++ b/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx @@ -13,7 +13,7 @@ import {t} from "i18next"; function LatestTestComponent() { const status = useContext(StatusContext)[0]; - const [latest, setLatest] = useState({}); + const [latest, setLatest] = useState(null); const [latestTestTime, setLatestTestTime] = useState("N/A"); const [setDialog] = useContext(InputDialogContext); const [speedtests] = useContext(SpeedtestContext); @@ -30,6 +30,7 @@ function LatestTestComponent() { }, [latest]); if (Object.entries(config).length === 0) return (<>); + if (latest === null) return (<>); return (
From 256b2586413256295e03e1038024d3df2e997e6d Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 02:01:33 +0200 Subject: [PATCH 05/23] Cleaned up the LatestTestComponent.jsx --- .../components/LatestTest/LatestTestComponent.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx b/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx index 16d59617..ce3cd8fb 100644 --- a/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx +++ b/client/src/pages/Home/components/LatestTest/LatestTestComponent.jsx @@ -39,7 +39,8 @@ function LatestTestComponent() {
setDialog(pingInfo())} icon={faPingPongPaddleBall} className={"container-icon help-icon icon-" + getIconBySpeed(latest.ping, config.ping, false)}/> -

{t("latest.ping")}{t("latest.ping_unit")}

+

{t("latest.ping")}{t("latest.ping_unit")}

{latest.ping === -1 ? "N/A" : latest.ping}

@@ -51,7 +52,8 @@ function LatestTestComponent() {
setDialog(downloadInfo())} icon={faArrowDown} className={"container-icon help-icon icon-" + getIconBySpeed(latest.download, config.download, true)}/> -

{t("latest.down")}{t("latest.speed_unit")}

+

{t("latest.down")}{t("latest.speed_unit")}

{latest.download === -1 ? "N/A" : latest.download}

@@ -65,7 +67,8 @@ function LatestTestComponent() {
setDialog(uploadInfo())} icon={faArrowUp} className={"container-icon help-icon icon-" + getIconBySpeed(latest.upload, config.upload, true)}/> -

{t("latest.up")}{t("latest.speed_unit")}

+

{t("latest.up")}{t("latest.speed_unit")}

{latest.upload === -1 ? "N/A" : latest.upload}

@@ -77,7 +80,8 @@ function LatestTestComponent() {
setDialog(latestTestInfo(latest))} icon={faClockRotateLeft} className="container-icon icon-blue help-icon"/> -

{t("latest.latest")}{t("latest.before")}

+

{t("latest.latest")}{t("latest.before")}

{latestTestTime}

From b2ef65dbb89db335768a8c1c3bc038fbfddebd5e Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 13:51:47 +0200 Subject: [PATCH 06/23] Migrated to axios & added the checkNode & proxyRequest methods to the node controller --- server/controller/node.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/server/controller/node.js b/server/controller/node.js index 56a880fb..9464ecbe 100644 --- a/server/controller/node.js +++ b/server/controller/node.js @@ -1,3 +1,4 @@ +const axios = require('axios'); const nodes = require('../models/Node'); // Gets all node entries @@ -28,4 +29,34 @@ module.exports.updateName = async (nodeId, name) => { // Update the password of the node entry module.exports.updatePassword = async (nodeId, password) => { return await nodes.update({password: password}, {where: {id: nodeId}}); +} + +module.exports.checkNode = async (url, password) => { + const api = await axios.get(url + "/api/config", {headers: {password: password}}).catch(() => { + return "INVALID_URL"; + }); + + if (api === "INVALID_URL" || api.status !== 200) return "INVALID_URL"; + + if (api.data.viewMode) return "PASSWORD_REQUIRED"; + + return "NODE_VALID"; +} + +module.exports.proxyRequest = async (url, req, res) => { + const response = await axios(url, { + method: req.method, + headers: req.headers, + data: req.method === "GET" ? undefined : JSON.stringify(req.body), + signal: req.signal, + validateStatus: (status) => status >= 200 && status < 400 + }).catch(() => "INVALID_URL"); + + if (response === "INVALID_URL") + return res.status(500).json({message: "Internal server error"}); + + if (response.headers["content-disposition"]) + res.setHeader("content-disposition", response.headers["content-disposition"]); + + res.status(response.status).json(response.data); } \ No newline at end of file From 3ab976efec040c99797956e3d256011b9c624764 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 13:52:05 +0200 Subject: [PATCH 07/23] Migrated the new methods to the node routes --- server/routes/nodes.js | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/server/routes/nodes.js b/server/routes/nodes.js index 42487df1..c4a406a4 100644 --- a/server/routes/nodes.js +++ b/server/routes/nodes.js @@ -1,6 +1,7 @@ const app = require('express').Router(); const nodes = require('../controller/node'); const password = require("../middlewares/password"); +const {checkNode, proxyRequest} = require("../controller/node"); // List all nodes app.get("/", password(false), async (req, res) => { @@ -13,18 +14,14 @@ app.put("/", password(false), async (req, res) => { const url = req.body.url.replace(/\/+$/, ""); - const headers = req.body.password ? {password: req.body.password} : {}; - - fetch(url + "/api/config", {headers}).then(async api => { - if (api.status !== 200) + checkNode(url, req.body.password).then(async (result) => { + if (result === "INVALID_URL") return res.status(400).json({message: "Invalid URL", type: "INVALID_URL"}); - if ((await api.json()).viewMode) + if (result === "PASSWORD_REQUIRED") return res.status(400).json({message: "Invalid password", type: "PASSWORD_REQUIRED"}); res.json({id: (await nodes.create(req.body.name, url, req.body.password)).id, type: "NODE_CREATED"}); - }).catch(async () => { - res.status(400).json({message: "Invalid URL", type: "INVALID_URL"}); }); }); @@ -55,17 +52,15 @@ app.patch("/:nodeId/password", password(false), async (req, res) => { const node = await nodes.get(req.params.nodeId); if (node === null) return res.status(404).json({message: "Node not found"}); - fetch(node.url + "/api/config", {headers: {password: req.body.password}}).then(async api => { - if (api.status !== 200) + checkNode(node.url, req.body.password).then(async (result) => { + if (result === "INVALID_URL") return res.status(400).json({message: "Invalid URL", type: "INVALID_URL"}); - if ((await api.json()).viewMode) + if (result === "PASSWORD_REQUIRED") return res.status(400).json({message: "Invalid password", type: "PASSWORD_REQUIRED"}); await nodes.updatePassword(req.params.nodeId, req.body.password); res.json({message: "Node password successfully updated", type: "PASSWORD_UPDATED"}); - }).catch(async () => { - res.status(400).json({message: "Invalid URL", type: "INVALID_URL"}); }); }); @@ -79,19 +74,7 @@ app.all("/:nodeId/*", password(false), async (req, res) => { req.headers['password'] = node.password; delete req.headers['host']; - fetch(url, { - method: req.method, - headers: req.headers, - body: req.method === "GET" ? undefined : JSON.stringify(req.body), - signal: req.signal - }).then(async api => { - if (api.headers.get("content-disposition")) - res.setHeader("content-disposition", api.headers.get("content-disposition")); - - res.status(api.status).json(await api.json()); - }).catch(() => { - res.status(500).json({message: "Internal server error"}); - }); + await proxyRequest(url, req, res); }); module.exports = app; \ No newline at end of file From 9c5b2a181552cdfa73458d1ceb4acec7151996f6 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:25:39 +0200 Subject: [PATCH 08/23] The baseRequests now aborts after 10 seconds --- client/src/common/utils/RequestUtil.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/common/utils/RequestUtil.js b/client/src/common/utils/RequestUtil.js index cc54973f..1df651ff 100644 --- a/client/src/common/utils/RequestUtil.js +++ b/client/src/common/utils/RequestUtil.js @@ -14,9 +14,12 @@ const getHeaders = () => { // Run a plain request with all default values using the base path export const baseRequest = async (path, method = "GET", body = {}, headers = {}) => { + const controller = new AbortController(); + setTimeout(() => controller.abort(), 10000); return await fetch("/api" + path, { headers: {...getHeaders(), ...headers}, method, - body: method !== "GET" ? JSON.stringify(body) : undefined + body: method !== "GET" ? JSON.stringify(body) : undefined, + signal: controller.signal }); } From 0e1922745152135acf69331b00aeb833f7e84cfc Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:45:09 +0200 Subject: [PATCH 09/23] Added a missing translation in the de.json --- client/public/locales/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/public/locales/de.json b/client/public/locales/de.json index eb68ba0b..93777e64 100644 --- a/client/public/locales/de.json +++ b/client/public/locales/de.json @@ -12,7 +12,8 @@ "password": { "title": "Passwort erforderlich", "placeholder": "Dein Passwort", - "wrong": "Das von dir eingegebene Passwort ist falsch" + "wrong": "Das von dir eingegebene Passwort ist falsch", + "unlock": "Sperre aufheben" }, "accept": { "title": "Wir brauchen deine Genehmigung", From 17fe454e7b42f15e1bda11d48b45122649f7235d Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:45:21 +0200 Subject: [PATCH 10/23] Updated the en.json language file --- client/public/locales/en.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/public/locales/en.json b/client/public/locales/en.json index c246b682..5b8d128b 100644 --- a/client/public/locales/en.json +++ b/client/public/locales/en.json @@ -12,7 +12,8 @@ "password": { "title": "Password required", "placeholder": "Your password", - "wrong": "The password you entered is incorrect" + "wrong": "The password you entered is incorrect", + "unlock": "Unblock" }, "accept": { "title": "We need your permission", @@ -129,7 +130,7 @@ "healthchecks": "MySpeed uses HealthChecks to notify you when your internet is down. To enable this, put your ping URL in the text box. Read more here", "credits": "MySpeed is provided by GNMYT and uses the Speedtest CLI from Ookla.", "recommendations_error": "You have to do at least 10 tests to get an average. It doesn't matter if the tests were done manually or automatically.", - "recommendations_info": "Based on the last 10 tests, it was found that the optimal ping was {{ping}} ms, the download at {{down}} Mbit/s and the upload at {{up}} Mbit/s. It is best to orientate yourself on your internet contract and only adopt it if it matches that.", + "recommendations_info": "Based on the last 10 tests, it was found that the optimal ping was {{ping}} ms, the download at {{down}} Mbps and the upload at {{up}} Mbps. It is best to orientate yourself on your internet contract and only adopt it if it matches that.", "update": "An update to version {{version}} is available. See the changes and download the update.", "down": { "title": "Download speed", From b527bc2319ef9b0e9f43c1918e7ab0cc5ea8474e Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:45:53 +0200 Subject: [PATCH 11/23] Added a findNode method in the NodeContext.jsx --- client/src/common/contexts/Node/NodeContext.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/common/contexts/Node/NodeContext.jsx b/client/src/common/contexts/Node/NodeContext.jsx index 4fe9c483..3fb0e40f 100644 --- a/client/src/common/contexts/Node/NodeContext.jsx +++ b/client/src/common/contexts/Node/NodeContext.jsx @@ -24,8 +24,10 @@ export const NodeProvider = (props) => { setCurrentNode(parseInt(node)); } + const findNode = (nodeId) => nodes.find(node => node.id === nodeId); + return ( - + {props.children} ) From 63944cac6bdebbdbdd2710ffe1939f6659555ec4 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:47:18 +0200 Subject: [PATCH 12/23] Updated the list method in the node controller --- server/controller/node.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/controller/node.js b/server/controller/node.js index 9464ecbe..dda03be0 100644 --- a/server/controller/node.js +++ b/server/controller/node.js @@ -2,8 +2,8 @@ const axios = require('axios'); const nodes = require('../models/Node'); // Gets all node entries -module.exports.list = async (excludePassword) => { - return await nodes.findAll({attributes: {exclude: excludePassword ? ['password'] : []}}); +module.exports.list = async () => { + return await nodes.findAll().then((result) => result.map((node) => ({...node, password: node.password !== null}))); } // Create a new node entry @@ -32,6 +32,7 @@ module.exports.updatePassword = async (nodeId, password) => { } module.exports.checkNode = async (url, password) => { + if (password === "none") password = undefined; const api = await axios.get(url + "/api/config", {headers: {password: password}}).catch(() => { return "INVALID_URL"; }); From 455b45ef04f5964c1ddf221f2d6b1668716251b2 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:48:24 +0200 Subject: [PATCH 13/23] Fixed a bug in the nodes.js route --- server/routes/nodes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/routes/nodes.js b/server/routes/nodes.js index c4a406a4..b3b89172 100644 --- a/server/routes/nodes.js +++ b/server/routes/nodes.js @@ -5,7 +5,7 @@ const {checkNode, proxyRequest} = require("../controller/node"); // List all nodes app.get("/", password(false), async (req, res) => { - return res.json(await nodes.list(true)); + return res.json(await nodes.list()); }); // Create a node @@ -59,7 +59,7 @@ app.patch("/:nodeId/password", password(false), async (req, res) => { if (result === "PASSWORD_REQUIRED") return res.status(400).json({message: "Invalid password", type: "PASSWORD_REQUIRED"}); - await nodes.updatePassword(req.params.nodeId, req.body.password); + await nodes.updatePassword(req.params.nodeId, req.body.password === "none" ? null : req.body.password); res.json({message: "Node password successfully updated", type: "PASSWORD_UPDATED"}); }); }); From 3c4f7af3c52bf4d023a2e93e352d994f981ef0cf Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:50:18 +0200 Subject: [PATCH 14/23] Added a missing translation & fixed the password button in the DropdownComponent.jsx --- .../components/Dropdown/DropdownComponent.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/src/common/components/Dropdown/DropdownComponent.jsx b/client/src/common/components/Dropdown/DropdownComponent.jsx index 8cc7621c..630ce55e 100644 --- a/client/src/common/components/Dropdown/DropdownComponent.jsx +++ b/client/src/common/components/Dropdown/DropdownComponent.jsx @@ -57,6 +57,8 @@ export const toggleDropdown = (setIcon) => { function DropdownComponent() { const [config, reloadConfig] = useContext(ConfigContext); const [status, updateStatus] = useContext(StatusContext); + const findNode = useContext(NodeContext)[4]; + const updateNodes = useContext(NodeContext)[1]; const currentNode = useContext(NodeContext)[2]; const updateTests = useContext(SpeedtestContext)[1]; const updateToast = useContext(ToastNotificationContext); @@ -145,19 +147,24 @@ function DropdownComponent() { const updatePassword = async () => { toggleDropdown(); + const passwordSet = currentNode !== 0 ? findNode(currentNode).password : localStorage.getItem("password") != null; + setDialog({ title: <>{t("update.new_password")} » {t("update.level")}, placeholder: t("update.password_placeholder"), type: "password", - unsetButton: localStorage.getItem("password") != null ? "Sperre aufheben" : undefined, + unsetButton: passwordSet ? t("dialog.password.unlock") : undefined, onClear: () => patchRequest("/config/password", {value: "none"}) .then(() => showFeedback("update.password_removed", false)) - .then(() => localStorage.removeItem("password")), + .then(() => { + currentNode !== 0 ? baseRequest("/nodes/" + currentNode + "/password", "PATCH", + {password: "none"}).then(() => updateNodes()) : localStorage.removeItem("password"); + }), onSuccess: (value) => patchRequest("/config/password", {value}) .then(() => showFeedback(undefined, false)) .then(() => { currentNode !== 0 ? baseRequest("/nodes/" + currentNode + "/password", "PATCH", - {password: value}) : localStorage.setItem("password", value); + {password: value}).then(() => updateNodes()) : localStorage.setItem("password", value); }) }) } From 74708d01241f77b6e5aba9f358878db4a231b010 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:51:41 +0200 Subject: [PATCH 15/23] Fixed a bug in the NodeContext.jsx --- client/src/common/contexts/Node/NodeContext.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/common/contexts/Node/NodeContext.jsx b/client/src/common/contexts/Node/NodeContext.jsx index 3fb0e40f..3d56906e 100644 --- a/client/src/common/contexts/Node/NodeContext.jsx +++ b/client/src/common/contexts/Node/NodeContext.jsx @@ -24,7 +24,7 @@ export const NodeProvider = (props) => { setCurrentNode(parseInt(node)); } - const findNode = (nodeId) => nodes.find(node => node.id === nodeId); + const findNode = (nodeId) => nodes?.find(node => node.id === nodeId); return ( From 7104188ce1354cf5fdc3ae7785c8dd33f4af9ce9 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:51:52 +0200 Subject: [PATCH 16/23] Updated the HeaderComponent.jsx --- client/src/common/components/Header/HeaderComponent.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/common/components/Header/HeaderComponent.jsx b/client/src/common/components/Header/HeaderComponent.jsx index d99d168b..cd04a64a 100644 --- a/client/src/common/components/Header/HeaderComponent.jsx +++ b/client/src/common/components/Header/HeaderComponent.jsx @@ -20,7 +20,7 @@ import {SpeedtestDialog} from "@/common/components/SpeedtestDialog"; import {NodeContext} from "@/common/contexts/Node"; function HeaderComponent(props) { - const nodes = useContext(NodeContext)[0]; + const findNode = useContext(NodeContext)[4]; const currentNode = useContext(NodeContext)[2]; const [setDialog] = useContext(InputDialogContext); @@ -82,8 +82,7 @@ function HeaderComponent(props) { if (!config.viewMode) updateVersion(); }, [config]); - const getNodeName = () => - currentNode === "0" ? t("header.title") : nodes?.find(node => node.id === currentNode)?.name || t("header.title"); + const getNodeName = () => currentNode === "0" ? t("header.title") : findNode(currentNode)?.name || t("header.title"); if (Object.keys(config).length === 0) return <>; From d3bb1d2023185effb1e858b51ee0bd997f69113f Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 14:56:11 +0200 Subject: [PATCH 17/23] Fixed a typo in the en.json --- client/public/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/public/locales/en.json b/client/public/locales/en.json index 5b8d128b..92cf212f 100644 --- a/client/public/locales/en.json +++ b/client/public/locales/en.json @@ -13,7 +13,7 @@ "title": "Password required", "placeholder": "Your password", "wrong": "The password you entered is incorrect", - "unlock": "Unblock" + "unlock": "Unlock" }, "accept": { "title": "We need your permission", From 80c6ff37de53ffe941a0520b4e6ff5504ed5d97b Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 15:26:13 +0200 Subject: [PATCH 18/23] The "This server" node now shows the host instead of the url --- client/src/pages/Nodes/Nodes.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/Nodes/Nodes.jsx b/client/src/pages/Nodes/Nodes.jsx index 1c0a4ac2..86467a43 100644 --- a/client/src/pages/Nodes/Nodes.jsx +++ b/client/src/pages/Nodes/Nodes.jsx @@ -19,7 +19,7 @@ export const Nodes = (props) => { {createDialogOpen && setCreateDialogOpen(false)}/>}
- {nodes.map(node => )} From dd2b780fa7f78f7cc90e307291482dd4dfa2be12 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 15:36:27 +0200 Subject: [PATCH 19/23] Removed the user select from the node-add class --- client/src/pages/Nodes/styles.sass | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/pages/Nodes/styles.sass b/client/src/pages/Nodes/styles.sass index 5481532d..6e74d17e 100644 --- a/client/src/pages/Nodes/styles.sass +++ b/client/src/pages/Nodes/styles.sass @@ -25,6 +25,7 @@ border: 2px dashed #696C73 border-radius: 15px cursor: pointer + user-select: none .node-add h1 font-size: 24pt From 5d8561cfd669c49eeab39d58e64f3a806f14b930 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 16:34:30 +0200 Subject: [PATCH 20/23] Added the test.no_latest translation --- client/public/locales/de.json | 1 + client/public/locales/en.json | 1 + 2 files changed, 2 insertions(+) diff --git a/client/public/locales/de.json b/client/public/locales/de.json index 93777e64..2de3d59f 100644 --- a/client/public/locales/de.json +++ b/client/public/locales/de.json @@ -161,6 +161,7 @@ }, "test": { "not_available": "Es liegen aktuell keine Tests vor", + "no_latest": "Es liegt kein aktueller Test vor. Bitte führe einen Test durch oder warte, bis der nächste Test durchgeführt wurde.", "unknown_error": "Unbekannter Fehler:", "failed": "Test fehlgeschlagen", "recheck": "Bitte überprüfe weitestgehend, ob das öfter passiert.", diff --git a/client/public/locales/en.json b/client/public/locales/en.json index 92cf212f..9ac99d83 100644 --- a/client/public/locales/en.json +++ b/client/public/locales/en.json @@ -161,6 +161,7 @@ }, "test": { "not_available": "There are currently no tests available", + "no_latest": "There is no current test available. Please perform a test or wait until the next test is performed.", "unknown_error": "Unknown error:", "failed": "Test failed", "recheck": "Please check as far as possible if this happens often.", From 56dae0a3dd759507439079991e3ec3ec4de5a448 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Wed, 5 Apr 2023 16:37:36 +0200 Subject: [PATCH 21/23] The latest dialog now shows a different message if no tests are available --- client/src/pages/Home/components/LatestTest/utils/dialogs.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pages/Home/components/LatestTest/utils/dialogs.jsx b/client/src/pages/Home/components/LatestTest/utils/dialogs.jsx index 30208561..589dd3cd 100644 --- a/client/src/pages/Home/components/LatestTest/utils/dialogs.jsx +++ b/client/src/pages/Home/components/LatestTest/utils/dialogs.jsx @@ -9,8 +9,8 @@ export const uploadInfo = () => ({title: t("info.up.title"), description: t("inf export const latestTestInfo = (latest) => ({ title: t("info.latest.title"), - description: }} values={{date: new Date(latest.created).toLocaleDateString(), + description: latest.created ? }} values={{date: new Date(latest.created).toLocaleDateString(), time: new Date(latest.created).toLocaleTimeString(undefined, {hour: "2-digit", minute: "2-digit"})}}> - info.latest.description, + info.latest.description : t("test.no_latest"), buttonText: t("dialog.okay") }); \ No newline at end of file From 94f6f203074a1c9c4994f68e4cde2479f7dc9118 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Thu, 6 Apr 2023 03:25:27 +0200 Subject: [PATCH 22/23] Removed the x-powered-by header from express in the server index.js --- server/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/index.js b/server/index.js index f005e99f..5dfb8d45 100755 --- a/server/index.js +++ b/server/index.js @@ -4,6 +4,9 @@ const timerTask = require('./tasks/timer'); const healthCheckTask = require('./tasks/healthchecks'); const app = express(); + +app.disable('x-powered-by'); + const port = process.env.port || 5216; // Create the data folder and the servers file From 8b76f609241bcc311811fb94bb4b4598c4c45e29 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Thu, 6 Apr 2023 03:50:29 +0200 Subject: [PATCH 23/23] Added an extra check in the node controller --- server/controller/node.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/controller/node.js b/server/controller/node.js index dda03be0..b5726194 100644 --- a/server/controller/node.js +++ b/server/controller/node.js @@ -39,6 +39,8 @@ module.exports.checkNode = async (url, password) => { if (api === "INVALID_URL" || api.status !== 200) return "INVALID_URL"; + if (!api.data.ping) return "INVALID_URL"; + if (api.data.viewMode) return "PASSWORD_REQUIRED"; return "NODE_VALID";