Convert backend to ESM

- About 5 years overdue
- Remove eslint, use bomejs instead
This commit is contained in:
Jamie Curnow
2025-09-02 21:43:00 +10:00
parent 5b6ca1bf00
commit a12553fec7
89 changed files with 4799 additions and 5107 deletions

View File

@@ -1,12 +1,15 @@
const _ = require('lodash');
const fs = require('node:fs');
const logger = require('../logger').nginx;
const config = require('../lib/config');
const utils = require('../lib/utils');
const error = require('../lib/error');
import fs from "node:fs";
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import _ from "lodash";
import errs from "../lib/error.js";
import utils from "../lib/utils.js";
import { nginx as logger } from "../logger.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const internalNginx = {
/**
* This will:
* - test the nginx config first to make sure it's OK
@@ -24,7 +27,8 @@ const internalNginx = {
configure: (model, host_type, host) => {
let combined_meta = {};
return internalNginx.test()
return internalNginx
.test()
.then(() => {
// Nginx is OK
// We're deleting this config regardless.
@@ -37,20 +41,18 @@ const internalNginx = {
})
.then(() => {
// Test nginx again and update meta with result
return internalNginx.test()
return internalNginx
.test()
.then(() => {
// nginx is ok
combined_meta = _.assign({}, host.meta, {
nginx_online: true,
nginx_err: null
nginx_err: null,
});
return model
.query()
.where('id', host.id)
.patch({
meta: combined_meta
});
return model.query().where("id", host.id).patch({
meta: combined_meta,
});
})
.catch((err) => {
// Remove the error_log line because it's a docker-ism false positive that doesn't need to be reported.
@@ -58,28 +60,27 @@ const internalNginx = {
// nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (6: No such device or address)
const valid_lines = [];
const err_lines = err.message.split('\n');
const err_lines = err.message.split("\n");
err_lines.map((line) => {
if (line.indexOf('/var/log/nginx/error.log') === -1) {
if (line.indexOf("/var/log/nginx/error.log") === -1) {
valid_lines.push(line);
}
return true;
});
if (config.debug()) {
logger.error('Nginx test failed:', valid_lines.join('\n'));
}
logger.debug("Nginx test failed:", valid_lines.join("\n"));
// config is bad, update meta and delete config
combined_meta = _.assign({}, host.meta, {
nginx_online: false,
nginx_err: valid_lines.join('\n')
nginx_err: valid_lines.join("\n"),
});
return model
.query()
.where('id', host.id)
.where("id", host.id)
.patch({
meta: combined_meta
meta: combined_meta,
})
.then(() => {
internalNginx.renameConfigAsError(host_type, host);
@@ -101,22 +102,18 @@ const internalNginx = {
* @returns {Promise}
*/
test: () => {
if (config.debug()) {
logger.info('Testing Nginx configuration');
}
return utils.execFile('/usr/sbin/nginx', ['-t', '-g', 'error_log off;']);
logger.debug("Testing Nginx configuration");
return utils.execFile("/usr/sbin/nginx", ["-t", "-g", "error_log off;"]);
},
/**
* @returns {Promise}
*/
reload: () => {
return internalNginx.test()
.then(() => {
logger.info('Reloading Nginx');
return utils.execFile('/usr/sbin/nginx', ['-s', 'reload']);
});
return internalNginx.test().then(() => {
logger.info("Reloading Nginx");
return utils.execFile("/usr/sbin/nginx", ["-s", "reload"]);
});
},
/**
@@ -125,8 +122,8 @@ const internalNginx = {
* @returns {String}
*/
getConfigName: (host_type, host_id) => {
if (host_type === 'default') {
return '/data/nginx/default_host/site.conf';
if (host_type === "default") {
return "/data/nginx/default_host/site.conf";
}
return `/data/nginx/${internalNginx.getFileFriendlyHostType(host_type)}/${host_id}.conf`;
},
@@ -141,38 +138,45 @@ const internalNginx = {
let template;
try {
template = fs.readFileSync(`${__dirname}/../templates/_location.conf`, {encoding: 'utf8'});
template = fs.readFileSync(`${__dirname}/../templates/_location.conf`, { encoding: "utf8" });
} catch (err) {
reject(new error.ConfigurationError(err.message));
reject(new errs.ConfigurationError(err.message));
return;
}
const renderEngine = utils.getRenderEngine();
let renderedLocations = '';
const renderEngine = utils.getRenderEngine();
let renderedLocations = "";
const locationRendering = async () => {
for (let i = 0; i < host.locations.length; i++) {
const locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
{certificate: host.certificate}, host.locations[i]);
const locationCopy = Object.assign(
{},
{ access_list_id: host.access_list_id },
{ certificate_id: host.certificate_id },
{ ssl_forced: host.ssl_forced },
{ caching_enabled: host.caching_enabled },
{ block_exploits: host.block_exploits },
{ allow_websocket_upgrade: host.allow_websocket_upgrade },
{ http2_support: host.http2_support },
{ hsts_enabled: host.hsts_enabled },
{ hsts_subdomains: host.hsts_subdomains },
{ access_list: host.access_list },
{ certificate: host.certificate },
host.locations[i],
);
if (locationCopy.forward_host.indexOf('/') > -1) {
const splitted = locationCopy.forward_host.split('/');
if (locationCopy.forward_host.indexOf("/") > -1) {
const splitted = locationCopy.forward_host.split("/");
locationCopy.forward_host = splitted.shift();
locationCopy.forward_path = `/${splitted.join('/')}`;
locationCopy.forward_path = `/${splitted.join("/")}`;
}
// eslint-disable-next-line
renderedLocations += await renderEngine.parseAndRender(template, locationCopy);
}
};
locationRendering().then(() => resolve(renderedLocations));
});
},
@@ -183,23 +187,21 @@ const internalNginx = {
*/
generateConfig: (host_type, host_row) => {
// Prevent modifying the original object:
const host = JSON.parse(JSON.stringify(host_row));
const host = JSON.parse(JSON.stringify(host_row));
const nice_host_type = internalNginx.getFileFriendlyHostType(host_type);
if (config.debug()) {
logger.info(`Generating ${nice_host_type} Config:`, JSON.stringify(host, null, 2));
}
logger.debug(`Generating ${nice_host_type} Config:`, JSON.stringify(host, null, 2));
const renderEngine = utils.getRenderEngine();
return new Promise((resolve, reject) => {
let template = null;
let template = null;
const filename = internalNginx.getConfigName(nice_host_type, host.id);
try {
template = fs.readFileSync(`${__dirname}/../templates/${nice_host_type}.conf`, {encoding: 'utf8'});
template = fs.readFileSync(`${__dirname}/../templates/${nice_host_type}.conf`, { encoding: "utf8" });
} catch (err) {
reject(new error.ConfigurationError(err.message));
reject(new errs.ConfigurationError(err.message));
return;
}
@@ -207,27 +209,26 @@ const internalNginx = {
let origLocations;
// Manipulate the data a bit before sending it to the template
if (nice_host_type !== 'default') {
if (nice_host_type !== "default") {
host.use_default_location = true;
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
if (typeof host.advanced_config !== "undefined" && host.advanced_config) {
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
}
}
if (host.locations) {
//logger.info ('host.locations = ' + JSON.stringify(host.locations, null, 2));
origLocations = [].concat(host.locations);
origLocations = [].concat(host.locations);
locationsPromise = internalNginx.renderLocations(host).then((renderedLocations) => {
host.locations = renderedLocations;
});
// Allow someone who is using / custom location path to use it, and skip the default / location
_.map(host.locations, (location) => {
if (location.path === '/') {
if (location.path === "/") {
host.use_default_location = false;
}
});
} else {
locationsPromise = Promise.resolve();
}
@@ -239,11 +240,8 @@ const internalNginx = {
renderEngine
.parseAndRender(template, host)
.then((config_text) => {
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
if (config.debug()) {
logger.success('Wrote config:', filename, config_text);
}
fs.writeFileSync(filename, config_text, { encoding: "utf8" });
logger.debug("Wrote config:", filename, config_text);
// Restore locations array
host.locations = origLocations;
@@ -251,11 +249,8 @@ const internalNginx = {
resolve(true);
})
.catch((err) => {
if (config.debug()) {
logger.warn(`Could not write ${filename}:`, err.message);
}
reject(new error.ConfigurationError(err.message));
logger.debug(`Could not write ${filename}:`, err.message);
reject(new errs.ConfigurationError(err.message));
});
});
});
@@ -270,20 +265,17 @@ const internalNginx = {
* @returns {Promise}
*/
generateLetsEncryptRequestConfig: (certificate) => {
if (config.debug()) {
logger.info('Generating LetsEncrypt Request Config:', certificate);
}
logger.debug("Generating LetsEncrypt Request Config:", certificate);
const renderEngine = utils.getRenderEngine();
return new Promise((resolve, reject) => {
let template = null;
let template = null;
const filename = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
try {
template = fs.readFileSync(`${__dirname}/../templates/letsencrypt-request.conf`, {encoding: 'utf8'});
template = fs.readFileSync(`${__dirname}/../templates/letsencrypt-request.conf`, { encoding: "utf8" });
} catch (err) {
reject(new error.ConfigurationError(err.message));
reject(new errs.ConfigurationError(err.message));
return;
}
@@ -292,20 +284,13 @@ const internalNginx = {
renderEngine
.parseAndRender(template, certificate)
.then((config_text) => {
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
if (config.debug()) {
logger.success('Wrote config:', filename, config_text);
}
fs.writeFileSync(filename, config_text, { encoding: "utf8" });
logger.debug("Wrote config:", filename, config_text);
resolve(true);
})
.catch((err) => {
if (config.debug()) {
logger.warn(`Could not write ${filename}:`, err.message);
}
reject(new error.ConfigurationError(err.message));
logger.debug(`Could not write ${filename}:`, err.message);
reject(new errs.ConfigurationError(err.message));
});
});
},
@@ -320,7 +305,7 @@ const internalNginx = {
try {
fs.unlinkSync(filename);
} catch (err) {
logger.debug('Could not delete file:', JSON.stringify(err, null, 2));
logger.debug("Could not delete file:", JSON.stringify(err, null, 2));
}
},
@@ -330,7 +315,7 @@ const internalNginx = {
* @returns String
*/
getFileFriendlyHostType: (host_type) => {
return host_type.replace(/-/g, '_');
return host_type.replace(/-/g, "_");
},
/**
@@ -341,7 +326,7 @@ const internalNginx = {
*/
deleteLetsEncryptRequestConfig: (certificate) => {
const config_file = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
return new Promise((resolve/*, reject*/) => {
return new Promise((resolve /*, reject*/) => {
internalNginx.deleteFile(config_file);
resolve();
});
@@ -354,10 +339,13 @@ const internalNginx = {
* @returns {Promise}
*/
deleteConfig: (host_type, host, delete_err_file) => {
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
const config_file = internalNginx.getConfigName(
internalNginx.getFileFriendlyHostType(host_type),
typeof host === "undefined" ? 0 : host.id,
);
const config_file_err = `${config_file}.err`;
return new Promise((resolve/*, reject*/) => {
return new Promise((resolve /*, reject*/) => {
internalNginx.deleteFile(config_file);
if (delete_err_file) {
internalNginx.deleteFile(config_file_err);
@@ -372,10 +360,13 @@ const internalNginx = {
* @returns {Promise}
*/
renameConfigAsError: (host_type, host) => {
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
const config_file = internalNginx.getConfigName(
internalNginx.getFileFriendlyHostType(host_type),
typeof host === "undefined" ? 0 : host.id,
);
const config_file_err = `${config_file}.err`;
return new Promise((resolve/*, reject*/) => {
return new Promise((resolve /*, reject*/) => {
fs.unlink(config_file, () => {
// ignore result, continue
fs.rename(config_file, config_file_err, () => {
@@ -395,6 +386,7 @@ const internalNginx = {
const promises = [];
hosts.map((host) => {
promises.push(internalNginx.generateConfig(host_type, host));
return true;
});
return Promise.all(promises);
@@ -409,6 +401,7 @@ const internalNginx = {
const promises = [];
hosts.map((host) => {
promises.push(internalNginx.deleteConfig(host_type, host, true));
return true;
});
return Promise.all(promises);
@@ -424,13 +417,13 @@ const internalNginx = {
* @returns {boolean}
*/
ipv6Enabled: () => {
if (typeof process.env.DISABLE_IPV6 !== 'undefined') {
if (typeof process.env.DISABLE_IPV6 !== "undefined") {
const disabled = process.env.DISABLE_IPV6.toLowerCase();
return !(disabled === 'on' || disabled === 'true' || disabled === '1' || disabled === 'yes');
return !(disabled === "on" || disabled === "true" || disabled === "1" || disabled === "yes");
}
return true;
}
},
};
module.exports = internalNginx;
export default internalNginx;