From 3d002b3ce95d51ead40b71c8c31cbe0bb3522e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bla=C5=BEej?= Date: Sat, 25 Dec 2021 20:25:21 +0100 Subject: [PATCH 01/69] add status boolean parameter to push monitor --- server/routers/api-router.js | 5 +++-- src/pages/EditMonitor.vue | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 1920cef7..1b313828 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -5,7 +5,7 @@ const server = require("../server"); const apicache = require("../modules/apicache"); const Monitor = require("../model/monitor"); const dayjs = require("dayjs"); -const { UP, flipStatus, debug } = require("../../src/util"); +const { UP, DOWN, flipStatus, debug } = require("../../src/util"); let router = express.Router(); let cache = apicache.middleware; @@ -22,6 +22,8 @@ router.get("/api/push/:pushToken", async (request, response) => { let pushToken = request.params.pushToken; let msg = request.query.msg || "OK"; let ping = request.query.ping || null; + let status = request.query.status || "true"; + status = status === "true" ? UP : DOWN; let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [ pushToken @@ -33,7 +35,6 @@ router.get("/api/push/:pushToken", async (request, response) => { const previousHeartbeat = await Monitor.getPreviousHeartbeat(monitor.id); - let status = UP; if (monitor.isUpsideDown()) { status = flipStatus(status); } diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 4b6a920c..7d31c7da 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -53,7 +53,7 @@
{{ $t("needPushEvery", [monitor.interval]) }}
- {{ $t("pushOptionalParams", ["msg, ping"]) }} + {{ $t("pushOptionalParams", ["status, msg, ping"]) }}
@@ -349,7 +349,7 @@ export default { }, pushURL() { - return this.$root.baseURL + "/api/push/" + this.monitor.pushToken + "?msg=OK&ping="; + return this.$root.baseURL + "/api/push/" + this.monitor.pushToken + "?status=true&msg=OK&ping="; }, bodyPlaceholder() { From 60c63cc18ef0b8d2228f2927e3e8872a3851017d Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sat, 16 Apr 2022 11:10:51 +0100 Subject: [PATCH 03/69] Add JSDoc to server/jobs/* Signed-off-by: Matthew Nickson --- server/jobs/util-worker.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/jobs/util-worker.js b/server/jobs/util-worker.js index 9426840d..52ad8f9a 100644 --- a/server/jobs/util-worker.js +++ b/server/jobs/util-worker.js @@ -2,12 +2,20 @@ const { parentPort, workerData } = require("worker_threads"); const Database = require("../database"); const path = require("path"); +/** + * Send message to parent process + * @param {any} any The message to log + */ const log = function (any) { if (parentPort) { parentPort.postMessage(any); } }; +/** + * Exit the worker process + * @param {number} error The status code to exit + */ const exit = function (error) { if (error && error != 0) { process.exit(error); @@ -20,6 +28,7 @@ const exit = function (error) { } }; +/** Connects to the database */ const connectDb = async function () { const dbPath = path.join( process.env.DATA_DIR || workerData["data-dir"] || "./data/" From 5a209c74e1411d2729e3ab06bb180048fd1cdc24 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sat, 16 Apr 2022 20:24:53 +0100 Subject: [PATCH 04/69] Add JSDoc to server/notification-providers/* Signed-off-by: Matthew Nickson --- server/notification-providers/aliyun-sms.js | 18 ++++++++++- server/notification-providers/bark.js | 20 +++++++++++-- server/notification-providers/dingding.js | 19 +++++++++++- .../notification-provider.js | 16 ++++++---- server/notification-providers/slack.js | 1 + server/notification-providers/teams.js | 30 +++++++++++++++++++ server/notification-providers/wecom.js | 6 ++++ 7 files changed, 101 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/aliyun-sms.js b/server/notification-providers/aliyun-sms.js index 6a206320..1a64690d 100644 --- a/server/notification-providers/aliyun-sms.js +++ b/server/notification-providers/aliyun-sms.js @@ -37,6 +37,12 @@ class AliyunSMS extends NotificationProvider { } } + /** + * Send the SMS notification + * @param {BeanModel} notification Notification details + * @param {string} msgbody Message template + * @returns {boolean} True if successful else false + */ async sendSms(notification, msgbody) { let params = { PhoneNumbers: notification.phonenumber, @@ -70,7 +76,12 @@ class AliyunSMS extends NotificationProvider { return false; } - /** Aliyun request sign */ + /** + * Aliyun request sign + * @param {Object} param Parameters object to sign + * @param {string} AccessKeySecret Secret key to sign parameters with + * @returns {string} + */ sign(param, AccessKeySecret) { let param2 = {}; let data = []; @@ -93,6 +104,11 @@ class AliyunSMS extends NotificationProvider { .digest("base64"); } + /** + * Convert status constant to string + * @param {const} status The status constant + * @returns {string} + */ statusToString(status) { switch (status) { case DOWN: diff --git a/server/notification-providers/bark.js b/server/notification-providers/bark.js index 4ebe978a..b2f25612 100644 --- a/server/notification-providers/bark.js +++ b/server/notification-providers/bark.js @@ -49,7 +49,12 @@ class Bark extends NotificationProvider { } } - // add additional parameter for better on device styles (iOS 15 optimized) + /** + * Add additional parameter for better on device styles (iOS 15 + * optimized) + * @param {string} postUrl URL to append parameters to + * @returns {string} + */ appendAdditionalParameters(postUrl) { // grouping all our notifications postUrl += "?group=" + barkNotificationGroup; @@ -60,7 +65,11 @@ class Bark extends NotificationProvider { return postUrl; } - // thrown if failed to check result, result code should be in range 2xx + /** + * Check if result is successful + * @param {Object} result Axios response object + * @throws {Error} The status code is not in range 2xx + */ checkResult(result) { if (result.status == null) { throw new Error("Bark notification failed with invalid response!"); @@ -70,6 +79,13 @@ class Bark extends NotificationProvider { } } + /** + * Send the message + * @param {string} title Message title + * @param {string} subtitle Message + * @param {string} endpoint Endpoint to send request to + * @returns {string} + */ async postNotification(title, subtitle, endpoint) { // url encode title and subtitle title = encodeURIComponent(title); diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index cf08f14b..f3946cf8 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -37,6 +37,12 @@ class DingDing extends NotificationProvider { } } + /** + * Send message to DingDing + * @param {BeanModel} notification + * @param {Object} params Parameters of message + * @returns {boolean} True if successful else false + */ async sendToDingDing(notification, params) { let timestamp = Date.now(); @@ -56,7 +62,12 @@ class DingDing extends NotificationProvider { return false; } - /** DingDing sign */ + /** + * DingDing sign + * @param {Date} timestamp Timestamp of message + * @param {string} secretKey Secret key to sign data with + * @returns {string} + */ sign(timestamp, secretKey) { return Crypto .createHmac("sha256", Buffer.from(secretKey, "utf8")) @@ -64,7 +75,13 @@ class DingDing extends NotificationProvider { .digest("base64"); } + /** + * Convert status constant to string + * @param {const} status The status constant + * @returns {string} + */ statusToString(status) { + // TODO: Move to notification-provider.js to avoid repetition in classes switch (status) { case DOWN: return "DOWN"; diff --git a/server/notification-providers/notification-provider.js b/server/notification-providers/notification-provider.js index 61c6242d..6765633d 100644 --- a/server/notification-providers/notification-provider.js +++ b/server/notification-providers/notification-provider.js @@ -7,17 +7,23 @@ class NotificationProvider { name = undefined; /** - * @param notification : BeanModel - * @param msg : string General Message - * @param monitorJSON : object Monitor details (For Up/Down only) - * @param heartbeatJSON : object Heartbeat details (For Up/Down only) + * Send a notification + * @param {BeanModel} notification + * @param {string} msg General Message + * @param {?Object} monitorJSON Monitor details (For Up/Down only) + * @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) * @returns {Promise} Return Successful Message - * Throw Error with fail msg + * @throws Error with fail msg */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { throw new Error("Have to override Notification.send(...)"); } + /** + * Throws an error + * @param {any} error The error to throw + * @throws {any} The error specified + */ throwGeneralAxiosError(error) { let msg = "Error: " + error + " "; diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index b4dad6fe..da1d6e66 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -10,6 +10,7 @@ class Slack extends NotificationProvider { /** * Deprecated property notification.slackbutton * Set it as primary base url if this is not yet set. + * @param {string} url The primary base URL to use */ static async deprecateURL(url) { let currentPrimaryBaseURL = await setting("primaryBaseURL"); diff --git a/server/notification-providers/teams.js b/server/notification-providers/teams.js index 859af569..c398e03c 100644 --- a/server/notification-providers/teams.js +++ b/server/notification-providers/teams.js @@ -5,6 +5,12 @@ const { DOWN, UP } = require("../../src/util"); class Teams extends NotificationProvider { name = "teams"; + /** + * Generate the message to send + * @param {const} status The status constant + * @param {string} monitorName Name of monitor + * @returns {string} + */ _statusMessageFactory = (status, monitorName) => { if (status === DOWN) { return `🔴 Application [${monitorName}] went down`; @@ -14,6 +20,11 @@ class Teams extends NotificationProvider { return "Notification"; }; + /** + * Select theme color to use based on status + * @param {const} status The status constant + * @returns {string} Selected color in hex RGB format + */ _getThemeColor = (status) => { if (status === DOWN) { return "ff0000"; @@ -24,6 +35,14 @@ class Teams extends NotificationProvider { return "008cff"; }; + /** + * Generate payload for notification + * @param {const} status The status of the monitor + * @param {string} monitorMessage Message to send + * @param {string} monitorName Name of monitor affected + * @param {string} monitorUrl URL of monitor affected + * @returns {Object} + */ _notificationPayloadFactory = ({ status, monitorMessage, @@ -74,10 +93,21 @@ class Teams extends NotificationProvider { }; }; + /** + * Send the notification + * @param {string} webhookUrl URL to send the request to + * @param {Object} payload Payload generated by _notificationPayloadFactory + */ _sendNotification = async (webhookUrl, payload) => { await axios.post(webhookUrl, payload); }; + /** + * Send a general notification + * @param {string} webhookUrl URL to send request to + * @param {string} msg Message to send + * @returns {Promise} + */ _handleGeneralNotification = (webhookUrl, msg) => { const payload = this._notificationPayloadFactory({ monitorMessage: msg diff --git a/server/notification-providers/wecom.js b/server/notification-providers/wecom.js index 7ba8c378..4da478ad 100644 --- a/server/notification-providers/wecom.js +++ b/server/notification-providers/wecom.js @@ -24,6 +24,12 @@ class WeCom extends NotificationProvider { } } + /** + * Generate the message to send + * @param {Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {string} msg General message + * @returns {Object} + */ composeMessage(heartbeatJSON, msg) { let title; if (msg != null && heartbeatJSON != null && heartbeatJSON['status'] == UP) { From 45f44b183d706aadc6c9af901e0e68fb2e73946e Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sat, 16 Apr 2022 21:11:45 +0100 Subject: [PATCH 05/69] Add JSDoc to server/model/* Signed-off-by: Matthew Nickson --- server/model/group.js | 9 +++++ server/model/heartbeat.js | 9 +++++ server/model/incident.js | 5 +++ server/model/monitor.js | 74 +++++++++++++++++++++++++++++++++++---- server/model/tag.js | 5 +++ 5 files changed, 96 insertions(+), 6 deletions(-) diff --git a/server/model/group.js b/server/model/group.js index 567f3865..eb5006e1 100644 --- a/server/model/group.js +++ b/server/model/group.js @@ -3,6 +3,11 @@ const { R } = require("redbean-node"); class Group extends BeanModel { + /** + * Return a object that ready to parse to JSON for public + * Only show necessary data to public + * @returns {Object} + */ async toPublicJSON() { let monitorBeanList = await this.getMonitorList(); let monitorList = []; @@ -19,6 +24,10 @@ class Group extends BeanModel { }; } + /** + * Get all monitors + * @returns {Array} + */ async getMonitorList() { return R.convertToBeans("monitor", await R.getAll(` SELECT monitor.* FROM monitor, monitor_group diff --git a/server/model/heartbeat.js b/server/model/heartbeat.js index e0a77c06..38ba6f46 100644 --- a/server/model/heartbeat.js +++ b/server/model/heartbeat.js @@ -13,6 +13,11 @@ const { BeanModel } = require("redbean-node/dist/bean-model"); */ class Heartbeat extends BeanModel { + /** + * Return a object that ready to parse to JSON for public + * Only show necessary data to public + * @returns {Object} + */ toPublicJSON() { return { status: this.status, @@ -22,6 +27,10 @@ class Heartbeat extends BeanModel { }; } + /** + * Return a object that ready to parse to JSON + * @returns {Object} + */ toJSON() { return { monitorID: this.monitor_id, diff --git a/server/model/incident.js b/server/model/incident.js index 89c117e9..e28478f7 100644 --- a/server/model/incident.js +++ b/server/model/incident.js @@ -2,6 +2,11 @@ const { BeanModel } = require("redbean-node/dist/bean-model"); class Incident extends BeanModel { + /** + * Return a object that ready to parse to JSON for public + * Only show necessary data to public + * @returns {Object} + */ toPublicJSON() { return { id: this.id, diff --git a/server/model/monitor.js b/server/model/monitor.js index c4441d63..31c5a9cb 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -26,6 +26,7 @@ class Monitor extends BeanModel { /** * Return a object that ready to parse to JSON for public * Only show necessary data to public + * @returns {Object} */ async toPublicJSON() { return { @@ -36,6 +37,7 @@ class Monitor extends BeanModel { /** * Return a object that ready to parse to JSON + * @returns {Object} */ async toJSON() { @@ -107,10 +109,18 @@ class Monitor extends BeanModel { return Boolean(this.upsideDown); } + /** + * Get status codes that are acceptable + * @returns {Object} + */ getAcceptedStatuscodes() { return JSON.parse(this.accepted_statuscodes_json); } + /** + * Start monitor + * @param {Server} io Socket server instance + */ start(io) { let previousBeat = null; let retries = 0; @@ -463,6 +473,7 @@ class Monitor extends BeanModel { } } + /** Stop monitor */ stop() { clearTimeout(this.heartbeatInterval); this.isStop = true; @@ -472,7 +483,7 @@ class Monitor extends BeanModel { * Helper Method: * returns URL object for further usage * returns null if url is invalid - * @returns {null|URL} + * @returns {(null|URL)} */ getUrl() { try { @@ -485,7 +496,7 @@ class Monitor extends BeanModel { /** * Store TLS info to database * @param checkCertificateResult - * @returns {Promise} + * @returns {Promise} */ async updateTlsInfo(checkCertificateResult) { let tls_info_bean = await R.findOne("monitor_tls_info", "monitor_id = ?", [ @@ -527,6 +538,12 @@ class Monitor extends BeanModel { return checkCertificateResult; } + /** + * Send statistics to clients + * @param {Server} io Socket server instance + * @param {number} monitorID ID of monitor to send + * @param {number} userID ID of user to send to + */ static async sendStats(io, monitorID, userID) { const hasClients = getTotalClientInRoom(io, userID) > 0; @@ -541,8 +558,8 @@ class Monitor extends BeanModel { } /** - * - * @param duration : int Hours + * Send the average ping to user + * @param {number} duration Hours */ static async sendAvgPing(duration, io, monitorID, userID) { const timeLogger = new TimeLogger(); @@ -562,6 +579,12 @@ class Monitor extends BeanModel { io.to(userID).emit("avgPing", monitorID, avgPing); } + /** + * Send certificate information to information + * @param {Server} io Socket server instance + * @param {number} monitorID ID of monitor to send + * @param {number} userID ID of user to send to + */ static async sendCertInfo(io, monitorID, userID) { let tls_info = await R.findOne("monitor_tls_info", "monitor_id = ?", [ monitorID, @@ -575,7 +598,8 @@ class Monitor extends BeanModel { * Uptime with calculation * Calculation based on: * https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime - * @param duration : int Hours + * @param {number} duration Hours + * @param {number} monitorID ID of monitor to calculate */ static async calcUptime(duration, monitorID) { const timeLogger = new TimeLogger(); @@ -641,13 +665,23 @@ class Monitor extends BeanModel { /** * Send Uptime - * @param duration : int Hours + * @param {number} duration Hours + * @param {Server} io Socket server instance + * @param {number} monitorID ID of monitor to send + * @param {number} userID ID of user to send to */ static async sendUptime(duration, io, monitorID, userID) { const uptime = await this.calcUptime(duration, monitorID); io.to(userID).emit("uptime", monitorID, duration, uptime); } + /** + * Has status of monitor changed since last beat? + * @param {boolean} isFirstBeat Is this the first beat of this monitor? + * @param {const} previousBeatStatus Status of the previous beat + * @param {const} currentBeatStatus Status of the current beat + * @returns {boolean} True if is an important beat else false + */ static isImportantBeat(isFirstBeat, previousBeatStatus, currentBeatStatus) { // * ? -> ANY STATUS = important [isFirstBeat] // UP -> PENDING = not important @@ -666,6 +700,12 @@ class Monitor extends BeanModel { return isImportant; } + /** + * Send a notification about a monitor + * @param {boolean} isFirstBeat Is this beat the first of this monitor? + * @param {Monitor} monitor The monitor to send a notificaton about + * @param {Bean} bean Status information about monitor + */ static async sendNotification(isFirstBeat, monitor, bean) { if (!isFirstBeat || bean.status === DOWN) { const notificationList = await Monitor.getNotificationList(monitor); @@ -690,6 +730,11 @@ class Monitor extends BeanModel { } } + /** + * Get list of notification providers for a given monitor + * @param {Monitor} monitor Monitor to get notification providers for + * @returns {Promise[]>} + */ static async getNotificationList(monitor) { let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [ monitor.id, @@ -697,6 +742,10 @@ class Monitor extends BeanModel { return notificationList; } + /** + * Send notification about a certificate + * @param {Object} tlsInfoObject Information about certificate + */ async sendCertNotification(tlsInfoObject) { if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) { const notificationList = await Monitor.getNotificationList(this); @@ -708,6 +757,14 @@ class Monitor extends BeanModel { } } + /** + * Send a certificate notification when certificate expires in less + * than target days + * @param {number} daysRemaining Number of days remaining on certifcate + * @param {number} targetDays Number of days to alert after + * @param {Array>} notificationList List of notification providers + * @returns {Promise} + */ async sendCertNotificationByTargetDays(daysRemaining, targetDays, notificationList) { if (daysRemaining > targetDays) { @@ -755,6 +812,11 @@ class Monitor extends BeanModel { } } + /** + * Get the status of the previous heartbeat + * @param {number} monitorID ID of monitor to check + * @returns {Promise>} + */ static async getPreviousHeartbeat(monitorID) { return await R.getRow(` SELECT status, time FROM heartbeat diff --git a/server/model/tag.js b/server/model/tag.js index 748280a7..5a8d97d3 100644 --- a/server/model/tag.js +++ b/server/model/tag.js @@ -1,6 +1,11 @@ const { BeanModel } = require("redbean-node/dist/bean-model"); class Tag extends BeanModel { + + /** + * Return a object that ready to parse to JSON + * @returns {Object} + */ toJSON() { return { id: this._id, From 59d9891105d8312ff36da153b7d18dedf4801a20 Mon Sep 17 00:00:00 2001 From: Koen Habets <6172623+koen20@users.noreply.github.com> Date: Tue, 19 Apr 2022 21:17:33 +0200 Subject: [PATCH 06/69] Update nl-NL.js --- src/languages/nl-NL.js | 260 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 259 insertions(+), 1 deletion(-) diff --git a/src/languages/nl-NL.js b/src/languages/nl-NL.js index d148ba36..96424a5f 100644 --- a/src/languages/nl-NL.js +++ b/src/languages/nl-NL.js @@ -171,7 +171,7 @@ export default { "Avg. Response": "Gemiddelde Response", "Entry Page": "Entry Page", statusPageNothing: "Niets hier, voeg een groep of monitor toe.", - "No Services": "No Services", + "No Services": "Geen diensten", "All Systems Operational": "Alle systemen operationeel", "Partially Degraded Service": "Gedeeltelijk verminderde prestaties", "Degraded Service": "Verminderde prestaties", @@ -205,4 +205,262 @@ export default { PushUrl: "Push URL", HeadersInvalidFormat: "The request headers is geen geldige JSON: ", BodyInvalidFormat: "De request body is geen geldige JSON: ", + "Primary Base URL": "Hoofd Basis URL", + "Push URL": "Push URL", + needPushEvery: "Je moet deze URL elke {0} seconden aanroepen.", + pushOptionalParams: "Optionele parameters: {0}", + defaultNotificationName: "Mijn {notification} Alert ({number})", + here: "hier", + Required: "Verplicht", + "Bot Token": "Bot Token", + wayToGetTelegramToken: "Je kunt een token krijgen van {0}.", + "Chat ID": "Chat ID", + supportTelegramChatID: "Ondersteuning Directe Chat / Groep / Kanaal Chat ID", + wayToGetTelegramChatID: "Je kunt je CHAT ID krijgen door een bericht te sturen naar de bot en naar deze URL te gaan om het chat_id te bekijken:", + "YOUR BOT TOKEN HERE": "DE BOT TOKEN HIER", + chatIDNotFound: "Chat ID is niet gevonden; stuur eerst een bericht naar de bot", + "Post URL": "Post URL", + "Content Type": "Content Type", + webhookJsonDesc: "{0} is goed voor een moderne HTTP server zoals Express.js", + webhookFormDataDesc: "{multipart} is goed voor PHP. De JSON moet worden ontleed met {decodeFunction}", + secureOptionNone: "Geen / STARTTLS (25, 587)", + secureOptionTLS: "TLS (465)", + "Ignore TLS Error": "Negeer TLS Error", + "From Email": "Van Email", + emailCustomSubject: "Aangepast Onderwerp", + "To Email": "Naar Email", + smtpCC: "CC", + smtpBCC: "BCC", + "Discord Webhook URL": "Discord Webhook URL", + wayToGetDiscordURL: "Je kunt dit krijgen door te gaan naar Server Instellingen -> Integraties -> Creëer Webhook", + "Bot Display Name": "Bot Weergave Naam", + "Prefix Custom Message": "Prefix Aangepast Bericht", + "Hello @everyone is...": "Hallo {'@'}iedereen is...", + "Webhook URL": "Webhook URL", + wayToGetTeamsURL: "Je kunt hier leren hoe je een webhook URL kunt maken {0}.", + Number: "Nummer", + Recipients: "Ontvangers", + needSignalAPI: "Je moet een signal client met REST API hebben.", + wayToCheckSignalURL: "Je kunt op deze URL zien hoe je een kunt instellen:", + signalImportant: "BELANGRIJK: Je kunt groepen en nummers niet mengen in ontvangers!", + "Application Token": "Applicatie Token", + "Server URL": "Server URL", + Priority: "Prioriteit", + "Icon Emoji": "Icoon Emoji", + "Channel Name": "Kanaal Naam", + "Uptime Kuma URL": "Uptime Kuma URL", + aboutWebhooks: "Meer info over Webhooks op: {0}", + aboutChannelName: "Voer de kanaal naam in op {0} Kannaal Naam veld als je het Webhook kanaal wilt omzeilen. Bv: #other-channel", + aboutKumaURL: "Als je de Uptime Kuma URL veld leeg laat, wordt standaard het GitHub project pagina weergegeven.", + emojiCheatSheet: "Emoji cheat sheet: {0}", + PushByTechulus: "Push door Techulus", + clicksendsms: "ClickSend SMS", + GoogleChat: "Google Chat (Google Workspace alleen)", + "User Key": "Gebruikers sleutel", + Device: "Apparaat", + "Message Title": "Bericht Titel", + "Notification Sound": "Notificatie Geluid", + "More info on:": "Meer info op: {0}", + pushoverDesc1: "Nood prioriteit (2) heeft standaard een 30 seconden timeout tussen pogingen en verloopt na 1 uur.", + pushoverDesc2: "Vul het appraat veld in als je notificaties naar andere apparaten wilt versturen.", + "SMS Type": "SMS Type", + octopushTypePremium: "Premium (Snel - aangeraden voor te alarmeren)", + octopushTypeLowCost: "Low Cost (Langzaam - wordt soms geblokkeerd door operator)", + checkPrice: "Controleer {0} prijzen:", + apiCredentials: "API referenties", + octopushLegacyHint: "Wil je de legacy versie van Octopush (2011-2020) gebruiken of de nieuwe versie?", + "Check octopush prices": "Controleer Octopush prijzen {0}.", + octopushPhoneNumber: "Telefoon nummer (Int. formaat, eg : +33612345678) ", + octopushSMSSender: "SMS zender naam : 3-11 alfanumerieke karakters en spatie (a-zA-Z0-9)", + "LunaSea Device ID": "LunaSea Apparaat ID", + "Apprise URL": "Apprise URL", + "Example:": "Voorbeeld: {0}", + "Read more:": "Lees meer: {0}", + "Status:": "Status: {0}", + "Read more": "Lees meer", + appriseInstalled: "Apprise is geïnstalleerd.", + appriseNotInstalled: "Apprise is niet geïnstalleerd. {0}", + "Access Token": "Access Token", + "Channel access token": "Kanaal access token", + "Line Developers Console": "Line Developers Console", + lineDevConsoleTo: "Line Developers Console - {0}", + "Basic Settings": "Basis Instellingen", + "User ID": "Gebruiker ID", + "Messaging API": "Berichten API", + wayToGetLineChannelToken: "Begin met {0} te openen, creëer een provider en kanaal (Messaging API), dan kun je de kanaal access token en gebruikers ID van de hierboven genoemde menu items krijgen.", + "Icon URL": "Icoon URL", + aboutIconURL: "Je kunt een link om de standaard profiel afbeelding te overschrijving in \"Icoon URL\" meegeven. Dit wordt niet gebruikt als Icon Emoji is ingesteld.", + aboutMattermostChannelName: "Je kunt het standaard kanaal dat de Webhook plaatst overschijven door de kanaal naam in te vullen in het \"Channel Name\" veld. Dit moet worden ingeschakeld in de Mattermost Webhook instellingen. Bv. #ander-kanaal", + matrix: "Matrix", + promosmsTypeEco: "SMS ECO - Goedkoop maar langzaam en vaak overbelast. Gelimiteerd tot Poolse ontvangers.", + promosmsTypeFlash: "SMS FLASH - Berichten worden automatisch weergegeven op het apparaat van de ontvanger. Gelimiteerd tot Poolse ontvangers.", + promosmsTypeFull: "SMS FULL - Premium tier van SMS, je kunt de ontvanger naam gebruiken (Je moet eerst de naam registreren). Betrouwbaar voor alarmeringen.", + promosmsTypeSpeed: "SMS SPEED - Hoogste prioriteit in systeem. Is veel sneller en betrouwbaarder maar kost meer (ongeveer twee keer zoveel als volle SMS prijs).", + promosmsPhoneNumber: "Telefoon nummer (voor Poolse ontvangers. Je kunt gebieds codes overslaan)", + promosmsSMSSender: "SMS Ontvanger naam : Voor geregistreerde naam of een van de standaarden: InfoSMS, SMS Info, MaxSMS, INFO, SMS", + "Feishu WebHookUrl": "Feishu WebHookURL", + matrixHomeserverURL: "Homeserver URL (met http(s):// en optioneel poort)", + "Internal Room Id": "Interne Room ID", + matrixDesc1: "Je kunt de interne room ID vinden door in de geavanceerde sectie van de room instellingen in je Matrix client te kijken. Het zou moeten uitzien als !QMdRCpUIfLwsfjxye6:home.server.", + matrixDesc2: "Het wordt ten zeerste aanbevolen om een nieuwe gebruiker aan te maken en niet de access token van je account te gebruiken, aangezien dit volledige toegang geeft tot je account en alle kamers waar je lid van bent. Maak in plaats daarvan een nieuwe gebruiker aan en nodig deze alleen uit voor de ruimte waarin je de melding wilt ontvangen. Je kunt de access token krijgen door het volgende uit te voeren {0}", + "Monitor History": "Monitor Geschiedenis", + clearDataOlderThan: "Bewaar monitor geschiedenis voor {0} dagen.", + PasswordsDoNotMatch: "Wachtwoorden komen niet overeen", + records: "records", + "One record": "Een record", + steamApiKeyDescription: "Om een Steam Game Server te monitoren heb je een Steam Web-API key nodig. Je kunt hier je API key registreren: ", + "Current User": "Huidge Gebruiker", + topic: "Onderwerp", + topicExplanation: "MQTT onderwerp om te monitoren", + successMessage: "Succesbericht", + successMessageExplanation: "MQTT bericht dat als succes wordt beschouwd.", + recent: "Recent", + Done: "Klaar", + Info: "Info", + Security: "Beveiliging", + "Steam API Key": "Steam API Sleutel", + "Shrink Database": "Verklein Database", + "Pick a RR-Type...": "Kies een RR-Type...", + "Pick Accepted Status Codes...": "Kies geaccepteerde Status Codes...", + Default: "Standaard", + "HTTP Options": "HTTP Opties", + "Create Incident": "Creëer Incident", + Title: "Titel", + Content: "Content", + Style: "Stijl", + info: "info", + warning: "waarschuwing", + danger: "gevaar", + primary: "primair", + light: "licht", + dark: "donker", + Post: "Post", + "Please input title and content": "Voer alstublieft titel en content in", + Created: "Gemaakt", + "Last Updated": "Laatst Bijgewerkt", + Unpin: "Losmaken", + "Switch to Light Theme": "Wissel naar Licht Thema", + "Switch to Dark Theme": "Wissel naar Donker Thema", + "Show Tags": "Toon Labels", + "Hide Tags": "Verberg Labels", + Description: "Beschrijving", + "No monitors available.": "Geen monitors beschikbaar.", + "Add one": "Voeg een toe", + "No Monitors": "Geen Monitors", + "Untitled Group": "Naamloze Groep", + Services: "Diensten", + Discard: "Weggooien", + Cancel: "Annuleren", + "Powered by": "Mogelijk gemaakt door", + shrinkDatabaseDescription: "Trigger database VACUUM voor SQLite. Als de database na 1.10.0 gemaakt is, dan is AUTO_VACUUM al aangezet en deze actie niet nodig.", + serwersms: "SerwerSMS.pl", + serwersmsAPIUser: "API Gebruikersnaam (incl. webapi_ prefix)", + serwersmsAPIPassword: "API Wachtwoord", + serwersmsPhoneNumber: "Telefoon nummer", + serwersmsSenderName: "SMS Zender Naam (geregistreerd via klant portaal)", + stackfield: "Stackfield", + Customize: "Aanpassen", + "Custom Footer": "Aangepaste Footer", + "Custom CSS": "Aangepaste CSS", + smtpDkimSettings: "DKIM Instellingen", + smtpDkimDesc: "Refereer alsjeblieft naar Nodemailer DKIM {0} voor gebruik.", + documentation: "documentatie", + smtpDkimDomain: "Domein Naam", + smtpDkimKeySelector: "Sleutel Kiezer", + smtpDkimPrivateKey: "Prive Sleutel", + smtpDkimHashAlgo: "Hash Algoritme (Optioneel)", + smtpDkimheaderFieldNames: "Header sleutels om te ondertekenen (Optioneel)", + smtpDkimskipFields: "Header sleutels niet om te ondertekenen (Optioneel)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API Eindpunt", + alertaEnvironment: "Omgeving", + alertaApiKey: "API Sleutel", + alertaAlertState: "Alert Staat", + alertaRecoverState: "Herstel Staat", + deleteStatusPageMsg: "Weet je zeker je deze status pagina wilt verwijderen?", + Proxies: "Proxies", + default: "Standaard", + enabled: "Ingeschakeld", + setAsDefault: "Stel in als standaard", + deleteProxyMsg: "Weet je zeker dat je deze proxy wilt verwijderen voor alle monitors?", + proxyDescription: "Proxies moeten worden toegewezen aan een monitor om te functioneren.", + enableProxyDescription: "Deze proxy heeft geen effect op monitor verzoeken totdat het is geactiveerd. Je kunt tijdelijk de proxy uitschakelen voor alle monitors voor activatie status.", + setAsDefaultProxyDescription: "Deze proxy wordt standaard aangezet voor alle nieuwe monitors. Je kunt nog steeds de proxy apart uitschakelen voor elke monitor.", + "Certificate Chain": "Certificaat Chain", + Valid: "Geldig", + Invalid: "Ongeldig", + AccessKeyId: "AccessKey ID", + SecretAccessKey: "AccessKey Secret", + PhoneNumbers: "TelefoonNummers", + TemplateCode: "TemplateCode", + SignName: "SignName", + "Sms template must contain parameters: ": "Sms sjabloon moet de volgende parameters bevatten: ", + "Bark Endpoint": "Bark Endpoint", + WebHookUrl: "WebHookUrl", + SecretKey: "SecretKey", + "For safety, must use secret key": "Voor de veiligheid moet je de secret key gebruiken", + "Device Token": "Apparaat Token", + Platform: "Platform", + iOS: "iOS", + Android: "Android", + Huawei: "Huawei", + High: "Hoog", + Retry: "Opnieuw", + Topic: "Onderwerp", + "WeCom Bot Key": "WeCom Bot Sleutel", + "Setup Proxy": "Proxy instellen", + "Proxy Protocol": "Proxy Protocol", + "Proxy Server": "Proxy Server", + "Proxy server has authentication": "Proxy server heeft authenticatie", + User: "Gebruiker", + Installed: "Geïnstalleerd", + "Not installed": "Niet geïnstalleerd", + Running: "Actief", + "Not running": "Niet actief", + "Remove Token": "Verwijder Token", + Start: "Start", + Stop: "Stop", + "Uptime Kuma": "Uptime Kuma", + "Add New Status Page": "Voeg nieuwe status pagina toe", + Slug: "Slug", + "Accept characters:": "Geaccepteerde tekens:", + startOrEndWithOnly: "Start of eindig alleen met {0}", + "No consecutive dashes": "Geen opeenvolgende streepjes", + Next: "Volgende", + "The slug is already taken. Please choose another slug.": "De slug is al in gebruik. Kies een andere slug.", + "No Proxy": "Geen Proxy", + "HTTP Basic Auth": "HTTP Basic Auth", + "New Status Page": "Nieuwe Status Pagina", + "Page Not Found": "Pagina Niet gevonden", + "Reverse Proxy": "Reverse Proxy", + Backup: "Backup", + About: "Over", + wayToGetCloudflaredURL: "(Download cloudflared van {0})", + cloudflareWebsite: "Cloudflare Website", + "Message:": "Bericht:", + "Don't know how to get the token? Please read the guide:": "Lees de uitleg als je niet weet hoe je een token krijgt:", + "The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "De huidge verbinding kan worden verbroken als je momenteel bent verbonden met Cloudflare Tunnel. Weet je zeker dat je het wilt stoppen? Typ je huidige wachtwoord om het te bevestigen.", + "Other Software": "Andere Software", + "For example: nginx, Apache and Traefik.": "Bijvoorbeeld: nginx, Apache and Traefik.", + "Please read": "Lees alstublieft", + "Subject:": "Onderwerp:", + "Valid To:": "Geldig Tot:", + "Days Remaining:": "Dagen Resterend:", + "Issuer:": "Uitgever:", + "Fingerprint:": "Vingerafruk:", + "No status pages": "Geen status pagina's", + "Domain Name Expiry Notification": "Domein Naam Verloop Notificatie", + Proxy: "Proxy", + "Date Created": "Datum Aangemaakt", + onebotHttpAddress: "OneBot HTTP Adres", + onebotMessageType: "OneBot Bericht Type", + onebotGroupMessage: "Groep", + onebotPrivateMessage: "Privé", + onebotUserOrGroupId: "Groep/Gebruiker ID", + onebotSafetyTips: "Voor de veiligheid moet een toegangssleutel worden ingesteld", + "PushDeer Key": "PushDeer Key", + "Footer Text": "Footer Tekst", + "Show Powered By": "Laat 'Mogeljik gemaakt door' zien", + "Domain Names": "Domein Namen", }; From e0966e55c8b5ba97b4880e07d1d08d7382427e98 Mon Sep 17 00:00:00 2001 From: Nelson Chan Date: Wed, 20 Apr 2022 15:01:13 +0800 Subject: [PATCH 07/69] Fix: Handle disabled auth in user dropdown --- src/layouts/Layout.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/layouts/Layout.vue b/src/layouts/Layout.vue index 293409a0..e7ec16b9 100644 --- a/src/layouts/Layout.vue +++ b/src/layouts/Layout.vue @@ -38,7 +38,10 @@