mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-03 12:02:33 +02:00

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>
205 lines
6.6 KiB
JavaScript
205 lines
6.6 KiB
JavaScript
const { R } = require("redbean-node");
|
|
const { HttpProxyAgent } = require("http-proxy-agent");
|
|
const { HttpsProxyAgent } = require("https-proxy-agent");
|
|
const { SocksProxyAgent } = require("socks-proxy-agent");
|
|
const { debug } = require("../src/util");
|
|
const { UptimeKumaServer } = require("./uptime-kuma-server");
|
|
const { CookieJar } = require("tough-cookie");
|
|
const { createCookieAgent } = require("http-cookie-agent/http");
|
|
|
|
class Proxy {
|
|
|
|
static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks5h", "socks4" ];
|
|
|
|
/**
|
|
* Saves and updates given proxy entity
|
|
* @param {object} proxy Proxy to store
|
|
* @param {number} proxyID ID of proxy to update
|
|
* @param {number} userID ID of user the proxy belongs to
|
|
* @returns {Promise<Bean>} Updated proxy
|
|
*/
|
|
static async save(proxy, proxyID, userID) {
|
|
let bean;
|
|
|
|
if (proxyID) {
|
|
bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
|
|
|
|
if (!bean) {
|
|
throw new Error("proxy not found");
|
|
}
|
|
|
|
} else {
|
|
bean = R.dispense("proxy");
|
|
}
|
|
|
|
// Make sure given proxy protocol is supported
|
|
if (!this.SUPPORTED_PROXY_PROTOCOLS.includes(proxy.protocol)) {
|
|
throw new Error(`
|
|
Unsupported proxy protocol "${proxy.protocol}.
|
|
Supported protocols are ${this.SUPPORTED_PROXY_PROTOCOLS.join(", ")}."`,
|
|
);
|
|
}
|
|
|
|
// When proxy is default update deactivate old default proxy
|
|
if (proxy.default) {
|
|
await R.exec("UPDATE proxy SET `default` = 0 WHERE `default` = 1");
|
|
}
|
|
|
|
bean.user_id = userID;
|
|
bean.protocol = proxy.protocol;
|
|
bean.host = proxy.host;
|
|
bean.port = proxy.port;
|
|
bean.auth = proxy.auth;
|
|
bean.username = proxy.username;
|
|
bean.password = proxy.password;
|
|
bean.active = proxy.active || true;
|
|
bean.default = proxy.default || false;
|
|
|
|
await R.store(bean);
|
|
|
|
if (proxy.applyExisting) {
|
|
await applyProxyEveryMonitor(bean.id, userID);
|
|
}
|
|
|
|
return bean;
|
|
}
|
|
|
|
/**
|
|
* Deletes proxy with given id and removes it from monitors
|
|
* @param {number} proxyID ID of proxy to delete
|
|
* @param {number} userID ID of proxy owner
|
|
* @returns {Promise<void>}
|
|
*/
|
|
static async delete(proxyID, userID) {
|
|
const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
|
|
|
|
if (!bean) {
|
|
throw new Error("proxy not found");
|
|
}
|
|
|
|
// Delete removed proxy from monitors if exists
|
|
await R.exec("UPDATE monitor SET proxy_id = null WHERE proxy_id = ?", [ proxyID ]);
|
|
|
|
// Delete proxy from list
|
|
await R.trash(bean);
|
|
}
|
|
|
|
/**
|
|
* Create HTTP and HTTPS agents related with given proxy bean object
|
|
* @param {object} proxy proxy bean object
|
|
* @param {object} options http and https agent options
|
|
* @returns {{httpAgent: Agent, httpsAgent: Agent}} New HTTP and HTTPS agents
|
|
* @throws Proxy protocol is unsupported
|
|
*/
|
|
static createAgents(proxy, options) {
|
|
const {
|
|
httpAgentOptions,
|
|
httpsAgentOptions,
|
|
} = options || {};
|
|
let agent;
|
|
let httpAgent;
|
|
let httpsAgent;
|
|
|
|
let jar = new CookieJar();
|
|
|
|
const proxyOptions = {
|
|
cookies: { jar },
|
|
};
|
|
|
|
const proxyUrl = new URL(`${proxy.protocol}://${proxy.host}:${proxy.port}`);
|
|
|
|
if (proxy.auth) {
|
|
proxyUrl.username = proxy.username;
|
|
proxyUrl.password = proxy.password;
|
|
}
|
|
|
|
debug(`Proxy URL: ${proxyUrl.toString()}`);
|
|
debug(`HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`);
|
|
debug(`HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`);
|
|
|
|
switch (proxy.protocol) {
|
|
case "http":
|
|
case "https":
|
|
// eslint-disable-next-line no-case-declarations
|
|
const HttpCookieProxyAgent = createCookieAgent(HttpProxyAgent);
|
|
// eslint-disable-next-line no-case-declarations
|
|
const HttpsCookieProxyAgent = createCookieAgent(HttpsProxyAgent);
|
|
|
|
httpAgent = new HttpCookieProxyAgent(proxyUrl.toString(), {
|
|
...(httpAgentOptions || {}),
|
|
...proxyOptions,
|
|
});
|
|
httpsAgent = new HttpsCookieProxyAgent(proxyUrl.toString(), {
|
|
...(httpsAgentOptions || {}),
|
|
...proxyOptions,
|
|
});
|
|
|
|
break;
|
|
case "socks":
|
|
case "socks5":
|
|
case "socks5h":
|
|
case "socks4":
|
|
// eslint-disable-next-line no-case-declarations
|
|
const SocksCookieProxyAgent = createCookieAgent(SocksProxyAgent);
|
|
agent = new SocksCookieProxyAgent(proxyUrl.toString(), {
|
|
...httpAgentOptions,
|
|
...httpsAgentOptions,
|
|
tls: {
|
|
rejectUnauthorized: httpsAgentOptions.rejectUnauthorized,
|
|
},
|
|
});
|
|
|
|
httpAgent = agent;
|
|
httpsAgent = agent;
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unsupported proxy protocol provided. ${proxy.protocol}`);
|
|
}
|
|
|
|
return {
|
|
httpAgent,
|
|
httpsAgent,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Reload proxy settings for current monitors
|
|
* @returns {Promise<void>}
|
|
*/
|
|
static async reloadProxy() {
|
|
const server = UptimeKumaServer.getInstance();
|
|
|
|
let updatedList = await R.getAssoc("SELECT id, proxy_id FROM monitor");
|
|
|
|
for (let monitorID in server.monitorList) {
|
|
let monitor = server.monitorList[monitorID];
|
|
|
|
if (updatedList[monitorID]) {
|
|
monitor.proxy_id = updatedList[monitorID].proxy_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies given proxy id to monitors
|
|
* @param {number} proxyID ID of proxy to apply
|
|
* @param {number} userID ID of proxy owner
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function applyProxyEveryMonitor(proxyID, userID) {
|
|
// Find all monitors with id and proxy id
|
|
const monitors = await R.getAll("SELECT id, proxy_id FROM monitor WHERE user_id = ?", [ userID ]);
|
|
|
|
// Update proxy id not match with given proxy id
|
|
for (const monitor of monitors) {
|
|
if (monitor.proxy_id !== proxyID) {
|
|
await R.exec("UPDATE monitor SET proxy_id = ? WHERE id = ?", [ proxyID, monitor.id ]);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
Proxy,
|
|
};
|