mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-03 12:02:33 +02:00
Refactor modules for improved readability and consistency
Reformatted code across multiple modules, standardizing string quotes, indentation, and spacing. Improved readability by restructuring blocks and aligning object properties consistently. These changes ensure better code maintainability and follow standard conventions. Signed-off-by: Toby Liddicoat <toby@codesure.co.uk>
This commit is contained in:
parent
200f179b5f
commit
9081025c4a
35 changed files with 699 additions and 369 deletions
|
@ -3,7 +3,10 @@ const passwordHash = require("./password-hash");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { setting } = require("./util-server");
|
const { setting } = require("./util-server");
|
||||||
const { log } = require("../src/util");
|
const { log } = require("../src/util");
|
||||||
const { loginRateLimiter, apiRateLimiter } = require("./rate-limiter");
|
const {
|
||||||
|
loginRateLimiter,
|
||||||
|
apiRateLimiter,
|
||||||
|
} = require("./rate-limiter");
|
||||||
const { Settings } = require("./settings");
|
const { Settings } = require("./settings");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,11 @@ async function sendNotificationList(socket) {
|
||||||
*/
|
*/
|
||||||
async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
|
async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
|
||||||
let list = await R.getAll(`
|
let list = await R.getAll(`
|
||||||
SELECT * FROM heartbeat
|
SELECT *
|
||||||
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
ORDER BY time DESC
|
ORDER BY time DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
`, [
|
`, [
|
||||||
monitorID,
|
monitorID,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { setSetting, setting } = require("./util-server");
|
const {
|
||||||
const { log, sleep } = require("../src/util");
|
setSetting,
|
||||||
|
setting,
|
||||||
|
} = require("./util-server");
|
||||||
|
const {
|
||||||
|
log,
|
||||||
|
sleep,
|
||||||
|
} = require("../src/util");
|
||||||
const knex = require("knex");
|
const knex = require("knex");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { EmbeddedMariaDB } = require("./embedded-mariadb");
|
const { EmbeddedMariaDB } = require("./embedded-mariadb");
|
||||||
|
@ -136,24 +142,24 @@ class Database {
|
||||||
Database.dataDir = process.env.DATA_DIR || args["data-dir"] || "./data/";
|
Database.dataDir = process.env.DATA_DIR || args["data-dir"] || "./data/";
|
||||||
|
|
||||||
Database.sqlitePath = path.join(Database.dataDir, "kuma.db");
|
Database.sqlitePath = path.join(Database.dataDir, "kuma.db");
|
||||||
if (! fs.existsSync(Database.dataDir)) {
|
if (!fs.existsSync(Database.dataDir)) {
|
||||||
fs.mkdirSync(Database.dataDir, { recursive: true });
|
fs.mkdirSync(Database.dataDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
Database.uploadDir = path.join(Database.dataDir, "upload/");
|
Database.uploadDir = path.join(Database.dataDir, "upload/");
|
||||||
|
|
||||||
if (! fs.existsSync(Database.uploadDir)) {
|
if (!fs.existsSync(Database.uploadDir)) {
|
||||||
fs.mkdirSync(Database.uploadDir, { recursive: true });
|
fs.mkdirSync(Database.uploadDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create screenshot dir
|
// Create screenshot dir
|
||||||
Database.screenshotDir = path.join(Database.dataDir, "screenshots/");
|
Database.screenshotDir = path.join(Database.dataDir, "screenshots/");
|
||||||
if (! fs.existsSync(Database.screenshotDir)) {
|
if (!fs.existsSync(Database.screenshotDir)) {
|
||||||
fs.mkdirSync(Database.screenshotDir, { recursive: true });
|
fs.mkdirSync(Database.screenshotDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
Database.dockerTLSDir = path.join(Database.dataDir, "docker-tls/");
|
Database.dockerTLSDir = path.join(Database.dataDir, "docker-tls/");
|
||||||
if (! fs.existsSync(Database.dockerTLSDir)) {
|
if (!fs.existsSync(Database.dockerTLSDir)) {
|
||||||
fs.mkdirSync(Database.dockerTLSDir, { recursive: true });
|
fs.mkdirSync(Database.dockerTLSDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +237,7 @@ class Database {
|
||||||
|
|
||||||
if (dbConfig.type === "sqlite") {
|
if (dbConfig.type === "sqlite") {
|
||||||
|
|
||||||
if (! fs.existsSync(Database.sqlitePath)) {
|
if (!fs.existsSync(Database.sqlitePath)) {
|
||||||
log.info("server", "Copying Database");
|
log.info("server", "Copying Database");
|
||||||
fs.copyFileSync(Database.templatePath, Database.sqlitePath);
|
fs.copyFileSync(Database.templatePath, Database.sqlitePath);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +258,7 @@ class Database {
|
||||||
idleTimeoutMillis: 120 * 1000,
|
idleTimeoutMillis: 120 * 1000,
|
||||||
propagateCreateError: false,
|
propagateCreateError: false,
|
||||||
acquireTimeoutMillis: acquireConnectionTimeout,
|
acquireTimeoutMillis: acquireConnectionTimeout,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
} else if (dbConfig.type === "mariadb") {
|
} else if (dbConfig.type === "mariadb") {
|
||||||
if (!/^\w+$/.test(dbConfig.dbName)) {
|
if (!/^\w+$/.test(dbConfig.dbName)) {
|
||||||
|
@ -451,7 +457,7 @@ class Database {
|
||||||
static async patchSqlite() {
|
static async patchSqlite() {
|
||||||
let version = parseInt(await setting("database_version"));
|
let version = parseInt(await setting("database_version"));
|
||||||
|
|
||||||
if (! version) {
|
if (!version) {
|
||||||
version = 0;
|
version = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +508,7 @@ class Database {
|
||||||
log.debug("db", "Database Patch 2.0 Process");
|
log.debug("db", "Database Patch 2.0 Process");
|
||||||
let databasePatchedFiles = await setting("databasePatchedFiles");
|
let databasePatchedFiles = await setting("databasePatchedFiles");
|
||||||
|
|
||||||
if (! databasePatchedFiles) {
|
if (!databasePatchedFiles) {
|
||||||
databasePatchedFiles = {};
|
databasePatchedFiles = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,11 +585,11 @@ class Database {
|
||||||
let id = await R.store(statusPage);
|
let id = await R.store(statusPage);
|
||||||
|
|
||||||
await R.exec("UPDATE incident SET status_page_id = ? WHERE status_page_id IS NULL", [
|
await R.exec("UPDATE incident SET status_page_id = ? WHERE status_page_id IS NULL", [
|
||||||
id
|
id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await R.exec("UPDATE [group] SET status_page_id = ? WHERE status_page_id IS NULL", [
|
await R.exec("UPDATE [group] SET status_page_id = ? WHERE status_page_id IS NULL", [
|
||||||
id
|
id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await R.exec("DELETE FROM setting WHERE type = 'statusPage'");
|
await R.exec("DELETE FROM setting WHERE type = 'statusPage'");
|
||||||
|
@ -611,13 +617,13 @@ class Database {
|
||||||
static async patch2Recursion(sqlFilename, databasePatchedFiles) {
|
static async patch2Recursion(sqlFilename, databasePatchedFiles) {
|
||||||
let value = this.patchList[sqlFilename];
|
let value = this.patchList[sqlFilename];
|
||||||
|
|
||||||
if (! value) {
|
if (!value) {
|
||||||
log.info("db", sqlFilename + " skip");
|
log.info("db", sqlFilename + " skip");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if patched
|
// Check if patched
|
||||||
if (! databasePatchedFiles[sqlFilename]) {
|
if (!databasePatchedFiles[sqlFilename]) {
|
||||||
log.info("db", sqlFilename + " is not patched");
|
log.info("db", sqlFilename + " is not patched");
|
||||||
|
|
||||||
if (value.parents) {
|
if (value.parents) {
|
||||||
|
@ -652,7 +658,7 @@ class Database {
|
||||||
// Remove all comments (--)
|
// Remove all comments (--)
|
||||||
let lines = text.split("\n");
|
let lines = text.split("\n");
|
||||||
lines = lines.filter((line) => {
|
lines = lines.filter((line) => {
|
||||||
return ! line.startsWith("--");
|
return !line.startsWith("--");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Split statements by semicolon
|
// Split statements by semicolon
|
||||||
|
@ -797,7 +803,8 @@ class Database {
|
||||||
|
|
||||||
// Stop if stat_* tables are not empty
|
// Stop if stat_* tables are not empty
|
||||||
for (let table of [ "stat_minutely", "stat_hourly", "stat_daily" ]) {
|
for (let table of [ "stat_minutely", "stat_hourly", "stat_daily" ]) {
|
||||||
let countResult = await R.getRow(`SELECT COUNT(*) AS count FROM ${table}`);
|
let countResult = await R.getRow(`SELECT COUNT(*) AS count
|
||||||
|
FROM ${table}`);
|
||||||
let count = countResult.count;
|
let count = countResult.count;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
log.warn("db", `Aggregate table ${table} is not empty, migration will not be started (Maybe you were using 2.0.0-dev?)`);
|
log.warn("db", `Aggregate table ${table} is not empty, migration will not be started (Maybe you were using 2.0.0-dev?)`);
|
||||||
|
@ -814,12 +821,12 @@ class Database {
|
||||||
for (let monitor of monitors) {
|
for (let monitor of monitors) {
|
||||||
// Get a list of unique dates from the heartbeat table, using raw sql
|
// Get a list of unique dates from the heartbeat table, using raw sql
|
||||||
let dates = await R.getAll(`
|
let dates = await R.getAll(`
|
||||||
SELECT DISTINCT DATE(time) AS date
|
SELECT DISTINCT DATE (time) AS date
|
||||||
FROM heartbeat
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
ORDER BY date ASC
|
ORDER BY date ASC
|
||||||
`, [
|
`, [
|
||||||
monitor.monitor_id
|
monitor.monitor_id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let date of dates) {
|
for (let date of dates) {
|
||||||
|
@ -833,7 +840,7 @@ class Database {
|
||||||
SELECT status, ping, time
|
SELECT status, ping, time
|
||||||
FROM heartbeat
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
AND DATE(time) = ?
|
AND DATE (time) = ?
|
||||||
ORDER BY time ASC
|
ORDER BY time ASC
|
||||||
`, [ monitor.monitor_id, date.date ]);
|
`, [ monitor.monitor_id, date.date ]);
|
||||||
|
|
||||||
|
@ -887,19 +894,21 @@ class Database {
|
||||||
log.info("db", "Deleting non-important heartbeats for monitor " + monitor.id);
|
log.info("db", "Deleting non-important heartbeats for monitor " + monitor.id);
|
||||||
}
|
}
|
||||||
await R.exec(`
|
await R.exec(`
|
||||||
DELETE FROM heartbeat
|
DELETE
|
||||||
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
AND important = 0
|
AND important = 0
|
||||||
AND time < ${sqlHourOffset}
|
AND time
|
||||||
AND id NOT IN (
|
< ${sqlHourOffset}
|
||||||
|
AND id NOT IN (
|
||||||
SELECT id FROM ( -- written this way for Maria's support
|
SELECT id FROM ( -- written this way for Maria's support
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM heartbeat
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
ORDER BY time DESC
|
ORDER BY time DESC
|
||||||
LIMIT ?
|
LIMIT ?
|
||||||
) AS limited_ids
|
) AS limited_ids
|
||||||
)
|
)
|
||||||
`, [
|
`, [
|
||||||
monitor.id,
|
monitor.id,
|
||||||
-24,
|
-24,
|
||||||
|
|
|
@ -146,7 +146,7 @@ class DockerHost {
|
||||||
static getHttpsAgentOptions(dockerType, url) {
|
static getHttpsAgentOptions(dockerType, url) {
|
||||||
let baseOptions = {
|
let baseOptions = {
|
||||||
maxCachedSessions: 0,
|
maxCachedSessions: 0,
|
||||||
rejectUnauthorized: true
|
rejectUnauthorized: true,
|
||||||
};
|
};
|
||||||
let certOptions = {};
|
let certOptions = {};
|
||||||
|
|
||||||
|
@ -163,13 +163,13 @@ class DockerHost {
|
||||||
certOptions = {
|
certOptions = {
|
||||||
ca,
|
ca,
|
||||||
key,
|
key,
|
||||||
cert
|
cert,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...baseOptions,
|
...baseOptions,
|
||||||
...certOptions
|
...certOptions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const jobs = [
|
||||||
interval: "*/5 * * * *",
|
interval: "*/5 * * * *",
|
||||||
jobFunc: incrementalVacuum,
|
jobFunc: incrementalVacuum,
|
||||||
croner: null,
|
croner: null,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,5 +54,5 @@ const stopBackgroundJobs = function () {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initBackgroundJobs,
|
initBackgroundJobs,
|
||||||
stopBackgroundJobs
|
stopBackgroundJobs,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const { parseTimeObject, parseTimeFromTimeObject, log } = require("../../src/util");
|
const {
|
||||||
|
parseTimeObject,
|
||||||
|
parseTimeFromTimeObject,
|
||||||
|
log,
|
||||||
|
} = require("../../src/util");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const Cron = require("croner");
|
const Cron = require("croner");
|
||||||
|
@ -192,7 +196,8 @@ class Maintenance extends BeanModel {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
static validateCron(cron) {
|
static validateCron(cron) {
|
||||||
let job = new Cron(cron, () => {});
|
let job = new Cron(cron, () => {
|
||||||
|
});
|
||||||
job.stop();
|
job.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,37 @@
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const { Prometheus } = require("../prometheus");
|
const { Prometheus } = require("../prometheus");
|
||||||
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND,
|
const {
|
||||||
SQL_DATETIME_FORMAT, evaluateJsonQuery
|
log,
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
PENDING,
|
||||||
|
MAINTENANCE,
|
||||||
|
flipStatus,
|
||||||
|
MAX_INTERVAL_SECOND,
|
||||||
|
MIN_INTERVAL_SECOND,
|
||||||
|
SQL_DATETIME_FORMAT,
|
||||||
|
evaluateJsonQuery,
|
||||||
} = require("../../src/util");
|
} = require("../../src/util");
|
||||||
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery,
|
const {
|
||||||
redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
|
tcping,
|
||||||
|
ping,
|
||||||
|
checkCertificate,
|
||||||
|
checkStatusCode,
|
||||||
|
getTotalClientInRoom,
|
||||||
|
setting,
|
||||||
|
mssqlQuery,
|
||||||
|
postgresQuery,
|
||||||
|
mysqlQuery,
|
||||||
|
setSetting,
|
||||||
|
httpNtlm,
|
||||||
|
radius,
|
||||||
|
grpcQuery,
|
||||||
|
redisPingAsync,
|
||||||
|
kafkaProducerAsync,
|
||||||
|
getOidcTokenClientCredentials,
|
||||||
|
rootCertificatesFingerprints,
|
||||||
|
axiosAbortSignal,
|
||||||
} = require("../util-server");
|
} = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
|
@ -61,7 +87,10 @@ class Monitor extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (certExpiry && (this.type === "http" || this.type === "keyword" || this.type === "json-query") && this.getURLProtocol() === "https:") {
|
if (certExpiry && (this.type === "http" || this.type === "keyword" || this.type === "json-query") && this.getURLProtocol() === "https:") {
|
||||||
const { certExpiryDaysRemaining, validCert } = await this.getCertExpiry(this.id);
|
const {
|
||||||
|
certExpiryDaysRemaining,
|
||||||
|
validCert,
|
||||||
|
} = await this.getCertExpiry(this.id);
|
||||||
obj.certExpiryDaysRemaining = certExpiryDaysRemaining;
|
obj.certExpiryDaysRemaining = certExpiryDaysRemaining;
|
||||||
obj.validCert = validCert;
|
obj.validCert = validCert;
|
||||||
}
|
}
|
||||||
|
@ -218,13 +247,13 @@ class Monitor extends BeanModel {
|
||||||
if (tlsInfo?.valid && tlsInfo?.certInfo?.daysRemaining) {
|
if (tlsInfo?.valid && tlsInfo?.certInfo?.daysRemaining) {
|
||||||
return {
|
return {
|
||||||
certExpiryDaysRemaining: tlsInfo.certInfo.daysRemaining,
|
certExpiryDaysRemaining: tlsInfo.certInfo.daysRemaining,
|
||||||
validCert: true
|
validCert: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
certExpiryDaysRemaining: "",
|
certExpiryDaysRemaining: "",
|
||||||
validCert: false
|
validCert: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +363,7 @@ class Monitor extends BeanModel {
|
||||||
|
|
||||||
let beatInterval = this.interval;
|
let beatInterval = this.interval;
|
||||||
|
|
||||||
if (! beatInterval) {
|
if (!beatInterval) {
|
||||||
beatInterval = 1;
|
beatInterval = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +508,7 @@ class Monitor extends BeanModel {
|
||||||
...(contentType ? { "Content-Type": contentType } : {}),
|
...(contentType ? { "Content-Type": contentType } : {}),
|
||||||
...(basicAuthHeader),
|
...(basicAuthHeader),
|
||||||
...(oauth2AuthHeader),
|
...(oauth2AuthHeader),
|
||||||
...(this.headers ? JSON.parse(this.headers) : {})
|
...(this.headers ? JSON.parse(this.headers) : {}),
|
||||||
},
|
},
|
||||||
maxRedirects: this.maxredirects,
|
maxRedirects: this.maxredirects,
|
||||||
validateStatus: (status) => {
|
validateStatus: (status) => {
|
||||||
|
@ -504,7 +533,10 @@ class Monitor extends BeanModel {
|
||||||
const proxy = await R.load("proxy", this.proxy_id);
|
const proxy = await R.load("proxy", this.proxy_id);
|
||||||
|
|
||||||
if (proxy && proxy.active) {
|
if (proxy && proxy.active) {
|
||||||
const { httpAgent, httpsAgent } = Proxy.createAgents(proxy, {
|
const {
|
||||||
|
httpAgent,
|
||||||
|
httpsAgent,
|
||||||
|
} = Proxy.createAgents(proxy, {
|
||||||
httpsAgentOptions: httpsAgentOptions,
|
httpsAgentOptions: httpsAgentOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -518,7 +550,7 @@ class Monitor extends BeanModel {
|
||||||
let jar = new CookieJar();
|
let jar = new CookieJar();
|
||||||
let httpsCookieAgentOptions = {
|
let httpsCookieAgentOptions = {
|
||||||
...httpsAgentOptions,
|
...httpsAgentOptions,
|
||||||
cookies: { jar }
|
cookies: { jar },
|
||||||
};
|
};
|
||||||
options.httpsAgent = new HttpsCookieAgent(httpsCookieAgentOptions);
|
options.httpsAgent = new HttpsCookieAgent(httpsCookieAgentOptions);
|
||||||
}
|
}
|
||||||
|
@ -600,7 +632,10 @@ class Monitor extends BeanModel {
|
||||||
} else if (this.type === "json-query") {
|
} else if (this.type === "json-query") {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
|
|
||||||
const { status, response } = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue);
|
const {
|
||||||
|
status,
|
||||||
|
response,
|
||||||
|
} = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
|
@ -681,7 +716,7 @@ class Monitor extends BeanModel {
|
||||||
params: {
|
params: {
|
||||||
filter: filter,
|
filter: filter,
|
||||||
key: steamAPIKey,
|
key: steamAPIKey,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) {
|
if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) {
|
||||||
|
@ -690,7 +725,8 @@ class Monitor extends BeanModel {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bean.ping = await ping(this.hostname, this.packetSize);
|
bean.ping = await ping(this.hostname, this.packetSize);
|
||||||
} catch (_) { }
|
} catch (_) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Server not found on Steam");
|
throw new Error("Server not found on Steam");
|
||||||
}
|
}
|
||||||
|
@ -739,7 +775,7 @@ class Monitor extends BeanModel {
|
||||||
} else if (dockerHost._dockerType === "tcp") {
|
} else if (dockerHost._dockerType === "tcp") {
|
||||||
options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
|
options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
|
||||||
options.httpsAgent = new https.Agent(
|
options.httpsAgent = new https.Agent(
|
||||||
DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL)
|
DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,12 +1020,12 @@ class Monitor extends BeanModel {
|
||||||
|
|
||||||
previousBeat = bean;
|
previousBeat = bean;
|
||||||
|
|
||||||
if (! this.isStop) {
|
if (!this.isStop) {
|
||||||
log.debug("monitor", `[${this.name}] SetTimeout for next check.`);
|
log.debug("monitor", `[${this.name}] SetTimeout for next check.`);
|
||||||
|
|
||||||
let intervalRemainingMs = Math.max(
|
let intervalRemainingMs = Math.max(
|
||||||
1,
|
1,
|
||||||
beatInterval * 1000 - dayjs().diff(dayjs.utc(bean.time))
|
beatInterval * 1000 - dayjs().diff(dayjs.utc(bean.time)),
|
||||||
);
|
);
|
||||||
|
|
||||||
log.debug("monitor", `[${this.name}] Next heartbeat in: ${intervalRemainingMs}ms`);
|
log.debug("monitor", `[${this.name}] Next heartbeat in: ${intervalRemainingMs}ms`);
|
||||||
|
@ -1013,7 +1049,7 @@ class Monitor extends BeanModel {
|
||||||
UptimeKumaServer.errorLog(e, false);
|
UptimeKumaServer.errorLog(e, false);
|
||||||
log.error("monitor", "Please report to https://github.com/louislam/uptime-kuma/issues");
|
log.error("monitor", "Please report to https://github.com/louislam/uptime-kuma/issues");
|
||||||
|
|
||||||
if (! this.isStop) {
|
if (!this.isStop) {
|
||||||
log.info("monitor", "Try to restart the monitor");
|
log.info("monitor", "Try to restart the monitor");
|
||||||
this.heartbeatInterval = setTimeout(safeBeat, this.interval * 1000);
|
this.heartbeatInterval = setTimeout(safeBeat, this.interval * 1000);
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +1083,7 @@ class Monitor extends BeanModel {
|
||||||
username: this.basic_auth_user,
|
username: this.basic_auth_user,
|
||||||
password: this.basic_auth_pass,
|
password: this.basic_auth_pass,
|
||||||
domain: this.authDomain,
|
domain: this.authDomain,
|
||||||
workstation: this.authWorkstation ? this.authWorkstation : undefined
|
workstation: this.authWorkstation ? this.authWorkstation : undefined,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
res = await axios.request(options);
|
res = await axios.request(options);
|
||||||
|
@ -1065,8 +1101,9 @@ class Monitor extends BeanModel {
|
||||||
let oauth2AuthHeader = {
|
let oauth2AuthHeader = {
|
||||||
"Authorization": this.oauthAccessToken.token_type + " " + this.oauthAccessToken.access_token,
|
"Authorization": this.oauthAccessToken.token_type + " " + this.oauthAccessToken.access_token,
|
||||||
};
|
};
|
||||||
options.headers = { ...(options.headers),
|
options.headers = {
|
||||||
...(oauth2AuthHeader)
|
...(options.headers),
|
||||||
|
...(oauth2AuthHeader),
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.makeAxiosRequest(options, true);
|
return this.makeAxiosRequest(options, true);
|
||||||
|
@ -1158,7 +1195,7 @@ class Monitor extends BeanModel {
|
||||||
if (oldCertInfo.certInfo.fingerprint256 !== checkCertificateResult.certInfo.fingerprint256) {
|
if (oldCertInfo.certInfo.fingerprint256 !== checkCertificateResult.certInfo.fingerprint256) {
|
||||||
log.debug("monitor", "Resetting sent_history");
|
log.debug("monitor", "Resetting sent_history");
|
||||||
await R.exec("DELETE FROM notification_sent_history WHERE type = 'certificate' AND monitor_id = ?", [
|
await R.exec("DELETE FROM notification_sent_history WHERE type = 'certificate' AND monitor_id = ?", [
|
||||||
this.id
|
this.id,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
log.debug("monitor", "No need to reset sent_history");
|
log.debug("monitor", "No need to reset sent_history");
|
||||||
|
@ -1168,7 +1205,8 @@ class Monitor extends BeanModel {
|
||||||
} else {
|
} else {
|
||||||
log.debug("monitor", "Not valid object");
|
log.debug("monitor", "Not valid object");
|
||||||
}
|
}
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1326,8 +1364,9 @@ class Monitor extends BeanModel {
|
||||||
for (let notification of notificationList) {
|
for (let notification of notificationList) {
|
||||||
try {
|
try {
|
||||||
const heartbeatJSON = bean.toJSON();
|
const heartbeatJSON = bean.toJSON();
|
||||||
const monitorData = [{ id: monitor.id,
|
const monitorData = [ {
|
||||||
active: monitor.active
|
id: monitor.id,
|
||||||
|
active: monitor.active,
|
||||||
}];
|
}];
|
||||||
const preloadData = await Monitor.preparePreloadData(monitorData);
|
const preloadData = await Monitor.preparePreloadData(monitorData);
|
||||||
// Prevent if the msg is undefined, notifications such as Discord cannot send out.
|
// Prevent if the msg is undefined, notifications such as Discord cannot send out.
|
||||||
|
@ -1370,7 +1409,7 @@ class Monitor extends BeanModel {
|
||||||
if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) {
|
if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) {
|
||||||
const notificationList = await Monitor.getNotificationList(this);
|
const notificationList = await Monitor.getNotificationList(this);
|
||||||
|
|
||||||
if (! notificationList.length > 0) {
|
if (!notificationList.length > 0) {
|
||||||
// fail fast. If no notification is set, all the following checks can be skipped.
|
// fail fast. If no notification is set, all the following checks can be skipped.
|
||||||
log.debug("monitor", "No notification, no need to send cert notification");
|
log.debug("monitor", "No notification, no need to send cert notification");
|
||||||
return;
|
return;
|
||||||
|
@ -1458,7 +1497,7 @@ class Monitor extends BeanModel {
|
||||||
*/
|
*/
|
||||||
static async getPreviousHeartbeat(monitorID) {
|
static async getPreviousHeartbeat(monitorID) {
|
||||||
return await R.findOne("heartbeat", " id = (select MAX(id) from heartbeat where monitor_id = ?)", [
|
return await R.findOne("heartbeat", " id = (select MAX(id) from heartbeat where monitor_id = ?)", [
|
||||||
monitorID
|
monitorID,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,7 +1609,7 @@ class Monitor extends BeanModel {
|
||||||
monitor_id: row.monitor_id,
|
monitor_id: row.monitor_id,
|
||||||
value: row.value,
|
value: row.value,
|
||||||
name: row.name,
|
name: row.name,
|
||||||
color: row.color
|
color: row.color,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1687,7 +1726,7 @@ class Monitor extends BeanModel {
|
||||||
*/
|
*/
|
||||||
static async unlinkAllChildren(groupID) {
|
static async unlinkAllChildren(groupID) {
|
||||||
return await R.exec("UPDATE `monitor` SET parent = ? WHERE parent = ? ", [
|
return await R.exec("UPDATE `monitor` SET parent = ? WHERE parent = ? ", [
|
||||||
null, groupID
|
null, groupID,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,15 @@ const { marked } = require("marked");
|
||||||
const { Feed } = require("feed");
|
const { Feed } = require("feed");
|
||||||
const config = require("../config");
|
const config = require("../config");
|
||||||
|
|
||||||
const { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE, DOWN } = require("../../src/util");
|
const {
|
||||||
|
STATUS_PAGE_ALL_DOWN,
|
||||||
|
STATUS_PAGE_ALL_UP,
|
||||||
|
STATUS_PAGE_MAINTENANCE,
|
||||||
|
STATUS_PAGE_PARTIAL_DOWN,
|
||||||
|
UP,
|
||||||
|
MAINTENANCE,
|
||||||
|
DOWN,
|
||||||
|
} = require("../../src/util");
|
||||||
|
|
||||||
class StatusPage extends BeanModel {
|
class StatusPage extends BeanModel {
|
||||||
|
|
||||||
|
@ -16,7 +24,7 @@ class StatusPage extends BeanModel {
|
||||||
* Like this: { "test-uptime.kuma.pet": "default" }
|
* Like this: { "test-uptime.kuma.pet": "default" }
|
||||||
* @type {{}}
|
* @type {{}}
|
||||||
*/
|
*/
|
||||||
static domainMappingList = { };
|
static domainMappingList = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle responses to RSS pages
|
* Handle responses to RSS pages
|
||||||
|
@ -26,7 +34,7 @@ class StatusPage extends BeanModel {
|
||||||
*/
|
*/
|
||||||
static async handleStatusPageRSSResponse(response, slug) {
|
static async handleStatusPageRSSResponse(response, slug) {
|
||||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
slug
|
slug,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (statusPage) {
|
if (statusPage) {
|
||||||
|
@ -51,7 +59,7 @@ class StatusPage extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
slug
|
slug,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (statusPage) {
|
if (statusPage) {
|
||||||
|
@ -68,7 +76,10 @@ class StatusPage extends BeanModel {
|
||||||
* @returns {Promise<string>} the rendered html
|
* @returns {Promise<string>} the rendered html
|
||||||
*/
|
*/
|
||||||
static async renderRSS(statusPage, slug) {
|
static async renderRSS(statusPage, slug) {
|
||||||
const { heartbeats, statusDescription } = await StatusPage.getRSSPageData(statusPage);
|
const {
|
||||||
|
heartbeats,
|
||||||
|
statusDescription,
|
||||||
|
} = await StatusPage.getRSSPageData(statusPage);
|
||||||
|
|
||||||
let proto = config.isSSL ? "https" : "http";
|
let proto = config.isSSL ? "https" : "http";
|
||||||
let host = `${proto}://${config.hostname || "localhost"}:${config.port}/status/${slug}`;
|
let host = `${proto}://${config.hostname || "localhost"}:${config.port}/status/${slug}`;
|
||||||
|
@ -135,7 +146,7 @@ class StatusPage extends BeanModel {
|
||||||
// Preload data
|
// Preload data
|
||||||
// Add jsesc, fix https://github.com/louislam/uptime-kuma/issues/2186
|
// Add jsesc, fix https://github.com/louislam/uptime-kuma/issues/2186
|
||||||
const escapedJSONObject = jsesc(await StatusPage.getStatusPageData(statusPage), {
|
const escapedJSONObject = jsesc(await StatusPage.getStatusPageData(statusPage), {
|
||||||
"isScriptContext": true
|
"isScriptContext": true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const script = $(`
|
const script = $(`
|
||||||
|
@ -174,7 +185,7 @@ class StatusPage extends BeanModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! hasUp) {
|
if (!hasUp) {
|
||||||
status = STATUS_PAGE_ALL_DOWN;
|
status = STATUS_PAGE_ALL_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +234,7 @@ class StatusPage extends BeanModel {
|
||||||
const showTags = !!statusPage.show_tags;
|
const showTags = !!statusPage.show_tags;
|
||||||
|
|
||||||
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
||||||
statusPage.id
|
statusPage.id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let heartbeats = [];
|
let heartbeats = [];
|
||||||
|
@ -236,7 +247,7 @@ class StatusPage extends BeanModel {
|
||||||
heartbeats.push({
|
heartbeats.push({
|
||||||
...monitor,
|
...monitor,
|
||||||
status: heartbeat.status,
|
status: heartbeat.status,
|
||||||
time: heartbeat.time
|
time: heartbeat.time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +262,7 @@ class StatusPage extends BeanModel {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
heartbeats,
|
heartbeats,
|
||||||
statusDescription
|
statusDescription,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +290,7 @@ class StatusPage extends BeanModel {
|
||||||
const showTags = !!statusPage.show_tags;
|
const showTags = !!statusPage.show_tags;
|
||||||
|
|
||||||
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
||||||
statusPage.id
|
statusPage.id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let groupBean of list) {
|
for (let groupBean of list) {
|
||||||
|
@ -442,7 +453,7 @@ class StatusPage extends BeanModel {
|
||||||
*/
|
*/
|
||||||
static async slugToID(slug) {
|
static async slugToID(slug) {
|
||||||
return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [
|
return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [
|
||||||
slug
|
slug,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const passwordHash = require("../password-hash");
|
const passwordHash = require("../password-hash");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const jwt = require("jsonwebtoken");
|
const jwt = require("jsonwebtoken");
|
||||||
const { shake256, SHAKE256_LENGTH } = require("../util-server");
|
const {
|
||||||
|
shake256,
|
||||||
|
SHAKE256_LENGTH,
|
||||||
|
} = require("../util-server");
|
||||||
|
|
||||||
class User extends BeanModel {
|
class User extends BeanModel {
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +18,7 @@ class User extends BeanModel {
|
||||||
static async resetPassword(userID, newPassword) {
|
static async resetPassword(userID, newPassword) {
|
||||||
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
|
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
|
||||||
passwordHash.generate(newPassword),
|
passwordHash.generate(newPassword),
|
||||||
userID
|
userID,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ class User extends BeanModel {
|
||||||
|
|
||||||
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
|
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
|
||||||
hashedPassword,
|
hashedPassword,
|
||||||
this.id
|
this.id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.password = hashedPassword;
|
this.password = hashedPassword;
|
||||||
|
|
|
@ -100,7 +100,7 @@ function ApiCache() {
|
||||||
* Generated by Trelent
|
* Generated by Trelent
|
||||||
*/
|
*/
|
||||||
function debug(a, b, c, d) {
|
function debug(a, b, c, d) {
|
||||||
let arr = ["\x1b[36m[apicache]\x1b[0m", a, b, c, d].filter(function (arg) {
|
let arr = [ "\x1b[36m[apicache]\x1b[0m", a, b, c, d ].filter(function (arg) {
|
||||||
return arg !== undefined;
|
return arg !== undefined;
|
||||||
});
|
});
|
||||||
let debugEnv = process.env.DEBUG && process.env.DEBUG.split(",").indexOf("apicache") !== -1;
|
let debugEnv = process.env.DEBUG && process.env.DEBUG.split(",").indexOf("apicache") !== -1;
|
||||||
|
@ -210,7 +210,8 @@ function ApiCache() {
|
||||||
try {
|
try {
|
||||||
redis.hset(key, "response", JSON.stringify(value));
|
redis.hset(key, "response", JSON.stringify(value));
|
||||||
redis.hset(key, "duration", duration);
|
redis.hset(key, "duration", duration);
|
||||||
redis.expire(key, duration / 1000, expireCallback || function () {});
|
redis.expire(key, duration / 1000, expireCallback || function () {
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debug("[apicache] error in redis.hset()");
|
debug("[apicache] error in redis.hset()");
|
||||||
}
|
}
|
||||||
|
@ -247,8 +248,8 @@ function ApiCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
res._apicache.content = Buffer.concat(
|
res._apicache.content = Buffer.concat(
|
||||||
[oldContent, content],
|
[ oldContent, content ],
|
||||||
oldContent.length + content.length
|
oldContent.length + content.length,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
res._apicache.content = content;
|
res._apicache.content = content;
|
||||||
|
@ -268,7 +269,7 @@ function ApiCache() {
|
||||||
* @param {function(Object, Object):boolean} toggle
|
* @param {function(Object, Object):boolean} toggle
|
||||||
*/
|
*/
|
||||||
function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) {
|
function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) {
|
||||||
// monkeypatch res.end to create cache object
|
// monkeypatch res.end to create cache object
|
||||||
res._apicache = {
|
res._apicache = {
|
||||||
write: res.write,
|
write: res.write,
|
||||||
writeHead: res.writeHead,
|
writeHead: res.writeHead,
|
||||||
|
@ -314,7 +315,7 @@ function ApiCache() {
|
||||||
res.statusCode,
|
res.statusCode,
|
||||||
headers,
|
headers,
|
||||||
res._apicache.content,
|
res._apicache.content,
|
||||||
encoding
|
encoding,
|
||||||
);
|
);
|
||||||
cacheResponse(key, cacheObject, duration);
|
cacheResponse(key, cacheObject, duration);
|
||||||
|
|
||||||
|
@ -367,7 +368,7 @@ function ApiCache() {
|
||||||
let data = cacheObject.data;
|
let data = cacheObject.data;
|
||||||
if (data && data.type === "Buffer") {
|
if (data && data.type === "Buffer") {
|
||||||
data =
|
data =
|
||||||
typeof data.data === "number" ? new Buffer.alloc(data.data) : new Buffer.from(data.data);
|
typeof data.data === "number" ? new Buffer.alloc(data.data) : new Buffer.from(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test Etag against If-None-Match for 304
|
// test Etag against If-None-Match for 304
|
||||||
|
@ -511,15 +512,15 @@ function ApiCache() {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return cache performance statistics (hit rate). Suitable for
|
* Return cache performance statistics (hit rate). Suitable for
|
||||||
* putting into a route:
|
* putting into a route:
|
||||||
* <code>
|
* <code>
|
||||||
* app.get('/api/cache/performance', (req, res) => {
|
* app.get('/api/cache/performance', (req, res) => {
|
||||||
* res.json(apicache.getPerformance())
|
* res.json(apicache.getPerformance())
|
||||||
* })
|
* })
|
||||||
* </code>
|
* </code>
|
||||||
* @returns {any[]}
|
* @returns {any[]}
|
||||||
*/
|
*/
|
||||||
this.getPerformance = function () {
|
this.getPerformance = function () {
|
||||||
return performanceArray.map(function (p) {
|
return performanceArray.map(function (p) {
|
||||||
return p.report();
|
return p.report();
|
||||||
|
@ -528,7 +529,7 @@ function ApiCache() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get index of a group
|
* Get index of a group
|
||||||
* @param {string} group
|
* @param {string} group
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
this.getIndex = function (group) {
|
this.getIndex = function (group) {
|
||||||
|
@ -543,9 +544,9 @@ function ApiCache() {
|
||||||
* Express middleware
|
* Express middleware
|
||||||
* @param {(string|number)} strDuration Duration to cache responses
|
* @param {(string|number)} strDuration Duration to cache responses
|
||||||
* for.
|
* for.
|
||||||
* @param {function(Object, Object):boolean} middlewareToggle
|
* @param {function(Object, Object):boolean} middlewareToggle
|
||||||
* @param {Object} localOptions Options for APICache
|
* @param {Object} localOptions Options for APICache
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
this.middleware = function cache(strDuration, middlewareToggle, localOptions) {
|
this.middleware = function cache(strDuration, middlewareToggle, localOptions) {
|
||||||
let duration = instance.getDuration(strDuration);
|
let duration = instance.getDuration(strDuration);
|
||||||
|
@ -573,7 +574,8 @@ function ApiCache() {
|
||||||
* A Function for non tracking performance
|
* A Function for non tracking performance
|
||||||
*/
|
*/
|
||||||
function NOOPCachePerformance() {
|
function NOOPCachePerformance() {
|
||||||
this.report = this.hit = this.miss = function () {}; // noop;
|
this.report = this.hit = this.miss = function () {
|
||||||
|
}; // noop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -762,8 +764,8 @@ function ApiCache() {
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
req.headers["x-apicache-bypass"] ||
|
req.headers["x-apicache-bypass"] ||
|
||||||
req.headers["x-apicache-force-fetch"] ||
|
req.headers["x-apicache-force-fetch"] ||
|
||||||
(opt.respectCacheControl && req.headers["cache-control"] == "no-cache")
|
(opt.respectCacheControl && req.headers["cache-control"] == "no-cache")
|
||||||
) {
|
) {
|
||||||
return bypass();
|
return bypass();
|
||||||
}
|
}
|
||||||
|
@ -826,7 +828,7 @@ function ApiCache() {
|
||||||
JSON.parse(obj.response),
|
JSON.parse(obj.response),
|
||||||
middlewareToggle,
|
middlewareToggle,
|
||||||
next,
|
next,
|
||||||
duration
|
duration,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
perf.miss(key);
|
perf.miss(key);
|
||||||
|
@ -837,7 +839,7 @@ function ApiCache() {
|
||||||
key,
|
key,
|
||||||
duration,
|
duration,
|
||||||
strDuration,
|
strDuration,
|
||||||
middlewareToggle
|
middlewareToggle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -859,7 +861,7 @@ function ApiCache() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process options
|
* Process options
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
this.options = function (options) {
|
this.options = function (options) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ const apicache = require("./apicache");
|
||||||
|
|
||||||
apicache.options({
|
apicache.options({
|
||||||
headerBlacklist: [
|
headerBlacklist: [
|
||||||
"cache-control"
|
"cache-control",
|
||||||
],
|
],
|
||||||
headers: {
|
headers: {
|
||||||
// Disable client side cache, only server side cache.
|
// Disable client side cache, only server side cache.
|
||||||
|
|
|
@ -4,7 +4,7 @@ function MemoryCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} key Key to store cache as
|
* @param {string} key Key to store cache as
|
||||||
* @param {any} value Value to store
|
* @param {any} value Value to store
|
||||||
* @param {number} time Time to store for
|
* @param {number} time Time to store for
|
||||||
|
@ -22,7 +22,7 @@ MemoryCache.prototype.add = function (key, value, time, timeoutCallback) {
|
||||||
timeout: setTimeout(function () {
|
timeout: setTimeout(function () {
|
||||||
instance.delete(key);
|
instance.delete(key);
|
||||||
return timeoutCallback && typeof timeoutCallback === "function" && timeoutCallback(value, key);
|
return timeoutCallback && typeof timeoutCallback === "function" && timeoutCallback(value, key);
|
||||||
}, time)
|
}, time),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.cache[key] = entry;
|
this.cache[key] = entry;
|
||||||
|
@ -52,7 +52,7 @@ MemoryCache.prototype.delete = function (key) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value of key
|
* Get value of key
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
MemoryCache.prototype.get = function (key) {
|
MemoryCache.prototype.get = function (key) {
|
||||||
|
@ -63,7 +63,7 @@ MemoryCache.prototype.get = function (key) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value of cache entry
|
* Get value of cache entry
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
MemoryCache.prototype.getValue = function (key) {
|
MemoryCache.prototype.getValue = function (key) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
'use strict';
|
"use strict";
|
||||||
// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/flags.js
|
// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/flags.js
|
||||||
module.exports.NTLMFLAG_NEGOTIATE_UNICODE = 1 << 0;
|
module.exports.NTLMFLAG_NEGOTIATE_UNICODE = 1 << 0;
|
||||||
/* Indicates that Unicode strings are supported for use in security buffer
|
/* Indicates that Unicode strings are supported for use in security buffer
|
||||||
|
@ -74,4 +74,4 @@ module.exports.NTLMFLAG_NEGOTIATE_KEY_EXCHANGE = 1 << 30;
|
||||||
/* Indicates that the client will provide an encrypted master key in
|
/* Indicates that the client will provide an encrypted master key in
|
||||||
the "Session Key" field of the Type 3 message. */
|
the "Session Key" field of the Type 3 message. */
|
||||||
module.exports.NTLMFLAG_NEGOTIATE_56 = 1 << 31;
|
module.exports.NTLMFLAG_NEGOTIATE_56 = 1 << 31;
|
||||||
//# sourceMappingURL=flags.js.map
|
//# sourceMappingURL=flags.js.map
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict';
|
"use strict";
|
||||||
// Original source at https://github.com/elasticio/node-ntlm-client/blob/master/lib/hash.js
|
// Original source at https://github.com/elasticio/node-ntlm-client/blob/master/lib/hash.js
|
||||||
var crypto = require('crypto');
|
var crypto = require("crypto");
|
||||||
|
|
||||||
function createLMResponse(challenge, lmhash) {
|
function createLMResponse(challenge, lmhash) {
|
||||||
var buf = new Buffer.alloc(24), pwBuffer = new Buffer.alloc(21).fill(0);
|
var buf = new Buffer.alloc(24), pwBuffer = new Buffer.alloc(21).fill(0);
|
||||||
lmhash.copy(pwBuffer);
|
lmhash.copy(pwBuffer);
|
||||||
|
@ -9,19 +10,21 @@ function createLMResponse(challenge, lmhash) {
|
||||||
calculateDES(pwBuffer.slice(14), challenge).copy(buf, 16);
|
calculateDES(pwBuffer.slice(14), challenge).copy(buf, 16);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLMHash(password) {
|
function createLMHash(password) {
|
||||||
var buf = new Buffer.alloc(16), pwBuffer = new Buffer.alloc(14), magicKey = new Buffer.from('KGS!@#$%', 'ascii');
|
var buf = new Buffer.alloc(16), pwBuffer = new Buffer.alloc(14), magicKey = new Buffer.from("KGS!@#$%", "ascii");
|
||||||
if (password.length > 14) {
|
if (password.length > 14) {
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
pwBuffer.fill(0);
|
pwBuffer.fill(0);
|
||||||
pwBuffer.write(password.toUpperCase(), 0, 'ascii');
|
pwBuffer.write(password.toUpperCase(), 0, "ascii");
|
||||||
return Buffer.concat([
|
return Buffer.concat([
|
||||||
calculateDES(pwBuffer.slice(0, 7), magicKey),
|
calculateDES(pwBuffer.slice(0, 7), magicKey),
|
||||||
calculateDES(pwBuffer.slice(7), magicKey)
|
calculateDES(pwBuffer.slice(7), magicKey),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateDES(key, message) {
|
function calculateDES(key, message) {
|
||||||
var desKey = new Buffer.alloc(8);
|
var desKey = new Buffer.alloc(8);
|
||||||
desKey[0] = key[0] & 0xFE;
|
desKey[0] = key[0] & 0xFE;
|
||||||
|
@ -39,9 +42,10 @@ function calculateDES(key, message) {
|
||||||
}
|
}
|
||||||
desKey[i] |= (parity % 2) === 0 ? 1 : 0;
|
desKey[i] |= (parity % 2) === 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
var des = crypto.createCipheriv('DES-ECB', desKey, '');
|
var des = crypto.createCipheriv("DES-ECB", desKey, "");
|
||||||
return des.update(message);
|
return des.update(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNTLMResponse(challenge, ntlmhash) {
|
function createNTLMResponse(challenge, ntlmhash) {
|
||||||
var buf = new Buffer.alloc(24), ntlmBuffer = new Buffer.alloc(21).fill(0);
|
var buf = new Buffer.alloc(24), ntlmBuffer = new Buffer.alloc(21).fill(0);
|
||||||
ntlmhash.copy(ntlmBuffer);
|
ntlmhash.copy(ntlmBuffer);
|
||||||
|
@ -50,30 +54,36 @@ function createNTLMResponse(challenge, ntlmhash) {
|
||||||
calculateDES(ntlmBuffer.slice(14), challenge).copy(buf, 16);
|
calculateDES(ntlmBuffer.slice(14), challenge).copy(buf, 16);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNTLMHash(password) {
|
function createNTLMHash(password) {
|
||||||
var md4sum = crypto.createHash('md4');
|
var md4sum = crypto.createHash("md4");
|
||||||
md4sum.update(new Buffer.from(password, 'ucs2'));
|
md4sum.update(new Buffer.from(password, "ucs2"));
|
||||||
return md4sum.digest();
|
return md4sum.digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNTLMv2Hash(ntlmhash, username, authTargetName) {
|
function createNTLMv2Hash(ntlmhash, username, authTargetName) {
|
||||||
var hmac = crypto.createHmac('md5', ntlmhash);
|
var hmac = crypto.createHmac("md5", ntlmhash);
|
||||||
hmac.update(new Buffer.from(username.toUpperCase() + authTargetName, 'ucs2'));
|
hmac.update(new Buffer.from(username.toUpperCase() + authTargetName, "ucs2"));
|
||||||
return hmac.digest();
|
return hmac.digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLMv2Response(type2message, username, ntlmhash, nonce, targetName) {
|
function createLMv2Response(type2message, username, ntlmhash, nonce, targetName) {
|
||||||
var buf = new Buffer.alloc(24), ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName), hmac = crypto.createHmac('md5', ntlm2hash);
|
var buf = new Buffer.alloc(24), ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName),
|
||||||
|
hmac = crypto.createHmac("md5", ntlm2hash);
|
||||||
//server challenge
|
//server challenge
|
||||||
type2message.challenge.copy(buf, 8);
|
type2message.challenge.copy(buf, 8);
|
||||||
//client nonce
|
//client nonce
|
||||||
buf.write(nonce || createPseudoRandomValue(16), 16, 'hex');
|
buf.write(nonce || createPseudoRandomValue(16), 16, "hex");
|
||||||
//create hash
|
//create hash
|
||||||
hmac.update(buf.slice(8));
|
hmac.update(buf.slice(8));
|
||||||
var hashedBuffer = hmac.digest();
|
var hashedBuffer = hmac.digest();
|
||||||
hashedBuffer.copy(buf);
|
hashedBuffer.copy(buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNTLMv2Response(type2message, username, ntlmhash, nonce, targetName) {
|
function createNTLMv2Response(type2message, username, ntlmhash, nonce, targetName) {
|
||||||
var buf = new Buffer.alloc(48 + type2message.targetInfo.buffer.length), ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName), hmac = crypto.createHmac('md5', ntlm2hash);
|
var buf = new Buffer.alloc(48 + type2message.targetInfo.buffer.length),
|
||||||
|
ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName), hmac = crypto.createHmac("md5", ntlm2hash);
|
||||||
//the first 8 bytes are spare to store the hashed value before the blob
|
//the first 8 bytes are spare to store the hashed value before the blob
|
||||||
//server challenge
|
//server challenge
|
||||||
type2message.challenge.copy(buf, 8);
|
type2message.challenge.copy(buf, 8);
|
||||||
|
@ -86,12 +96,12 @@ function createNTLMv2Response(type2message, username, ntlmhash, nonce, targetNam
|
||||||
// maybe think about a different solution here
|
// maybe think about a different solution here
|
||||||
// 11644473600000 = diff between 1970 and 1601
|
// 11644473600000 = diff between 1970 and 1601
|
||||||
var timestamp = ((Date.now() + 11644473600000) * 10000).toString(16);
|
var timestamp = ((Date.now() + 11644473600000) * 10000).toString(16);
|
||||||
var timestampLow = Number('0x' + timestamp.substring(Math.max(0, timestamp.length - 8)));
|
var timestampLow = Number("0x" + timestamp.substring(Math.max(0, timestamp.length - 8)));
|
||||||
var timestampHigh = Number('0x' + timestamp.substring(0, Math.max(0, timestamp.length - 8)));
|
var timestampHigh = Number("0x" + timestamp.substring(0, Math.max(0, timestamp.length - 8)));
|
||||||
buf.writeUInt32LE(timestampLow, 24, false);
|
buf.writeUInt32LE(timestampLow, 24, false);
|
||||||
buf.writeUInt32LE(timestampHigh, 28, false);
|
buf.writeUInt32LE(timestampHigh, 28, false);
|
||||||
//random client nonce
|
//random client nonce
|
||||||
buf.write(nonce || createPseudoRandomValue(16), 32, 'hex');
|
buf.write(nonce || createPseudoRandomValue(16), 32, "hex");
|
||||||
//zero
|
//zero
|
||||||
buf.writeUInt32LE(0, 40);
|
buf.writeUInt32LE(0, 40);
|
||||||
//complete target information block from type 2 message
|
//complete target information block from type 2 message
|
||||||
|
@ -103,13 +113,15 @@ function createNTLMv2Response(type2message, username, ntlmhash, nonce, targetNam
|
||||||
hashedBuffer.copy(buf);
|
hashedBuffer.copy(buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPseudoRandomValue(length) {
|
function createPseudoRandomValue(length) {
|
||||||
var str = '';
|
var str = "";
|
||||||
while (str.length < length) {
|
while (str.length < length) {
|
||||||
str += Math.floor(Math.random() * 16).toString(16);
|
str += Math.floor(Math.random() * 16).toString(16);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createLMHash: createLMHash,
|
createLMHash: createLMHash,
|
||||||
createNTLMHash: createNTLMHash,
|
createNTLMHash: createNTLMHash,
|
||||||
|
@ -117,6 +129,6 @@ module.exports = {
|
||||||
createNTLMResponse: createNTLMResponse,
|
createNTLMResponse: createNTLMResponse,
|
||||||
createLMv2Response: createLMv2Response,
|
createLMv2Response: createLMv2Response,
|
||||||
createNTLMv2Response: createNTLMv2Response,
|
createNTLMv2Response: createNTLMv2Response,
|
||||||
createPseudoRandomValue: createPseudoRandomValue
|
createPseudoRandomValue: createPseudoRandomValue,
|
||||||
};
|
};
|
||||||
//# sourceMappingURL=hash.js.map
|
//# sourceMappingURL=hash.js.map
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
'use strict';
|
"use strict";
|
||||||
// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/ntlm.js
|
// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/ntlm.js
|
||||||
var os = require('os'), flags = require('./flags'), hash = require('./hash');
|
var os = require("os"), flags = require("./flags"), hash = require("./hash");
|
||||||
var NTLMSIGNATURE = "NTLMSSP\0";
|
var NTLMSIGNATURE = "NTLMSSP\0";
|
||||||
|
|
||||||
function createType1Message(workstation, target) {
|
function createType1Message(workstation, target) {
|
||||||
var dataPos = 32, pos = 0, buf = new Buffer.alloc(1024);
|
var dataPos = 32, pos = 0, buf = new Buffer.alloc(1024);
|
||||||
workstation = workstation === undefined ? os.hostname() : workstation;
|
workstation = workstation === undefined ? os.hostname() : workstation;
|
||||||
target = target === undefined ? '' : target;
|
target = target === undefined ? "" : target;
|
||||||
//signature
|
//signature
|
||||||
buf.write(NTLMSIGNATURE, pos, NTLMSIGNATURE.length, 'ascii');
|
buf.write(NTLMSIGNATURE, pos, NTLMSIGNATURE.length, "ascii");
|
||||||
pos += NTLMSIGNATURE.length;
|
pos += NTLMSIGNATURE.length;
|
||||||
//message type
|
//message type
|
||||||
buf.writeUInt32LE(1, pos);
|
buf.writeUInt32LE(1, pos);
|
||||||
|
@ -27,7 +28,7 @@ function createType1Message(workstation, target) {
|
||||||
buf.writeUInt32LE(target.length === 0 ? 0 : dataPos, pos);
|
buf.writeUInt32LE(target.length === 0 ? 0 : dataPos, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (target.length > 0) {
|
if (target.length > 0) {
|
||||||
dataPos += buf.write(target, dataPos, 'ascii');
|
dataPos += buf.write(target, dataPos, "ascii");
|
||||||
}
|
}
|
||||||
//workstation security buffer
|
//workstation security buffer
|
||||||
buf.writeUInt16LE(workstation.length, pos);
|
buf.writeUInt16LE(workstation.length, pos);
|
||||||
|
@ -37,39 +38,39 @@ function createType1Message(workstation, target) {
|
||||||
buf.writeUInt32LE(workstation.length === 0 ? 0 : dataPos, pos);
|
buf.writeUInt32LE(workstation.length === 0 ? 0 : dataPos, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (workstation.length > 0) {
|
if (workstation.length > 0) {
|
||||||
dataPos += buf.write(workstation, dataPos, 'ascii');
|
dataPos += buf.write(workstation, dataPos, "ascii");
|
||||||
}
|
}
|
||||||
return 'NTLM ' + buf.toString('base64', 0, dataPos);
|
return "NTLM " + buf.toString("base64", 0, dataPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeType2Message(str) {
|
function decodeType2Message(str) {
|
||||||
if (str === undefined) {
|
if (str === undefined) {
|
||||||
throw new Error('Invalid argument');
|
throw new Error("Invalid argument");
|
||||||
}
|
}
|
||||||
//convenience
|
//convenience
|
||||||
if (Object.prototype.toString.call(str) !== '[object String]') {
|
if (Object.prototype.toString.call(str) !== "[object String]") {
|
||||||
if (str.hasOwnProperty('headers') && str.headers.hasOwnProperty('www-authenticate')) {
|
if (str.hasOwnProperty("headers") && str.headers.hasOwnProperty("www-authenticate")) {
|
||||||
str = str.headers['www-authenticate'];
|
str = str.headers["www-authenticate"];
|
||||||
}
|
} else {
|
||||||
else {
|
throw new Error("Invalid argument");
|
||||||
throw new Error('Invalid argument');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var ntlmMatch = /^NTLM ([^,\s]+)/.exec(str);
|
var ntlmMatch = /^NTLM ([^,\s]+)/.exec(str);
|
||||||
if (ntlmMatch) {
|
if (ntlmMatch) {
|
||||||
str = ntlmMatch[1];
|
str = ntlmMatch[1];
|
||||||
}
|
}
|
||||||
var buf = new Buffer.from(str, 'base64'), obj = {};
|
var buf = new Buffer.from(str, "base64"), obj = {};
|
||||||
//check signature
|
//check signature
|
||||||
if (buf.toString('ascii', 0, NTLMSIGNATURE.length) !== NTLMSIGNATURE) {
|
if (buf.toString("ascii", 0, NTLMSIGNATURE.length) !== NTLMSIGNATURE) {
|
||||||
throw new Error('Invalid message signature: ' + str);
|
throw new Error("Invalid message signature: " + str);
|
||||||
}
|
}
|
||||||
//check message type
|
//check message type
|
||||||
if (buf.readUInt32LE(NTLMSIGNATURE.length) !== 2) {
|
if (buf.readUInt32LE(NTLMSIGNATURE.length) !== 2) {
|
||||||
throw new Error('Invalid message type (no type 2)');
|
throw new Error("Invalid message type (no type 2)");
|
||||||
}
|
}
|
||||||
//read flags
|
//read flags
|
||||||
obj.flags = buf.readUInt32LE(20);
|
obj.flags = buf.readUInt32LE(20);
|
||||||
obj.encoding = (obj.flags & flags.NTLMFLAG_NEGOTIATE_OEM) ? 'ascii' : 'ucs2';
|
obj.encoding = (obj.flags & flags.NTLMFLAG_NEGOTIATE_OEM) ? "ascii" : "ucs2";
|
||||||
obj.version = (obj.flags & flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY) ? 2 : 1;
|
obj.version = (obj.flags & flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY) ? 2 : 1;
|
||||||
obj.challenge = buf.slice(24, 32);
|
obj.challenge = buf.slice(24, 32);
|
||||||
//read target name
|
//read target name
|
||||||
|
@ -78,10 +79,10 @@ function decodeType2Message(str) {
|
||||||
//skipping allocated space
|
//skipping allocated space
|
||||||
var offset = buf.readUInt32LE(16);
|
var offset = buf.readUInt32LE(16);
|
||||||
if (length === 0) {
|
if (length === 0) {
|
||||||
return '';
|
return "";
|
||||||
}
|
}
|
||||||
if ((offset + length) > buf.length || offset < 32) {
|
if ((offset + length) > buf.length || offset < 32) {
|
||||||
throw new Error('Bad type 2 message');
|
throw new Error("Bad type 2 message");
|
||||||
}
|
}
|
||||||
return buf.toString(obj.encoding, offset, offset + length);
|
return buf.toString(obj.encoding, offset, offset + length);
|
||||||
})();
|
})();
|
||||||
|
@ -98,7 +99,7 @@ function decodeType2Message(str) {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
if ((offset + length) > buf.length || offset < 32) {
|
if ((offset + length) > buf.length || offset < 32) {
|
||||||
throw new Error('Bad type 2 message');
|
throw new Error("Bad type 2 message");
|
||||||
}
|
}
|
||||||
var pos = offset;
|
var pos = offset;
|
||||||
while (pos < (offset + length)) {
|
while (pos < (offset + length)) {
|
||||||
|
@ -113,37 +114,38 @@ function decodeType2Message(str) {
|
||||||
var blockTypeStr = void 0;
|
var blockTypeStr = void 0;
|
||||||
switch (blockType) {
|
switch (blockType) {
|
||||||
case 1:
|
case 1:
|
||||||
blockTypeStr = 'SERVER';
|
blockTypeStr = "SERVER";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
blockTypeStr = 'DOMAIN';
|
blockTypeStr = "DOMAIN";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
blockTypeStr = 'FQDN';
|
blockTypeStr = "FQDN";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
blockTypeStr = 'DNS';
|
blockTypeStr = "DNS";
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
blockTypeStr = 'PARENT_DNS';
|
blockTypeStr = "PARENT_DNS";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
blockTypeStr = '';
|
blockTypeStr = "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (blockTypeStr) {
|
if (blockTypeStr) {
|
||||||
info[blockTypeStr] = buf.toString('ucs2', pos, pos + blockLength);
|
info[blockTypeStr] = buf.toString("ucs2", pos, pos + blockLength);
|
||||||
}
|
}
|
||||||
pos += blockLength;
|
pos += blockLength;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
parsed: info,
|
parsed: info,
|
||||||
buffer: targetInfoBuffer
|
buffer: targetInfoBuffer,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createType3Message(type2Message, username, password, workstation, target) {
|
function createType3Message(type2Message, username, password, workstation, target) {
|
||||||
var dataPos = 52, buf = new Buffer.alloc(1024);
|
var dataPos = 52, buf = new Buffer.alloc(1024);
|
||||||
if (workstation === undefined) {
|
if (workstation === undefined) {
|
||||||
|
@ -153,12 +155,14 @@ function createType3Message(type2Message, username, password, workstation, targe
|
||||||
target = type2Message.targetName;
|
target = type2Message.targetName;
|
||||||
}
|
}
|
||||||
//signature
|
//signature
|
||||||
buf.write(NTLMSIGNATURE, 0, NTLMSIGNATURE.length, 'ascii');
|
buf.write(NTLMSIGNATURE, 0, NTLMSIGNATURE.length, "ascii");
|
||||||
//message type
|
//message type
|
||||||
buf.writeUInt32LE(3, 8);
|
buf.writeUInt32LE(3, 8);
|
||||||
if (type2Message.version === 2) {
|
if (type2Message.version === 2) {
|
||||||
dataPos = 64;
|
dataPos = 64;
|
||||||
var ntlmHash = hash.createNTLMHash(password), nonce = hash.createPseudoRandomValue(16), lmv2 = hash.createLMv2Response(type2Message, username, ntlmHash, nonce, target), ntlmv2 = hash.createNTLMv2Response(type2Message, username, ntlmHash, nonce, target);
|
var ntlmHash = hash.createNTLMHash(password), nonce = hash.createPseudoRandomValue(16),
|
||||||
|
lmv2 = hash.createLMv2Response(type2Message, username, ntlmHash, nonce, target),
|
||||||
|
ntlmv2 = hash.createNTLMv2Response(type2Message, username, ntlmHash, nonce, target);
|
||||||
//lmv2 security buffer
|
//lmv2 security buffer
|
||||||
buf.writeUInt16LE(lmv2.length, 12);
|
buf.writeUInt16LE(lmv2.length, 12);
|
||||||
buf.writeUInt16LE(lmv2.length, 14);
|
buf.writeUInt16LE(lmv2.length, 14);
|
||||||
|
@ -171,9 +175,10 @@ function createType3Message(type2Message, username, password, workstation, targe
|
||||||
buf.writeUInt32LE(dataPos, 24);
|
buf.writeUInt32LE(dataPos, 24);
|
||||||
ntlmv2.copy(buf, dataPos);
|
ntlmv2.copy(buf, dataPos);
|
||||||
dataPos += ntlmv2.length;
|
dataPos += ntlmv2.length;
|
||||||
}
|
} else {
|
||||||
else {
|
var lmHash = hash.createLMHash(password), ntlmHash = hash.createNTLMHash(password),
|
||||||
var lmHash = hash.createLMHash(password), ntlmHash = hash.createNTLMHash(password), lm = hash.createLMResponse(type2Message.challenge, lmHash), ntlm = hash.createNTLMResponse(type2Message.challenge, ntlmHash);
|
lm = hash.createLMResponse(type2Message.challenge, lmHash),
|
||||||
|
ntlm = hash.createNTLMResponse(type2Message.challenge, ntlmHash);
|
||||||
//lm security buffer
|
//lm security buffer
|
||||||
buf.writeUInt16LE(lm.length, 12);
|
buf.writeUInt16LE(lm.length, 12);
|
||||||
buf.writeUInt16LE(lm.length, 14);
|
buf.writeUInt16LE(lm.length, 14);
|
||||||
|
@ -188,18 +193,18 @@ function createType3Message(type2Message, username, password, workstation, targe
|
||||||
dataPos += ntlm.length;
|
dataPos += ntlm.length;
|
||||||
}
|
}
|
||||||
//target name security buffer
|
//target name security buffer
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 28);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? target.length : target.length * 2, 28);
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 30);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? target.length : target.length * 2, 30);
|
||||||
buf.writeUInt32LE(dataPos, 32);
|
buf.writeUInt32LE(dataPos, 32);
|
||||||
dataPos += buf.write(target, dataPos, type2Message.encoding);
|
dataPos += buf.write(target, dataPos, type2Message.encoding);
|
||||||
//user name security buffer
|
//user name security buffer
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 36);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? username.length : username.length * 2, 36);
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 38);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? username.length : username.length * 2, 38);
|
||||||
buf.writeUInt32LE(dataPos, 40);
|
buf.writeUInt32LE(dataPos, 40);
|
||||||
dataPos += buf.write(username, dataPos, type2Message.encoding);
|
dataPos += buf.write(username, dataPos, type2Message.encoding);
|
||||||
//workstation name security buffer
|
//workstation name security buffer
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 44);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? workstation.length : workstation.length * 2, 44);
|
||||||
buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 46);
|
buf.writeUInt16LE(type2Message.encoding === "ascii" ? workstation.length : workstation.length * 2, 46);
|
||||||
buf.writeUInt32LE(dataPos, 48);
|
buf.writeUInt32LE(dataPos, 48);
|
||||||
dataPos += buf.write(workstation, dataPos, type2Message.encoding);
|
dataPos += buf.write(workstation, dataPos, type2Message.encoding);
|
||||||
if (type2Message.version === 2) {
|
if (type2Message.version === 2) {
|
||||||
|
@ -210,11 +215,12 @@ function createType3Message(type2Message, username, password, workstation, targe
|
||||||
//flags
|
//flags
|
||||||
buf.writeUInt32LE(type2Message.flags, 60);
|
buf.writeUInt32LE(type2Message.flags, 60);
|
||||||
}
|
}
|
||||||
return 'NTLM ' + buf.toString('base64', 0, dataPos);
|
return "NTLM " + buf.toString("base64", 0, dataPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createType1Message: createType1Message,
|
createType1Message: createType1Message,
|
||||||
decodeType2Message: decodeType2Message,
|
decodeType2Message: decodeType2Message,
|
||||||
createType3Message: createType3Message
|
createType3Message: createType3Message,
|
||||||
};
|
};
|
||||||
//# sourceMappingURL=ntlm.js.map
|
//# sourceMappingURL=ntlm.js.map
|
||||||
|
|
|
@ -1,57 +1,172 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function (o, m, k, k2) {
|
||||||
if (k2 === undefined) k2 = k;
|
if (k2 === undefined) {
|
||||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
k2 = k;
|
||||||
}) : (function(o, m, k, k2) {
|
}
|
||||||
if (k2 === undefined) k2 = k;
|
Object.defineProperty(o, k2, {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return m[k];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}) : (function (o, m, k, k2) {
|
||||||
|
if (k2 === undefined) {
|
||||||
|
k2 = k;
|
||||||
|
}
|
||||||
o[k2] = m[k];
|
o[k2] = m[k];
|
||||||
}));
|
}));
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function (o, v) {
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
Object.defineProperty(o, "default", {
|
||||||
}) : function(o, v) {
|
enumerable: true,
|
||||||
|
value: v,
|
||||||
|
});
|
||||||
|
}) : function (o, v) {
|
||||||
o["default"] = v;
|
o["default"] = v;
|
||||||
});
|
});
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
if (mod && mod.__esModule) return mod;
|
if (mod && mod.__esModule) {
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
var result = {};
|
var result = {};
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
if (mod != null) {
|
||||||
|
for (var k in mod) {
|
||||||
|
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) {
|
||||||
|
__createBinding(result, mod, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
__setModuleDefault(result, mod);
|
__setModuleDefault(result, mod);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) {
|
||||||
|
return value instanceof P ? value : new P(function (resolve) {
|
||||||
|
resolve(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
function fulfilled(value) {
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
try {
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
step(generator.next(value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejected(value) {
|
||||||
|
try {
|
||||||
|
step(generator["throw"](value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function step(result) {
|
||||||
|
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
||||||
|
}
|
||||||
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
var _ = {
|
||||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
label: 0,
|
||||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
sent: function () {
|
||||||
function step(op) {
|
if (t[0] & 1) {
|
||||||
if (f) throw new TypeError("Generator is already executing.");
|
throw t[1];
|
||||||
while (_) try {
|
|
||||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
||||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
||||||
switch (op[0]) {
|
|
||||||
case 0: case 1: t = op; break;
|
|
||||||
case 4: _.label++; return { value: op[1], done: false };
|
|
||||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
||||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
||||||
default:
|
|
||||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
||||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
||||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
||||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
||||||
if (t[2]) _.ops.pop();
|
|
||||||
_.trys.pop(); continue;
|
|
||||||
}
|
}
|
||||||
op = body.call(thisArg, _);
|
return t[1];
|
||||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
},
|
||||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
trys: [],
|
||||||
|
ops: [],
|
||||||
|
}, f, y, t, g;
|
||||||
|
return g = {
|
||||||
|
next: verb(0),
|
||||||
|
"throw": verb(1),
|
||||||
|
"return": verb(2),
|
||||||
|
}, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
|
||||||
|
return this;
|
||||||
|
}), g;
|
||||||
|
|
||||||
|
function verb(n) {
|
||||||
|
return function (v) {
|
||||||
|
return step([ n, v ]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function step(op) {
|
||||||
|
if (f) {
|
||||||
|
throw new TypeError("Generator is already executing.");
|
||||||
|
}
|
||||||
|
while (_) {
|
||||||
|
try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (y = 0, t) {
|
||||||
|
op = [ op[0] & 2, t.value ];
|
||||||
|
}
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
t = op;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_.label++;
|
||||||
|
return {
|
||||||
|
value: op[1],
|
||||||
|
done: false,
|
||||||
|
};
|
||||||
|
case 5:
|
||||||
|
_.label++;
|
||||||
|
y = op[1];
|
||||||
|
op = [ 0 ];
|
||||||
|
continue;
|
||||||
|
case 7:
|
||||||
|
op = _.ops.pop();
|
||||||
|
_.trys.pop();
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
||||||
|
_ = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
|
||||||
|
_.label = op[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (op[0] === 6 && _.label < t[1]) {
|
||||||
|
_.label = t[1];
|
||||||
|
t = op;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (t && _.label < t[2]) {
|
||||||
|
_.label = t[2];
|
||||||
|
_.ops.push(op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (t[2]) {
|
||||||
|
_.ops.pop();
|
||||||
|
}
|
||||||
|
_.trys.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) {
|
||||||
|
op = [ 6, e ];
|
||||||
|
y = 0;
|
||||||
|
} finally {
|
||||||
|
f = t = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op[0] & 5) {
|
||||||
|
throw op[1];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value: op[0] ? op[1] : void 0,
|
||||||
|
done: true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
@ -64,12 +179,13 @@ var ntlm = __importStar(require("./ntlm"));
|
||||||
var https = __importStar(require("https"));
|
var https = __importStar(require("https"));
|
||||||
var http = __importStar(require("http"));
|
var http = __importStar(require("http"));
|
||||||
var dev_null_1 = __importDefault(require("dev-null"));
|
var dev_null_1 = __importDefault(require("dev-null"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param credentials An NtlmCredentials object containing the username and password
|
* @param credentials An NtlmCredentials object containing the username and password
|
||||||
* @param AxiosConfig The Axios config for the instance you wish to create
|
* @param AxiosConfig The Axios config for the instance you wish to create
|
||||||
*
|
*
|
||||||
* @returns This function returns an axios instance configured to use the provided credentials
|
* @returns This function returns an axios instance configured to use the provided credentials
|
||||||
*/
|
*/
|
||||||
function NtlmClient(credentials, AxiosConfig) {
|
function NtlmClient(credentials, AxiosConfig) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var config = AxiosConfig !== null && AxiosConfig !== void 0 ? AxiosConfig : {};
|
var config = AxiosConfig !== null && AxiosConfig !== void 0 ? AxiosConfig : {};
|
||||||
|
@ -82,46 +198,56 @@ function NtlmClient(credentials, AxiosConfig) {
|
||||||
var client = axios_1.default.create(config);
|
var client = axios_1.default.create(config);
|
||||||
client.interceptors.response.use(function (response) {
|
client.interceptors.response.use(function (response) {
|
||||||
return response;
|
return response;
|
||||||
}, function (err) { return __awaiter(_this, void 0, void 0, function () {
|
}, function (err) {
|
||||||
var error, t1Msg, t2Msg, t3Msg, stream_1;
|
return __awaiter(_this, void 0, void 0, function () {
|
||||||
var _a;
|
var error, t1Msg, t2Msg, t3Msg, stream_1;
|
||||||
return __generator(this, function (_b) {
|
var _a;
|
||||||
switch (_b.label) {
|
return __generator(this, function (_b) {
|
||||||
case 0:
|
switch (_b.label) {
|
||||||
error = err.response;
|
case 0:
|
||||||
if (!(error && error.status === 401
|
error = err.response;
|
||||||
&& error.headers['www-authenticate']
|
if (!(error && error.status === 401
|
||||||
&& error.headers['www-authenticate'].includes('NTLM'))) return [3 /*break*/, 3];
|
&& error.headers["www-authenticate"]
|
||||||
// This length check is a hack because SharePoint is awkward and will
|
&& error.headers["www-authenticate"].includes("NTLM"))) {
|
||||||
// include the Negotiate option when responding with the T2 message
|
return [ 3 /*break*/, 3 ];
|
||||||
// There is nore we could do to ensure we are processing correctly,
|
}
|
||||||
// but this is the easiest option for now
|
// This length check is a hack because SharePoint is awkward and will
|
||||||
if (error.headers['www-authenticate'].length < 50) {
|
// include the Negotiate option when responding with the T2 message
|
||||||
t1Msg = ntlm.createType1Message(credentials.workstation, credentials.domain);
|
// There is nore we could do to ensure we are processing correctly,
|
||||||
error.config.headers["Authorization"] = t1Msg;
|
// but this is the easiest option for now
|
||||||
}
|
if (error.headers["www-authenticate"].length < 50) {
|
||||||
else {
|
t1Msg = ntlm.createType1Message(credentials.workstation, credentials.domain);
|
||||||
t2Msg = ntlm.decodeType2Message((error.headers['www-authenticate'].match(/^NTLM\s+(.+?)(,|\s+|$)/) || [])[1]);
|
error.config.headers["Authorization"] = t1Msg;
|
||||||
t3Msg = ntlm.createType3Message(t2Msg, credentials.username, credentials.password, credentials.workstation, credentials.domain);
|
} else {
|
||||||
error.config.headers["X-retry"] = "false";
|
t2Msg = ntlm.decodeType2Message((error.headers["www-authenticate"].match(/^NTLM\s+(.+?)(,|\s+|$)/) || [])[1]);
|
||||||
error.config.headers["Authorization"] = t3Msg;
|
t3Msg = ntlm.createType3Message(t2Msg, credentials.username, credentials.password, credentials.workstation, credentials.domain);
|
||||||
}
|
error.config.headers["X-retry"] = "false";
|
||||||
if (!(error.config.responseType === "stream")) return [3 /*break*/, 2];
|
error.config.headers["Authorization"] = t3Msg;
|
||||||
stream_1 = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data;
|
}
|
||||||
if (!(stream_1 && !stream_1.readableEnded)) return [3 /*break*/, 2];
|
if (!(error.config.responseType === "stream")) {
|
||||||
return [4 /*yield*/, new Promise(function (resolve) {
|
return [ 3 /*break*/, 2 ];
|
||||||
|
}
|
||||||
|
stream_1 = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data;
|
||||||
|
if (!(stream_1 && !stream_1.readableEnded)) {
|
||||||
|
return [ 3 /*break*/, 2 ];
|
||||||
|
}
|
||||||
|
return [ 4 /*yield*/, new Promise(function (resolve) {
|
||||||
stream_1.pipe((0, dev_null_1.default)());
|
stream_1.pipe((0, dev_null_1.default)());
|
||||||
stream_1.once('close', resolve);
|
stream_1.once('close', resolve);
|
||||||
})];
|
}) ];
|
||||||
case 1:
|
case 1:
|
||||||
_b.sent();
|
_b.sent();
|
||||||
_b.label = 2;
|
_b.label = 2;
|
||||||
case 2: return [2 /*return*/, client(error.config)];
|
case 2:
|
||||||
case 3: throw err;
|
return [ 2 /*return*/, client(error.config) ];
|
||||||
}
|
case 3:
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}); });
|
});
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.NtlmClient = NtlmClient;
|
exports.NtlmClient = NtlmClient;
|
||||||
//# sourceMappingURL=ntlmClient.js.map
|
//# sourceMappingURL=ntlmClient.js.map
|
||||||
|
|
32
server/modules/dayjs/plugin/timezone.d.ts
vendored
32
server/modules/dayjs/plugin/timezone.d.ts
vendored
|
@ -1,20 +1,24 @@
|
||||||
import { PluginFunc, ConfigType } from 'dayjs'
|
import { PluginFunc, ConfigType } from "dayjs";
|
||||||
|
|
||||||
declare const plugin: PluginFunc
|
declare const plugin: PluginFunc;
|
||||||
export = plugin
|
export = plugin
|
||||||
|
|
||||||
declare module 'dayjs' {
|
declare module "dayjs" {
|
||||||
interface Dayjs {
|
interface Dayjs {
|
||||||
tz(timezone?: string, keepLocalTime?: boolean): Dayjs
|
tz(timezone?: string, keepLocalTime?: boolean): Dayjs;
|
||||||
offsetName(type?: 'short' | 'long'): string | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DayjsTimezone {
|
offsetName(type?: "short" | "long"): string | undefined;
|
||||||
(date: ConfigType, timezone?: string): Dayjs
|
}
|
||||||
(date: ConfigType, format: string, timezone?: string): Dayjs
|
|
||||||
guess(): string
|
|
||||||
setDefault(timezone?: string): void
|
|
||||||
}
|
|
||||||
|
|
||||||
const tz: DayjsTimezone
|
interface DayjsTimezone {
|
||||||
|
(date: ConfigType, timezone?: string): Dayjs;
|
||||||
|
|
||||||
|
(date: ConfigType, format: string, timezone?: string): Dayjs;
|
||||||
|
|
||||||
|
guess(): string;
|
||||||
|
|
||||||
|
setDefault(timezone?: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tz: DayjsTimezone;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
day: 2,
|
day: 2,
|
||||||
hour: 3,
|
hour: 3,
|
||||||
minute: 4,
|
minute: 4,
|
||||||
second: 5
|
second: 5,
|
||||||
};
|
};
|
||||||
let e = {};
|
let e = {};
|
||||||
return function (n, i, o) {
|
return function (n, i, o) {
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
timeZoneName: i
|
timeZoneName: i,
|
||||||
}), e[o] = r), r;
|
}), e[o] = r), r;
|
||||||
}(n, i);
|
}(n, i);
|
||||||
return r.formatToParts(o);
|
return r.formatToParts(o);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { UP, DOWN } = require("../../src/util");
|
const {
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
} = require("../../src/util");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { dnsResolve } = require("../util-server");
|
const { dnsResolve } = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
|
@ -14,7 +17,7 @@ class DnsMonitorType extends MonitorType {
|
||||||
supportsConditions = true;
|
supportsConditions = true;
|
||||||
|
|
||||||
conditionVariables = [
|
conditionVariables = [
|
||||||
new ConditionVariable("record", defaultStringOperators ),
|
new ConditionVariable("record", defaultStringOperators),
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { log, UP } = require("../../src/util");
|
const {
|
||||||
|
log,
|
||||||
|
UP,
|
||||||
|
} = require("../../src/util");
|
||||||
const mqtt = require("mqtt");
|
const mqtt = require("mqtt");
|
||||||
const jsonata = require("jsonata");
|
const jsonata = require("jsonata");
|
||||||
|
|
||||||
|
@ -57,7 +60,12 @@ class MqttMonitorType extends MonitorType {
|
||||||
*/
|
*/
|
||||||
mqttAsync(hostname, topic, options = {}) {
|
mqttAsync(hostname, topic, options = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { port, username, password, interval = 20 } = options;
|
const {
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
interval = 20,
|
||||||
|
} = options;
|
||||||
|
|
||||||
// Adds MQTT protocol to the hostname if not already present
|
// Adds MQTT protocol to the hostname if not already present
|
||||||
if (!/^(?:http|mqtt|ws)s?:\/\//.test(hostname)) {
|
if (!/^(?:http|mqtt|ws)s?:\/\//.test(hostname)) {
|
||||||
|
@ -77,7 +85,7 @@ class MqttMonitorType extends MonitorType {
|
||||||
let client = mqtt.connect(mqttUrl, {
|
let client = mqtt.connect(mqttUrl, {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
clientId: "uptime-kuma_" + Math.random().toString(16).substr(2, 8)
|
clientId: "uptime-kuma_" + Math.random().toString(16).substr(2, 8),
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on("connect", () => {
|
client.on("connect", () => {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { log, UP, DOWN } = require("../../src/util");
|
const {
|
||||||
|
log,
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
} = require("../../src/util");
|
||||||
const { axiosAbortSignal } = require("../util-server");
|
const { axiosAbortSignal } = require("../util-server");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ class RabbitMqMonitorType extends MonitorType {
|
||||||
for (let baseUrl of baseUrls) {
|
for (let baseUrl of baseUrls) {
|
||||||
try {
|
try {
|
||||||
// Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com
|
// Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com
|
||||||
if ( !baseUrl.endsWith("/") ) {
|
if (!baseUrl.endsWith("/")) {
|
||||||
baseUrl += "/";
|
baseUrl += "/";
|
||||||
}
|
}
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { chromium } = require("playwright-core");
|
const { chromium } = require("playwright-core");
|
||||||
const { UP, log } = require("../../src/util");
|
const {
|
||||||
|
UP,
|
||||||
|
log,
|
||||||
|
} = require("../../src/util");
|
||||||
const { Settings } = require("../settings");
|
const { Settings } = require("../settings");
|
||||||
const commandExistsSync = require("command-exists").sync;
|
const commandExistsSync = require("command-exists").sync;
|
||||||
const childProcess = require("child_process");
|
const childProcess = require("child_process");
|
||||||
|
@ -122,7 +125,7 @@ async function prepareChromeExecutable(executablePath) {
|
||||||
executablePath = "/usr/bin/chromium";
|
executablePath = "/usr/bin/chromium";
|
||||||
|
|
||||||
// Install chromium in container via apt install
|
// Install chromium in container via apt install
|
||||||
if ( !commandExistsSync(executablePath)) {
|
if (!commandExistsSync(executablePath)) {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
log.info("Chromium", "Installing Chromium...");
|
log.info("Chromium", "Installing Chromium...");
|
||||||
let child = childProcess.exec("apt update && apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk");
|
let child = childProcess.exec("apt update && apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk");
|
||||||
|
@ -213,6 +216,7 @@ async function testChrome(executablePath) {
|
||||||
throw new Error(e.message);
|
throw new Error(e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test remote browser
|
// test remote browser
|
||||||
/**
|
/**
|
||||||
* @param {string} remoteBrowserURL Remote Browser URL
|
* @param {string} remoteBrowserURL Remote Browser URL
|
||||||
|
@ -228,6 +232,7 @@ async function testRemoteBrowser(remoteBrowserURL) {
|
||||||
throw new Error(e.message);
|
throw new Error(e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealBrowserMonitorType extends MonitorType {
|
class RealBrowserMonitorType extends MonitorType {
|
||||||
|
|
||||||
name = "real-browser";
|
name = "real-browser";
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { UP, log, evaluateJsonQuery } = require("../../src/util");
|
const {
|
||||||
|
UP,
|
||||||
|
log,
|
||||||
|
evaluateJsonQuery,
|
||||||
|
} = require("../../src/util");
|
||||||
const snmp = require("net-snmp");
|
const snmp = require("net-snmp");
|
||||||
|
|
||||||
class SNMPMonitorType extends MonitorType {
|
class SNMPMonitorType extends MonitorType {
|
||||||
|
@ -42,7 +46,10 @@ class SNMPMonitorType extends MonitorType {
|
||||||
// We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in.
|
// We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in.
|
||||||
const value = varbinds[0].value;
|
const value = varbinds[0].value;
|
||||||
|
|
||||||
const { status, response } = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue);
|
const {
|
||||||
|
status,
|
||||||
|
response,
|
||||||
|
} = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
heartbeat.status = UP;
|
heartbeat.status = UP;
|
||||||
|
|
|
@ -5,6 +5,15 @@ const NotifyClient = require("notifications-node-client").NotifyClient;
|
||||||
class GovNotify extends NotificationProvider {
|
class GovNotify extends NotificationProvider {
|
||||||
name = "GovNotify";
|
name = "GovNotify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends notifications via email and SMS using the GOV.UK Notify service.
|
||||||
|
* @param {object} notification The notification object containing configuration such as API key, email recipients, SMS recipients, message template, and template IDs for email and SMS.
|
||||||
|
* @param {string} msg The message content to send if no message template is provided in the notification object.
|
||||||
|
* @param {object | null} monitorJSON Optional parameter containing monitoring-related data.
|
||||||
|
* @param {object | null} heartbeatJSON Optional parameter containing heartbeat-related data, used to determine notification subject (e.g., status up or down).
|
||||||
|
* @returns {Promise<string>} A promise that resolves to a success message after sending notifications or rejects with an error if the sending fails.
|
||||||
|
* @throws {Error} Throws an error if notification sending fails.
|
||||||
|
*/
|
||||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
try {
|
try {
|
||||||
const apiKey = notification.apiKey;
|
const apiKey = notification.apiKey;
|
||||||
|
|
|
@ -20,19 +20,21 @@ class HomeAssistant extends NotificationProvider {
|
||||||
{
|
{
|
||||||
title: "Uptime Kuma",
|
title: "Uptime Kuma",
|
||||||
message: msg,
|
message: msg,
|
||||||
...(notificationService !== "persistent_notification" && { data: {
|
...(notificationService !== "persistent_notification" && {
|
||||||
name: monitorJSON?.name,
|
data: {
|
||||||
status: heartbeatJSON?.status,
|
name: monitorJSON?.name,
|
||||||
channel: "Uptime Kuma",
|
status: heartbeatJSON?.status,
|
||||||
icon_url: "https://github.com/louislam/uptime-kuma/blob/master/public/icon.png?raw=true",
|
channel: "Uptime Kuma",
|
||||||
} }),
|
icon_url: "https://github.com/louislam/uptime-kuma/blob/master/public/icon.png?raw=true",
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${notification.longLivedAccessToken}`,
|
Authorization: `Bearer ${notification.longLivedAccessToken}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return okMsg;
|
return okMsg;
|
||||||
|
|
|
@ -159,7 +159,7 @@ class Notification {
|
||||||
new GovNotify(),
|
new GovNotify(),
|
||||||
];
|
];
|
||||||
for (let item of list) {
|
for (let item of list) {
|
||||||
if (! item.name) {
|
if (!item.name) {
|
||||||
throw new Error("Notification provider without name");
|
throw new Error("Notification provider without name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ class Notification {
|
||||||
userID,
|
userID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! bean) {
|
if (!bean) {
|
||||||
throw new Error("notification not found");
|
throw new Error("notification not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ class Notification {
|
||||||
userID,
|
userID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! bean) {
|
if (!bean) {
|
||||||
throw new Error("notification not found");
|
throw new Error("notification not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ class Notification {
|
||||||
*/
|
*/
|
||||||
async function applyNotificationEveryMonitor(notificationID, userID) {
|
async function applyNotificationEveryMonitor(notificationID, userID) {
|
||||||
let monitors = await R.getAll("SELECT id FROM monitor WHERE user_id = ?", [
|
let monitors = await R.getAll("SELECT id FROM monitor WHERE user_id = ?", [
|
||||||
userID
|
userID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let i = 0; i < monitors.length; i++) {
|
for (let i = 0; i < monitors.length; i++) {
|
||||||
|
@ -272,7 +272,7 @@ async function applyNotificationEveryMonitor(notificationID, userID) {
|
||||||
notificationID,
|
notificationID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! checkNotification) {
|
if (!checkNotification) {
|
||||||
let relation = R.dispense("monitor_notification");
|
let relation = R.dispense("monitor_notification");
|
||||||
relation.monitor_id = monitors[i].id;
|
relation.monitor_id = monitors[i].id;
|
||||||
relation.notification_id = notificationID;
|
relation.notification_id = notificationID;
|
||||||
|
|
|
@ -12,24 +12,24 @@ const commonLabels = [
|
||||||
const monitorCertDaysRemaining = new PrometheusClient.Gauge({
|
const monitorCertDaysRemaining = new PrometheusClient.Gauge({
|
||||||
name: "monitor_cert_days_remaining",
|
name: "monitor_cert_days_remaining",
|
||||||
help: "The number of days remaining until the certificate expires",
|
help: "The number of days remaining until the certificate expires",
|
||||||
labelNames: commonLabels
|
labelNames: commonLabels,
|
||||||
});
|
});
|
||||||
|
|
||||||
const monitorCertIsValid = new PrometheusClient.Gauge({
|
const monitorCertIsValid = new PrometheusClient.Gauge({
|
||||||
name: "monitor_cert_is_valid",
|
name: "monitor_cert_is_valid",
|
||||||
help: "Is the certificate still valid? (1 = Yes, 0= No)",
|
help: "Is the certificate still valid? (1 = Yes, 0= No)",
|
||||||
labelNames: commonLabels
|
labelNames: commonLabels,
|
||||||
});
|
});
|
||||||
const monitorResponseTime = new PrometheusClient.Gauge({
|
const monitorResponseTime = new PrometheusClient.Gauge({
|
||||||
name: "monitor_response_time",
|
name: "monitor_response_time",
|
||||||
help: "Monitor Response Time (ms)",
|
help: "Monitor Response Time (ms)",
|
||||||
labelNames: commonLabels
|
labelNames: commonLabels,
|
||||||
});
|
});
|
||||||
|
|
||||||
const monitorStatus = new PrometheusClient.Gauge({
|
const monitorStatus = new PrometheusClient.Gauge({
|
||||||
name: "monitor_status",
|
name: "monitor_status",
|
||||||
help: "Monitor Status (1 = UP, 0= DOWN, 2= PENDING, 3= MAINTENANCE)",
|
help: "Monitor Status (1 = UP, 0= DOWN, 2= PENDING, 3= MAINTENANCE)",
|
||||||
labelNames: commonLabels
|
labelNames: commonLabels,
|
||||||
});
|
});
|
||||||
|
|
||||||
class Prometheus {
|
class Prometheus {
|
||||||
|
@ -44,7 +44,7 @@ class Prometheus {
|
||||||
monitor_type: monitor.type,
|
monitor_type: monitor.type,
|
||||||
monitor_url: monitor.url,
|
monitor_url: monitor.url,
|
||||||
monitor_hostname: monitor.hostname,
|
monitor_hostname: monitor.hostname,
|
||||||
monitor_port: monitor.port
|
monitor_port: monitor.port,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,5 +119,5 @@ class Prometheus {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Prometheus
|
Prometheus,
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Proxy {
|
||||||
if (!this.SUPPORTED_PROXY_PROTOCOLS.includes(proxy.protocol)) {
|
if (!this.SUPPORTED_PROXY_PROTOCOLS.includes(proxy.protocol)) {
|
||||||
throw new Error(`
|
throw new Error(`
|
||||||
Unsupported proxy protocol "${proxy.protocol}.
|
Unsupported proxy protocol "${proxy.protocol}.
|
||||||
Supported protocols are ${this.SUPPORTED_PROXY_PROTOCOLS.join(", ")}."`
|
Supported protocols are ${this.SUPPORTED_PROXY_PROTOCOLS.join(", ")}."`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,10 @@ class Proxy {
|
||||||
* @throws Proxy protocol is unsupported
|
* @throws Proxy protocol is unsupported
|
||||||
*/
|
*/
|
||||||
static createAgents(proxy, options) {
|
static createAgents(proxy, options) {
|
||||||
const { httpAgentOptions, httpsAgentOptions } = options || {};
|
const {
|
||||||
|
httpAgentOptions,
|
||||||
|
httpsAgentOptions,
|
||||||
|
} = options || {};
|
||||||
let agent;
|
let agent;
|
||||||
let httpAgent;
|
let httpAgent;
|
||||||
let httpsAgent;
|
let httpsAgent;
|
||||||
|
@ -150,12 +153,13 @@ class Proxy {
|
||||||
httpsAgent = agent;
|
httpsAgent = agent;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: throw new Error(`Unsupported proxy protocol provided. ${proxy.protocol}`);
|
default:
|
||||||
|
throw new Error(`Unsupported proxy protocol provided. ${proxy.protocol}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
httpAgent,
|
httpAgent,
|
||||||
httpsAgent
|
httpsAgent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,15 @@ const { R } = require("redbean-node");
|
||||||
const apicache = require("../modules/apicache");
|
const apicache = require("../modules/apicache");
|
||||||
const Monitor = require("../model/monitor");
|
const Monitor = require("../model/monitor");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { UP, MAINTENANCE, DOWN, PENDING, flipStatus, log, badgeConstants } = require("../../src/util");
|
const {
|
||||||
|
UP,
|
||||||
|
MAINTENANCE,
|
||||||
|
DOWN,
|
||||||
|
PENDING,
|
||||||
|
flipStatus,
|
||||||
|
log,
|
||||||
|
badgeConstants,
|
||||||
|
} = require("../../src/util");
|
||||||
const StatusPage = require("../model/status_page");
|
const StatusPage = require("../model/status_page");
|
||||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||||
const { makeBadge } = require("badge-maker");
|
const { makeBadge } = require("badge-maker");
|
||||||
|
@ -28,7 +36,7 @@ let io = server.io;
|
||||||
router.get("/api/entry-page", async (request, response) => {
|
router.get("/api/entry-page", async (request, response) => {
|
||||||
allowDevAllOrigin(response);
|
allowDevAllOrigin(response);
|
||||||
|
|
||||||
let result = { };
|
let result = {};
|
||||||
let hostname = request.hostname;
|
let hostname = request.hostname;
|
||||||
if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) {
|
if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) {
|
||||||
hostname = request.headers["x-forwarded-host"];
|
hostname = request.headers["x-forwarded-host"];
|
||||||
|
@ -53,10 +61,10 @@ router.all("/api/push/:pushToken", async (request, response) => {
|
||||||
let status = (statusString === "up") ? UP : DOWN;
|
let status = (statusString === "up") ? UP : DOWN;
|
||||||
|
|
||||||
let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [
|
let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [
|
||||||
pushToken
|
pushToken,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! monitor) {
|
if (!monitor) {
|
||||||
throw new Error("Monitor not found or not active.");
|
throw new Error("Monitor not found or not active.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +135,7 @@ router.all("/api/push/:pushToken", async (request, response) => {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
response.status(404).json({
|
response.status(404).json({
|
||||||
ok: false,
|
ok: false,
|
||||||
msg: e.message
|
msg: e.message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -159,7 +167,7 @@ router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response
|
||||||
AND monitor_group.monitor_id = ?
|
AND monitor_group.monitor_id = ?
|
||||||
AND public = 1
|
AND public = 1
|
||||||
`,
|
`,
|
||||||
[ requestedMonitorId ]
|
[ requestedMonitorId ],
|
||||||
);
|
);
|
||||||
|
|
||||||
const badgeValues = { style };
|
const badgeValues = { style };
|
||||||
|
@ -242,7 +250,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
|
||||||
AND monitor_group.monitor_id = ?
|
AND monitor_group.monitor_id = ?
|
||||||
AND public = 1
|
AND public = 1
|
||||||
`,
|
`,
|
||||||
[ requestedMonitorId ]
|
[ requestedMonitorId ],
|
||||||
);
|
);
|
||||||
|
|
||||||
const badgeValues = { style };
|
const badgeValues = { style };
|
||||||
|
@ -362,7 +370,7 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async (
|
||||||
request.params.duration
|
request.params.duration
|
||||||
? parseInt(request.params.duration, 10)
|
? parseInt(request.params.duration, 10)
|
||||||
: 24,
|
: 24,
|
||||||
720
|
720,
|
||||||
);
|
);
|
||||||
const overrideValue = value && parseFloat(value);
|
const overrideValue = value && parseFloat(value);
|
||||||
|
|
||||||
|
@ -376,7 +384,7 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async (
|
||||||
AND public = 1
|
AND public = 1
|
||||||
AND heartbeat.monitor_id = ?
|
AND heartbeat.monitor_id = ?
|
||||||
`,
|
`,
|
||||||
[ -requestedDuration, requestedMonitorId ]
|
[ -requestedDuration, requestedMonitorId ],
|
||||||
));
|
));
|
||||||
|
|
||||||
const badgeValues = { style };
|
const badgeValues = { style };
|
||||||
|
@ -443,7 +451,7 @@ router.get("/api/badge/:id/cert-exp", cache("5 minutes"), async (request, respon
|
||||||
AND monitor_group.monitor_id = ?
|
AND monitor_group.monitor_id = ?
|
||||||
AND public = 1
|
AND public = 1
|
||||||
`,
|
`,
|
||||||
[ requestedMonitorId ]
|
[ requestedMonitorId ],
|
||||||
);
|
);
|
||||||
|
|
||||||
const badgeValues = { style };
|
const badgeValues = { style };
|
||||||
|
@ -528,7 +536,7 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon
|
||||||
AND monitor_group.monitor_id = ?
|
AND monitor_group.monitor_id = ?
|
||||||
AND public = 1
|
AND public = 1
|
||||||
`,
|
`,
|
||||||
[ requestedMonitorId ]
|
[ requestedMonitorId ],
|
||||||
);
|
);
|
||||||
|
|
||||||
const badgeValues = { style };
|
const badgeValues = { style };
|
||||||
|
@ -540,7 +548,7 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon
|
||||||
badgeValues.color = badgeConstants.naColor;
|
badgeValues.color = badgeConstants.naColor;
|
||||||
} else {
|
} else {
|
||||||
const heartbeat = await Monitor.getPreviousHeartbeat(
|
const heartbeat = await Monitor.getPreviousHeartbeat(
|
||||||
requestedMonitorId
|
requestedMonitorId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!heartbeat.ping) {
|
if (!heartbeat.ping) {
|
||||||
|
|
|
@ -2,7 +2,10 @@ let express = require("express");
|
||||||
const apicache = require("../modules/apicache");
|
const apicache = require("../modules/apicache");
|
||||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||||
const StatusPage = require("../model/status_page");
|
const StatusPage = require("../model/status_page");
|
||||||
const { allowDevAllOrigin, sendHttpError } = require("../util-server");
|
const {
|
||||||
|
allowDevAllOrigin,
|
||||||
|
sendHttpError,
|
||||||
|
} = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { badgeConstants } = require("../../src/util");
|
const { badgeConstants } = require("../../src/util");
|
||||||
const { makeBadge } = require("badge-maker");
|
const { makeBadge } = require("badge-maker");
|
||||||
|
@ -44,7 +47,7 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons
|
||||||
try {
|
try {
|
||||||
// Get Status Page
|
// Get Status Page
|
||||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
slug
|
slug,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!statusPage) {
|
if (!statusPage) {
|
||||||
|
@ -81,7 +84,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||||
AND public = 1
|
AND public = 1
|
||||||
AND \`group\`.status_page_id = ?
|
AND \`group\`.status_page_id = ?
|
||||||
`, [
|
`, [
|
||||||
statusPageID
|
statusPageID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for (let monitorID of monitorIDList) {
|
for (let monitorID of monitorIDList) {
|
||||||
|
@ -103,7 +106,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||||
|
|
||||||
response.json({
|
response.json({
|
||||||
heartbeatList,
|
heartbeatList,
|
||||||
uptimeList
|
uptimeList,
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -120,7 +123,7 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
|
||||||
try {
|
try {
|
||||||
// Get Status Page
|
// Get Status Page
|
||||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
slug
|
slug,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!statusPage) {
|
if (!statusPage) {
|
||||||
|
@ -137,9 +140,9 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
|
||||||
{
|
{
|
||||||
"src": statusPage.icon,
|
"src": statusPage.icon,
|
||||||
"sizes": "128x128",
|
"sizes": "128x128",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -159,7 +162,7 @@ router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, r
|
||||||
downColor = badgeConstants.defaultDownColor,
|
downColor = badgeConstants.defaultDownColor,
|
||||||
partialColor = "#F6BE00",
|
partialColor = "#F6BE00",
|
||||||
maintenanceColor = "#808080",
|
maintenanceColor = "#808080",
|
||||||
style = badgeConstants.defaultStyle
|
style = badgeConstants.defaultStyle,
|
||||||
} = request.query;
|
} = request.query;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -169,7 +172,7 @@ router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, r
|
||||||
AND public = 1
|
AND public = 1
|
||||||
AND \`group\`.status_page_id = ?
|
AND \`group\`.status_page_id = ?
|
||||||
`, [
|
`, [
|
||||||
statusPageID
|
statusPageID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let hasUp = false;
|
let hasUp = false;
|
||||||
|
|
|
@ -37,13 +37,19 @@ if (!semver.satisfies(nodeVersion, requiredNodeVersions)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = require("args-parser")(process.argv);
|
const args = require("args-parser")(process.argv);
|
||||||
const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util");
|
const {
|
||||||
|
sleep,
|
||||||
|
log,
|
||||||
|
getRandomInt,
|
||||||
|
genSecret,
|
||||||
|
isDev,
|
||||||
|
} = require("../src/util");
|
||||||
const config = require("./config");
|
const config = require("./config");
|
||||||
|
|
||||||
log.debug("server", "Arguments");
|
log.debug("server", "Arguments");
|
||||||
log.debug("server", args);
|
log.debug("server", args);
|
||||||
|
|
||||||
if (! process.env.NODE_ENV) {
|
if (!process.env.NODE_ENV) {
|
||||||
process.env.NODE_ENV = "production";
|
process.env.NODE_ENV = "production";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +96,16 @@ const Monitor = require("./model/monitor");
|
||||||
const User = require("./model/user");
|
const User = require("./model/user");
|
||||||
|
|
||||||
log.debug("server", "Importing Settings");
|
log.debug("server", "Importing Settings");
|
||||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin,
|
const {
|
||||||
|
getSettings,
|
||||||
|
setSettings,
|
||||||
|
setting,
|
||||||
|
initJWTSecret,
|
||||||
|
checkLogin,
|
||||||
|
doubleCheckPassword,
|
||||||
|
shake256,
|
||||||
|
SHAKE256_LENGTH,
|
||||||
|
allowDevAllOrigin,
|
||||||
} = require("./util-server");
|
} = require("./util-server");
|
||||||
|
|
||||||
log.debug("server", "Importing Notification");
|
log.debug("server", "Importing Notification");
|
||||||
|
@ -101,8 +116,14 @@ log.debug("server", "Importing Database");
|
||||||
const Database = require("./database");
|
const Database = require("./database");
|
||||||
|
|
||||||
log.debug("server", "Importing Background Jobs");
|
log.debug("server", "Importing Background Jobs");
|
||||||
const { initBackgroundJobs, stopBackgroundJobs } = require("./jobs");
|
const {
|
||||||
const { loginRateLimiter, twoFaRateLimiter } = require("./rate-limiter");
|
initBackgroundJobs,
|
||||||
|
stopBackgroundJobs,
|
||||||
|
} = require("./jobs");
|
||||||
|
const {
|
||||||
|
loginRateLimiter,
|
||||||
|
twoFaRateLimiter,
|
||||||
|
} = require("./rate-limiter");
|
||||||
|
|
||||||
const { apiAuth } = require("./auth");
|
const { apiAuth } = require("./auth");
|
||||||
const { login } = require("./auth");
|
const { login } = require("./auth");
|
||||||
|
@ -122,7 +143,7 @@ const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CL
|
||||||
// 2FA / notp verification defaults
|
// 2FA / notp verification defaults
|
||||||
const twoFAVerifyOptions = {
|
const twoFAVerifyOptions = {
|
||||||
"window": 1,
|
"window": 1,
|
||||||
"time": 30
|
"time": 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,13 +153,26 @@ const twoFAVerifyOptions = {
|
||||||
const testMode = !!args["test"] || false;
|
const testMode = !!args["test"] || false;
|
||||||
|
|
||||||
// Must be after io instantiation
|
// Must be after io instantiation
|
||||||
const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList, sendRemoteBrowserList, sendMonitorTypeList } = require("./client");
|
const {
|
||||||
|
sendNotificationList,
|
||||||
|
sendHeartbeatList,
|
||||||
|
sendInfo,
|
||||||
|
sendProxyList,
|
||||||
|
sendDockerHostList,
|
||||||
|
sendAPIKeyList,
|
||||||
|
sendRemoteBrowserList,
|
||||||
|
sendMonitorTypeList,
|
||||||
|
} = require("./client");
|
||||||
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
|
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
|
||||||
const { databaseSocketHandler } = require("./socket-handlers/database-socket-handler");
|
const { databaseSocketHandler } = require("./socket-handlers/database-socket-handler");
|
||||||
const { remoteBrowserSocketHandler } = require("./socket-handlers/remote-browser-socket-handler");
|
const { remoteBrowserSocketHandler } = require("./socket-handlers/remote-browser-socket-handler");
|
||||||
const TwoFA = require("./2fa");
|
const TwoFA = require("./2fa");
|
||||||
const StatusPage = require("./model/status_page");
|
const StatusPage = require("./model/status_page");
|
||||||
const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudflaredStop } = require("./socket-handlers/cloudflared-socket-handler");
|
const {
|
||||||
|
cloudflaredSocketHandler,
|
||||||
|
autoStart: cloudflaredAutoStart,
|
||||||
|
stop: cloudflaredStop,
|
||||||
|
} = require("./socket-handlers/cloudflared-socket-handler");
|
||||||
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
|
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
|
||||||
const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler");
|
const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler");
|
||||||
const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-socket-handler");
|
const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-socket-handler");
|
||||||
|
@ -933,8 +967,9 @@ let needSetup = false;
|
||||||
monitorID,
|
monitorID,
|
||||||
socket.userID,
|
socket.userID,
|
||||||
]);
|
]);
|
||||||
const monitorData = [{ id: monitor.id,
|
const monitorData = [ {
|
||||||
active: monitor.active
|
id: monitor.id,
|
||||||
|
active: monitor.active,
|
||||||
}];
|
}];
|
||||||
const preloadData = await Monitor.preparePreloadData(monitorData);
|
const preloadData = await Monitor.preparePreloadData(monitorData);
|
||||||
callback({
|
callback({
|
||||||
|
@ -966,7 +1001,8 @@ let needSetup = false;
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM heartbeat
|
FROM heartbeat
|
||||||
WHERE monitor_id = ?
|
WHERE monitor_id = ?
|
||||||
AND time > ${sqlHourOffset}
|
AND time
|
||||||
|
> ${sqlHourOffset}
|
||||||
ORDER BY time ASC
|
ORDER BY time ASC
|
||||||
`, [
|
`, [
|
||||||
monitorID,
|
monitorID,
|
||||||
|
@ -1519,7 +1555,7 @@ let needSetup = false;
|
||||||
log.info("manage", `Clear Heartbeats Monitor: ${monitorID} User ID: ${socket.userID}`);
|
log.info("manage", `Clear Heartbeats Monitor: ${monitorID} User ID: ${socket.userID}`);
|
||||||
|
|
||||||
await R.exec("DELETE FROM heartbeat WHERE monitor_id = ?", [
|
await R.exec("DELETE FROM heartbeat WHERE monitor_id = ?", [
|
||||||
monitorID
|
monitorID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sendHeartbeatList(socket, monitorID, true, true);
|
await sendHeartbeatList(socket, monitorID, true, true);
|
||||||
|
@ -1658,7 +1694,7 @@ async function checkOwner(userID, monitorID) {
|
||||||
userID,
|
userID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! row) {
|
if (!row) {
|
||||||
throw new Error("You do not own this monitor.");
|
throw new Error("You do not own this monitor.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1698,7 +1734,7 @@ async function afterLogin(socket, user) {
|
||||||
|
|
||||||
// Set server timezone from client browser if not set
|
// Set server timezone from client browser if not set
|
||||||
// It should be run once only
|
// It should be run once only
|
||||||
if (! await Settings.get("initServerTimezone")) {
|
if (!await Settings.get("initServerTimezone")) {
|
||||||
log.debug("server", "emit initServerTimezone");
|
log.debug("server", "emit initServerTimezone");
|
||||||
socket.emit("initServerTimezone");
|
socket.emit("initServerTimezone");
|
||||||
}
|
}
|
||||||
|
@ -1722,7 +1758,7 @@ async function initDatabase(testMode = false) {
|
||||||
"jwtSecret",
|
"jwtSecret",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! jwtSecretBean) {
|
if (!jwtSecretBean) {
|
||||||
log.info("server", "JWT secret is not found, generate one.");
|
log.info("server", "JWT secret is not found, generate one.");
|
||||||
jwtSecretBean = await initJWTSecret();
|
jwtSecretBean = await initJWTSecret();
|
||||||
log.info("server", "Stored JWT secret into database");
|
log.info("server", "Stored JWT secret into database");
|
||||||
|
|
|
@ -17,9 +17,7 @@ class Settings {
|
||||||
* }
|
* }
|
||||||
* @type {{}}
|
* @type {{}}
|
||||||
*/
|
*/
|
||||||
static cacheList = {
|
static cacheList = {};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static cacheCleaner = null;
|
static cacheCleaner = null;
|
||||||
|
|
||||||
|
@ -61,7 +59,7 @@ class Settings {
|
||||||
|
|
||||||
Settings.cacheList[key] = {
|
Settings.cacheList[key] = {
|
||||||
value: v,
|
value: v,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
@ -129,7 +127,7 @@ class Settings {
|
||||||
|
|
||||||
for (let key of keyList) {
|
for (let key of keyList) {
|
||||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||||
key
|
key,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (bean == null) {
|
if (bean == null) {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
const tcpp = require("tcp-ping");
|
const tcpp = require("tcp-ping");
|
||||||
const ping = require("@louislam/ping");
|
const ping = require("@louislam/ping");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { log, genSecret, badgeConstants } = require("../src/util");
|
const {
|
||||||
|
log,
|
||||||
|
genSecret,
|
||||||
|
badgeConstants,
|
||||||
|
} = require("../src/util");
|
||||||
const passwordHash = require("./password-hash");
|
const passwordHash = require("./password-hash");
|
||||||
const { Resolver } = require("dns");
|
const { Resolver } = require("dns");
|
||||||
const iconv = require("iconv-lite");
|
const iconv = require("iconv-lite");
|
||||||
|
@ -22,14 +26,20 @@ const tls = require("tls");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
dictionaries: {
|
dictionaries: {
|
||||||
rfc2865: { file, attributes },
|
rfc2865: {
|
||||||
|
file,
|
||||||
|
attributes,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} = require("node-radius-utils");
|
} = require("node-radius-utils");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
|
|
||||||
// SASLOptions used in JSDoc
|
// SASLOptions used in JSDoc
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const { Kafka, SASLOptions } = require("kafkajs");
|
const {
|
||||||
|
Kafka,
|
||||||
|
SASLOptions,
|
||||||
|
} = require("kafkajs");
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
|
|
||||||
const isWindows = process.platform === /^win/.test(process.platform);
|
const isWindows = process.platform === /^win/.test(process.platform);
|
||||||
|
@ -75,7 +85,7 @@ exports.getOidcTokenClientCredentials = async (tokenEndpoint, clientId, clientSe
|
||||||
let client = new oauthProvider.Client({
|
let client = new oauthProvider.Client({
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
client_secret: clientSecret,
|
client_secret: clientSecret,
|
||||||
token_endpoint_auth_method: authMethod
|
token_endpoint_auth_method: authMethod,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Increase default timeout and clock tolerance
|
// Increase default timeout and clock tolerance
|
||||||
|
@ -185,7 +195,12 @@ exports.pingAsync = function (hostname, ipv6 = false, size = 56) {
|
||||||
*/
|
*/
|
||||||
exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, saslOptions = {}) {
|
exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, saslOptions = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { interval = 20, allowAutoTopicCreation = false, ssl = false, clientId = "Uptime-Kuma" } = options;
|
const {
|
||||||
|
interval = 20,
|
||||||
|
allowAutoTopicCreation = false,
|
||||||
|
ssl = false,
|
||||||
|
clientId = "Uptime-Kuma",
|
||||||
|
} = options;
|
||||||
|
|
||||||
let connectedToKafka = false;
|
let connectedToKafka = false;
|
||||||
|
|
||||||
|
@ -213,7 +228,7 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa
|
||||||
allowAutoTopicCreation: allowAutoTopicCreation,
|
allowAutoTopicCreation: allowAutoTopicCreation,
|
||||||
retry: {
|
retry: {
|
||||||
retries: 0,
|
retries: 0,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
producer.connect().then(
|
producer.connect().then(
|
||||||
|
@ -234,14 +249,14 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa
|
||||||
connectedToKafka = true;
|
connectedToKafka = true;
|
||||||
clearTimeout(timeoutID);
|
clearTimeout(timeoutID);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
).catch(
|
).catch(
|
||||||
(e) => {
|
(e) => {
|
||||||
connectedToKafka = true;
|
connectedToKafka = true;
|
||||||
producer.disconnect();
|
producer.disconnect();
|
||||||
clearTimeout(timeoutID);
|
clearTimeout(timeoutID);
|
||||||
reject(new Error("Error in producer connection: " + e.message));
|
reject(new Error("Error in producer connection: " + e.message));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
producer.on("producer.network.request_timeout", (_) => {
|
producer.on("producer.network.request_timeout", (_) => {
|
||||||
|
@ -409,7 +424,7 @@ exports.mysqlQuery = function (connectionString, query, password = undefined) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const connection = mysql.createConnection({
|
const connection = mysql.createConnection({
|
||||||
uri: connectionString,
|
uri: connectionString,
|
||||||
password
|
password,
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.on("error", (err) => {
|
connection.on("error", (err) => {
|
||||||
|
@ -494,8 +509,8 @@ exports.redisPingAsync = function (dsn, rejectUnauthorized) {
|
||||||
const client = redis.createClient({
|
const client = redis.createClient({
|
||||||
url: dsn,
|
url: dsn,
|
||||||
socket: {
|
socket: {
|
||||||
rejectUnauthorized
|
rejectUnauthorized,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
client.on("error", (err) => {
|
client.on("error", (err) => {
|
||||||
if (client.isOpen) {
|
if (client.isOpen) {
|
||||||
|
@ -661,7 +676,7 @@ exports.checkCertificate = function (socket) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valid: valid,
|
valid: valid,
|
||||||
certInfo: parsedInfo
|
certInfo: parsedInfo,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -693,7 +708,7 @@ exports.checkStatusCode = function (status, acceptedCodes) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.error("monitor", `${codeRange} is not a valid status code range`);
|
log.error("monitor", `${codeRange} is not a valid status code range`);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,14 +940,21 @@ module.exports.timeObjectToLocal = (obj, timezone = undefined) => {
|
||||||
* @returns {Promise<object>} Result of gRPC query
|
* @returns {Promise<object>} Result of gRPC query
|
||||||
*/
|
*/
|
||||||
module.exports.grpcQuery = async (options) => {
|
module.exports.grpcQuery = async (options) => {
|
||||||
const { grpcUrl, grpcProtobufData, grpcServiceName, grpcEnableTls, grpcMethod, grpcBody } = options;
|
const {
|
||||||
|
grpcUrl,
|
||||||
|
grpcProtobufData,
|
||||||
|
grpcServiceName,
|
||||||
|
grpcEnableTls,
|
||||||
|
grpcMethod,
|
||||||
|
grpcBody,
|
||||||
|
} = options;
|
||||||
const protocObject = protojs.parse(grpcProtobufData);
|
const protocObject = protojs.parse(grpcProtobufData);
|
||||||
const protoServiceObject = protocObject.root.lookupService(grpcServiceName);
|
const protoServiceObject = protocObject.root.lookupService(grpcServiceName);
|
||||||
const Client = grpc.makeGenericClientConstructor({});
|
const Client = grpc.makeGenericClientConstructor({});
|
||||||
const credentials = grpcEnableTls ? grpc.credentials.createSsl() : grpc.credentials.createInsecure();
|
const credentials = grpcEnableTls ? grpc.credentials.createSsl() : grpc.credentials.createInsecure();
|
||||||
const client = new Client(
|
const client = new Client(
|
||||||
grpcUrl,
|
grpcUrl,
|
||||||
credentials
|
credentials,
|
||||||
);
|
);
|
||||||
const grpcService = protoServiceObject.create(function (method, requestData, cb) {
|
const grpcService = protoServiceObject.create(function (method, requestData, cb) {
|
||||||
const fullServiceName = method.fullName;
|
const fullServiceName = method.fullName;
|
||||||
|
@ -955,14 +977,14 @@ module.exports.grpcQuery = async (options) => {
|
||||||
return resolve({
|
return resolve({
|
||||||
code: err.code,
|
code: err.code,
|
||||||
errorMessage: err.details,
|
errorMessage: err.details,
|
||||||
data: ""
|
data: "",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
log.debug("monitor:", `gRPC response: ${JSON.stringify(response)}`);
|
log.debug("monitor:", `gRPC response: ${JSON.stringify(response)}`);
|
||||||
return resolve({
|
return resolve({
|
||||||
code: 1,
|
code: 1,
|
||||||
errorMessage: "",
|
errorMessage: "",
|
||||||
data: responseData
|
data: responseData,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -970,7 +992,7 @@ module.exports.grpcQuery = async (options) => {
|
||||||
return resolve({
|
return resolve({
|
||||||
code: -1,
|
code: -1,
|
||||||
errorMessage: `Error ${err}. Please review your gRPC configuration option. The service name must not include package name value, and the method name must follow camelCase format`,
|
errorMessage: `Error ${err}. Please review your gRPC configuration option. The service name must not include package name value, and the method name must follow camelCase format`,
|
||||||
data: ""
|
data: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,5 +81,5 @@ class ArrayWithKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ArrayWithKey
|
ArrayWithKey,
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,5 +44,5 @@ class LimitQueue extends ArrayWithKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
LimitQueue
|
LimitQueue,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue