mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-08-09 12:21:22 +08:00
Added JSDoc to ESLint (#3529)
* Added JSDoc to eslint rules Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com> * Fixed JSDoc eslint errors Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com> * Update the check-linters workflow to Node.js 20 --------- Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com> Co-authored-by: Louis Lam <louislam@users.noreply.github.com>
This commit is contained in:
@@ -9,9 +9,9 @@ const dayjs = require("dayjs");
|
||||
|
||||
/**
|
||||
* Login to web app
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
* @returns {Promise<(Bean|null)>}
|
||||
* @param {string} username Username to login with
|
||||
* @param {string} password Password to login with
|
||||
* @returns {Promise<(Bean|null)>} User or null if login failed
|
||||
*/
|
||||
exports.login = async function (username, password) {
|
||||
if (typeof username !== "string" || typeof password !== "string") {
|
||||
@@ -39,6 +39,7 @@ exports.login = async function (username, password) {
|
||||
/**
|
||||
* Validate a provided API key
|
||||
* @param {string} key API key to verify
|
||||
* @returns {boolean} API is ok?
|
||||
*/
|
||||
async function verifyAPIKey(key) {
|
||||
if (typeof key !== "string") {
|
||||
@@ -73,9 +74,10 @@ async function verifyAPIKey(key) {
|
||||
|
||||
/**
|
||||
* Custom authorizer for express-basic-auth
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
* @param {authCallback} callback
|
||||
* @param {string} username Username to login with
|
||||
* @param {string} password Password to login with
|
||||
* @param {authCallback} callback Callback to handle login result
|
||||
* @returns {void}
|
||||
*/
|
||||
function apiAuthorizer(username, password, callback) {
|
||||
// API Rate Limit
|
||||
@@ -99,9 +101,10 @@ function apiAuthorizer(username, password, callback) {
|
||||
|
||||
/**
|
||||
* Custom authorizer for express-basic-auth
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
* @param {authCallback} callback
|
||||
* @param {string} username Username to login with
|
||||
* @param {string} password Password to login with
|
||||
* @param {authCallback} callback Callback to handle login result
|
||||
* @returns {void}
|
||||
*/
|
||||
function userAuthorizer(username, password, callback) {
|
||||
// Login Rate Limit
|
||||
@@ -126,7 +129,8 @@ function userAuthorizer(username, password, callback) {
|
||||
* Use basic auth if auth is not disabled
|
||||
* @param {express.Request} req Express request object
|
||||
* @param {express.Response} res Express response object
|
||||
* @param {express.NextFunction} next
|
||||
* @param {express.NextFunction} next Next handler in chain
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.basicAuth = async function (req, res, next) {
|
||||
const middleware = basicAuth({
|
||||
@@ -148,7 +152,8 @@ exports.basicAuth = async function (req, res, next) {
|
||||
* Use use API Key if API keys enabled, else use basic auth
|
||||
* @param {express.Request} req Express request object
|
||||
* @param {express.Response} res Express response object
|
||||
* @param {express.NextFunction} next
|
||||
* @param {express.NextFunction} next Next handler in chain
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.apiAuth = async function (req, res, next) {
|
||||
if (!await Settings.get("disableAuth")) {
|
||||
|
@@ -15,6 +15,7 @@ class CacheableDnsHttpAgent {
|
||||
|
||||
/**
|
||||
* Register/Disable cacheable to global agents
|
||||
* @returns {void}
|
||||
*/
|
||||
static async update() {
|
||||
log.debug("CacheableDnsHttpAgent", "update");
|
||||
@@ -40,14 +41,15 @@ class CacheableDnsHttpAgent {
|
||||
/**
|
||||
* Attach cacheable to HTTP agent
|
||||
* @param {http.Agent} agent Agent to install
|
||||
* @returns {void}
|
||||
*/
|
||||
static install(agent) {
|
||||
this.cacheable.install(agent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var {https.AgentOptions} agentOptions
|
||||
* @return {https.Agent}
|
||||
* @param {https.AgentOptions} agentOptions Options to pass to HTTPS agent
|
||||
* @returns {https.Agent} The new HTTPS agent
|
||||
*/
|
||||
static getHttpsAgent(agentOptions) {
|
||||
if (!this.enable) {
|
||||
@@ -63,8 +65,8 @@ class CacheableDnsHttpAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* @var {http.AgentOptions} agentOptions
|
||||
* @return {https.Agents}
|
||||
* @param {http.AgentOptions} agentOptions Options to pass to the HTTP agent
|
||||
* @returns {https.Agents} The new HTTP agent
|
||||
*/
|
||||
static getHttpAgent(agentOptions) {
|
||||
if (!this.enable) {
|
||||
|
@@ -12,7 +12,7 @@ const checkVersion = require("./check-version");
|
||||
/**
|
||||
* Send list of notification providers to client
|
||||
* @param {Socket} socket Socket.io socket instance
|
||||
* @returns {Promise<Bean[]>}
|
||||
* @returns {Promise<Bean[]>} List of notifications
|
||||
*/
|
||||
async function sendNotificationList(socket) {
|
||||
const timeLogger = new TimeLogger();
|
||||
@@ -40,8 +40,8 @@ async function sendNotificationList(socket) {
|
||||
* Send Heartbeat History list to socket
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @param {number} monitorID ID of monitor to send heartbeat history
|
||||
* @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only
|
||||
* @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list
|
||||
* @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only
|
||||
* @param {boolean} overwrite Overwrite client-side's heartbeat list
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
|
||||
@@ -71,8 +71,8 @@ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite =
|
||||
* Important Heart beat list (aka event list)
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @param {number} monitorID ID of monitor to send heartbeat history
|
||||
* @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only
|
||||
* @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list
|
||||
* @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only
|
||||
* @param {boolean} overwrite Overwrite client-side's heartbeat list
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
|
||||
@@ -100,7 +100,7 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove
|
||||
/**
|
||||
* Emit proxy list to client
|
||||
* @param {Socket} socket Socket.io socket instance
|
||||
* @return {Promise<Bean[]>}
|
||||
* @returns {Promise<Bean[]>} List of proxies
|
||||
*/
|
||||
async function sendProxyList(socket) {
|
||||
const timeLogger = new TimeLogger();
|
||||
@@ -141,7 +141,7 @@ async function sendAPIKeyList(socket) {
|
||||
/**
|
||||
* Emits the version information to the client.
|
||||
* @param {Socket} socket Socket.io socket instance
|
||||
* @param {boolean} hideVersion
|
||||
* @param {boolean} hideVersion Should we hide the version information in the response?
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sendInfo(socket, hideVersion = false) {
|
||||
@@ -165,7 +165,7 @@ async function sendInfo(socket, hideVersion = false) {
|
||||
/**
|
||||
* Send list of docker hosts to client
|
||||
* @param {Socket} socket Socket.io socket instance
|
||||
* @returns {Promise<Bean[]>}
|
||||
* @returns {Promise<Bean[]>} List of docker hosts
|
||||
*/
|
||||
async function sendDockerHostList(socket) {
|
||||
const timeLogger = new TimeLogger();
|
||||
|
@@ -101,7 +101,8 @@ class Database {
|
||||
|
||||
/**
|
||||
* Initialize the data directory
|
||||
* @param {Object} args Arguments to initialize DB with
|
||||
* @param {object} args Arguments to initialize DB with
|
||||
* @returns {void}
|
||||
*/
|
||||
static initDataDir(args) {
|
||||
// Data Directory (must be end with "/")
|
||||
@@ -154,11 +155,11 @@ class Database {
|
||||
|
||||
/**
|
||||
* Connect to the database
|
||||
* @param {boolean} [testMode=false] Should the connection be
|
||||
* @param {boolean} testMode Should the connection be
|
||||
* started in test mode?
|
||||
* @param {boolean} [autoloadModels=true] Should models be
|
||||
* @param {boolean} autoloadModels Should models be
|
||||
* automatically loaded?
|
||||
* @param {boolean} [noLog=false] Should logs not be output?
|
||||
* @param {boolean} noLog Should logs not be output?
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async connect(testMode = false, autoloadModels = true, noLog = false) {
|
||||
@@ -312,6 +313,10 @@ class Database {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the database
|
||||
* @returns {void}
|
||||
*/
|
||||
static async patch() {
|
||||
// Still need to keep this for old versions of Uptime Kuma
|
||||
if (Database.dbConfig.type === "sqlite") {
|
||||
@@ -497,8 +502,8 @@ class Database {
|
||||
* Patch database using new patching process
|
||||
* Used it patch2() only
|
||||
* @private
|
||||
* @param sqlFilename
|
||||
* @param databasePatchedFiles
|
||||
* @param {string} sqlFilename Name of SQL file to load
|
||||
* @param {object} databasePatchedFiles Patch status of database files
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async patch2Recursion(sqlFilename, databasePatchedFiles) {
|
||||
@@ -533,7 +538,7 @@ class Database {
|
||||
|
||||
/**
|
||||
* Load an SQL file and execute it
|
||||
* @param filename Filename of SQL file to import
|
||||
* @param {string} filename Filename of SQL file to import
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async importSQLFile(filename) {
|
||||
@@ -567,7 +572,7 @@ class Database {
|
||||
|
||||
/**
|
||||
* Aquire a direct connection to database
|
||||
* @returns {any}
|
||||
* @returns {any} Database connection
|
||||
*/
|
||||
static getBetterSQLite3Database() {
|
||||
return R.knex.client.acquireConnection();
|
||||
@@ -604,7 +609,10 @@ class Database {
|
||||
process.removeListener("unhandledRejection", listener);
|
||||
}
|
||||
|
||||
/** Get the size of the database */
|
||||
/**
|
||||
* Get the size of the database
|
||||
* @returns {number} Size of database
|
||||
*/
|
||||
static getSize() {
|
||||
log.debug("db", "Database.getSize()");
|
||||
let stats = fs.statSync(Database.sqlitePath);
|
||||
|
@@ -14,10 +14,10 @@ class DockerHost {
|
||||
|
||||
/**
|
||||
* Save a docker host
|
||||
* @param {Object} dockerHost Docker host to save
|
||||
* @param {object} dockerHost Docker host to save
|
||||
* @param {?number} dockerHostID ID of the docker host to update
|
||||
* @param {number} userID ID of the user who adds the docker host
|
||||
* @returns {Promise<Bean>}
|
||||
* @returns {Promise<Bean>} Updated docker host
|
||||
*/
|
||||
static async save(dockerHost, dockerHostID, userID) {
|
||||
let bean;
|
||||
@@ -64,7 +64,7 @@ class DockerHost {
|
||||
|
||||
/**
|
||||
* Fetches the amount of containers on the Docker host
|
||||
* @param {Object} dockerHost Docker host to check for
|
||||
* @param {object} dockerHost Docker host to check for
|
||||
* @returns {number} Total amount of containers on the host
|
||||
*/
|
||||
static async testDockerHost(dockerHost) {
|
||||
@@ -108,6 +108,8 @@ class DockerHost {
|
||||
/**
|
||||
* Since axios 0.27.X, it does not accept `tcp://` protocol.
|
||||
* Change it to `http://` on the fly in order to fix it. (https://github.com/louislam/uptime-kuma/issues/2165)
|
||||
* @param {any} url URL to fix
|
||||
* @returns {any} URL with tcp:// replaced by http://
|
||||
*/
|
||||
static patchDockerURL(url) {
|
||||
if (typeof url === "string") {
|
||||
@@ -129,11 +131,10 @@ class DockerHost {
|
||||
* 'data/docker-tls/example.com/' would be searched for certificate files),
|
||||
* then 'ca.pem', 'key.pem' and 'cert.pem' files are included in the agent options.
|
||||
* File names can also be overridden via 'DOCKER_TLS_FILE_NAME_(CA|KEY|CERT)'.
|
||||
*
|
||||
* @param {String} dockerType i.e. "tcp" or "socket"
|
||||
* @param {String} url The docker host URL rewritten to https://
|
||||
* @return {Object}
|
||||
* */
|
||||
* @param {string} dockerType i.e. "tcp" or "socket"
|
||||
* @param {string} url The docker host URL rewritten to https://
|
||||
* @returns {object} HTTP agent options
|
||||
*/
|
||||
static getHttpsAgentOptions(dockerType, url) {
|
||||
let baseOptions = {
|
||||
maxCachedSessions: 0,
|
||||
|
@@ -3,8 +3,8 @@ const jsesc = require("jsesc");
|
||||
/**
|
||||
* Returns a string that represents the javascript that is required to insert the Google Analytics scripts
|
||||
* into a webpage.
|
||||
* @param tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script.
|
||||
* @returns {string}
|
||||
* @param {string} tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script.
|
||||
* @returns {string} HTML script tags to inject into page
|
||||
*/
|
||||
function getGoogleAnalyticsScript(tagId) {
|
||||
let escapedTagId = jsesc(tagId, { isScriptContext: true });
|
||||
|
@@ -10,7 +10,7 @@ let ImageDataURI = (() => {
|
||||
/**
|
||||
* Decode the data:image/ URI
|
||||
* @param {string} dataURI data:image/ URI to decode
|
||||
* @returns {?Object} An object with properties "imageType" and "dataBase64".
|
||||
* @returns {?object} An object with properties "imageType" and "dataBase64".
|
||||
* The former is the image type, e.g., "png", and the latter is a base64
|
||||
* encoded string of the image's binary data. If it fails to parse, returns
|
||||
* null instead of an object.
|
||||
@@ -52,8 +52,8 @@ let ImageDataURI = (() => {
|
||||
/**
|
||||
* Write data URI to file
|
||||
* @param {string} dataURI data:image/ URI
|
||||
* @param {string} [filePath] Path to write file to
|
||||
* @returns {Promise<string>}
|
||||
* @param {string} filePath Path to write file to
|
||||
* @returns {Promise<string|void>} Write file error
|
||||
*/
|
||||
function outputFile(dataURI, filePath) {
|
||||
filePath = filePath || "./";
|
||||
|
@@ -39,7 +39,10 @@ const initBackgroundJobs = async function () {
|
||||
|
||||
};
|
||||
|
||||
/** Stop all background jobs if running */
|
||||
/**
|
||||
* Stop all background jobs if running
|
||||
* @returns {void}
|
||||
*/
|
||||
const stopBackgroundJobs = function () {
|
||||
for (const job of jobs) {
|
||||
if (job.croner) {
|
||||
|
@@ -7,7 +7,7 @@ const DEFAULT_KEEP_PERIOD = 180;
|
||||
|
||||
/**
|
||||
* Clears old data from the heartbeat table of the database.
|
||||
* @return {Promise<void>} A promise that resolves when the data has been cleared.
|
||||
* @returns {Promise<void>} A promise that resolves when the data has been cleared.
|
||||
*/
|
||||
|
||||
const clearOldData = async () => {
|
||||
|
@@ -4,7 +4,7 @@ const Database = require("../database");
|
||||
|
||||
/**
|
||||
* Run incremental_vacuum and checkpoint the WAL.
|
||||
* @return {Promise<void>} A promise that resolves when the process is finished.
|
||||
* @returns {Promise<void>} A promise that resolves when the process is finished.
|
||||
*/
|
||||
|
||||
const incrementalVacuum = async () => {
|
||||
|
@@ -19,7 +19,7 @@ class APIKey extends BeanModel {
|
||||
|
||||
/**
|
||||
* Returns an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
@@ -37,7 +37,7 @@ class APIKey extends BeanModel {
|
||||
/**
|
||||
* Returns an object that ready to parse to JSON with sensitive fields
|
||||
* removed
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toPublicJSON() {
|
||||
return {
|
||||
@@ -53,9 +53,9 @@ class APIKey extends BeanModel {
|
||||
|
||||
/**
|
||||
* Create a new API Key and store it in the database
|
||||
* @param {Object} key Object sent by client
|
||||
* @param {object} key Object sent by client
|
||||
* @param {int} userID ID of socket user
|
||||
* @returns {Promise<bean>}
|
||||
* @returns {Promise<bean>} API key
|
||||
*/
|
||||
static async save(key, userID) {
|
||||
let bean;
|
||||
|
@@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
class DockerHost extends BeanModel {
|
||||
/**
|
||||
* Returns an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
|
@@ -4,10 +4,12 @@ const { R } = require("redbean-node");
|
||||
class Group extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @param {boolean} [showTags=false] Should the JSON include monitor tags
|
||||
* @returns {Object}
|
||||
* Return an object that ready to parse to JSON for public Only show
|
||||
* necessary data to public
|
||||
* @param {boolean} showTags Should the JSON include monitor tags
|
||||
* @param {boolean} certExpiry Should JSON include info about
|
||||
* certificate expiry?
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toPublicJSON(showTags = false, certExpiry = false) {
|
||||
let monitorBeanList = await this.getMonitorList();
|
||||
@@ -27,7 +29,7 @@ class Group extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get all monitors
|
||||
* @returns {Bean[]}
|
||||
* @returns {Bean[]} List of monitors
|
||||
*/
|
||||
async getMonitorList() {
|
||||
return R.convertToBeans("monitor", await R.getAll(`
|
||||
|
@@ -12,7 +12,7 @@ class Heartbeat extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toPublicJSON() {
|
||||
return {
|
||||
@@ -25,7 +25,7 @@ class Heartbeat extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
|
@@ -5,7 +5,7 @@ class Incident extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toPublicJSON() {
|
||||
return {
|
||||
|
@@ -11,7 +11,7 @@ class Maintenance extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toPublicJSON() {
|
||||
|
||||
@@ -98,7 +98,7 @@ class Maintenance extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @param {string} timezone If not specified, the timeRange will be in UTC
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toJSON(timezone = null) {
|
||||
return this.toPublicJSON(timezone);
|
||||
@@ -142,7 +142,7 @@ class Maintenance extends BeanModel {
|
||||
/**
|
||||
* Convert data from socket to bean
|
||||
* @param {Bean} bean Bean to fill in
|
||||
* @param {Object} obj Data to fill bean with
|
||||
* @param {object} obj Data to fill bean with
|
||||
* @returns {Bean} Filled bean
|
||||
*/
|
||||
static async jsonToBean(bean, obj) {
|
||||
@@ -188,7 +188,7 @@ class Maintenance extends BeanModel {
|
||||
|
||||
/**
|
||||
* Throw error if cron is invalid
|
||||
* @param cron
|
||||
* @param {string|Date} cron Pattern or date
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async validateCron(cron) {
|
||||
@@ -198,6 +198,8 @@ class Maintenance extends BeanModel {
|
||||
|
||||
/**
|
||||
* Run the cron
|
||||
* @param {boolean} throwError Should an error be thrown on failure
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async run(throwError = false) {
|
||||
if (this.beanMeta.job) {
|
||||
@@ -290,6 +292,10 @@ class Maintenance extends BeanModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timeslots where maintenance is running
|
||||
* @returns {object|null} Maintenance time slot
|
||||
*/
|
||||
getRunningTimeslot() {
|
||||
let start = dayjs(this.beanMeta.job.nextRun(dayjs().add(-this.duration, "second").toDate()));
|
||||
let end = start.add(this.duration, "second");
|
||||
@@ -305,6 +311,10 @@ class Maintenance extends BeanModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the maintenance
|
||||
* @returns {void}
|
||||
*/
|
||||
stop() {
|
||||
if (this.beanMeta.job) {
|
||||
this.beanMeta.job.stop();
|
||||
@@ -312,10 +322,18 @@ class Maintenance extends BeanModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this maintenance currently active
|
||||
* @returns {boolean} The maintenance is active?
|
||||
*/
|
||||
async isUnderMaintenance() {
|
||||
return (await this.getStatus()) === "under-maintenance";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timezone of the maintenance
|
||||
* @returns {string} timezone
|
||||
*/
|
||||
async getTimezone() {
|
||||
if (!this.timezone || this.timezone === "SAME_AS_SERVER") {
|
||||
return await UptimeKumaServer.getInstance().getTimezone();
|
||||
@@ -323,10 +341,18 @@ class Maintenance extends BeanModel {
|
||||
return this.timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset for timezone
|
||||
* @returns {string} offset
|
||||
*/
|
||||
async getTimezoneOffset() {
|
||||
return dayjs.tz(dayjs(), await this.getTimezone()).format("Z");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current status of the maintenance
|
||||
* @returns {string} Current status
|
||||
*/
|
||||
async getStatus() {
|
||||
if (!this.active) {
|
||||
return "inactive";
|
||||
|
@@ -34,9 +34,12 @@ const Database = require("../database");
|
||||
class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @returns {Object}
|
||||
* Return an object that ready to parse to JSON for public Only show
|
||||
* necessary data to public
|
||||
* @param {boolean} showTags Include tags in JSON
|
||||
* @param {boolean} certExpiry Include certificate expiry info in
|
||||
* JSON
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toPublicJSON(showTags = false, certExpiry = false) {
|
||||
let obj = {
|
||||
@@ -65,7 +68,9 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @param {boolean} includeSensitiveData Include sensitive data in
|
||||
* JSON
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toJSON(includeSensitiveData = true) {
|
||||
|
||||
@@ -183,9 +188,9 @@ class Monitor extends BeanModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the monitor is active based on itself and its parents
|
||||
* @returns {Promise<Boolean>}
|
||||
*/
|
||||
* Checks if the monitor is active based on itself and its parents
|
||||
* @returns {Promise<boolean>} Is the monitor active?
|
||||
*/
|
||||
async isActive() {
|
||||
const parentActive = await Monitor.isParentActive(this.id);
|
||||
|
||||
@@ -194,7 +199,8 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get all tags applied to this monitor
|
||||
* @returns {Promise<LooseObject<any>[]>}
|
||||
* @returns {Promise<LooseObject<any>[]>} List of tags on the
|
||||
* monitor
|
||||
*/
|
||||
async getTags() {
|
||||
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]);
|
||||
@@ -203,7 +209,8 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Gets certificate expiry for this monitor
|
||||
* @param {number} monitorID ID of monitor to send
|
||||
* @returns {Promise<LooseObject<any>>}
|
||||
* @returns {Promise<LooseObject<any>>} Certificate expiry info for
|
||||
* monitor
|
||||
*/
|
||||
async getCertExpiry(monitorID) {
|
||||
let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
|
||||
@@ -228,7 +235,9 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Encode user and password to Base64 encoding
|
||||
* for HTTP "basic" auth, as per RFC-7617
|
||||
* @returns {string}
|
||||
* @param {string} user Username to encode
|
||||
* @param {string} pass Password to encode
|
||||
* @returns {string} Encoded username:password
|
||||
*/
|
||||
encodeBase64(user, pass) {
|
||||
return Buffer.from(user + ":" + pass).toString("base64");
|
||||
@@ -236,7 +245,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Is the TLS expiry notification enabled?
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} Enabled?
|
||||
*/
|
||||
isEnabledExpiryNotification() {
|
||||
return Boolean(this.expiryNotification);
|
||||
@@ -244,7 +253,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Parse to boolean
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} Should TLS errors be ignored?
|
||||
*/
|
||||
getIgnoreTls() {
|
||||
return Boolean(this.ignoreTls);
|
||||
@@ -252,7 +261,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Parse to boolean
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} Is the monitor in upside down mode?
|
||||
*/
|
||||
isUpsideDown() {
|
||||
return Boolean(this.upsideDown);
|
||||
@@ -260,7 +269,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Parse to boolean
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} Invert keyword match?
|
||||
*/
|
||||
isInvertKeyword() {
|
||||
return Boolean(this.invertKeyword);
|
||||
@@ -268,7 +277,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Parse to boolean
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} Enable TLS for gRPC?
|
||||
*/
|
||||
getGrpcEnableTls() {
|
||||
return Boolean(this.grpcEnableTls);
|
||||
@@ -276,7 +285,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get accepted status codes
|
||||
* @returns {Object}
|
||||
* @returns {object} Accepted status codes
|
||||
*/
|
||||
getAcceptedStatuscodes() {
|
||||
return JSON.parse(this.accepted_statuscodes_json);
|
||||
@@ -289,6 +298,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Start monitor
|
||||
* @param {Server} io Socket server instance
|
||||
* @returns {void}
|
||||
*/
|
||||
start(io) {
|
||||
let previousBeat = null;
|
||||
@@ -980,7 +990,10 @@ class Monitor extends BeanModel {
|
||||
|
||||
};
|
||||
|
||||
/** Get a heartbeat and handle errors */
|
||||
/**
|
||||
* Get a heartbeat and handle errors7
|
||||
* @returns {void}
|
||||
*/
|
||||
const safeBeat = async () => {
|
||||
try {
|
||||
await beat();
|
||||
@@ -1008,10 +1021,10 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Make a request using axios
|
||||
* @param {Object} options Options for Axios
|
||||
* @param {object} options Options for Axios
|
||||
* @param {boolean} finalCall Should this be the final call i.e
|
||||
* don't retry on faliure
|
||||
* @returns {Object} Axios response
|
||||
* don't retry on failure
|
||||
* @returns {object} Axios response
|
||||
*/
|
||||
async makeAxiosRequest(options, finalCall = false) {
|
||||
try {
|
||||
@@ -1046,7 +1059,10 @@ class Monitor extends BeanModel {
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop monitor */
|
||||
/**
|
||||
* Stop monitor
|
||||
* @returns {void}
|
||||
*/
|
||||
stop() {
|
||||
clearTimeout(this.heartbeatInterval);
|
||||
this.isStop = true;
|
||||
@@ -1056,7 +1072,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get prometheus instance
|
||||
* @returns {Prometheus|undefined}
|
||||
* @returns {Prometheus|undefined} Current prometheus instance
|
||||
*/
|
||||
getPrometheus() {
|
||||
return this.prometheus;
|
||||
@@ -1066,7 +1082,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)} Monitor URL
|
||||
*/
|
||||
getUrl() {
|
||||
try {
|
||||
@@ -1078,8 +1094,8 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Store TLS info to database
|
||||
* @param checkCertificateResult
|
||||
* @returns {Promise<Object>}
|
||||
* @param {object} checkCertificateResult Certificate to update
|
||||
* @returns {Promise<object>} Updated certificate
|
||||
*/
|
||||
async updateTlsInfo(checkCertificateResult) {
|
||||
let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
|
||||
@@ -1126,6 +1142,7 @@ class Monitor extends BeanModel {
|
||||
* @param {Server} io Socket server instance
|
||||
* @param {number} monitorID ID of monitor to send
|
||||
* @param {number} userID ID of user to send to
|
||||
* @returns {void}
|
||||
*/
|
||||
static async sendStats(io, monitorID, userID) {
|
||||
const hasClients = getTotalClientInRoom(io, userID) > 0;
|
||||
@@ -1143,6 +1160,10 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Send the average ping to user
|
||||
* @param {number} duration Hours
|
||||
* @param {Server} io Socket instance to send data to
|
||||
* @param {number} monitorID ID of monitor to read
|
||||
* @param {number} userID ID of user to send data to
|
||||
* @returns {void}
|
||||
*/
|
||||
static async sendAvgPing(duration, io, monitorID, userID) {
|
||||
const timeLogger = new TimeLogger();
|
||||
@@ -1168,6 +1189,7 @@ class Monitor extends BeanModel {
|
||||
* @param {Server} io Socket server instance
|
||||
* @param {number} monitorID ID of monitor to send
|
||||
* @param {number} userID ID of user to send to
|
||||
* @returns {void}
|
||||
*/
|
||||
static async sendCertInfo(io, monitorID, userID) {
|
||||
let tlsInfo = await R.findOne("monitor_tls_info", "monitor_id = ?", [
|
||||
@@ -1184,6 +1206,8 @@ class Monitor extends BeanModel {
|
||||
* https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime
|
||||
* @param {number} duration Hours
|
||||
* @param {number} monitorID ID of monitor to calculate
|
||||
* @param {boolean} forceNoCache Should the uptime be recalculated?
|
||||
* @returns {number} Uptime of monitor
|
||||
*/
|
||||
static async calcUptime(duration, monitorID, forceNoCache = false) {
|
||||
|
||||
@@ -1264,6 +1288,7 @@ class Monitor extends BeanModel {
|
||||
* @param {Server} io Socket server instance
|
||||
* @param {number} monitorID ID of monitor to send
|
||||
* @param {number} userID ID of user to send to
|
||||
* @returns {void}
|
||||
*/
|
||||
static async sendUptime(duration, io, monitorID, userID) {
|
||||
const uptime = await this.calcUptime(duration, monitorID);
|
||||
@@ -1338,6 +1363,7 @@ class Monitor extends BeanModel {
|
||||
* @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
|
||||
* @returns {void}
|
||||
*/
|
||||
static async sendNotification(isFirstBeat, monitor, bean) {
|
||||
if (!isFirstBeat || bean.status === DOWN) {
|
||||
@@ -1378,7 +1404,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Get list of notification providers for a given monitor
|
||||
* @param {Monitor} monitor Monitor to get notification providers for
|
||||
* @returns {Promise<LooseObject<any>[]>}
|
||||
* @returns {Promise<LooseObject<any>[]>} List of notifications
|
||||
*/
|
||||
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 ", [
|
||||
@@ -1389,7 +1415,8 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* checks certificate chain for expiring certificates
|
||||
* @param {Object} tlsInfoObject Information about certificate
|
||||
* @param {object} tlsInfoObject Information about certificate
|
||||
* @returns {void}
|
||||
*/
|
||||
async checkCertExpiryNotifications(tlsInfoObject) {
|
||||
if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) {
|
||||
@@ -1476,7 +1503,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Get the status of the previous heartbeat
|
||||
* @param {number} monitorID ID of monitor to check
|
||||
* @returns {Promise<LooseObject<any>>}
|
||||
* @returns {Promise<LooseObject<any>>} Previous heartbeat
|
||||
*/
|
||||
static async getPreviousHeartbeat(monitorID) {
|
||||
return await R.getRow(`
|
||||
@@ -1490,7 +1517,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Check if monitor is under maintenance
|
||||
* @param {number} monitorID ID of monitor to check
|
||||
* @returns {Promise<boolean>}
|
||||
* @returns {Promise<boolean>} Is the monitor under maintenance
|
||||
*/
|
||||
static async isUnderMaintenance(monitorID) {
|
||||
const maintenanceIDList = await R.getCol(`
|
||||
@@ -1513,7 +1540,11 @@ class Monitor extends BeanModel {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Make sure monitor interval is between bounds */
|
||||
/**
|
||||
* Make sure monitor interval is between bounds
|
||||
* @returns {void}
|
||||
* @throws Interval is outside of range
|
||||
*/
|
||||
validate() {
|
||||
if (this.interval > MAX_INTERVAL_SECOND) {
|
||||
throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`);
|
||||
@@ -1526,7 +1557,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Gets Parent of the monitor
|
||||
* @param {number} monitorID ID of monitor to get
|
||||
* @returns {Promise<LooseObject<any>>}
|
||||
* @returns {Promise<LooseObject<any>>} Parent
|
||||
*/
|
||||
static async getParent(monitorID) {
|
||||
return await R.getRow(`
|
||||
@@ -1542,7 +1573,7 @@ class Monitor extends BeanModel {
|
||||
/**
|
||||
* Gets all Children of the monitor
|
||||
* @param {number} monitorID ID of monitor to get
|
||||
* @returns {Promise<LooseObject<any>>}
|
||||
* @returns {Promise<LooseObject<any>>} Children
|
||||
*/
|
||||
static async getChildren(monitorID) {
|
||||
return await R.getAll(`
|
||||
@@ -1555,7 +1586,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Gets Full Path-Name (Groups and Name)
|
||||
* @returns {Promise<String>}
|
||||
* @returns {Promise<string>} Full path name of this monitor
|
||||
*/
|
||||
async getPathName() {
|
||||
let path = this.name;
|
||||
@@ -1575,8 +1606,8 @@ class Monitor extends BeanModel {
|
||||
|
||||
/**
|
||||
* Gets recursive all child ids
|
||||
* @param {number} monitorID ID of the monitor to get
|
||||
* @returns {Promise<Array>}
|
||||
* @param {number} monitorID ID of the monitor to get
|
||||
* @returns {Promise<Array>} IDs of all children
|
||||
*/
|
||||
static async getAllChildrenIDs(monitorID) {
|
||||
const childs = await Monitor.getChildren(monitorID);
|
||||
@@ -1607,10 +1638,10 @@ class Monitor extends BeanModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks recursive if parent (ancestors) are active
|
||||
* @param {number} monitorID ID of the monitor to get
|
||||
* @returns {Promise<Boolean>}
|
||||
*/
|
||||
* Checks recursive if parent (ancestors) are active
|
||||
* @param {number} monitorID ID of the monitor to get
|
||||
* @returns {Promise<boolean>} Is the parent monitor active?
|
||||
*/
|
||||
static async isParentActive(monitorID) {
|
||||
const parent = await Monitor.getParent(monitorID);
|
||||
|
||||
|
@@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
class Proxy extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
|
@@ -14,10 +14,11 @@ class StatusPage extends BeanModel {
|
||||
static domainMappingList = { };
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Response} response
|
||||
* @param {string} indexHTML
|
||||
* @param {string} slug
|
||||
* Handle responses to status page
|
||||
* @param {Response} response Response object
|
||||
* @param {string} indexHTML HTML to render
|
||||
* @param {string} slug Status page slug
|
||||
* @returns {void}
|
||||
*/
|
||||
static async handleStatusPageResponse(response, indexHTML, slug) {
|
||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||
@@ -33,8 +34,9 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* SSR for status pages
|
||||
* @param {string} indexHTML
|
||||
* @param {StatusPage} statusPage
|
||||
* @param {string} indexHTML HTML page to render
|
||||
* @param {StatusPage} statusPage Status page populate HTML with
|
||||
* @returns {void}
|
||||
*/
|
||||
static async renderHTML(indexHTML, statusPage) {
|
||||
const $ = cheerio.load(indexHTML);
|
||||
@@ -87,7 +89,8 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get all status page data in one call
|
||||
* @param {StatusPage} statusPage
|
||||
* @param {StatusPage} statusPage Status page to get data for
|
||||
* @returns {object} Status page data
|
||||
*/
|
||||
static async getStatusPageData(statusPage) {
|
||||
const config = await statusPage.toPublicJSON();
|
||||
@@ -142,7 +145,7 @@ class StatusPage extends BeanModel {
|
||||
* Send status page list to client
|
||||
* @param {Server} io io Socket server instance
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {Promise<Bean[]>}
|
||||
* @returns {Promise<Bean[]>} Status page list
|
||||
*/
|
||||
static async sendStatusPageList(io, socket) {
|
||||
let result = {};
|
||||
@@ -159,7 +162,7 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Update list of domain names
|
||||
* @param {string[]} domainNameList
|
||||
* @param {string[]} domainNameList List of status page domains
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async updateDomainNameList(domainNameList) {
|
||||
@@ -203,7 +206,7 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get list of domain names
|
||||
* @returns {Object[]}
|
||||
* @returns {object[]} List of status page domains
|
||||
*/
|
||||
getDomainNameList() {
|
||||
let domainList = [];
|
||||
@@ -219,7 +222,7 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toJSON() {
|
||||
return {
|
||||
@@ -243,7 +246,7 @@ class StatusPage extends BeanModel {
|
||||
/**
|
||||
* Return an object that ready to parse to JSON for public
|
||||
* Only show necessary data to public
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
async toPublicJSON() {
|
||||
return {
|
||||
@@ -264,7 +267,8 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Convert slug to status page ID
|
||||
* @param {string} slug
|
||||
* @param {string} slug Status page slug
|
||||
* @returns {Promise<number>} ID of status page
|
||||
*/
|
||||
static async slugToID(slug) {
|
||||
return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [
|
||||
@@ -274,7 +278,7 @@ class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Get path to the icon for the page
|
||||
* @returns {string}
|
||||
* @returns {string} Path
|
||||
*/
|
||||
getIcon() {
|
||||
if (!this.icon) {
|
||||
@@ -287,7 +291,7 @@ class StatusPage extends BeanModel {
|
||||
/**
|
||||
* Get list of maintenances
|
||||
* @param {number} statusPageId ID of status page to get maintenance for
|
||||
* @returns {Object} Object representing maintenances sanitized for public
|
||||
* @returns {object} Object representing maintenances sanitized for public
|
||||
*/
|
||||
static async getMaintenanceList(statusPageId) {
|
||||
try {
|
||||
|
@@ -4,7 +4,7 @@ class Tag extends BeanModel {
|
||||
|
||||
/**
|
||||
* Return an object that ready to parse to JSON
|
||||
* @returns {Object}
|
||||
* @returns {object} Object ready to parse
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
|
@@ -7,7 +7,7 @@ class User extends BeanModel {
|
||||
* Reset user password
|
||||
* Fix #1510, as in the context reset-password.js, there is no auto model mapping. Call this static function instead.
|
||||
* @param {number} userID ID of user to update
|
||||
* @param {string} newPassword
|
||||
* @param {string} newPassword Users new password
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async resetPassword(userID, newPassword) {
|
||||
@@ -19,7 +19,7 @@ class User extends BeanModel {
|
||||
|
||||
/**
|
||||
* Reset this users password
|
||||
* @param {string} newPassword
|
||||
* @param {string} newPassword Users new password
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async resetPassword(newPassword) {
|
||||
|
@@ -3,10 +3,10 @@ class MonitorType {
|
||||
name = undefined;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Monitor} monitor
|
||||
* @param {Heartbeat} heartbeat
|
||||
* @param {UptimeKumaServer} server
|
||||
* Run the monitoring check on the given monitor
|
||||
* @param {Monitor} monitor Monitor to check
|
||||
* @param {Heartbeat} heartbeat Monitor heartbeat to update
|
||||
* @param {UptimeKumaServer} server Uptime Kuma server
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async check(monitor, heartbeat, server) {
|
||||
|
@@ -51,6 +51,11 @@ if (process.platform === "win32") {
|
||||
|
||||
log.debug("chrome", allowedList);
|
||||
|
||||
/**
|
||||
* Is the executable path allowed?
|
||||
* @param {string} executablePath Path to executable
|
||||
* @returns {Promise<boolean>} The executable is allowed?
|
||||
*/
|
||||
async function isAllowedChromeExecutable(executablePath) {
|
||||
console.log(config.args);
|
||||
if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") {
|
||||
@@ -61,6 +66,11 @@ async function isAllowedChromeExecutable(executablePath) {
|
||||
return allowedList.includes(executablePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current instance of the browser. If there isn't one, create
|
||||
* it.
|
||||
* @returns {Promise<Browser>} The browser
|
||||
*/
|
||||
async function getBrowser() {
|
||||
if (!browser) {
|
||||
let executablePath = await Settings.get("chromeExecutable");
|
||||
@@ -75,6 +85,11 @@ async function getBrowser() {
|
||||
return browser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the chrome executable path
|
||||
* @param {string} executablePath Path to chrome executable
|
||||
* @returns {Promise<string>} Executable path
|
||||
*/
|
||||
async function prepareChromeExecutable(executablePath) {
|
||||
// Special code for using the playwright_chromium
|
||||
if (typeof executablePath === "string" && executablePath.toLocaleLowerCase() === "#playwright_chromium") {
|
||||
@@ -121,6 +136,12 @@ async function prepareChromeExecutable(executablePath) {
|
||||
return executablePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the chrome executable
|
||||
* @param {any[]} executables Executables to search through
|
||||
* @returns {any} Executable
|
||||
* @throws Could not find executable
|
||||
*/
|
||||
function findChrome(executables) {
|
||||
// Use the last working executable, so we don't have to search for it again
|
||||
if (lastAutoDetectChromeExecutable) {
|
||||
@@ -138,6 +159,10 @@ function findChrome(executables) {
|
||||
throw new Error("Chromium not found, please specify Chromium executable path in the settings page.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset chrome
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function resetChrome() {
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
@@ -147,8 +172,8 @@ async function resetChrome() {
|
||||
|
||||
/**
|
||||
* Test if the chrome executable is valid and return the version
|
||||
* @param executablePath
|
||||
* @returns {Promise<string>}
|
||||
* @param {string} executablePath Path to executable
|
||||
* @returns {Promise<string>} Chrome version
|
||||
*/
|
||||
async function testChrome(executablePath) {
|
||||
try {
|
||||
@@ -175,6 +200,9 @@ class RealBrowserMonitorType extends MonitorType {
|
||||
|
||||
name = "real-browser";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async check(monitor, heartbeat, server) {
|
||||
const browser = await getBrowser();
|
||||
const context = await browser.newContext();
|
||||
|
@@ -13,9 +13,9 @@ class TailscalePing extends MonitorType {
|
||||
/**
|
||||
* Checks the ping status of the URL associated with the monitor.
|
||||
* It then parses the Tailscale ping command output to update the heatrbeat.
|
||||
*
|
||||
* @param {Object} monitor - The monitor object associated with the check.
|
||||
* @param {Object} heartbeat - The heartbeat object to update.
|
||||
* @param {object} monitor The monitor object associated with the check.
|
||||
* @param {object} heartbeat The heartbeat object to update.
|
||||
* @returns {Promise<void>}
|
||||
* @throws Will throw an error if checking Tailscale ping encounters any error
|
||||
*/
|
||||
async check(monitor, heartbeat) {
|
||||
@@ -31,9 +31,9 @@ class TailscalePing extends MonitorType {
|
||||
|
||||
/**
|
||||
* Runs the Tailscale ping command to the given URL.
|
||||
*
|
||||
* @param {string} hostname - The hostname to ping.
|
||||
* @returns {Promise<string>} - A Promise that resolves to the output of the Tailscale ping command
|
||||
* @param {string} hostname The hostname to ping.
|
||||
* @param {number} interval Interval to send ping
|
||||
* @returns {Promise<string>} A Promise that resolves to the output of the Tailscale ping command
|
||||
* @throws Will throw an error if the command execution encounters any error.
|
||||
*/
|
||||
async runTailscalePing(hostname, interval) {
|
||||
@@ -61,9 +61,9 @@ class TailscalePing extends MonitorType {
|
||||
|
||||
/**
|
||||
* Parses the output of the Tailscale ping command to update the heartbeat.
|
||||
*
|
||||
* @param {string} tailscaleOutput - The output of the Tailscale ping command.
|
||||
* @param {Object} heartbeat - The heartbeat object to update.
|
||||
* @param {string} tailscaleOutput The output of the Tailscale ping command.
|
||||
* @param {object} heartbeat The heartbeat object to update.
|
||||
* @returns {void}
|
||||
* @throws Will throw an eror if the output contains any unexpected string.
|
||||
*/
|
||||
parseTailscaleOutput(tailscaleOutput, heartbeat) {
|
||||
|
@@ -6,6 +6,9 @@ class Alerta extends NotificationProvider {
|
||||
|
||||
name = "alerta";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -7,6 +7,9 @@ class AlertNow extends NotificationProvider {
|
||||
|
||||
name = "AlertNow";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -7,6 +7,9 @@ const qs = require("qs");
|
||||
class AliyunSMS extends NotificationProvider {
|
||||
name = "AliyunSMS";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
@@ -78,9 +81,9 @@ class AliyunSMS extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Aliyun request sign
|
||||
* @param {Object} param Parameters object to sign
|
||||
* @param {object} param Parameters object to sign
|
||||
* @param {string} AccessKeySecret Secret key to sign parameters with
|
||||
* @returns {string}
|
||||
* @returns {string} Base64 encoded request
|
||||
*/
|
||||
sign(param, AccessKeySecret) {
|
||||
let param2 = {};
|
||||
@@ -122,7 +125,7 @@ class AliyunSMS extends NotificationProvider {
|
||||
/**
|
||||
* Convert status constant to string
|
||||
* @param {const} status The status constant
|
||||
* @returns {string}
|
||||
* @returns {string} Status
|
||||
*/
|
||||
statusToString(status) {
|
||||
switch (status) {
|
||||
|
@@ -5,6 +5,9 @@ class Apprise extends NotificationProvider {
|
||||
|
||||
name = "apprise";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const args = [ "-vv", "-b", msg, notification.appriseURL ];
|
||||
if (notification.title) {
|
||||
|
@@ -18,6 +18,9 @@ const successMessage = "Successes!";
|
||||
class Bark extends NotificationProvider {
|
||||
name = "Bark";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let barkEndpoint = notification.barkEndpoint;
|
||||
|
||||
@@ -45,8 +48,9 @@ class Bark extends NotificationProvider {
|
||||
/**
|
||||
* Add additional parameter for better on device styles (iOS 15
|
||||
* optimized)
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} postUrl URL to append parameters to
|
||||
* @returns {string}
|
||||
* @returns {string} Additional URL parameters
|
||||
*/
|
||||
appendAdditionalParameters(notification, postUrl) {
|
||||
// set icon to uptime kuma icon, 11kb should be fine
|
||||
@@ -70,7 +74,8 @@ class Bark extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Check if result is successful
|
||||
* @param {Object} result Axios response object
|
||||
* @param {object} result Axios response object
|
||||
* @returns {void}
|
||||
* @throws {Error} The status code is not in range 2xx
|
||||
*/
|
||||
checkResult(result) {
|
||||
@@ -84,10 +89,11 @@ class Bark extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Send the message
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} title Message title
|
||||
* @param {string} subtitle Message
|
||||
* @param {string} endpoint Endpoint to send request to
|
||||
* @returns {string}
|
||||
* @returns {string} Success message
|
||||
*/
|
||||
async postNotification(notification, title, subtitle, endpoint) {
|
||||
// url encode title and subtitle
|
||||
|
@@ -5,6 +5,9 @@ class ClickSendSMS extends NotificationProvider {
|
||||
|
||||
name = "clicksendsms";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -6,6 +6,9 @@ const Crypto = require("crypto");
|
||||
class DingDing extends NotificationProvider {
|
||||
name = "DingDing";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
@@ -39,8 +42,8 @@ class DingDing extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Send message to DingDing
|
||||
* @param {BeanModel} notification
|
||||
* @param {Object} params Parameters of message
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {object} params Parameters of message
|
||||
* @returns {boolean} True if successful else false
|
||||
*/
|
||||
async sendToDingDing(notification, params) {
|
||||
@@ -66,7 +69,7 @@ class DingDing extends NotificationProvider {
|
||||
* DingDing sign
|
||||
* @param {Date} timestamp Timestamp of message
|
||||
* @param {string} secretKey Secret key to sign data with
|
||||
* @returns {string}
|
||||
* @returns {string} Base64 encoded signature
|
||||
*/
|
||||
sign(timestamp, secretKey) {
|
||||
return Crypto
|
||||
@@ -78,7 +81,7 @@ class DingDing extends NotificationProvider {
|
||||
/**
|
||||
* Convert status constant to string
|
||||
* @param {const} status The status constant
|
||||
* @returns {string}
|
||||
* @returns {string} Status
|
||||
*/
|
||||
statusToString(status) {
|
||||
// TODO: Move to notification-provider.js to avoid repetition in classes
|
||||
|
@@ -6,6 +6,9 @@ class Discord extends NotificationProvider {
|
||||
|
||||
name = "discord";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ const { DOWN, UP } = require("../../src/util");
|
||||
class Feishu extends NotificationProvider {
|
||||
name = "Feishu";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let feishuWebHookUrl = notification.feishuWebHookUrl;
|
||||
|
@@ -7,6 +7,9 @@ const successMessage = "Sent Successfully.";
|
||||
class FlashDuty extends NotificationProvider {
|
||||
name = "FlashDuty";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
@@ -33,12 +36,12 @@ class FlashDuty extends NotificationProvider {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a monitor url from the monitors infomation
|
||||
* @param {Object} monitorInfo Monitor details
|
||||
* @returns {string|undefined}
|
||||
* @param {object} monitorInfo Monitor details
|
||||
* @returns {string|undefined} Monitor URL
|
||||
*/
|
||||
|
||||
genMonitorUrl(monitorInfo) {
|
||||
if (monitorInfo.type === "port" && monitorInfo.port) {
|
||||
return monitorInfo.hostname + ":" + monitorInfo.port;
|
||||
@@ -54,9 +57,9 @@ class FlashDuty extends NotificationProvider {
|
||||
* @param {BeanModel} notification Message title
|
||||
* @param {string} title Message
|
||||
* @param {string} body Message
|
||||
* @param {Object} monitorInfo Monitor details
|
||||
* @param {object} monitorInfo Monitor details
|
||||
* @param {string} eventStatus Monitor status (Info, Warning, Critical, Ok)
|
||||
* @returns {string}
|
||||
* @returns {string} Success message
|
||||
*/
|
||||
async postNotification(notification, title, body, monitorInfo, eventStatus) {
|
||||
const options = {
|
||||
|
@@ -5,6 +5,9 @@ class FreeMobile extends NotificationProvider {
|
||||
|
||||
name = "FreeMobile";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -6,6 +6,9 @@ class GoAlert extends NotificationProvider {
|
||||
|
||||
name = "GoAlert";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -8,6 +8,9 @@ class GoogleChat extends NotificationProvider {
|
||||
|
||||
name = "GoogleChat";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -5,6 +5,9 @@ class Gorush extends NotificationProvider {
|
||||
|
||||
name = "gorush";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class Gotify extends NotificationProvider {
|
||||
|
||||
name = "gotify";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -6,6 +6,9 @@ const defaultNotificationService = "notify";
|
||||
class HomeAssistant extends NotificationProvider {
|
||||
name = "HomeAssistant";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, message, monitor = null, heartbeat = null) {
|
||||
const notificationService = notification?.notificationService || defaultNotificationService;
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class Kook extends NotificationProvider {
|
||||
|
||||
name = "Kook";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let url = "https://www.kookapp.cn/api/v3/message/create";
|
||||
|
@@ -6,6 +6,9 @@ class Line extends NotificationProvider {
|
||||
|
||||
name = "line";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -7,6 +7,9 @@ class LineNotify extends NotificationProvider {
|
||||
|
||||
name = "LineNotify";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -6,6 +6,9 @@ class LunaSea extends NotificationProvider {
|
||||
|
||||
name = "lunasea";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let lunaseaurl = "";
|
||||
|
@@ -6,6 +6,9 @@ const { log } = require("../../src/util");
|
||||
class Matrix extends NotificationProvider {
|
||||
name = "matrix";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -6,6 +6,9 @@ class Mattermost extends NotificationProvider {
|
||||
|
||||
name = "mattermost";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -33,6 +33,9 @@ if (semver.lt(nodeVersion, "16.0.0")) {
|
||||
class Nostr extends NotificationProvider {
|
||||
name = "nostr";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
// All DMs should have same timestamp
|
||||
const createdAt = Math.floor(Date.now() / 1000);
|
||||
@@ -86,6 +89,11 @@ class Nostr extends NotificationProvider {
|
||||
return `${successfulRelays}/${relays.length} relays connected.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the private key for the sender
|
||||
* @param {string} sender Sender to retrieve key for
|
||||
* @returns {nip19.DecodeResult} Private key
|
||||
*/
|
||||
async getPrivateKey(sender) {
|
||||
try {
|
||||
const senderDecodeResult = await nip19.decode(sender);
|
||||
@@ -96,6 +104,11 @@ class Nostr extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public keys for recipients
|
||||
* @param {string} recipients Newline delimited list of recipients
|
||||
* @returns {nip19.DecodeResult[]} Public keys
|
||||
*/
|
||||
async getPublicKeys(recipients) {
|
||||
const recipientsList = recipients.split("\n");
|
||||
const publicKeys = [];
|
||||
|
@@ -2,16 +2,16 @@ class NotificationProvider {
|
||||
|
||||
/**
|
||||
* Notification Provider Name
|
||||
* @type string
|
||||
* @type {string}
|
||||
*/
|
||||
name = undefined;
|
||||
|
||||
/**
|
||||
* Send a notification
|
||||
* @param {BeanModel} notification
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} msg General Message
|
||||
* @param {?Object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {?object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @returns {Promise<string>} Return Successful Message
|
||||
* @throws Error with fail msg
|
||||
*/
|
||||
@@ -22,6 +22,7 @@ class NotificationProvider {
|
||||
/**
|
||||
* Throws an error
|
||||
* @param {any} error The error to throw
|
||||
* @returns {void}
|
||||
* @throws {any} The error specified
|
||||
*/
|
||||
throwGeneralAxiosError(error) {
|
||||
|
@@ -6,6 +6,9 @@ class Ntfy extends NotificationProvider {
|
||||
|
||||
name = "ntfy";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -5,6 +5,9 @@ class Octopush extends NotificationProvider {
|
||||
|
||||
name = "octopush";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class OneBot extends NotificationProvider {
|
||||
|
||||
name = "OneBot";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -68,11 +68,11 @@ class Opsgenie extends NotificationProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {BeanModel} notification
|
||||
* Make POST request to Opsgenie
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} url Request url
|
||||
* @param {Object} data Request body
|
||||
* @returns {Promise<string>}
|
||||
* @param {object} data Request body
|
||||
* @returns {Promise<string>} Success message
|
||||
*/
|
||||
async post(notification, url, data) {
|
||||
let config = {
|
||||
|
@@ -39,7 +39,8 @@ class PagerDuty extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Check if result is successful, result code should be in range 2xx
|
||||
* @param {Object} result Axios response object
|
||||
* @param {object} result Axios response object
|
||||
* @returns {void}
|
||||
* @throws {Error} The status code is not in range 2xx
|
||||
*/
|
||||
checkResult(result) {
|
||||
@@ -56,9 +57,9 @@ class PagerDuty extends NotificationProvider {
|
||||
* @param {BeanModel} notification Message title
|
||||
* @param {string} title Message title
|
||||
* @param {string} body Message
|
||||
* @param {Object} monitorInfo Monitor details (For Up/Down only)
|
||||
* @param {object} monitorInfo Monitor details (For Up/Down only)
|
||||
* @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve)
|
||||
* @returns {string}
|
||||
* @returns {Promise<string>} Success message
|
||||
*/
|
||||
async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") {
|
||||
|
||||
|
@@ -32,7 +32,8 @@ class PagerTree extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Check if result is successful, result code should be in range 2xx
|
||||
* @param {Object} result Axios response object
|
||||
* @param {object} result Axios response object
|
||||
* @returns {void}
|
||||
* @throws {Error} The status code is not in range 2xx
|
||||
*/
|
||||
checkResult(result) {
|
||||
@@ -48,9 +49,10 @@ class PagerTree extends NotificationProvider {
|
||||
* Send the message
|
||||
* @param {BeanModel} notification Message title
|
||||
* @param {string} title Message title
|
||||
* @param {Object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {?string} eventAction Action event for PagerTree (create, resolve)
|
||||
* @returns {string}
|
||||
* @returns {Promise<string>} Success state
|
||||
*/
|
||||
async postNotification(notification, title, monitorJSON, heartbeatJSON, eventAction = "create") {
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class PromoSMS extends NotificationProvider {
|
||||
|
||||
name = "promosms";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -7,6 +7,9 @@ class Pushbullet extends NotificationProvider {
|
||||
|
||||
name = "pushbullet";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -6,6 +6,9 @@ class PushDeer extends NotificationProvider {
|
||||
|
||||
name = "PushDeer";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let endpoint = "/message/push";
|
||||
|
@@ -5,6 +5,9 @@ class Pushover extends NotificationProvider {
|
||||
|
||||
name = "pushover";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let pushoverlink = "https://api.pushover.net/1/messages.json";
|
||||
|
@@ -5,6 +5,9 @@ class Pushy extends NotificationProvider {
|
||||
|
||||
name = "pushy";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -8,6 +8,9 @@ class RocketChat extends NotificationProvider {
|
||||
|
||||
name = "rocket.chat";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -6,6 +6,9 @@ class ServerChan extends NotificationProvider {
|
||||
|
||||
name = "ServerChan";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
@@ -23,8 +26,8 @@ class ServerChan extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Get the formatted title for message
|
||||
* @param {?Object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {?object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @returns {string} Formatted title
|
||||
*/
|
||||
checkStatus(heartbeatJSON, monitorJSON) {
|
||||
|
@@ -5,6 +5,9 @@ class SerwerSMS extends NotificationProvider {
|
||||
|
||||
name = "serwersms";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class Signal extends NotificationProvider {
|
||||
|
||||
name = "signal";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -10,7 +10,9 @@ class Slack extends NotificationProvider {
|
||||
/**
|
||||
* Deprecated property notification.slackbutton
|
||||
* Set it as primary base url if this is not yet set.
|
||||
* @deprecated
|
||||
* @param {string} url The primary base URL to use
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async deprecateURL(url) {
|
||||
let currentPrimaryBaseURL = await setting("primaryBaseURL");
|
||||
@@ -25,6 +27,9 @@ class Slack extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -4,6 +4,9 @@ const axios = require("axios");
|
||||
class SMSC extends NotificationProvider {
|
||||
name = "smsc";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -5,6 +5,9 @@ class SMSEagle extends NotificationProvider {
|
||||
|
||||
name = "SMSEagle";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class SMSManager extends NotificationProvider {
|
||||
|
||||
name = "SMSManager";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
try {
|
||||
let data = {
|
||||
|
@@ -6,6 +6,9 @@ class SMTP extends NotificationProvider {
|
||||
|
||||
name = "smtp";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
|
||||
const config = {
|
||||
|
@@ -37,7 +37,8 @@ class Splunk extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Check if result is successful, result code should be in range 2xx
|
||||
* @param {Object} result Axios response object
|
||||
* @param {object} result Axios response object
|
||||
* @returns {void}
|
||||
* @throws {Error} The status code is not in range 2xx
|
||||
*/
|
||||
checkResult(result) {
|
||||
@@ -54,9 +55,9 @@ class Splunk extends NotificationProvider {
|
||||
* @param {BeanModel} notification Message title
|
||||
* @param {string} title Message title
|
||||
* @param {string} body Message
|
||||
* @param {Object} monitorInfo Monitor details (For Up/Down only)
|
||||
* @param {object} monitorInfo Monitor details (For Up/Down only)
|
||||
* @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve)
|
||||
* @returns {string}
|
||||
* @returns {Promise<string>} Success state
|
||||
*/
|
||||
async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") {
|
||||
|
||||
|
@@ -6,6 +6,9 @@ class Squadcast extends NotificationProvider {
|
||||
|
||||
name = "squadcast";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -7,6 +7,9 @@ class Stackfield extends NotificationProvider {
|
||||
|
||||
name = "stackfield";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
|
@@ -9,7 +9,7 @@ class Teams extends NotificationProvider {
|
||||
* Generate the message to send
|
||||
* @param {const} status The status constant
|
||||
* @param {string} monitorName Name of monitor
|
||||
* @returns {string}
|
||||
* @returns {string} Status message
|
||||
*/
|
||||
_statusMessageFactory = (status, monitorName) => {
|
||||
if (status === DOWN) {
|
||||
@@ -37,11 +37,12 @@ class Teams extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* @param {object} args Method arguments
|
||||
* @param {const} args.status The status of the monitor
|
||||
* @param {string} args.monitorMessage Message to send
|
||||
* @param {string} args.monitorName Name of monitor affected
|
||||
* @param {string} args.monitorUrl URL of monitor affected
|
||||
* @returns {object} Notification payload
|
||||
*/
|
||||
_notificationPayloadFactory = ({
|
||||
status,
|
||||
@@ -96,7 +97,8 @@ class Teams extends NotificationProvider {
|
||||
/**
|
||||
* Send the notification
|
||||
* @param {string} webhookUrl URL to send the request to
|
||||
* @param {Object} payload Payload generated by _notificationPayloadFactory
|
||||
* @param {object} payload Payload generated by _notificationPayloadFactory
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
_sendNotification = async (webhookUrl, payload) => {
|
||||
await axios.post(webhookUrl, payload);
|
||||
@@ -116,6 +118,9 @@ class Teams extends NotificationProvider {
|
||||
return this._sendNotification(webhookUrl, payload);
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class TechulusPush extends NotificationProvider {
|
||||
|
||||
name = "PushByTechulus";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class Telegram extends NotificationProvider {
|
||||
|
||||
name = "telegram";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -5,6 +5,9 @@ class Twilio extends NotificationProvider {
|
||||
|
||||
name = "twilio";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
@@ -7,6 +7,9 @@ class Webhook extends NotificationProvider {
|
||||
|
||||
name = "webhook";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -6,6 +6,9 @@ class WeCom extends NotificationProvider {
|
||||
|
||||
name = "WeCom";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
@@ -26,9 +29,9 @@ class WeCom extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* Generate the message to send
|
||||
* @param {Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {string} msg General message
|
||||
* @returns {Object}
|
||||
* @returns {object} Message
|
||||
*/
|
||||
composeMessage(heartbeatJSON, msg) {
|
||||
let title;
|
||||
|
@@ -10,7 +10,7 @@ class ZohoCliq extends NotificationProvider {
|
||||
* Generate the message to send
|
||||
* @param {const} status The status constant
|
||||
* @param {string} monitorName Name of monitor
|
||||
* @returns {string}
|
||||
* @returns {string} Status message
|
||||
*/
|
||||
_statusMessageFactory = (status, monitorName) => {
|
||||
if (status === DOWN) {
|
||||
@@ -25,6 +25,7 @@ class ZohoCliq extends NotificationProvider {
|
||||
* Send the notification
|
||||
* @param {string} webhookUrl URL to send the request to
|
||||
* @param {Array} payload Payload generated by _notificationPayloadFactory
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
_sendNotification = async (webhookUrl, payload) => {
|
||||
await axios.post(webhookUrl, { text: payload.join("\n") });
|
||||
@@ -32,11 +33,12 @@ class ZohoCliq extends NotificationProvider {
|
||||
|
||||
/**
|
||||
* 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 {Array}
|
||||
* @param {object} args Method arguments
|
||||
* @param {const} args.status The status of the monitor
|
||||
* @param {string} args.monitorMessage Message to send
|
||||
* @param {string} args.monitorName Name of monitor affected
|
||||
* @param {string} args.monitorUrl URL of monitor affected
|
||||
* @returns {Array} Notification payload
|
||||
*/
|
||||
_notificationPayloadFactory = ({
|
||||
status,
|
||||
@@ -74,6 +76,9 @@ class ZohoCliq extends NotificationProvider {
|
||||
return this._sendNotification(webhookUrl, payload);
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
|
@@ -58,7 +58,12 @@ class Notification {
|
||||
|
||||
providerList = {};
|
||||
|
||||
/** Initialize the notification providers */
|
||||
/**
|
||||
* Initialize the notification providers
|
||||
* @returns {void}
|
||||
* @throws Notification provider does not have a name
|
||||
* @throws Duplicate notification providers in list
|
||||
*/
|
||||
static init() {
|
||||
log.info("notification", "Prepare Notification Providers");
|
||||
|
||||
@@ -133,10 +138,10 @@ class Notification {
|
||||
|
||||
/**
|
||||
* Send a notification
|
||||
* @param {BeanModel} notification
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} msg General Message
|
||||
* @param {Object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @returns {Promise<string>} Successful msg
|
||||
* @throws Error with fail msg
|
||||
*/
|
||||
@@ -150,10 +155,10 @@ class Notification {
|
||||
|
||||
/**
|
||||
* Save a notification
|
||||
* @param {Object} notification Notification to save
|
||||
* @param {object} notification Notification to save
|
||||
* @param {?number} notificationID ID of notification to update
|
||||
* @param {number} userID ID of user who adds notification
|
||||
* @returns {Promise<Bean>}
|
||||
* @returns {Promise<Bean>} Notification that was saved
|
||||
*/
|
||||
static async save(notification, notificationID, userID) {
|
||||
let bean;
|
||||
|
@@ -4,8 +4,8 @@ const saltRounds = 10;
|
||||
|
||||
/**
|
||||
* Hash a password
|
||||
* @param {string} password
|
||||
* @returns {string}
|
||||
* @param {string} password Password to hash
|
||||
* @returns {string} Hash
|
||||
*/
|
||||
exports.generate = function (password) {
|
||||
return bcrypt.hashSync(password, saltRounds);
|
||||
@@ -13,8 +13,8 @@ exports.generate = function (password) {
|
||||
|
||||
/**
|
||||
* Verify a password against a hash
|
||||
* @param {string} password
|
||||
* @param {string} hash
|
||||
* @param {string} password Password to verify
|
||||
* @param {string} hash Hash to verify against
|
||||
* @returns {boolean} Does the password match the hash?
|
||||
*/
|
||||
exports.verify = function (password, hash) {
|
||||
@@ -27,8 +27,8 @@ exports.verify = function (password, hash) {
|
||||
|
||||
/**
|
||||
* Is the hash a SHA1 hash
|
||||
* @param {string} hash
|
||||
* @returns {boolean}
|
||||
* @param {string} hash Hash to check
|
||||
* @returns {boolean} Is SHA1 hash?
|
||||
*/
|
||||
function isSHA1(hash) {
|
||||
return (typeof hash === "string" && hash.startsWith("sha1"));
|
||||
@@ -36,7 +36,8 @@ function isSHA1(hash) {
|
||||
|
||||
/**
|
||||
* Does the hash need to be rehashed?
|
||||
* @returns {boolean}
|
||||
* @param {string} hash Hash to check
|
||||
* @returns {boolean} Needs to be rehashed?
|
||||
*/
|
||||
exports.needRehash = function (hash) {
|
||||
return isSHA1(hash);
|
||||
|
@@ -36,7 +36,7 @@ class Prometheus {
|
||||
monitorLabelValues = {};
|
||||
|
||||
/**
|
||||
* @param {Object} monitor Monitor object to monitor
|
||||
* @param {object} monitor Monitor object to monitor
|
||||
*/
|
||||
constructor(monitor) {
|
||||
this.monitorLabelValues = {
|
||||
@@ -50,8 +50,9 @@ class Prometheus {
|
||||
|
||||
/**
|
||||
* Update the metrics page
|
||||
* @param {Object} heartbeat Heartbeat details
|
||||
* @param {Object} tlsInfo TLS details
|
||||
* @param {object} heartbeat Heartbeat details
|
||||
* @param {object} tlsInfo TLS details
|
||||
* @returns {void}
|
||||
*/
|
||||
update(heartbeat, tlsInfo) {
|
||||
|
||||
@@ -99,7 +100,10 @@ class Prometheus {
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove monitor from prometheus */
|
||||
/**
|
||||
* Remove monitor from prometheus
|
||||
* @returns {void}
|
||||
*/
|
||||
remove() {
|
||||
try {
|
||||
monitorCertDaysRemaining.remove(this.monitorLabelValues);
|
||||
|
@@ -11,11 +11,10 @@ class Proxy {
|
||||
|
||||
/**
|
||||
* Saves and updates given proxy entity
|
||||
*
|
||||
* @param proxy
|
||||
* @param proxyID
|
||||
* @param userID
|
||||
* @return {Promise<Bean>}
|
||||
* @param {object} proxy Proxy to store
|
||||
* @param {number} proxyID ID of proxy to update
|
||||
* @param {number} userID ID of user the proxy belongs to
|
||||
* @returns {Promise<Bean>} Updated proxy
|
||||
*/
|
||||
static async save(proxy, proxyID, userID) {
|
||||
let bean;
|
||||
@@ -65,10 +64,9 @@ class Proxy {
|
||||
|
||||
/**
|
||||
* Deletes proxy with given id and removes it from monitors
|
||||
*
|
||||
* @param proxyID
|
||||
* @param userID
|
||||
* @return {Promise<void>}
|
||||
* @param {number} proxyID ID of proxy to delete
|
||||
* @param {number} userID ID of proxy owner
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async delete(proxyID, userID) {
|
||||
const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
|
||||
@@ -86,10 +84,10 @@ class Proxy {
|
||||
|
||||
/**
|
||||
* Create HTTP and HTTPS agents related with given proxy bean object
|
||||
*
|
||||
* @param proxy proxy bean object
|
||||
* @param options http and https agent options
|
||||
* @return {{httpAgent: Agent, httpsAgent: Agent}}
|
||||
* @param {object} proxy proxy bean object
|
||||
* @param {object} options http and https agent options
|
||||
* @returns {{httpAgent: Agent, httpsAgent: Agent}} New HTTP and HTTPS agents
|
||||
* @throws Proxy protocol is unsupported
|
||||
*/
|
||||
static createAgents(proxy, options) {
|
||||
const { httpAgentOptions, httpsAgentOptions } = options || {};
|
||||
@@ -171,10 +169,9 @@ class Proxy {
|
||||
|
||||
/**
|
||||
* Applies given proxy id to monitors
|
||||
*
|
||||
* @param proxyID
|
||||
* @param userID
|
||||
* @return {Promise<void>}
|
||||
* @param {number} proxyID ID of proxy to apply
|
||||
* @param {number} userID ID of proxy owner
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function applyProxyEveryMonitor(proxyID, userID) {
|
||||
// Find all monitors with id and proxy id
|
||||
|
@@ -3,7 +3,7 @@ const { log } = require("../src/util");
|
||||
|
||||
class KumaRateLimiter {
|
||||
/**
|
||||
* @param {Object} config Rate limiter configuration object
|
||||
* @param {object} config Rate limiter configuration object
|
||||
*/
|
||||
constructor(config) {
|
||||
this.errorMessage = config.errorMessage;
|
||||
@@ -13,14 +13,14 @@ class KumaRateLimiter {
|
||||
/**
|
||||
* Callback for pass
|
||||
* @callback passCB
|
||||
* @param {Object} err Too many requests
|
||||
* @param {object} err Too many requests
|
||||
*/
|
||||
|
||||
/**
|
||||
* Should the request be passed through
|
||||
* @param {passCB} callback
|
||||
* @param {number} [num=1] Number of tokens to remove
|
||||
* @returns {Promise<boolean>}
|
||||
* @param {passCB} callback Callback function to call with decision
|
||||
* @param {number} num Number of tokens to remove
|
||||
* @returns {Promise<boolean>} Should the request be allowed?
|
||||
*/
|
||||
async pass(callback, num = 1) {
|
||||
const remainingRequests = await this.removeTokens(num);
|
||||
@@ -39,8 +39,8 @@ class KumaRateLimiter {
|
||||
|
||||
/**
|
||||
* Remove a given number of tokens
|
||||
* @param {number} [num=1] Number of tokens to remove
|
||||
* @returns {Promise<number>}
|
||||
* @param {number} num Number of tokens to remove
|
||||
* @returns {Promise<number>} Number of remaining tokens
|
||||
*/
|
||||
async removeTokens(num = 1) {
|
||||
return await this.rateLimiter.removeTokens(num);
|
||||
|
@@ -1699,8 +1699,8 @@ async function updateMonitorNotification(monitorID, notificationIDList) {
|
||||
|
||||
/**
|
||||
* Check if a given user owns a specific monitor
|
||||
* @param {number} userID
|
||||
* @param {number} monitorID
|
||||
* @param {number} userID ID of user to check
|
||||
* @param {number} monitorID ID of monitor to check
|
||||
* @returns {Promise<void>}
|
||||
* @throws {Error} The specified user does not own the monitor
|
||||
*/
|
||||
@@ -1719,7 +1719,7 @@ async function checkOwner(userID, monitorID) {
|
||||
* Function called after user login
|
||||
* This function is used to send the heartbeat list of a monitor.
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @param {Object} user User object
|
||||
* @param {object} user User object
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function afterLogin(socket, user) {
|
||||
@@ -1760,7 +1760,7 @@ async function afterLogin(socket, user) {
|
||||
|
||||
/**
|
||||
* Initialize the database
|
||||
* @param {boolean} [testMode=false] Should the connection be
|
||||
* @param {boolean} testMode Should the connection be
|
||||
* started in test mode?
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@@ -1852,7 +1852,10 @@ async function pauseMonitor(userID, monitorID) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Resume active monitors */
|
||||
/**
|
||||
* Resume active monitors
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function startMonitors() {
|
||||
let list = await R.find("monitor", " active = 1 ");
|
||||
|
||||
@@ -1896,7 +1899,10 @@ async function shutdownFunction(signal) {
|
||||
Settings.stopCacheCleaner();
|
||||
}
|
||||
|
||||
/** Final function called before application exits */
|
||||
/**
|
||||
* Final function called before application exits
|
||||
* @returns {void}
|
||||
*/
|
||||
function finalFunction() {
|
||||
log.info("server", "Graceful shutdown successful!");
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ class Settings {
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
* @returns {Promise<Bean>} Settings
|
||||
*/
|
||||
static async getSettings(type) {
|
||||
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
|
||||
@@ -119,7 +119,7 @@ class Settings {
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @param {object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async setSettings(type, data) {
|
||||
@@ -150,8 +150,9 @@ class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string[]} keyList
|
||||
* Delete selected keys from settings cache
|
||||
* @param {string[]} keyList Keys to remove
|
||||
* @returns {void}
|
||||
*/
|
||||
static deleteCache(keyList) {
|
||||
for (let key of keyList) {
|
||||
@@ -159,6 +160,10 @@ class Settings {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the cache cleaner if running
|
||||
* @returns {void}
|
||||
*/
|
||||
static stopCacheCleaner() {
|
||||
if (Settings.cacheCleaner) {
|
||||
clearInterval(Settings.cacheCleaner);
|
||||
|
@@ -9,8 +9,9 @@ const { Settings } = require("../settings");
|
||||
const { sendAPIKeyList } = require("../client");
|
||||
|
||||
/**
|
||||
* Handlers for Maintenance
|
||||
* Handlers for API keys
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.apiKeySocketHandler = (socket) => {
|
||||
// Add a new api key
|
||||
|
@@ -11,6 +11,7 @@ const cloudflared = new CloudflaredTunnel();
|
||||
* Change running state
|
||||
* @param {string} running Is it running?
|
||||
* @param {string} message Message to pass
|
||||
* @returns {void}
|
||||
*/
|
||||
cloudflared.change = (running, message) => {
|
||||
io.to("cloudflared").emit(prefix + "running", running);
|
||||
@@ -19,7 +20,8 @@ cloudflared.change = (running, message) => {
|
||||
|
||||
/**
|
||||
* Emit an error message
|
||||
* @param {string} errorMessage
|
||||
* @param {string} errorMessage Error message to send
|
||||
* @returns {void}
|
||||
*/
|
||||
cloudflared.error = (errorMessage) => {
|
||||
io.to("cloudflared").emit(prefix + "errorMessage", errorMessage);
|
||||
@@ -28,6 +30,7 @@ cloudflared.error = (errorMessage) => {
|
||||
/**
|
||||
* Handler for cloudflared
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.cloudflaredSocketHandler = (socket) => {
|
||||
|
||||
@@ -89,6 +92,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
|
||||
/**
|
||||
* Automatically start cloudflared
|
||||
* @param {string} token Cloudflared tunnel token
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
module.exports.autoStart = async (token) => {
|
||||
if (!token) {
|
||||
@@ -106,7 +110,10 @@ module.exports.autoStart = async (token) => {
|
||||
}
|
||||
};
|
||||
|
||||
/** Stop cloudflared */
|
||||
/**
|
||||
* Stop cloudflared
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
module.exports.stop = async () => {
|
||||
log.info("cloudflared", "Stop cloudflared");
|
||||
if (cloudflared) {
|
||||
|
@@ -4,6 +4,7 @@ const Database = require("../database");
|
||||
/**
|
||||
* Handlers for database
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports = (socket) => {
|
||||
|
||||
|
@@ -6,6 +6,7 @@ const { log } = require("../../src/util");
|
||||
/**
|
||||
* Handlers for docker hosts
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.dockerSocketHandler = (socket) => {
|
||||
socket.on("addDockerHost", async (dockerHost, dockerHostID, callback) => {
|
||||
|
@@ -10,7 +10,7 @@ let gameList = null;
|
||||
|
||||
/**
|
||||
* Get a game list via GameDig
|
||||
* @returns {Object[]} list of games supported by GameDig
|
||||
* @returns {object[]} list of games supported by GameDig
|
||||
*/
|
||||
function getGameList() {
|
||||
if (gameList == null) {
|
||||
|
@@ -9,6 +9,7 @@ const server = UptimeKumaServer.getInstance();
|
||||
/**
|
||||
* Handlers for Maintenance
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.maintenanceSocketHandler = (socket) => {
|
||||
// Add a new maintenance
|
||||
|
@@ -7,6 +7,7 @@ const server = UptimeKumaServer.getInstance();
|
||||
/**
|
||||
* Handlers for proxy
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.proxySocketHandler = (socket) => {
|
||||
socket.on("addProxy", async (proxy, proxyID, callback) => {
|
||||
|
@@ -11,6 +11,7 @@ const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
/**
|
||||
* Socket handlers for status page
|
||||
* @param {Socket} socket Socket.io instance to add listeners on
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.statusPageSocketHandler = (socket) => {
|
||||
|
||||
@@ -350,6 +351,8 @@ module.exports.statusPageSocketHandler = (socket) => {
|
||||
* Check slug a-z, 0-9, - only
|
||||
* Regex from: https://stackoverflow.com/questions/22454258/js-regex-string-validation-for-slug
|
||||
* @param {string} slug Slug to test
|
||||
* @returns {void}
|
||||
* @throws Slug is not valid
|
||||
*/
|
||||
function checkSlug(slug) {
|
||||
if (typeof slug !== "string") {
|
||||
|
@@ -7,9 +7,9 @@ class UptimeCacheList {
|
||||
|
||||
/**
|
||||
* Get the uptime for a specific period
|
||||
* @param {number} monitorID
|
||||
* @param {number} duration
|
||||
* @return {number}
|
||||
* @param {number} monitorID ID of monitor to query
|
||||
* @param {number} duration Duration to query
|
||||
* @returns {(number|null)} Uptime for provided duration, if it exists
|
||||
*/
|
||||
static getUptime(monitorID, duration) {
|
||||
if (UptimeCacheList.list[monitorID] && UptimeCacheList.list[monitorID][duration]) {
|
||||
@@ -22,9 +22,10 @@ class UptimeCacheList {
|
||||
|
||||
/**
|
||||
* Add uptime for specified monitor
|
||||
* @param {number} monitorID
|
||||
* @param {number} duration
|
||||
* @param {number} monitorID ID of monitor to insert for
|
||||
* @param {number} duration Duration to insert for
|
||||
* @param {number} uptime Uptime to add
|
||||
* @returns {void}
|
||||
*/
|
||||
static addUptime(monitorID, duration, uptime) {
|
||||
log.debug("UptimeCacheList", "addUptime: " + monitorID + " " + duration);
|
||||
@@ -36,7 +37,8 @@ class UptimeCacheList {
|
||||
|
||||
/**
|
||||
* Clear cache for specified monitor
|
||||
* @param {number} monitorID
|
||||
* @param {number} monitorID ID of monitor to clear
|
||||
* @returns {void}
|
||||
*/
|
||||
static clearCache(monitorID) {
|
||||
log.debug("UptimeCacheList", "clearCache: " + monitorID);
|
||||
|
@@ -20,7 +20,7 @@ const path = require("path");
|
||||
*/
|
||||
class UptimeKumaServer {
|
||||
/**
|
||||
*
|
||||
* Current server instance
|
||||
* @type {UptimeKumaServer}
|
||||
*/
|
||||
static instance = null;
|
||||
@@ -49,7 +49,6 @@ class UptimeKumaServer {
|
||||
indexHTML = "";
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {{}}
|
||||
*/
|
||||
static monitorTypeList = {
|
||||
@@ -62,6 +61,12 @@ class UptimeKumaServer {
|
||||
*/
|
||||
jwtSecret = null;
|
||||
|
||||
/**
|
||||
* Get the current instance of the server if it exists, otherwise
|
||||
* create a new instance.
|
||||
* @param {object} args Arguments to pass to instance constructor
|
||||
* @returns {UptimeKumaServer} Server instance
|
||||
*/
|
||||
static getInstance(args) {
|
||||
if (UptimeKumaServer.instance == null) {
|
||||
UptimeKumaServer.instance = new UptimeKumaServer(args);
|
||||
@@ -69,6 +74,9 @@ class UptimeKumaServer {
|
||||
return UptimeKumaServer.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} args Arguments to initialise server with
|
||||
*/
|
||||
constructor(args) {
|
||||
// SSL
|
||||
const sslKey = args["ssl-key"] || process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || undefined;
|
||||
@@ -106,7 +114,10 @@ class UptimeKumaServer {
|
||||
this.io = new Server(this.httpServer);
|
||||
}
|
||||
|
||||
/** Initialise app after the database has been set up */
|
||||
/**
|
||||
* Initialise app after the database has been set up
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async initAfterDatabaseReady() {
|
||||
// Static
|
||||
this.app.use("/screenshots", express.static(Database.screenshotDir));
|
||||
@@ -123,8 +134,8 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Send list of monitors to client
|
||||
* @param {Socket} socket
|
||||
* @returns {Object} List of monitors
|
||||
* @param {Socket} socket Socket to send list on
|
||||
* @returns {object} List of monitors
|
||||
*/
|
||||
async sendMonitorList(socket) {
|
||||
let list = await this.getMonitorJSONList(socket.userID);
|
||||
@@ -135,7 +146,7 @@ class UptimeKumaServer {
|
||||
/**
|
||||
* Get a list of monitors for the given user.
|
||||
* @param {string} userID - The ID of the user to get monitors for.
|
||||
* @returns {Promise<Object>} A promise that resolves to an object with monitor IDs as keys and monitor objects as values.
|
||||
* @returns {Promise<object>} A promise that resolves to an object with monitor IDs as keys and monitor objects as values.
|
||||
*
|
||||
* Generated by Trelent
|
||||
*/
|
||||
@@ -156,7 +167,7 @@ class UptimeKumaServer {
|
||||
/**
|
||||
* Send maintenance list to client
|
||||
* @param {Socket} socket Socket.io instance to send to
|
||||
* @returns {Object}
|
||||
* @returns {object} Maintenance list
|
||||
*/
|
||||
async sendMaintenanceList(socket) {
|
||||
return await this.sendMaintenanceListByUserID(socket.userID);
|
||||
@@ -164,8 +175,8 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Send list of maintenances to user
|
||||
* @param {number} userID
|
||||
* @returns {Object}
|
||||
* @param {number} userID User to send list to
|
||||
* @returns {object} Maintenance list
|
||||
*/
|
||||
async sendMaintenanceListByUserID(userID) {
|
||||
let list = await this.getMaintenanceJSONList(userID);
|
||||
@@ -176,7 +187,7 @@ class UptimeKumaServer {
|
||||
/**
|
||||
* Get a list of maintenances for the given user.
|
||||
* @param {string} userID - The ID of the user to get maintenances for.
|
||||
* @returns {Promise<Object>} A promise that resolves to an object with maintenance IDs as keys and maintenances objects as values.
|
||||
* @returns {Promise<object>} A promise that resolves to an object with maintenance IDs as keys and maintenances objects as values.
|
||||
*/
|
||||
async getMaintenanceJSONList(userID) {
|
||||
let result = {};
|
||||
@@ -188,7 +199,7 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Load maintenance list and run
|
||||
* @param userID
|
||||
* @param {any} userID Unused
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async loadMaintenanceList(userID) {
|
||||
@@ -202,6 +213,11 @@ class UptimeKumaServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific maintenance
|
||||
* @param {number} maintenanceID ID of maintenance to retrieve
|
||||
* @returns {(object|null)} Maintenance if it exists
|
||||
*/
|
||||
getMaintenance(maintenanceID) {
|
||||
if (this.maintenanceList[maintenanceID]) {
|
||||
return this.maintenanceList[maintenanceID];
|
||||
@@ -213,6 +229,7 @@ class UptimeKumaServer {
|
||||
* Write error to log file
|
||||
* @param {any} error The error to write
|
||||
* @param {boolean} outputToConsole Should the error also be output to console?
|
||||
* @returns {void}
|
||||
*/
|
||||
static errorLog(error, outputToConsole = true) {
|
||||
const errorLogStream = fs.createWriteStream(path.join(Database.dataDir, "/error.log"), {
|
||||
@@ -237,8 +254,8 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Get the IP of the client connected to the socket
|
||||
* @param {Socket} socket
|
||||
* @returns {string}
|
||||
* @param {Socket} socket Socket to query
|
||||
* @returns {string} IP of client
|
||||
*/
|
||||
async getClientIP(socket) {
|
||||
let clientIP = socket.client.conn.remoteAddress;
|
||||
@@ -262,7 +279,7 @@ class UptimeKumaServer {
|
||||
* Attempt to get the current server timezone
|
||||
* If this fails, fall back to environment variables and then make a
|
||||
* guess.
|
||||
* @returns {Promise<string>}
|
||||
* @returns {Promise<string>} Current timezone
|
||||
*/
|
||||
async getTimezone() {
|
||||
// From process.env.TZ
|
||||
@@ -307,7 +324,7 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Get the current offset
|
||||
* @returns {string}
|
||||
* @returns {string} Time offset
|
||||
*/
|
||||
getTimezoneOffset() {
|
||||
return dayjs().format("Z");
|
||||
@@ -315,7 +332,9 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Throw an error if the timezone is invalid
|
||||
* @param timezone
|
||||
* @param {string} timezone Timezone to test
|
||||
* @returns {void}
|
||||
* @throws The timezone is invalid
|
||||
*/
|
||||
checkTimezone(timezone) {
|
||||
try {
|
||||
@@ -327,7 +346,8 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Set the current server timezone and environment variables
|
||||
* @param {string} timezone
|
||||
* @param {string} timezone Timezone to set
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async setTimezone(timezone) {
|
||||
this.checkTimezone(timezone);
|
||||
@@ -355,6 +375,7 @@ class UptimeKumaServer {
|
||||
/**
|
||||
* Start all system services (e.g. nscd)
|
||||
* For now, only used in Docker
|
||||
* @returns {void}
|
||||
*/
|
||||
startServices() {
|
||||
if (process.env.UPTIME_KUMA_IS_CONTAINER) {
|
||||
@@ -369,6 +390,7 @@ class UptimeKumaServer {
|
||||
|
||||
/**
|
||||
* Stop all system services
|
||||
* @returns {void}
|
||||
*/
|
||||
stopServices() {
|
||||
if (process.env.UPTIME_KUMA_IS_CONTAINER) {
|
||||
|
@@ -40,7 +40,7 @@ const { Kafka, SASLOptions } = require("kafkajs");
|
||||
const isWindows = process.platform === /^win/.test(process.platform);
|
||||
/**
|
||||
* Init or reset JWT secret
|
||||
* @returns {Promise<Bean>}
|
||||
* @returns {Promise<Bean>} JWT secret
|
||||
*/
|
||||
exports.initJWTSecret = async () => {
|
||||
let jwtSecretBean = await R.findOne("setting", " `key` = ? ", [
|
||||
@@ -60,7 +60,7 @@ exports.initJWTSecret = async () => {
|
||||
/**
|
||||
* Decodes a jwt and returns the payload portion without verifying the jqt.
|
||||
* @param {string} jwt The input jwt as a string
|
||||
* @returns {Object} Decoded jwt payload object
|
||||
* @returns {object} Decoded jwt payload object
|
||||
*/
|
||||
exports.decodeJwt = (jwt) => {
|
||||
return JSON.parse(Buffer.from(jwt.split(".")[1], "base64").toString());
|
||||
@@ -124,7 +124,7 @@ exports.tcping = function (hostname, port) {
|
||||
/**
|
||||
* Ping the specified machine
|
||||
* @param {string} hostname Hostname / address of machine
|
||||
* @param {number} [size=56] Size of packet to send
|
||||
* @param {number} size Size of packet to send
|
||||
* @returns {Promise<number>} Time for ping in ms rounded to nearest integer
|
||||
*/
|
||||
exports.ping = async (hostname, size = 56) => {
|
||||
@@ -147,7 +147,7 @@ exports.ping = async (hostname, size = 56) => {
|
||||
* Ping the specified machine
|
||||
* @param {string} hostname Hostname / address of machine to ping
|
||||
* @param {boolean} ipv6 Should IPv6 be used?
|
||||
* @param {number} [size = 56] Size of ping packet to send
|
||||
* @param {number} size Size of ping packet to send
|
||||
* @returns {Promise<number>} Time for ping in ms rounded to nearest integer
|
||||
*/
|
||||
exports.pingAsync = function (hostname, ipv6 = false, size = 56) {
|
||||
@@ -179,9 +179,9 @@ exports.pingAsync = function (hostname, ipv6 = false, size = 56) {
|
||||
* @param {string} hostname Hostname / address of machine to test
|
||||
* @param {string} topic MQTT topic
|
||||
* @param {string} okMessage Expected result
|
||||
* @param {Object} [options={}] MQTT options. Contains port, username,
|
||||
* @param {object} options MQTT options. Contains port, username,
|
||||
* password and interval (interval defaults to 20)
|
||||
* @returns {Promise<string>}
|
||||
* @returns {Promise<string>} Received MQTT message
|
||||
*/
|
||||
exports.mqttAsync = function (hostname, topic, okMessage, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -243,16 +243,17 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) {
|
||||
|
||||
/**
|
||||
* Monitor Kafka using Producer
|
||||
* @param {string[]} brokers List of kafka brokers to connect, host and
|
||||
* port joined by ':'
|
||||
* @param {string} topic Topic name to produce into
|
||||
* @param {string} message Message to produce
|
||||
* @param {Object} [options={interval = 20, allowAutoTopicCreation = false, ssl = false, clientId = "Uptime-Kuma"}]
|
||||
* Kafka client options. Contains ssl, clientId, allowAutoTopicCreation and
|
||||
* interval (interval defaults to 20, allowAutoTopicCreation defaults to false, clientId defaults to "Uptime-Kuma"
|
||||
* and ssl defaults to false)
|
||||
* @param {string[]} brokers List of kafka brokers to connect, host and port joined by ':'
|
||||
* @param {SASLOptions} [saslOptions={}] Options for kafka client Authentication (SASL) (defaults to
|
||||
* {})
|
||||
* @returns {Promise<string>}
|
||||
* @param {object} options Kafka client options. Contains ssl, clientId,
|
||||
* allowAutoTopicCreation and interval (interval defaults to 20,
|
||||
* allowAutoTopicCreation defaults to false, clientId defaults to
|
||||
* "Uptime-Kuma" and ssl defaults to false)
|
||||
* @param {SASLOptions} saslOptions Options for kafka client
|
||||
* Authentication (SASL) (defaults to {})
|
||||
* @returns {Promise<string>} Status message
|
||||
*/
|
||||
exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, saslOptions = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -331,9 +332,9 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa
|
||||
|
||||
/**
|
||||
* Use NTLM Auth for a http request.
|
||||
* @param {Object} options The http request options
|
||||
* @param {Object} ntlmOptions The auth options
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
* @param {object} options The http request options
|
||||
* @param {object} ntlmOptions The auth options
|
||||
* @returns {Promise<(string[] | object[] | object)>} NTLM response
|
||||
*/
|
||||
exports.httpNtlm = function (options, ntlmOptions) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -355,7 +356,7 @@ exports.httpNtlm = function (options, ntlmOptions) {
|
||||
* @param {string} resolverServer The DNS server to use
|
||||
* @param {string} resolverPort Port the DNS server is listening on
|
||||
* @param {string} rrtype The type of record to request
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
* @returns {Promise<(string[] | object[] | object)>} DNS response
|
||||
*/
|
||||
exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
|
||||
const resolver = new Resolver();
|
||||
@@ -388,7 +389,8 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
|
||||
* Run a query on SQL Server
|
||||
* @param {string} connectionString The database connection string
|
||||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
* @returns {Promise<(string[] | object[] | object)>} Response from
|
||||
* server
|
||||
*/
|
||||
exports.mssqlQuery = async function (connectionString, query) {
|
||||
let pool;
|
||||
@@ -409,7 +411,8 @@ exports.mssqlQuery = async function (connectionString, query) {
|
||||
* Run a query on Postgres
|
||||
* @param {string} connectionString The database connection string
|
||||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
* @returns {Promise<(string[] | object[] | object)>} Response from
|
||||
* server
|
||||
*/
|
||||
exports.postgresQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -455,7 +458,7 @@ exports.postgresQuery = function (connectionString, query) {
|
||||
* Run a query on MySQL/MariaDB
|
||||
* @param {string} connectionString The database connection string
|
||||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string)>}
|
||||
* @returns {Promise<(string)>} Response from server
|
||||
*/
|
||||
exports.mysqlQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -486,9 +489,10 @@ exports.mysqlQuery = function (connectionString, query) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to and Ping a MongoDB database
|
||||
* Connect to and ping a MongoDB database
|
||||
* @param {string} connectionString The database connection string
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
* @returns {Promise<(string[] | object[] | object)>} Response from
|
||||
* server
|
||||
*/
|
||||
exports.mongodbPing = async function (connectionString) {
|
||||
let client = await MongoClient.connect(connectionString);
|
||||
@@ -510,9 +514,9 @@ exports.mongodbPing = async function (connectionString) {
|
||||
* @param {string} calledStationId ID of called station
|
||||
* @param {string} callingStationId ID of calling station
|
||||
* @param {string} secret Secret to use
|
||||
* @param {number} [port=1812] Port to contact radius server on
|
||||
* @param {number} [timeout=2500] Timeout for connection to use
|
||||
* @returns {Promise<any>}
|
||||
* @param {number} port Port to contact radius server on
|
||||
* @param {number} timeout Timeout for connection to use
|
||||
* @returns {Promise<any>} Response from server
|
||||
*/
|
||||
exports.radius = function (
|
||||
hostname,
|
||||
@@ -552,6 +556,7 @@ exports.radius = function (
|
||||
/**
|
||||
* Redis server ping
|
||||
* @param {string} dsn The redis connection string
|
||||
* @returns {Promise<any>} Response from redis server
|
||||
*/
|
||||
exports.redisPingAsync = function (dsn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -593,7 +598,7 @@ exports.setting = async function (key) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the specified setting to specifed value
|
||||
* Sets the specified setting to specified value
|
||||
* @param {string} key Key of setting to set
|
||||
* @param {any} value Value to set to
|
||||
* @param {?string} type Type of setting
|
||||
@@ -606,7 +611,7 @@ exports.setSetting = async function (key, value, type = null) {
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
* @returns {Promise<Bean>} Settings of requested type
|
||||
*/
|
||||
exports.getSettings = async function (type) {
|
||||
return await Settings.getSettings(type);
|
||||
@@ -615,7 +620,7 @@ exports.getSettings = async function (type) {
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @param {object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setSettings = async function (type, data) {
|
||||
@@ -629,7 +634,7 @@ exports.setSettings = async function (type, data) {
|
||||
* Get number of days between two dates
|
||||
* @param {Date} validFrom Start date
|
||||
* @param {Date} validTo End date
|
||||
* @returns {number}
|
||||
* @returns {number} Number of days
|
||||
*/
|
||||
const getDaysBetween = (validFrom, validTo) =>
|
||||
Math.round(Math.abs(+validFrom - +validTo) / 8.64e7);
|
||||
@@ -638,7 +643,7 @@ const getDaysBetween = (validFrom, validTo) =>
|
||||
* Get days remaining from a time range
|
||||
* @param {Date} validFrom Start date
|
||||
* @param {Date} validTo End date
|
||||
* @returns {number}
|
||||
* @returns {number} Number of days remaining
|
||||
*/
|
||||
const getDaysRemaining = (validFrom, validTo) => {
|
||||
const daysRemaining = getDaysBetween(validFrom, validTo);
|
||||
@@ -650,8 +655,9 @@ const getDaysRemaining = (validFrom, validTo) => {
|
||||
|
||||
/**
|
||||
* Fix certificate info for display
|
||||
* @param {Object} info The chain obtained from getPeerCertificate()
|
||||
* @returns {Object} An object representing certificate information
|
||||
* @param {object} info The chain obtained from getPeerCertificate()
|
||||
* @returns {object} An object representing certificate information
|
||||
* @throws The certificate chain length exceeded 500.
|
||||
*/
|
||||
const parseCertificateInfo = function (info) {
|
||||
let link = info;
|
||||
@@ -698,8 +704,9 @@ const parseCertificateInfo = function (info) {
|
||||
|
||||
/**
|
||||
* Check if certificate is valid
|
||||
* @param {Object} res Response object from axios
|
||||
* @returns {Object} Object containing certificate information
|
||||
* @param {object} res Response object from axios
|
||||
* @returns {object} Object containing certificate information
|
||||
* @throws No socket was found to check certificate for
|
||||
*/
|
||||
exports.checkCertificate = function (res) {
|
||||
if (!res.request.res.socket) {
|
||||
@@ -757,7 +764,7 @@ exports.checkStatusCode = function (status, acceptedCodes) {
|
||||
* Get total number of clients in room
|
||||
* @param {Server} io Socket server instance
|
||||
* @param {string} roomName Name of room to check
|
||||
* @returns {number}
|
||||
* @returns {number} Total clients in room
|
||||
*/
|
||||
exports.getTotalClientInRoom = (io, roomName) => {
|
||||
|
||||
@@ -784,7 +791,8 @@ exports.getTotalClientInRoom = (io, roomName) => {
|
||||
|
||||
/**
|
||||
* Allow CORS all origins if development
|
||||
* @param {Object} res Response object from axios
|
||||
* @param {object} res Response object from axios
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.allowDevAllOrigin = (res) => {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
@@ -794,7 +802,8 @@ exports.allowDevAllOrigin = (res) => {
|
||||
|
||||
/**
|
||||
* Allow CORS all origins
|
||||
* @param {Object} res Response object from axios
|
||||
* @param {object} res Response object from axios
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.allowAllOrigin = (res) => {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
@@ -805,6 +814,8 @@ exports.allowAllOrigin = (res) => {
|
||||
/**
|
||||
* Check if a user is logged in
|
||||
* @param {Socket} socket Socket instance
|
||||
* @returns {void}
|
||||
* @throws The user is not logged in
|
||||
*/
|
||||
exports.checkLogin = (socket) => {
|
||||
if (!socket.userID) {
|
||||
@@ -815,8 +826,10 @@ exports.checkLogin = (socket) => {
|
||||
/**
|
||||
* For logged-in users, double-check the password
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @param {string} currentPassword
|
||||
* @returns {Promise<Bean>}
|
||||
* @param {string} currentPassword Password to validate
|
||||
* @returns {Promise<Bean>} User
|
||||
* @throws The current password is not a string
|
||||
* @throws The provided password is not correct
|
||||
*/
|
||||
exports.doubleCheckPassword = async (socket, currentPassword) => {
|
||||
if (typeof currentPassword !== "string") {
|
||||
@@ -834,7 +847,10 @@ exports.doubleCheckPassword = async (socket, currentPassword) => {
|
||||
return user;
|
||||
};
|
||||
|
||||
/** Start Unit tests */
|
||||
/**
|
||||
* Start Unit tests
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.startUnitTest = async () => {
|
||||
console.log("Starting unit test...");
|
||||
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
|
||||
@@ -854,7 +870,10 @@ exports.startUnitTest = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
/** Start end-to-end tests */
|
||||
/**
|
||||
* Start end-to-end tests
|
||||
* @returns {void}
|
||||
*/
|
||||
exports.startE2eTests = async () => {
|
||||
console.log("Starting unit test...");
|
||||
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
|
||||
@@ -877,7 +896,7 @@ exports.startE2eTests = async () => {
|
||||
/**
|
||||
* Convert unknown string to UTF8
|
||||
* @param {Uint8Array} body Buffer
|
||||
* @returns {string}
|
||||
* @returns {string} UTF8 string
|
||||
*/
|
||||
exports.convertToUTF8 = (body) => {
|
||||
const guessEncoding = chardet.detect(body);
|
||||
@@ -889,11 +908,10 @@ exports.convertToUTF8 = (body) => {
|
||||
* Returns a color code in hex format based on a given percentage:
|
||||
* 0% => hue = 10 => red
|
||||
* 100% => hue = 90 => green
|
||||
*
|
||||
* @param {number} percentage float, 0 to 1
|
||||
* @param {number} maxHue
|
||||
* @param {number} minHue, int
|
||||
* @returns {string}, hex value
|
||||
* @param {number} maxHue Maximum hue - int
|
||||
* @param {number} minHue Minimum hue - int
|
||||
* @returns {string} Color in hex
|
||||
*/
|
||||
exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => {
|
||||
const hue = percentage * (maxHue - minHue) + minHue;
|
||||
@@ -906,10 +924,9 @@ exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => {
|
||||
|
||||
/**
|
||||
* Joins and array of string to one string after filtering out empty values
|
||||
*
|
||||
* @param {string[]} parts
|
||||
* @param {string} connector
|
||||
* @returns {string}
|
||||
* @param {string[]} parts Strings to join
|
||||
* @param {string} connector Separator for joined strings
|
||||
* @returns {string} Joined strings
|
||||
*/
|
||||
exports.filterAndJoin = (parts, connector = "") => {
|
||||
return parts.filter((part) => !!part && part !== "").join(connector);
|
||||
@@ -917,8 +934,9 @@ exports.filterAndJoin = (parts, connector = "") => {
|
||||
|
||||
/**
|
||||
* Send an Error response
|
||||
* @param {Object} res Express response object
|
||||
* @param {string} [msg=""] Message to send
|
||||
* @param {object} res Express response object
|
||||
* @param {string} msg Message to send
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.sendHttpError = (res, msg = "") => {
|
||||
if (msg.includes("SQLITE_BUSY") || msg.includes("SQLITE_LOCKED")) {
|
||||
@@ -939,6 +957,13 @@ module.exports.sendHttpError = (res, msg = "") => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert timezone of time object
|
||||
* @param {object} obj Time object to update
|
||||
* @param {string} timezone New timezone to set
|
||||
* @param {boolean} timeObjectToUTC Convert time object to UTC
|
||||
* @returns {object} Time object with updated timezone
|
||||
*/
|
||||
function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {
|
||||
let offsetString;
|
||||
|
||||
@@ -981,20 +1006,20 @@ function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} obj
|
||||
* @param {string} timezone
|
||||
* @returns {object}
|
||||
* Convert time object to UTC
|
||||
* @param {object} obj Object to convert
|
||||
* @param {string} timezone Timezone of time object
|
||||
* @returns {object} Updated time object
|
||||
*/
|
||||
module.exports.timeObjectToUTC = (obj, timezone = undefined) => {
|
||||
return timeObjectConvertTimezone(obj, timezone, true);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} obj
|
||||
* @param {string} timezone
|
||||
* @returns {object}
|
||||
* Convert time object to local time
|
||||
* @param {object} obj Object to convert
|
||||
* @param {string} timezone Timezone to convert to
|
||||
* @returns {object} Updated object
|
||||
*/
|
||||
module.exports.timeObjectToLocal = (obj, timezone = undefined) => {
|
||||
return timeObjectConvertTimezone(obj, timezone, false);
|
||||
@@ -1002,7 +1027,8 @@ module.exports.timeObjectToLocal = (obj, timezone = undefined) => {
|
||||
|
||||
/**
|
||||
* Create gRPC client stib
|
||||
* @param {Object} options from gRPC client
|
||||
* @param {object} options from gRPC client
|
||||
* @returns {Promise<object>} Result of gRPC query
|
||||
*/
|
||||
module.exports.grpcQuery = async (options) => {
|
||||
const { grpcUrl, grpcProtobufData, grpcServiceName, grpcEnableTls, grpcMethod, grpcBody } = options;
|
||||
|
Reference in New Issue
Block a user