Merge remote-tracking branch 'origin/master' into radius-check

# Conflicts:
#	server/database.js
#	server/model/monitor.js
#	server/server.js
#	server/util-server.js
#	src/pages/EditMonitor.vue
This commit is contained in:
Louis Lam
2022-08-11 21:08:06 +08:00
138 changed files with 11924 additions and 7918 deletions

View File

@@ -10,6 +10,11 @@ const chardet = require("chardet");
const mqtt = require("mqtt");
const chroma = require("chroma-js");
const { badgeConstants } = require("./config");
const mssql = require("mssql");
const { Client } = require("pg");
const postgresConParse = require("pg-connection-string").parse;
const { NtlmClient } = require("axios-ntlm");
const { Settings } = require("./settings");
const radiusClient = require("node-radius-client");
const {
dictionaries: {
@@ -178,16 +183,40 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) {
});
};
/**
* 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)>}
*/
exports.httpNtlm = function (options, ntlmOptions) {
return new Promise((resolve, reject) => {
let client = NtlmClient(ntlmOptions);
client(options)
.then((resp) => {
resolve(resp);
})
.catch((err) => {
reject(err);
});
});
};
/**
* Resolves a given record using the specified DNS server
* @param {string} hostname The hostname of the record to lookup
* @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)>}
*/
exports.dnsResolve = function (hostname, resolverServer, rrtype) {
exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
const resolver = new Resolver();
resolver.setServers([ resolverServer ]);
// Remove brackets from IPv6 addresses so we can re-add them to
// prevent issues with ::1:5300 (::1 port 5300)
resolverServer = resolverServer.replace("[", "").replace("]", "");
resolver.setServers([ `[${resolverServer}]:${resolverPort}` ]);
return new Promise((resolve, reject) => {
if (rrtype === "PTR") {
resolver.reverse(hostname, (err, records) => {
@@ -209,6 +238,59 @@ exports.dnsResolve = function (hostname, resolverServer, 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)>}
*/
exports.mssqlQuery = function (connectionString, query) {
return new Promise((resolve, reject) => {
mssql.connect(connectionString).then(pool => {
return pool.request()
.query(query);
}).then(result => {
resolve(result);
}).catch(err => {
reject(err);
}).finally(() => {
mssql.close();
});
});
};
/**
* 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)>}
*/
exports.postgresQuery = function (connectionString, query) {
return new Promise((resolve, reject) => {
const config = postgresConParse(connectionString);
if (config.password === "") {
// See https://github.com/brianc/node-postgres/issues/1927
return reject(new Error("Password is undefined."));
}
const client = new Client({ connectionString });
client.connect();
return client.query(query)
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
})
.finally(() => {
client.end();
});
});
};
exports.radius = function (
hostname,
username,
@@ -237,19 +319,10 @@ exports.radius = function (
* Retrieve value of setting based on key
* @param {string} key Key of setting to retrieve
* @returns {Promise<any>} Value
* @deprecated Use await Settings.get(key)
*/
exports.setting = async function (key) {
let value = await R.getCell("SELECT `value` FROM setting WHERE `key` = ? ", [
key,
]);
try {
const v = JSON.parse(value);
log.debug("util", `Get Setting: ${key}: ${v}`);
return v;
} catch (e) {
return value;
}
return await Settings.get(key);
};
/**
@@ -260,70 +333,26 @@ exports.setting = async function (key) {
* @returns {Promise<void>}
*/
exports.setSetting = async function (key, value, type = null) {
let bean = await R.findOne("setting", " `key` = ? ", [
key,
]);
if (!bean) {
bean = R.dispense("setting");
bean.key = key;
}
bean.type = type;
bean.value = JSON.stringify(value);
await R.store(bean);
await Settings.set(key, value, type);
};
/**
* Get settings based on type
* @param {?string} type The type of setting
* @param {string} type The type of setting
* @returns {Promise<Bean>}
*/
exports.getSettings = async function (type) {
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
type,
]);
let result = {};
for (let row of list) {
try {
result[row.key] = JSON.parse(row.value);
} catch (e) {
result[row.key] = row.value;
}
}
return result;
return await Settings.getSettings(type);
};
/**
* Set settings based on type
* @param {?string} type Type of settings to set
* @param {string} type Type of settings to set
* @param {Object} data Values of settings
* @returns {Promise<void>}
*/
exports.setSettings = async function (type, data) {
let keyList = Object.keys(data);
let promiseList = [];
for (let key of keyList) {
let bean = await R.findOne("setting", " `key` = ? ", [
key
]);
if (bean == null) {
bean = R.dispense("setting");
bean.type = type;
bean.key = key;
}
if (bean.type === type) {
bean.value = JSON.stringify(data[key]);
promiseList.push(R.store(bean));
}
}
await Promise.all(promiseList);
await Settings.setSettings(type, data);
};
// ssl-checker by @dyaa
@@ -416,7 +445,7 @@ exports.checkCertificate = function (res) {
/**
* Check if the provided status code is within the accepted ranges
* @param {string} status The status code to check
* @param {number} status The status code to check
* @param {string[]} acceptedCodes An array of accepted status codes
* @returns {boolean} True if status code within range, false otherwise
* @throws {Error} Will throw an error if the provided status code is not a valid range string or code string
@@ -584,3 +613,15 @@ exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => {
exports.filterAndJoin = (parts, connector = "") => {
return parts.filter((part) => !!part && part !== "").join(connector);
};
/**
* Send a 403 response
* @param {Object} res Express response object
* @param {string} [msg=""] Message to send
*/
module.exports.send403 = (res, msg = "") => {
res.status(403).json({
"status": "fail",
"msg": msg,
});
};