Refactor config out of Helper (#4558)

* Remove config from Helper

Helper is the usual util grab bag of useful stuff.
Somehow the config ended up there historically but
structurally that doesn't make any sense.

* Add cert folder to prettier ignore file
This commit is contained in:
Reto 2022-05-01 21:12:39 +02:00 committed by GitHub
parent 38f13525e6
commit d4cc2dd361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 457 additions and 453 deletions

View File

@ -2,7 +2,7 @@
root: true root: true
parserOptions: parserOptions:
ecmaVersion: 2020 ecmaVersion: 2022
env: env:
es6: true es6: true

View File

@ -1,6 +1,7 @@
coverage/ coverage/
public/ public/
test/fixtures/.thelounge/logs/ test/fixtures/.thelounge/logs/
test/fixtures/.thelounge/certificates/
test/fixtures/.thelounge/storage/ test/fixtures/.thelounge/storage/
*.log *.log

View File

@ -7,7 +7,7 @@ const Chan = require("./models/chan");
const crypto = require("crypto"); const crypto = require("crypto");
const Msg = require("./models/msg"); const Msg = require("./models/msg");
const Network = require("./models/network"); const Network = require("./models/network");
const Helper = require("./helper"); const Config = require("./config");
const UAParser = require("ua-parser-js"); const UAParser = require("ua-parser-js");
const {v4: uuidv4} = require("uuid"); const {v4: uuidv4} = require("uuid");
const escapeRegExp = require("lodash/escapeRegExp"); const escapeRegExp = require("lodash/escapeRegExp");
@ -72,13 +72,13 @@ function Client(manager, name, config = {}) {
client.config.log = Boolean(client.config.log); client.config.log = Boolean(client.config.log);
client.config.password = String(client.config.password); client.config.password = String(client.config.password);
if (!Helper.config.public && client.config.log) { if (!Config.values.public && client.config.log) {
if (Helper.config.messageStorage.includes("sqlite")) { if (Config.values.messageStorage.includes("sqlite")) {
client.messageProvider = new MessageStorage(client); client.messageProvider = new MessageStorage(client);
client.messageStorage.push(client.messageProvider); client.messageStorage.push(client.messageProvider);
} }
if (Helper.config.messageStorage.includes("text")) { if (Config.values.messageStorage.includes("text")) {
client.messageStorage.push(new TextFileMessageStorage(client)); client.messageStorage.push(new TextFileMessageStorage(client));
} }
@ -236,7 +236,7 @@ Client.prototype.connect = function (args, isStartup = false) {
const network = new Network({ const network = new Network({
uuid: args.uuid, uuid: args.uuid,
name: String( name: String(
args.name || (Helper.config.lockNetwork ? Helper.config.defaults.name : "") || "" args.name || (Config.values.lockNetwork ? Config.values.defaults.name : "") || ""
), ),
host: String(args.host || ""), host: String(args.host || ""),
port: parseInt(args.port, 10), port: parseInt(args.port, 10),
@ -759,7 +759,7 @@ Client.prototype.unregisterPushSubscription = function (token) {
Client.prototype.save = _.debounce( Client.prototype.save = _.debounce(
function SaveClient() { function SaveClient() {
if (Helper.config.public) { if (Config.values.public) {
return; return;
} }

View File

@ -8,7 +8,7 @@ const fs = require("fs");
const path = require("path"); const path = require("path");
const Auth = require("./plugins/auth"); const Auth = require("./plugins/auth");
const Client = require("./client"); const Client = require("./client");
const Helper = require("./helper"); const Config = require("./config");
const WebPush = require("./plugins/webpush"); const WebPush = require("./plugins/webpush");
module.exports = ClientManager; module.exports = ClientManager;
@ -22,12 +22,12 @@ ClientManager.prototype.init = function (identHandler, sockets) {
this.identHandler = identHandler; this.identHandler = identHandler;
this.webPush = new WebPush(); this.webPush = new WebPush();
if (!Helper.config.public) { if (!Config.values.public) {
this.loadUsers(); this.loadUsers();
// LDAP does not have user commands, and users are dynamically // LDAP does not have user commands, and users are dynamically
// created upon logon, so we don't need to watch for new files // created upon logon, so we don't need to watch for new files
if (!Helper.config.ldap.enable) { if (!Config.values.ldap.enable) {
this.autoloadUsers(); this.autoloadUsers();
} }
} }
@ -81,7 +81,7 @@ ClientManager.prototype.loadUsers = function () {
ClientManager.prototype.autoloadUsers = function () { ClientManager.prototype.autoloadUsers = function () {
fs.watch( fs.watch(
Helper.getUsersPath(), Config.getUsersPath(),
_.debounce( _.debounce(
() => { () => {
const loaded = this.clients.map((c) => c.name); const loaded = this.clients.map((c) => c.name);
@ -145,12 +145,12 @@ ClientManager.prototype.loadUser = function (name) {
}; };
ClientManager.prototype.getUsers = function () { ClientManager.prototype.getUsers = function () {
if (!fs.existsSync(Helper.getUsersPath())) { if (!fs.existsSync(Config.getUsersPath())) {
return []; return [];
} }
return fs return fs
.readdirSync(Helper.getUsersPath()) .readdirSync(Config.getUsersPath())
.filter((file) => file.endsWith(".json")) .filter((file) => file.endsWith(".json"))
.map((file) => file.slice(0, -5)); .map((file) => file.slice(0, -5));
}; };
@ -160,7 +160,7 @@ ClientManager.prototype.addUser = function (name, password, enableLog) {
throw new Error(`${name} is an invalid username.`); throw new Error(`${name} is an invalid username.`);
} }
const userPath = Helper.getUserConfigPath(name); const userPath = Config.getUserConfigPath(name);
if (fs.existsSync(userPath)) { if (fs.existsSync(userPath)) {
log.error(`User ${colors.green(name)} already exists.`); log.error(`User ${colors.green(name)} already exists.`);
@ -182,7 +182,7 @@ ClientManager.prototype.addUser = function (name, password, enableLog) {
} }
try { try {
const userFolderStat = fs.statSync(Helper.getUsersPath()); const userFolderStat = fs.statSync(Config.getUsersPath());
const userFileStat = fs.statSync(userPath); const userFileStat = fs.statSync(userPath);
if ( if (
@ -231,7 +231,7 @@ ClientManager.prototype.saveUser = function (client, callback) {
return; return;
} }
const pathReal = Helper.getUserConfigPath(client.name); const pathReal = Config.getUserConfigPath(client.name);
const pathTemp = pathReal + ".tmp"; const pathTemp = pathReal + ".tmp";
try { try {
@ -253,7 +253,7 @@ ClientManager.prototype.saveUser = function (client, callback) {
}; };
ClientManager.prototype.removeUser = function (name) { ClientManager.prototype.removeUser = function (name) {
const userPath = Helper.getUserConfigPath(name); const userPath = Config.getUserConfigPath(name);
if (!fs.existsSync(userPath)) { if (!fs.existsSync(userPath)) {
log.error(`Tried to remove non-existing user ${colors.green(name)}.`); log.error(`Tried to remove non-existing user ${colors.green(name)}.`);
@ -266,7 +266,7 @@ ClientManager.prototype.removeUser = function (name) {
}; };
function readUserConfig(name) { function readUserConfig(name) {
const userPath = Helper.getUserConfigPath(name); const userPath = Config.getUserConfigPath(name);
if (!fs.existsSync(userPath)) { if (!fs.existsSync(userPath)) {
log.error(`Tried to read non-existing user ${colors.green(name)}`); log.error(`Tried to read non-existing user ${colors.green(name)}`);

View File

@ -6,6 +6,7 @@ const path = require("path");
const colors = require("chalk"); const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const Helper = require("../helper"); const Helper = require("../helper");
const Config = require("../config");
const Utils = require("./utils"); const Utils = require("./utils");
program program
@ -20,7 +21,7 @@ program
// Parse options from `argv` returning `argv` void of these options. // Parse options from `argv` returning `argv` void of these options.
const argvWithoutOptions = program.parseOptions(process.argv); const argvWithoutOptions = program.parseOptions(process.argv);
Helper.setHome(process.env.THELOUNGE_HOME || Utils.defaultHome()); Config.setHome(process.env.THELOUNGE_HOME || Utils.defaultHome());
// Check config file owner and warn if we're running under a different user // Check config file owner and warn if we're running under a different user
try { try {
@ -34,11 +35,11 @@ try {
createPackagesFolder(); createPackagesFolder();
// Merge config key-values passed as CLI options into the main config // Merge config key-values passed as CLI options into the main config
Helper.mergeConfig(Helper.config, program.opts().config); Config.merge(program.opts().config);
require("./start"); require("./start");
if (!Helper.config.public) { if (!Config.values.public) {
require("./users"); require("./users");
} }
@ -56,7 +57,7 @@ require("./outdated");
program.parse(argvWithoutOptions.operands.concat(argvWithoutOptions.unknown)); program.parse(argvWithoutOptions.operands.concat(argvWithoutOptions.unknown));
function createPackagesFolder() { function createPackagesFolder() {
const packagesPath = Helper.getPackagesPath(); const packagesPath = Config.getPackagesPath();
const packagesConfig = path.join(packagesPath, "package.json"); const packagesConfig = path.join(packagesPath, "package.json");
// Create node_modules folder, otherwise yarn will start walking upwards to find one // Create node_modules folder, otherwise yarn will start walking upwards to find one
@ -95,7 +96,7 @@ function verifyFileOwner() {
); );
} }
const configStat = fs.statSync(path.join(Helper.getHomePath(), "config.js")); const configStat = fs.statSync(path.join(Config.getHomePath(), "config.js"));
if (configStat && configStat.uid !== uid) { if (configStat && configStat.uid !== uid) {
log.warn( log.warn(

View File

@ -5,6 +5,7 @@ const colors = require("chalk");
const semver = require("semver"); const semver = require("semver");
const program = require("commander"); const program = require("commander");
const Helper = require("../helper"); const Helper = require("../helper");
const Config = require("../config");
const Utils = require("./utils"); const Utils = require("./utils");
program program
@ -17,8 +18,8 @@ program
const path = require("path"); const path = require("path");
const packageJson = require("package-json"); const packageJson = require("package-json");
if (!fs.existsSync(Helper.getConfigPath())) { if (!fs.existsSync(Config.getConfigPath())) {
log.error(`${Helper.getConfigPath()} does not exist.`); log.error(`${Config.getConfigPath()} does not exist.`);
return; return;
} }

View File

@ -5,7 +5,7 @@ const colors = require("chalk");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const program = require("commander"); const program = require("commander");
const Helper = require("../helper"); const Config = require("../config");
const Utils = require("./utils"); const Utils = require("./utils");
program program
@ -21,15 +21,15 @@ program
}); });
function initalizeConfig() { function initalizeConfig() {
if (!fs.existsSync(Helper.getConfigPath())) { if (!fs.existsSync(Config.getConfigPath())) {
fs.mkdirSync(Helper.getHomePath(), {recursive: true}); fs.mkdirSync(Config.getHomePath(), {recursive: true});
fs.chmodSync(Helper.getHomePath(), "0700"); fs.chmodSync(Config.getHomePath(), "0700");
fs.copyFileSync( fs.copyFileSync(
path.resolve(path.join(__dirname, "..", "..", "defaults", "config.js")), path.resolve(path.join(__dirname, "..", "..", "defaults", "config.js")),
Helper.getConfigPath() Config.getConfigPath()
); );
log.info(`Configuration file created at ${colors.green(Helper.getConfigPath())}.`); log.info(`Configuration file created at ${colors.green(Config.getConfigPath())}.`);
} }
fs.mkdirSync(Helper.getUsersPath(), {recursive: true, mode: 0o700}); fs.mkdirSync(Config.getUsersPath(), {recursive: true, mode: 0o700});
} }

View File

@ -3,7 +3,7 @@
const log = require("../log"); const log = require("../log");
const colors = require("chalk"); const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const Helper = require("../helper"); const Config = require("../config");
const Utils = require("./utils"); const Utils = require("./utils");
program program
@ -14,7 +14,7 @@ program
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const packagesConfig = path.join(Helper.getPackagesPath(), "package.json"); const packagesConfig = path.join(Config.getPackagesPath(), "package.json");
const packages = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")); const packages = JSON.parse(fs.readFileSync(packagesConfig, "utf-8"));
if ( if (

View File

@ -3,7 +3,7 @@
const log = require("../log"); const log = require("../log");
const colors = require("chalk"); const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const Helper = require("../helper"); const Config = require("../config");
const Utils = require("./utils"); const Utils = require("./utils");
program program
@ -15,7 +15,7 @@ program
const path = require("path"); const path = require("path");
// Get paths to the location of packages directory // Get paths to the location of packages directory
const packagesConfig = path.join(Helper.getPackagesPath(), "package.json"); const packagesConfig = path.join(Config.getPackagesPath(), "package.json");
const packagesList = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")).dependencies; const packagesList = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")).dependencies;
const argsList = ["upgrade", "--latest"]; const argsList = ["upgrade", "--latest"];

View File

@ -5,6 +5,7 @@ const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Helper = require("../../helper");
const Config = require("../../config");
const Utils = require("../utils"); const Utils = require("../utils");
program program
@ -14,8 +15,8 @@ program
.option("--password [password]", "new password, will be prompted if not specified") .option("--password [password]", "new password, will be prompted if not specified")
.option("--save-logs", "if password is specified, this enables saving logs to disk") .option("--save-logs", "if password is specified, this enables saving logs to disk")
.action(function (name, cmdObj) { .action(function (name, cmdObj) {
if (!fs.existsSync(Helper.getUsersPath())) { if (!fs.existsSync(Config.getUsersPath())) {
log.error(`${Helper.getUsersPath()} does not exist.`); log.error(`${Config.getUsersPath()} does not exist.`);
return; return;
} }
@ -76,5 +77,5 @@ function add(manager, name, password, enableLog) {
manager.addUser(name, hash, enableLog); manager.addUser(name, hash, enableLog);
log.info(`User ${colors.bold(name)} created.`); log.info(`User ${colors.bold(name)} created.`);
log.info(`User file located at ${colors.green(Helper.getUserConfigPath(name))}.`); log.info(`User file located at ${colors.green(Config.getUserConfigPath(name))}.`);
} }

View File

@ -5,16 +5,16 @@ const program = require("commander");
const child = require("child_process"); const child = require("child_process");
const colors = require("chalk"); const colors = require("chalk");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Config = require("../../config");
const Utils = require("../utils"); const Utils = require("../utils");
program program
.command("edit <name>") .command("edit <name>")
.description(`Edit user file located at ${colors.green(Helper.getUserConfigPath("<name>"))}`) .description(`Edit user file located at ${colors.green(Config.getUserConfigPath("<name>"))}`)
.on("--help", Utils.extraHelp) .on("--help", Utils.extraHelp)
.action(function (name) { .action(function (name) {
if (!fs.existsSync(Helper.getUsersPath())) { if (!fs.existsSync(Config.getUsersPath())) {
log.error(`${Helper.getUsersPath()} does not exist.`); log.error(`${Config.getUsersPath()} does not exist.`);
return; return;
} }
@ -33,12 +33,12 @@ program
const child_spawn = child.spawn( const child_spawn = child.spawn(
process.env.EDITOR || "vi", process.env.EDITOR || "vi",
[Helper.getUserConfigPath(name)], [Config.getUserConfigPath(name)],
{stdio: "inherit"} {stdio: "inherit"}
); );
child_spawn.on("error", function () { child_spawn.on("error", function () {
log.error( log.error(
`Unable to open ${colors.green(Helper.getUserConfigPath(name))}. ${colors.bold( `Unable to open ${colors.green(Config.getUserConfigPath(name))}. ${colors.bold(
"$EDITOR" "$EDITOR"
)} is not set, and ${colors.bold("vi")} was not found.` )} is not set, and ${colors.bold("vi")} was not found.`
); );

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
if (!require("../../helper").config.ldap.enable) { if (!require("../../config").values.ldap.enable) {
require("./add"); require("./add");
require("./reset"); require("./reset");
} }

View File

@ -4,7 +4,7 @@ const log = require("../../log");
const colors = require("chalk"); const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Config = require("../../config");
const Utils = require("../utils"); const Utils = require("../utils");
program program
@ -12,8 +12,8 @@ program
.description("Remove an existing user") .description("Remove an existing user")
.on("--help", Utils.extraHelp) .on("--help", Utils.extraHelp)
.action(function (name) { .action(function (name) {
if (!fs.existsSync(Helper.getUsersPath())) { if (!fs.existsSync(Config.getUsersPath())) {
log.error(`${Helper.getUsersPath()} does not exist.`); log.error(`${Config.getUsersPath()} does not exist.`);
return; return;
} }

View File

@ -5,6 +5,7 @@ const colors = require("chalk");
const program = require("commander"); const program = require("commander");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Helper = require("../../helper");
const Config = require("../../config");
const Utils = require("../utils"); const Utils = require("../utils");
program program
@ -13,8 +14,8 @@ program
.on("--help", Utils.extraHelp) .on("--help", Utils.extraHelp)
.option("--password [password]", "new password, will be prompted if not specified") .option("--password [password]", "new password, will be prompted if not specified")
.action(function (name, cmdObj) { .action(function (name, cmdObj) {
if (!fs.existsSync(Helper.getUsersPath())) { if (!fs.existsSync(Config.getUsersPath())) {
log.error(`${Helper.getUsersPath()} does not exist.`); log.error(`${Config.getUsersPath()} does not exist.`);
return; return;
} }
@ -52,7 +53,7 @@ program
}); });
function change(name, password) { function change(name, password) {
const pathReal = Helper.getUserConfigPath(name); const pathReal = Config.getUserConfigPath(name);
const pathTemp = pathReal + ".tmp"; const pathTemp = pathReal + ".tmp";
const user = JSON.parse(fs.readFileSync(pathReal, "utf-8")); const user = JSON.parse(fs.readFileSync(pathReal, "utf-8"));

View File

@ -5,6 +5,7 @@ const log = require("../log");
const colors = require("chalk"); const colors = require("chalk");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../helper"); const Helper = require("../helper");
const Config = require("../config");
const path = require("path"); const path = require("path");
let home; let home;
@ -91,7 +92,7 @@ class Utils {
static executeYarnCommand(command, ...parameters) { static executeYarnCommand(command, ...parameters) {
const yarn = require.resolve("yarn/bin/yarn.js"); const yarn = require.resolve("yarn/bin/yarn.js");
const packagesPath = Helper.getPackagesPath(); const packagesPath = Config.getPackagesPath();
const cachePath = path.join(packagesPath, "package_manager_cache"); const cachePath = path.join(packagesPath, "package_manager_cache");
const staticParameters = [ const staticParameters = [

182
src/config.js Normal file
View File

@ -0,0 +1,182 @@
"use strict";
const path = require("path");
const fs = require("fs");
const os = require("os");
const _ = require("lodash");
const colors = require("chalk");
const log = require("./log");
const Helper = require("./helper");
class Config {
values = require(path.resolve(path.join(__dirname, "..", "defaults", "config.js")));
#homePath;
getHomePath() {
return this.#homePath;
}
getConfigPath() {
return path.join(this.#homePath, "config.js");
}
getUserLogsPath() {
return path.join(this.#homePath, "logs");
}
getStoragePath() {
return path.join(this.#homePath, "storage");
}
getFileUploadPath() {
return path.join(this.#homePath, "uploads");
}
getUsersPath() {
return path.join(this.#homePath, "users");
}
getUserConfigPath(name) {
return path.join(this.getUsersPath(), `${name}.json`);
}
getClientCertificatesPath() {
return path.join(this.#homePath, "certificates");
}
getPackagesPath() {
return path.join(this.#homePath, "packages");
}
getPackageModulePath(packageName) {
return path.join(this.getPackagesPath(), "node_modules", packageName);
}
getDefaultNick() {
if (!this.values.defaults.nick) {
return "thelounge";
}
return this.values.defaults.nick.replace(/%/g, () => Math.floor(Math.random() * 10));
}
merge(newConfig) {
this._merge_config_objects(this.values, newConfig);
}
_merge_config_objects(oldConfig, newConfig) {
// semi exposed function so that we can test it
// it mutates the oldConfig, but returns it as a convenience for testing
for (const key in newConfig) {
if (!Object.prototype.hasOwnProperty.call(oldConfig, key)) {
log.warn(`Unknown key "${colors.bold(key)}", please verify your config.`);
}
}
return _.mergeWith(oldConfig, newConfig, (objValue, srcValue, key) => {
// Do not override config variables if the type is incorrect (e.g. object changed into a string)
if (
typeof objValue !== "undefined" &&
objValue !== null &&
typeof objValue !== typeof srcValue
) {
log.warn(`Incorrect type for "${colors.bold(key)}", please verify your config.`);
return objValue;
}
// For arrays, simply override the value with user provided one.
if (_.isArray(objValue)) {
return srcValue;
}
});
}
setHome(newPath) {
this.#homePath = Helper.expandHome(newPath);
// Reload config from new home location
const configPath = this.getConfigPath();
if (fs.existsSync(configPath)) {
const userConfig = require(configPath);
if (_.isEmpty(userConfig)) {
log.warn(
`The file located at ${colors.green(
configPath
)} does not appear to expose anything.`
);
log.warn(
`Make sure it is non-empty and the configuration is exported using ${colors.bold(
"module.exports = { ... }"
)}.`
);
log.warn("Using default configuration...");
}
this.merge(userConfig);
}
if (this.values.fileUpload.baseUrl) {
try {
new URL("test/file.png", this.values.fileUpload.baseUrl);
} catch (e) {
this.values.fileUpload.baseUrl = null;
log.warn(`The ${colors.bold("fileUpload.baseUrl")} you specified is invalid: ${e}`);
}
}
const manifestPath = path.resolve(
path.join(__dirname, "..", "public", "thelounge.webmanifest")
);
// Check if manifest exists, if not, the app most likely was not built
if (!fs.existsSync(manifestPath)) {
log.error(
`The client application was not built. Run ${colors.bold(
"NODE_ENV=production yarn build"
)} to resolve this.`
);
process.exit(1);
}
// Load theme color from the web manifest
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
this.values.themeColor = manifest.theme_color;
// log dir probably shouldn't be world accessible.
// Create it with the desired permission bits if it doesn't exist yet.
let logsStat = undefined;
const userLogsPath = this.getUserLogsPath();
try {
logsStat = fs.statSync(userLogsPath);
} catch {
// ignored on purpose, node v14.17.0 will give us {throwIfNoEntry: false}
}
if (!logsStat) {
try {
fs.mkdirSync(userLogsPath, {recursive: true, mode: 0o750});
} catch (e) {
log.error("Unable to create logs directory", e);
}
} else if (logsStat && logsStat.mode & 0o001) {
log.warn(
"contents of",
userLogsPath,
"can be accessed by any user, the log files may be exposed"
);
if (os.platform() !== "win32") {
log.warn(`run \`chmod o-x ${userLogsPath}\` to correct it`);
}
}
}
}
module.exports = new Config();

View File

@ -2,45 +2,20 @@
const pkg = require("../package.json"); const pkg = require("../package.json");
const _ = require("lodash"); const _ = require("lodash");
const log = require("./log");
const path = require("path"); const path = require("path");
const os = require("os"); const os = require("os");
const fs = require("fs"); const fs = require("fs");
const net = require("net"); const net = require("net");
const bcrypt = require("bcryptjs"); const bcrypt = require("bcryptjs");
const colors = require("chalk");
const crypto = require("crypto"); const crypto = require("crypto");
let homePath;
let configPath;
let usersPath;
let storagePath;
let packagesPath;
let fileUploadPath;
let userLogsPath;
let clientCertificatesPath;
const Helper = { const Helper = {
config: null,
expandHome, expandHome,
getHomePath,
getPackagesPath,
getPackageModulePath,
getStoragePath,
getConfigPath,
getFileUploadPath,
getUsersPath,
getUserConfigPath,
getUserLogsPath,
getClientCertificatesPath,
setHome,
getVersion, getVersion,
getVersionCacheBust, getVersionCacheBust,
getVersionNumber, getVersionNumber,
getGitCommit, getGitCommit,
ip2hex, ip2hex,
mergeConfig,
getDefaultNick,
parseHostmask, parseHostmask,
compareHostmask, compareHostmask,
compareWithWildcard, compareWithWildcard,
@ -54,8 +29,6 @@ const Helper = {
module.exports = Helper; module.exports = Helper;
Helper.config = require(path.resolve(path.join(__dirname, "..", "defaults", "config.js")));
function getVersion() { function getVersion() {
const gitCommit = getGitCommit(); const gitCommit = getGitCommit();
const version = `v${pkg.version}`; const version = `v${pkg.version}`;
@ -100,134 +73,6 @@ function getVersionCacheBust() {
return hash.substring(0, 10); return hash.substring(0, 10);
} }
function setHome(newPath) {
homePath = expandHome(newPath);
configPath = path.join(homePath, "config.js");
usersPath = path.join(homePath, "users");
storagePath = path.join(homePath, "storage");
fileUploadPath = path.join(homePath, "uploads");
packagesPath = path.join(homePath, "packages");
userLogsPath = path.join(homePath, "logs");
clientCertificatesPath = path.join(homePath, "certificates");
// Reload config from new home location
if (fs.existsSync(configPath)) {
const userConfig = require(configPath);
if (_.isEmpty(userConfig)) {
log.warn(
`The file located at ${colors.green(
configPath
)} does not appear to expose anything.`
);
log.warn(
`Make sure it is non-empty and the configuration is exported using ${colors.bold(
"module.exports = { ... }"
)}.`
);
log.warn("Using default configuration...");
}
mergeConfig(this.config, userConfig);
}
if (this.config.fileUpload.baseUrl) {
try {
new URL("test/file.png", this.config.fileUpload.baseUrl);
} catch (e) {
this.config.fileUpload.baseUrl = null;
log.warn(`The ${colors.bold("fileUpload.baseUrl")} you specified is invalid: ${e}`);
}
}
const manifestPath = path.resolve(
path.join(__dirname, "..", "public", "thelounge.webmanifest")
);
// Check if manifest exists, if not, the app most likely was not built
if (!fs.existsSync(manifestPath)) {
log.error(
`The client application was not built. Run ${colors.bold(
"NODE_ENV=production yarn build"
)} to resolve this.`
);
process.exit(1);
}
// Load theme color from the web manifest
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
this.config.themeColor = manifest.theme_color;
// log dir probably shouldn't be world accessible.
// Create it with the desired permission bits if it doesn't exist yet.
let logsStat = undefined;
try {
logsStat = fs.statSync(userLogsPath);
} catch {
// ignored on purpose, node v14.17.0 will give us {throwIfNoEntry: false}
}
if (!logsStat) {
try {
fs.mkdirSync(userLogsPath, {recursive: true, mode: 0o750});
} catch (e) {
log.error("Unable to create logs directory", e);
}
} else if (logsStat && logsStat.mode & 0o001) {
log.warn(
"contents of",
userLogsPath,
"can be accessed by any user, the log files may be exposed"
);
if (os.platform() !== "win32") {
log.warn(`run \`chmod o-x ${userLogsPath}\` to correct it`);
}
}
}
function getHomePath() {
return homePath;
}
function getConfigPath() {
return configPath;
}
function getFileUploadPath() {
return fileUploadPath;
}
function getUsersPath() {
return usersPath;
}
function getUserConfigPath(name) {
return path.join(usersPath, name + ".json");
}
function getUserLogsPath() {
return userLogsPath;
}
function getClientCertificatesPath() {
return clientCertificatesPath;
}
function getStoragePath() {
return storagePath;
}
function getPackagesPath() {
return packagesPath;
}
function getPackageModulePath(packageName) {
return path.join(Helper.getPackagesPath(), "node_modules", packageName);
}
function ip2hex(address) { function ip2hex(address) {
// no ipv6 support // no ipv6 support
if (!net.isIPv4(address)) { if (!net.isIPv4(address)) {
@ -271,40 +116,6 @@ function passwordCompare(password, expected) {
return bcrypt.compare(password, expected); return bcrypt.compare(password, expected);
} }
function getDefaultNick() {
if (!this.config.defaults.nick) {
return "thelounge";
}
return this.config.defaults.nick.replace(/%/g, () => Math.floor(Math.random() * 10));
}
function mergeConfig(oldConfig, newConfig) {
for (const key in newConfig) {
if (!Object.prototype.hasOwnProperty.call(oldConfig, key)) {
log.warn(`Unknown key "${colors.bold(key)}", please verify your config.`);
}
}
return _.mergeWith(oldConfig, newConfig, (objValue, srcValue, key) => {
// Do not override config variables if the type is incorrect (e.g. object changed into a string)
if (
typeof objValue !== "undefined" &&
objValue !== null &&
typeof objValue !== typeof srcValue
) {
log.warn(`Incorrect type for "${colors.bold(key)}", please verify your config.`);
return objValue;
}
// For arrays, simply override the value with user provided one.
if (_.isArray(objValue)) {
return srcValue;
}
});
}
function parseHostmask(hostmask) { function parseHostmask(hostmask) {
let nick = ""; let nick = "";
let ident = "*"; let ident = "*";

View File

@ -5,20 +5,21 @@ const fs = require("fs");
const net = require("net"); const net = require("net");
const colors = require("chalk"); const colors = require("chalk");
const Helper = require("./helper"); const Helper = require("./helper");
const Config = require("./config");
class Identification { class Identification {
constructor(startedCallback) { constructor(startedCallback) {
this.connectionId = 0; this.connectionId = 0;
this.connections = new Map(); this.connections = new Map();
if (typeof Helper.config.oidentd === "string") { if (typeof Config.values.oidentd === "string") {
this.oidentdFile = Helper.expandHome(Helper.config.oidentd); this.oidentdFile = Helper.expandHome(Config.values.oidentd);
log.info(`Oidentd file: ${colors.green(this.oidentdFile)}`); log.info(`Oidentd file: ${colors.green(this.oidentdFile)}`);
this.refresh(); this.refresh();
} }
if (Helper.config.identd.enable) { if (Config.values.identd.enable) {
if (this.oidentdFile) { if (this.oidentdFile) {
log.warn( log.warn(
"Using both identd and oidentd at the same time, this is most likely not intended." "Using both identd and oidentd at the same time, this is most likely not intended."
@ -33,8 +34,8 @@ class Identification {
server.listen( server.listen(
{ {
port: Helper.config.identd.port || 113, port: Config.values.identd.port || 113,
host: Helper.config.bind, host: Config.values.bind,
}, },
() => { () => {
const address = server.address(); const address = server.address();

View File

@ -2,7 +2,7 @@
const _ = require("lodash"); const _ = require("lodash");
const log = require("../log"); const log = require("../log");
const Helper = require("../helper"); const Config = require("../config");
const User = require("./user"); const User = require("./user");
const Msg = require("./msg"); const Msg = require("./msg");
const storage = require("../plugins/storage"); const storage = require("../plugins/storage");
@ -81,7 +81,7 @@ Chan.prototype.pushMessage = function (client, msg, increasesUnread) {
// Never store messages in public mode as the session // Never store messages in public mode as the session
// is completely destroyed when the page gets closed // is completely destroyed when the page gets closed
if (Helper.config.public) { if (Config.values.public) {
return; return;
} }
@ -92,19 +92,19 @@ Chan.prototype.pushMessage = function (client, msg, increasesUnread) {
this.writeUserLog(client, msg); this.writeUserLog(client, msg);
if (Helper.config.maxHistory >= 0 && this.messages.length > Helper.config.maxHistory) { if (Config.values.maxHistory >= 0 && this.messages.length > Config.values.maxHistory) {
const deleted = this.messages.splice(0, this.messages.length - Helper.config.maxHistory); const deleted = this.messages.splice(0, this.messages.length - Config.values.maxHistory);
// If maxHistory is 0, image would be dereferenced before client had a chance to retrieve it, // If maxHistory is 0, image would be dereferenced before client had a chance to retrieve it,
// so for now, just don't implement dereferencing for this edge case. // so for now, just don't implement dereferencing for this edge case.
if (Helper.config.maxHistory > 0) { if (Config.values.maxHistory > 0) {
this.dereferencePreviews(deleted); this.dereferencePreviews(deleted);
} }
} }
}; };
Chan.prototype.dereferencePreviews = function (messages) { Chan.prototype.dereferencePreviews = function (messages) {
if (!Helper.config.prefetch || !Helper.config.prefetchStorage) { if (!Config.values.prefetch || !Config.values.prefetchStorage) {
return; return;
} }

View File

@ -7,6 +7,7 @@ const Chan = require("./chan");
const Msg = require("./msg"); const Msg = require("./msg");
const Prefix = require("./prefix"); const Prefix = require("./prefix");
const Helper = require("../helper"); const Helper = require("../helper");
const Config = require("../config");
const STSPolicies = require("../plugins/sts"); const STSPolicies = require("../plugins/sts");
const ClientCertificate = require("../plugins/clientCertificate"); const ClientCertificate = require("../plugins/clientCertificate");
@ -92,7 +93,7 @@ Network.prototype.validate = function (client) {
// Remove new lines and limit length // Remove new lines and limit length
const cleanString = (str) => str.replace(/[\x00\r\n]/g, "").substring(0, 300); const cleanString = (str) => str.replace(/[\x00\r\n]/g, "").substring(0, 300);
this.setNick(cleanNick(String(this.nick || Helper.getDefaultNick()))); this.setNick(cleanNick(String(this.nick || Config.getDefaultNick())));
if (!this.username) { if (!this.username) {
// If username is empty, make one from the provided nick // If username is empty, make one from the provided nick
@ -133,28 +134,28 @@ Network.prototype.validate = function (client) {
this.sasl = ""; this.sasl = "";
} }
if (Helper.config.lockNetwork) { if (Config.values.lockNetwork) {
// This check is needed to prevent invalid user configurations // This check is needed to prevent invalid user configurations
if ( if (
!Helper.config.public && !Config.values.public &&
this.host && this.host &&
this.host.length > 0 && this.host.length > 0 &&
this.host !== Helper.config.defaults.host this.host !== Config.values.defaults.host
) { ) {
error(this, `The hostname you specified (${this.host}) is not allowed.`); error(this, `The hostname you specified (${this.host}) is not allowed.`);
return false; return false;
} }
if (Helper.config.public) { if (Config.values.public) {
this.name = Helper.config.defaults.name; this.name = Config.values.defaults.name;
// Sync lobby channel name // Sync lobby channel name
this.channels[0].name = Helper.config.defaults.name; this.channels[0].name = Config.values.defaults.name;
} }
this.host = Helper.config.defaults.host; this.host = Config.values.defaults.host;
this.port = Helper.config.defaults.port; this.port = Config.values.defaults.port;
this.tls = Helper.config.defaults.tls; this.tls = Config.values.defaults.tls;
this.rejectUnauthorized = Helper.config.defaults.rejectUnauthorized; this.rejectUnauthorized = Config.values.defaults.rejectUnauthorized;
} }
if (this.host.length === 0) { if (this.host.length === 0) {
@ -181,7 +182,7 @@ Network.prototype.validate = function (client) {
Network.prototype.createIrcFramework = function (client) { Network.prototype.createIrcFramework = function (client) {
this.irc = new IrcFramework.Client({ this.irc = new IrcFramework.Client({
version: false, // We handle it ourselves version: false, // We handle it ourselves
outgoing_addr: Helper.config.bind, outgoing_addr: Config.values.bind,
enable_chghost: true, enable_chghost: true,
enable_echomessage: true, enable_echomessage: true,
enable_setname: true, enable_setname: true,
@ -205,7 +206,7 @@ Network.prototype.setIrcFrameworkOptions = function (client) {
this.irc.options.port = this.port; this.irc.options.port = this.port;
this.irc.options.password = this.password; this.irc.options.password = this.password;
this.irc.options.nick = this.nick; this.irc.options.nick = this.nick;
this.irc.options.username = Helper.config.useHexIp this.irc.options.username = Config.values.useHexIp
? Helper.ip2hex(client.config.browser.ip) ? Helper.ip2hex(client.config.browser.ip)
: this.username; : this.username;
this.irc.options.gecos = this.realname; this.irc.options.gecos = this.realname;
@ -243,14 +244,14 @@ Network.prototype.setIrcFrameworkOptions = function (client) {
Network.prototype.createWebIrc = function (client) { Network.prototype.createWebIrc = function (client) {
if ( if (
!Helper.config.webirc || !Config.values.webirc ||
!Object.prototype.hasOwnProperty.call(Helper.config.webirc, this.host) !Object.prototype.hasOwnProperty.call(Config.values.webirc, this.host)
) { ) {
return null; return null;
} }
const webircObject = { const webircObject = {
password: Helper.config.webirc[this.host], password: Config.values.webirc[this.host],
username: "thelounge", username: "thelounge",
address: client.config.browser.ip, address: client.config.browser.ip,
hostname: client.config.browser.hostname, hostname: client.config.browser.hostname,
@ -263,9 +264,9 @@ Network.prototype.createWebIrc = function (client) {
}; };
} }
if (typeof Helper.config.webirc[this.host] === "function") { if (typeof Config.values.webirc[this.host] === "function") {
webircObject.password = null; webircObject.password = null;
return Helper.config.webirc[this.host](webircObject, this); return Config.values.webirc[this.host](webircObject, this);
} }
return webircObject; return webircObject;
@ -462,7 +463,7 @@ Network.prototype.quit = function (quitMessage) {
// https://ircv3.net/specs/extensions/sts#rescheduling-expiry-on-disconnect // https://ircv3.net/specs/extensions/sts#rescheduling-expiry-on-disconnect
STSPolicies.refreshExpiration(this.host); STSPolicies.refreshExpiration(this.host);
this.irc.quit(quitMessage || this.leaveMessage || Helper.config.leaveMessage); this.irc.quit(quitMessage || this.leaveMessage || Config.values.leaveMessage);
}; };
Network.prototype.exportForEdit = function () { Network.prototype.exportForEdit = function () {
@ -486,7 +487,7 @@ Network.prototype.exportForEdit = function () {
"proxyPassword", "proxyPassword",
]; ];
if (!Helper.config.lockNetwork) { if (!Config.values.lockNetwork) {
fieldsToReturn.push("host"); fieldsToReturn.push("host");
fieldsToReturn.push("port"); fieldsToReturn.push("port");
fieldsToReturn.push("tls"); fieldsToReturn.push("tls");

View File

@ -1,12 +1,12 @@
"use strict"; "use strict";
const log = require("../../log"); const log = require("../../log");
const Helper = require("../../helper"); const Config = require("../../config");
const ldap = require("ldapjs"); const ldap = require("ldapjs");
const colors = require("chalk"); const colors = require("chalk");
function ldapAuthCommon(user, bindDN, password, callback) { function ldapAuthCommon(user, bindDN, password, callback) {
const config = Helper.config; const config = Config.values;
const ldapclient = ldap.createClient({ const ldapclient = ldap.createClient({
url: config.ldap.url, url: config.ldap.url,
@ -35,7 +35,7 @@ function simpleLdapAuth(user, password, callback) {
return callback(false); return callback(false);
} }
const config = Helper.config; const config = Config.values;
const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1"); const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1");
const bindDN = `${config.ldap.primaryKey}=${userDN},${config.ldap.baseDN}`; const bindDN = `${config.ldap.primaryKey}=${userDN},${config.ldap.baseDN}`;
@ -53,7 +53,7 @@ function advancedLdapAuth(user, password, callback) {
return callback(false); return callback(false);
} }
const config = Helper.config; const config = Config.values;
const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1"); const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1");
const ldapclient = ldap.createClient({ const ldapclient = ldap.createClient({
@ -132,7 +132,7 @@ function ldapAuth(manager, client, user, password, callback) {
let auth; let auth;
if ("baseDN" in Helper.config.ldap) { if ("baseDN" in Config.values.ldap) {
auth = simpleLdapAuth; auth = simpleLdapAuth;
} else { } else {
auth = advancedLdapAuth; auth = advancedLdapAuth;
@ -147,7 +147,7 @@ function ldapAuth(manager, client, user, password, callback) {
*/ */
function advancedLdapLoadUsers(users, callbackLoadUser) { function advancedLdapLoadUsers(users, callbackLoadUser) {
const config = Helper.config; const config = Config.values;
const ldapclient = ldap.createClient({ const ldapclient = ldap.createClient({
url: config.ldap.url, url: config.ldap.url,
@ -212,7 +212,7 @@ function advancedLdapLoadUsers(users, callbackLoadUser) {
} }
function ldapLoadUsers(users, callbackLoadUser) { function ldapLoadUsers(users, callbackLoadUser) {
if ("baseDN" in Helper.config.ldap) { if ("baseDN" in Config.values.ldap) {
// simple LDAP case can't test for user existence without access to the // simple LDAP case can't test for user existence without access to the
// user's unhashed password, so indicate need to fallback to default // user's unhashed password, so indicate need to fallback to default
// loadUser behaviour by returning false // loadUser behaviour by returning false
@ -223,7 +223,7 @@ function ldapLoadUsers(users, callbackLoadUser) {
} }
function isLdapEnabled() { function isLdapEnabled() {
return !Helper.config.public && Helper.config.ldap.enable; return !Config.values.public && Config.values.ldap.enable;
} }
module.exports = { module.exports = {

View File

@ -5,7 +5,7 @@ const fs = require("fs");
const crypto = require("crypto"); const crypto = require("crypto");
const {md, pki} = require("node-forge"); const {md, pki} = require("node-forge");
const log = require("../log"); const log = require("../log");
const Helper = require("../helper"); const Config = require("../config");
module.exports = { module.exports = {
get, get,
@ -13,11 +13,11 @@ module.exports = {
}; };
function get(uuid) { function get(uuid) {
if (Helper.config.public) { if (Config.values.public) {
return null; return null;
} }
const folderPath = Helper.getClientCertificatesPath(); const folderPath = Config.getClientCertificatesPath();
const paths = getPaths(folderPath, uuid); const paths = getPaths(folderPath, uuid);
if (!fs.existsSync(paths.privateKeyPath) || !fs.existsSync(paths.certificatePath)) { if (!fs.existsSync(paths.privateKeyPath) || !fs.existsSync(paths.certificatePath)) {
@ -37,11 +37,11 @@ function get(uuid) {
} }
function remove(uuid) { function remove(uuid) {
if (Helper.config.public) { if (Config.values.public) {
return null; return null;
} }
const paths = getPaths(Helper.getClientCertificatesPath(), uuid); const paths = getPaths(Config.getClientCertificatesPath(), uuid);
try { try {
if (fs.existsSync(paths.privateKeyPath)) { if (fs.existsSync(paths.privateKeyPath)) {

View File

@ -2,7 +2,7 @@
const Msg = require("../../models/msg"); const Msg = require("../../models/msg");
const Chan = require("../../models/chan"); const Chan = require("../../models/chan");
const Helper = require("../../helper"); const Config = require("../../config");
exports.commands = ["close", "leave", "part"]; exports.commands = ["close", "leave", "part"];
exports.allowDisconnected = true; exports.allowDisconnected = true;
@ -42,7 +42,7 @@ exports.input = function (network, chan, cmd, args) {
) { ) {
this.part(network, target); this.part(network, target);
} else { } else {
const partMessage = args.join(" ") || network.leaveMessage || Helper.config.leaveMessage; const partMessage = args.join(" ") || network.leaveMessage || Config.values.leaveMessage;
network.irc.part(target.name, partMessage); network.irc.part(target.name, partMessage);
} }

View File

@ -5,6 +5,7 @@ const log = require("../../log");
const Msg = require("../../models/msg"); const Msg = require("../../models/msg");
const Chan = require("../../models/chan"); const Chan = require("../../models/chan");
const Helper = require("../../helper"); const Helper = require("../../helper");
const Config = require("../../config");
module.exports = function (irc, network) { module.exports = function (irc, network) {
const client = this; const client = this;
@ -93,7 +94,7 @@ module.exports = function (irc, network) {
irc.on("raw socket connected", function (socket) { irc.on("raw socket connected", function (socket) {
let ident = client.name || network.username; let ident = client.name || network.username;
if (Helper.config.useHexIp) { if (Config.values.useHexIp) {
ident = Helper.ip2hex(client.config.browser.ip); ident = Helper.ip2hex(client.config.browser.ip);
} }
@ -138,7 +139,7 @@ module.exports = function (irc, network) {
sendStatus(); sendStatus();
}); });
if (Helper.config.debug.ircFramework) { if (Config.values.debug.ircFramework) {
irc.on("debug", function (message) { irc.on("debug", function (message) {
log.debug( log.debug(
`[${client.name} (${client.id}) on ${network.name} (${network.uuid}]`, `[${client.name} (${client.id}) on ${network.name} (${network.uuid}]`,
@ -147,7 +148,7 @@ module.exports = function (irc, network) {
}); });
} }
if (Helper.config.debug.raw) { if (Config.values.debug.raw) {
irc.on("raw", function (message) { irc.on("raw", function (message) {
network.channels[0].pushMessage( network.channels[0].pushMessage(
client, client,

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
const Msg = require("../../models/msg"); const Msg = require("../../models/msg");
const Helper = require("../../helper"); const Config = require("../../config");
module.exports = function (irc, network) { module.exports = function (irc, network) {
const client = this; const client = this;
@ -36,7 +36,7 @@ module.exports = function (irc, network) {
irc.on("nick in use", function (data) { irc.on("nick in use", function (data) {
let message = data.nick + ": " + (data.reason || "Nickname is already in use."); let message = data.nick + ": " + (data.reason || "Nickname is already in use.");
if (irc.connection.registered === false && !Helper.config.public) { if (irc.connection.registered === false && !Config.values.public) {
message += " An attempt to use it will be made when this nick quits."; message += " An attempt to use it will be made when this nick quits.";
// Clients usually get nick in use on connect when reconnecting to a network // Clients usually get nick in use on connect when reconnecting to a network
@ -81,7 +81,7 @@ module.exports = function (irc, network) {
lobby.pushMessage(client, msg, true); lobby.pushMessage(client, msg, true);
if (irc.connection.registered === false) { if (irc.connection.registered === false) {
irc.changeNick(Helper.getDefaultNick()); irc.changeNick(Config.getDefaultNick());
} }
client.emit("nick", { client.emit("nick", {

View File

@ -4,7 +4,7 @@ const cheerio = require("cheerio");
const got = require("got"); const got = require("got");
const URL = require("url").URL; const URL = require("url").URL;
const mime = require("mime-types"); const mime = require("mime-types");
const Helper = require("../../helper"); const Config = require("../../config");
const {findLinksWithSchema} = require("../../../client/js/helpers/ircmessageparser/findLinks"); const {findLinksWithSchema} = require("../../../client/js/helpers/ircmessageparser/findLinks");
const storage = require("../storage"); const storage = require("../storage");
const currentFetchPromises = new Map(); const currentFetchPromises = new Map();
@ -13,7 +13,7 @@ const mediaTypeRegex = /^(audio|video)\/.+/;
const log = require("../../log"); const log = require("../../log");
module.exports = function (client, chan, msg, cleanText) { module.exports = function (client, chan, msg, cleanText) {
if (!Helper.config.prefetch) { if (!Config.values.prefetch) {
return; return;
} }
@ -90,7 +90,7 @@ function parseHtml(preview, res, client) {
preview.body = preview.body.substr(0, 300); preview.body = preview.body.substr(0, 300);
} }
if (!Helper.config.prefetchStorage && Helper.config.disableMediaPreview) { if (!Config.values.prefetchStorage && Config.values.disableMediaPreview) {
resolve(res); resolve(res);
return; return;
} }
@ -113,7 +113,7 @@ function parseHtml(preview, res, client) {
if ( if (
resThumb !== null && resThumb !== null &&
imageTypeRegex.test(resThumb.type) && imageTypeRegex.test(resThumb.type) &&
resThumb.size <= Helper.config.prefetchMaxImageSize * 1024 resThumb.size <= Config.values.prefetchMaxImageSize * 1024
) { ) {
preview.thumbActualUrl = thumb; preview.thumbActualUrl = thumb;
} }
@ -130,7 +130,7 @@ function parseHtml(preview, res, client) {
function parseHtmlMedia($, preview, client) { function parseHtmlMedia($, preview, client) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (Helper.config.disableMediaPreview) { if (Config.values.disableMediaPreview) {
reject(); reject();
return; return;
} }
@ -226,14 +226,14 @@ function parse(msg, chan, preview, res, client) {
case "image/jxl": case "image/jxl":
case "image/webp": case "image/webp":
case "image/avif": case "image/avif":
if (!Helper.config.prefetchStorage && Helper.config.disableMediaPreview) { if (!Config.values.prefetchStorage && Config.values.disableMediaPreview) {
return removePreview(msg, preview); return removePreview(msg, preview);
} }
if (res.size > Helper.config.prefetchMaxImageSize * 1024) { if (res.size > Config.values.prefetchMaxImageSize * 1024) {
preview.type = "error"; preview.type = "error";
preview.error = "image-too-big"; preview.error = "image-too-big";
preview.maxSize = Helper.config.prefetchMaxImageSize * 1024; preview.maxSize = Config.values.prefetchMaxImageSize * 1024;
} else { } else {
preview.type = "image"; preview.type = "image";
preview.thumbActualUrl = preview.link; preview.thumbActualUrl = preview.link;
@ -259,7 +259,7 @@ function parse(msg, chan, preview, res, client) {
break; break;
} }
if (Helper.config.disableMediaPreview) { if (Config.values.disableMediaPreview) {
return removePreview(msg, preview); return removePreview(msg, preview);
} }
@ -276,7 +276,7 @@ function parse(msg, chan, preview, res, client) {
break; break;
} }
if (Helper.config.disableMediaPreview) { if (Config.values.disableMediaPreview) {
return removePreview(msg, preview); return removePreview(msg, preview);
} }
@ -301,7 +301,7 @@ function handlePreview(client, chan, msg, preview, res) {
const thumb = preview.thumbActualUrl || ""; const thumb = preview.thumbActualUrl || "";
delete preview.thumbActualUrl; delete preview.thumbActualUrl;
if (!thumb.length || !Helper.config.prefetchStorage) { if (!thumb.length || !Config.values.prefetchStorage) {
preview.thumb = thumb; preview.thumb = thumb;
return emitPreview(client, chan, msg, preview); return emitPreview(client, chan, msg, preview);
} }
@ -382,7 +382,7 @@ function fetch(uri, headers) {
return promise; return promise;
} }
const prefetchTimeout = Helper.config.prefetchTimeout; const prefetchTimeout = Config.values.prefetchTimeout;
if (!prefetchTimeout) { if (!prefetchTimeout) {
log.warn( log.warn(
@ -394,7 +394,7 @@ function fetch(uri, headers) {
let buffer = Buffer.from(""); let buffer = Buffer.from("");
let contentLength = 0; let contentLength = 0;
let contentType; let contentType;
let limit = Helper.config.prefetchMaxImageSize * 1024; let limit = Config.values.prefetchMaxImageSize * 1024;
try { try {
const gotStream = got.stream(uri, { const gotStream = got.stream(uri, {
@ -415,7 +415,7 @@ function fetch(uri, headers) {
// response is an image // response is an image
// if Content-Length header reports a size exceeding the prefetch limit, abort fetch // if Content-Length header reports a size exceeding the prefetch limit, abort fetch
// and if file is not to be stored we don't need to download further either // and if file is not to be stored we don't need to download further either
if (contentLength > limit || !Helper.config.prefetchStorage) { if (contentLength > limit || !Config.values.prefetchStorage) {
gotStream.destroy(); gotStream.destroy();
} }
} else if (mediaTypeRegex.test(contentType)) { } else if (mediaTypeRegex.test(contentType)) {
@ -426,8 +426,8 @@ function fetch(uri, headers) {
// twitter.com sends opengraph meta tags within ~20kb of data for individual tweets, the default is set to 50. // twitter.com sends opengraph meta tags within ~20kb of data for individual tweets, the default is set to 50.
// for sites like Youtube the og tags are in the first 300K and hence this is configurable by the admin // for sites like Youtube the og tags are in the first 300K and hence this is configurable by the admin
limit = limit =
"prefetchMaxSearchSize" in Helper.config "prefetchMaxSearchSize" in Config.values
? Helper.config.prefetchMaxSearchSize * 1024 ? Config.values.prefetchMaxSearchSize * 1024
: // set to the previous size if config option is unset : // set to the previous size if config option is unset
50 * 1024; 50 * 1024;
} }

View File

@ -3,7 +3,7 @@
const log = require("../../log"); const log = require("../../log");
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Config = require("../../config");
const Msg = require("../../models/msg"); const Msg = require("../../models/msg");
let sqlite3; let sqlite3;
@ -11,7 +11,7 @@ let sqlite3;
try { try {
sqlite3 = require("sqlite3"); sqlite3 = require("sqlite3");
} catch (e) { } catch (e) {
Helper.config.messageStorage = Helper.config.messageStorage.filter((item) => item !== "sqlite"); Config.values.messageStorage = Config.values.messageStorage.filter((item) => item !== "sqlite");
log.error( log.error(
"Unable to load sqlite3 module. See https://github.com/mapbox/node-sqlite3/wiki/Binaries" "Unable to load sqlite3 module. See https://github.com/mapbox/node-sqlite3/wiki/Binaries"
@ -35,7 +35,7 @@ class MessageStorage {
} }
enable() { enable() {
const logsPath = Helper.getUserLogsPath(); const logsPath = Config.getUserLogsPath();
const sqlitePath = path.join(logsPath, `${this.client.name}.sqlite3`); const sqlitePath = path.join(logsPath, `${this.client.name}.sqlite3`);
try { try {
@ -165,12 +165,12 @@ class MessageStorage {
* @param Chan channel - Channel object for which to load messages for * @param Chan channel - Channel object for which to load messages for
*/ */
getMessages(network, channel) { getMessages(network, channel) {
if (!this.isEnabled || Helper.config.maxHistory === 0) { if (!this.isEnabled || Config.values.maxHistory === 0) {
return Promise.resolve([]); return Promise.resolve([]);
} }
// If unlimited history is specified, load 100k messages // If unlimited history is specified, load 100k messages
const limit = Helper.config.maxHistory < 0 ? 100000 : Helper.config.maxHistory; const limit = Config.values.maxHistory < 0 ? 100000 : Config.values.maxHistory;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.database.serialize(() => this.database.serialize(() =>

View File

@ -4,7 +4,7 @@ const log = require("../../log");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const filenamify = require("filenamify"); const filenamify = require("filenamify");
const Helper = require("../../helper"); const Config = require("../../config");
const Msg = require("../../models/msg"); const Msg = require("../../models/msg");
class TextFileMessageStorage { class TextFileMessageStorage {
@ -31,7 +31,7 @@ class TextFileMessageStorage {
} }
const logPath = path.join( const logPath = path.join(
Helper.getUserLogsPath(), Config.getUserLogsPath(),
this.client.name, this.client.name,
TextFileMessageStorage.getNetworkFolderName(network) TextFileMessageStorage.getNetworkFolderName(network)
); );
@ -117,7 +117,7 @@ class TextFileMessageStorage {
} }
const logPath = path.join( const logPath = path.join(
Helper.getUserLogsPath(), Config.getUserLogsPath(),
this.client.name, this.client.name,
TextFileMessageStorage.getNetworkFolderName(network), TextFileMessageStorage.getNetworkFolderName(network),
TextFileMessageStorage.getChannelFileName(channel) TextFileMessageStorage.getChannelFileName(channel)

View File

@ -6,6 +6,7 @@ const colors = require("chalk");
const path = require("path"); const path = require("path");
const semver = require("semver"); const semver = require("semver");
const Helper = require("../../helper"); const Helper = require("../../helper");
const Config = require("../../config");
const themes = require("./themes"); const themes = require("./themes");
const packageMap = new Map(); const packageMap = new Map();
const inputs = require("../inputs"); const inputs = require("../inputs");
@ -45,7 +46,7 @@ const packageApis = function (packageInfo) {
client.inputLine({target: targetId, text: command}), client.inputLine({target: targetId, text: command}),
}, },
Config: { Config: {
getConfig: () => Helper.config, getConfig: () => Config.values,
getPersistentStorageDir: getPersistentStorageDir.bind(this, packageInfo.packageName), getPersistentStorageDir: getPersistentStorageDir.bind(this, packageInfo.packageName),
}, },
Logger: { Logger: {
@ -89,7 +90,7 @@ function getEnabledPackages(packageJson) {
} }
function getPersistentStorageDir(packageName) { function getPersistentStorageDir(packageName) {
const dir = path.join(Helper.getPackagesPath(), packageName); const dir = path.join(Config.getPackagesPath(), packageName);
fs.mkdirSync(dir, {recursive: true}); // we don't care if it already exists or not fs.mkdirSync(dir, {recursive: true}); // we don't care if it already exists or not
return dir; return dir;
} }
@ -99,7 +100,7 @@ function loadPackage(packageName) {
let packageFile; let packageFile;
try { try {
const packagePath = Helper.getPackageModulePath(packageName); const packagePath = Config.getPackageModulePath(packageName);
packageInfo = JSON.parse(fs.readFileSync(path.join(packagePath, "package.json"), "utf-8")); packageInfo = JSON.parse(fs.readFileSync(path.join(packagePath, "package.json"), "utf-8"));
@ -155,7 +156,7 @@ function loadPackage(packageName) {
} }
function loadPackages() { function loadPackages() {
const packageJson = path.join(Helper.getPackagesPath(), "package.json"); const packageJson = path.join(Config.getPackagesPath(), "package.json");
const packages = getEnabledPackages(packageJson); const packages = getEnabledPackages(packageJson);
packages.forEach(loadPackage); packages.forEach(loadPackage);
@ -193,7 +194,7 @@ async function outdated(cacheTimeout = TIME_TO_LIVE) {
} }
// Get paths to the location of packages directory // Get paths to the location of packages directory
const packagesPath = Helper.getPackagesPath(); const packagesPath = Config.getPackagesPath();
const packagesConfig = path.join(packagesPath, "package.json"); const packagesConfig = path.join(packagesPath, "package.json");
const packagesList = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")).dependencies; const packagesList = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")).dependencies;
const argsList = [ const argsList = [

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
const fs = require("fs"); const fs = require("fs");
const Helper = require("../../helper"); const Config = require("../../config");
const path = require("path"); const path = require("path");
const _ = require("lodash"); const _ = require("lodash");
const themes = new Map(); const themes = new Map();
@ -61,7 +61,7 @@ function makePackageThemeObject(moduleName, module) {
} }
const themeColor = /^#[0-9A-F]{6}$/i.test(module.themeColor) ? module.themeColor : null; const themeColor = /^#[0-9A-F]{6}$/i.test(module.themeColor) ? module.themeColor : null;
const modulePath = Helper.getPackageModulePath(moduleName); const modulePath = Config.getPackageModulePath(moduleName);
return { return {
displayName: module.name || moduleName, displayName: module.name || moduleName,
filename: path.join(modulePath, module.css), filename: path.join(modulePath, module.css),

View File

@ -4,7 +4,7 @@ const log = require("../log");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const crypto = require("crypto"); const crypto = require("crypto");
const helper = require("../helper"); const Config = require("../config");
class Storage { class Storage {
constructor() { constructor() {
@ -16,7 +16,7 @@ class Storage {
// Deletes directory contents if the directory is not empty. // Deletes directory contents if the directory is not empty.
// If the directory does not exist, it is created. // If the directory does not exist, it is created.
const dir = helper.getStoragePath(); const dir = Config.getStoragePath();
let items; let items;
try { try {
@ -44,7 +44,7 @@ class Storage {
this.references.delete(url); this.references.delete(url);
// Drop "storage/" from url and join it with full storage path // Drop "storage/" from url and join it with full storage path
const filePath = path.join(helper.getStoragePath(), url.substring(8)); const filePath = path.join(Config.getStoragePath(), url.substring(8));
fs.unlink(filePath, (err) => { fs.unlink(filePath, (err) => {
if (err) { if (err) {
@ -57,7 +57,7 @@ class Storage {
const hash = crypto.createHash("sha256").update(data).digest("hex"); const hash = crypto.createHash("sha256").update(data).digest("hex");
const a = hash.substring(0, 2); const a = hash.substring(0, 2);
const b = hash.substring(2, 4); const b = hash.substring(2, 4);
const folder = path.join(helper.getStoragePath(), a, b); const folder = path.join(Config.getStoragePath(), a, b);
const filePath = path.join(folder, `${hash.substring(4)}.${extension}`); const filePath = path.join(folder, `${hash.substring(4)}.${extension}`);
const url = `storage/${a}/${b}/${hash.substring(4)}.${extension}`; const url = `storage/${a}/${b}/${hash.substring(4)}.${extension}`;

View File

@ -4,11 +4,11 @@ const _ = require("lodash");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const log = require("../log"); const log = require("../log");
const Helper = require("../helper"); const Config = require("../config");
class STSPolicies { class STSPolicies {
constructor() { constructor() {
this.stsFile = path.join(Helper.getHomePath(), "sts-policies.json"); this.stsFile = path.join(Config.getHomePath(), "sts-policies.json");
this.policies = new Map(); this.policies = new Map();
this.refresh = _.debounce(this.saveFile, 10000, {maxWait: 60000}); this.refresh = _.debounce(this.saveFile, 10000, {maxWait: 60000});

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const Helper = require("../helper"); const Config = require("../config");
const busboy = require("@fastify/busboy"); const busboy = require("@fastify/busboy");
const {v4: uuidv4} = require("uuid"); const {v4: uuidv4} = require("uuid");
const path = require("path"); const path = require("path");
@ -86,7 +86,7 @@ class Uploader {
} }
const folder = name.substring(0, 2); const folder = name.substring(0, 2);
const uploadPath = Helper.getFileUploadPath(); const uploadPath = Config.getFileUploadPath();
const filePath = path.join(uploadPath, folder, name); const filePath = path.join(uploadPath, folder, name);
let detectedMimeType = await Uploader.getFileType(filePath); let detectedMimeType = await Uploader.getFileType(filePath);
@ -207,7 +207,7 @@ class Uploader {
// that already exists on disk // that already exists on disk
do { do {
randomName = crypto.randomBytes(8).toString("hex"); randomName = crypto.randomBytes(8).toString("hex");
destDir = path.join(Helper.getFileUploadPath(), randomName.substring(0, 2)); destDir = path.join(Config.getFileUploadPath(), randomName.substring(0, 2));
destPath = path.join(destDir, randomName); destPath = path.join(destDir, randomName);
} while (fs.existsSync(destPath)); } while (fs.existsSync(destPath));
@ -228,8 +228,8 @@ class Uploader {
busboyInstance.on("file", (fieldname, fileStream, filename) => { busboyInstance.on("file", (fieldname, fileStream, filename) => {
uploadUrl = `${randomName}/${encodeURIComponent(filename)}`; uploadUrl = `${randomName}/${encodeURIComponent(filename)}`;
if (Helper.config.fileUpload.baseUrl) { if (Config.values.fileUpload.baseUrl) {
uploadUrl = new URL(uploadUrl, Helper.config.fileUpload.baseUrl).toString(); uploadUrl = new URL(uploadUrl, Config.values.fileUpload.baseUrl).toString();
} else { } else {
uploadUrl = `uploads/${uploadUrl}`; uploadUrl = `uploads/${uploadUrl}`;
} }
@ -266,7 +266,7 @@ class Uploader {
} }
static getMaxFileSize() { static getMaxFileSize() {
const configOption = Helper.config.fileUpload.maxFileSize; const configOption = Config.values.fileUpload.maxFileSize;
// Busboy uses Infinity to allow unlimited file size // Busboy uses Infinity to allow unlimited file size
if (configOption < 1) { if (configOption < 1) {

View File

@ -5,11 +5,11 @@ const log = require("../log");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const WebPushAPI = require("web-push"); const WebPushAPI = require("web-push");
const Helper = require("../helper"); const Config = require("../config");
class WebPush { class WebPush {
constructor() { constructor() {
const vapidPath = path.join(Helper.getHomePath(), "vapid.json"); const vapidPath = path.join(Config.getHomePath(), "vapid.json");
let vapidStat = undefined; let vapidStat = undefined;

View File

@ -12,6 +12,7 @@ const io = require("socket.io");
const dns = require("dns"); const dns = require("dns");
const Uploader = require("./plugins/uploader"); const Uploader = require("./plugins/uploader");
const Helper = require("./helper"); const Helper = require("./helper");
const Config = require("./config");
const colors = require("chalk"); const colors = require("chalk");
const net = require("net"); const net = require("net");
const Identification = require("./identification"); const Identification = require("./identification");
@ -35,7 +36,7 @@ module.exports = function (options = {}) {
(Node.js ${colors.green(process.versions.node)} on ${colors.green(process.platform)} ${ (Node.js ${colors.green(process.versions.node)} on ${colors.green(process.platform)} ${
process.arch process.arch
})`); })`);
log.info(`Configuration file: ${colors.green(Helper.getConfigPath())}`); log.info(`Configuration file: ${colors.green(Config.getConfigPath())}`);
const staticOptions = { const staticOptions = {
redirect: false, redirect: false,
@ -57,9 +58,9 @@ module.exports = function (options = {}) {
.get("/js/bundle.js.map", forceNoCacheRequest) .get("/js/bundle.js.map", forceNoCacheRequest)
.get("/css/style.css.map", forceNoCacheRequest) .get("/css/style.css.map", forceNoCacheRequest)
.use(express.static(path.join(__dirname, "..", "public"), staticOptions)) .use(express.static(path.join(__dirname, "..", "public"), staticOptions))
.use("/storage/", express.static(Helper.getStoragePath(), staticOptions)); .use("/storage/", express.static(Config.getStoragePath(), staticOptions));
if (Helper.config.fileUpload.enable) { if (Config.values.fileUpload.enable) {
Uploader.router(app); Uploader.router(app);
} }
@ -87,25 +88,25 @@ module.exports = function (options = {}) {
return res.status(404).send("Not found"); return res.status(404).send("Not found");
} }
const packagePath = Helper.getPackageModulePath(packageName); const packagePath = Config.getPackageModulePath(packageName);
return res.sendFile(path.join(packagePath, fileName)); return res.sendFile(path.join(packagePath, fileName));
}); });
let server = null; let server = null;
if (Helper.config.public && (Helper.config.ldap || {}).enable) { if (Config.values.public && (Config.values.ldap || {}).enable) {
log.warn( log.warn(
"Server is public and set to use LDAP. Set to private mode if trying to use LDAP authentication." "Server is public and set to use LDAP. Set to private mode if trying to use LDAP authentication."
); );
} }
if (!Helper.config.https.enable) { if (!Config.values.https.enable) {
server = require("http"); server = require("http");
server = server.createServer(app); server = server.createServer(app);
} else { } else {
const keyPath = Helper.expandHome(Helper.config.https.key); const keyPath = Helper.expandHome(Config.values.https.key);
const certPath = Helper.expandHome(Helper.config.https.certificate); const certPath = Helper.expandHome(Config.values.https.certificate);
const caPath = Helper.expandHome(Helper.config.https.ca); const caPath = Helper.expandHome(Config.values.https.ca);
if (!keyPath.length || !fs.existsSync(keyPath)) { if (!keyPath.length || !fs.existsSync(keyPath)) {
log.error("Path to SSL key is invalid. Stopping server..."); log.error("Path to SSL key is invalid. Stopping server...");
@ -135,12 +136,12 @@ module.exports = function (options = {}) {
let listenParams; let listenParams;
if (typeof Helper.config.host === "string" && Helper.config.host.startsWith("unix:")) { if (typeof Config.values.host === "string" && Config.values.host.startsWith("unix:")) {
listenParams = Helper.config.host.replace(/^unix:/, ""); listenParams = Config.values.host.replace(/^unix:/, "");
} else { } else {
listenParams = { listenParams = {
port: Helper.config.port, port: Config.values.port,
host: Helper.config.host, host: Config.values.host,
}; };
} }
@ -150,7 +151,7 @@ module.exports = function (options = {}) {
if (typeof listenParams === "string") { if (typeof listenParams === "string") {
log.info("Available on socket " + colors.green(listenParams)); log.info("Available on socket " + colors.green(listenParams));
} else { } else {
const protocol = Helper.config.https.enable ? "https" : "http"; const protocol = Config.values.https.enable ? "https" : "http";
const address = server.address(); const address = server.address();
if (address.family === "IPv6") { if (address.family === "IPv6") {
@ -160,7 +161,7 @@ module.exports = function (options = {}) {
log.info( log.info(
"Available at " + "Available at " +
colors.green(`${protocol}://${address.address}:${address.port}/`) + colors.green(`${protocol}://${address.address}:${address.port}/`) +
` in ${colors.bold(Helper.config.public ? "public" : "private")} mode` ` in ${colors.bold(Config.values.public ? "public" : "private")} mode`
); );
} }
@ -168,14 +169,14 @@ module.exports = function (options = {}) {
wsEngine: require("ws").Server, wsEngine: require("ws").Server,
cookie: false, cookie: false,
serveClient: false, serveClient: false,
transports: Helper.config.transports, transports: Config.values.transports,
pingTimeout: 60000, pingTimeout: 60000,
}); });
sockets.on("connect", (socket) => { sockets.on("connect", (socket) => {
socket.on("error", (err) => log.error(`io socket error: ${err}`)); socket.on("error", (err) => log.error(`io socket error: ${err}`));
if (Helper.config.public) { if (Config.values.public) {
performAuthentication.call(socket, {}); performAuthentication.call(socket, {});
} else { } else {
socket.on("auth:perform", performAuthentication); socket.on("auth:perform", performAuthentication);
@ -186,17 +187,17 @@ module.exports = function (options = {}) {
manager = new ClientManager(); manager = new ClientManager();
packages.loadPackages(); packages.loadPackages();
const defaultTheme = themes.getByName(Helper.config.theme); const defaultTheme = themes.getByName(Config.values.theme);
if (defaultTheme === undefined) { if (defaultTheme === undefined) {
log.warn( log.warn(
`The specified default theme "${colors.red( `The specified default theme "${colors.red(
Helper.config.theme Config.values.theme
)}" does not exist, verify your config.` )}" does not exist, verify your config.`
); );
Helper.config.theme = "default"; Config.values.theme = "default";
} else if (defaultTheme.themeColor) { } else if (defaultTheme.themeColor) {
Helper.config.themeColor = defaultTheme.themeColor; Config.values.themeColor = defaultTheme.themeColor;
} }
new Identification((identHandler, err) => { new Identification((identHandler, err) => {
@ -221,7 +222,7 @@ module.exports = function (options = {}) {
// Close all client and IRC connections // Close all client and IRC connections
manager.clients.forEach((client) => client.quit()); manager.clients.forEach((client) => client.quit());
if (Helper.config.prefetchStorage) { if (Config.values.prefetchStorage) {
log.info("Clearing prefetch storage folder, this might take a while..."); log.info("Clearing prefetch storage folder, this might take a while...");
require("./plugins/storage").emptyDir(); require("./plugins/storage").emptyDir();
@ -241,7 +242,7 @@ module.exports = function (options = {}) {
process.on("SIGTERM", exitGracefully); process.on("SIGTERM", exitGracefully);
// Clear storage folder after server starts successfully // Clear storage folder after server starts successfully
if (Helper.config.prefetchStorage) { if (Config.values.prefetchStorage) {
require("./plugins/storage").emptyDir(); require("./plugins/storage").emptyDir();
} }
@ -265,7 +266,7 @@ function getClientLanguage(socket) {
function getClientIp(socket) { function getClientIp(socket) {
let ip = socket.handshake.address || "127.0.0.1"; let ip = socket.handshake.address || "127.0.0.1";
if (Helper.config.reverseProxy) { if (Config.values.reverseProxy) {
const forwarded = (socket.handshake.headers["x-forwarded-for"] || "") const forwarded = (socket.handshake.headers["x-forwarded-for"] || "")
.split(/\s*,\s*/) .split(/\s*,\s*/)
.filter(Boolean); .filter(Boolean);
@ -281,7 +282,7 @@ function getClientIp(socket) {
function getClientSecure(socket) { function getClientSecure(socket) {
let secure = socket.handshake.secure; let secure = socket.handshake.secure;
if (Helper.config.reverseProxy && socket.handshake.headers["x-forwarded-proto"] === "https") { if (Config.values.reverseProxy && socket.handshake.headers["x-forwarded-proto"] === "https") {
secure = true; secure = true;
} }
@ -310,7 +311,7 @@ function addSecurityHeaders(req, res, next) {
// If prefetch is enabled, but storage is not, we have to allow mixed content // If prefetch is enabled, but storage is not, we have to allow mixed content
// - https://user-images.githubusercontent.com is where we currently push our changelog screenshots // - https://user-images.githubusercontent.com is where we currently push our changelog screenshots
// - data: is required for the HTML5 video player // - data: is required for the HTML5 video player
if (Helper.config.prefetchStorage || !Helper.config.prefetch) { if (Config.values.prefetchStorage || !Config.values.prefetch) {
policies.push("img-src 'self' data: https://user-images.githubusercontent.com"); policies.push("img-src 'self' data: https://user-images.githubusercontent.com");
policies.unshift("block-all-mixed-content"); policies.unshift("block-all-mixed-content");
} else { } else {
@ -367,7 +368,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
openChannel = client.lastActiveChannel; openChannel = client.lastActiveChannel;
} }
if (Helper.config.fileUpload.enable) { if (Config.values.fileUpload.enable) {
new Uploader(socket); new Uploader(socket);
} }
@ -436,7 +437,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
} }
}); });
if (!Helper.config.public && !Helper.config.ldap.enable) { if (!Config.values.public && !Config.values.ldap.enable) {
socket.on("change-password", (data) => { socket.on("change-password", (data) => {
if (_.isPlainObject(data)) { if (_.isPlainObject(data)) {
const old = data.old_password; const old = data.old_password;
@ -510,7 +511,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
// In public mode only one client can be connected, // In public mode only one client can be connected,
// so there's no need to handle msg:preview:toggle // so there's no need to handle msg:preview:toggle
if (!Helper.config.public) { if (!Config.values.public) {
socket.on("msg:preview:toggle", (data) => { socket.on("msg:preview:toggle", (data) => {
if (_.isPlainObject(data)) { if (_.isPlainObject(data)) {
return; return;
@ -571,7 +572,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
client.mentions = []; client.mentions = [];
}); });
if (!Helper.config.public) { if (!Config.values.public) {
socket.on("push:register", (subscription) => { socket.on("push:register", (subscription) => {
if (!Object.prototype.hasOwnProperty.call(client.config.sessions, token)) { if (!Object.prototype.hasOwnProperty.call(client.config.sessions, token)) {
return; return;
@ -614,7 +615,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
socket.on("sessions:get", sendSessionList); socket.on("sessions:get", sendSessionList);
if (!Helper.config.public) { if (!Config.values.public) {
socket.on("setting:set", (newSetting) => { socket.on("setting:set", (newSetting) => {
if (!_.isPlainObject(newSetting)) { if (!_.isPlainObject(newSetting)) {
return; return;
@ -739,7 +740,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
socket.emit("commands", inputs.getCommands()); socket.emit("commands", inputs.getCommands());
}; };
if (Helper.config.public) { if (Config.values.public) {
sendInitEvent(null); sendInitEvent(null);
} else if (token === null) { } else if (token === null) {
client.generateToken((newToken) => { client.generateToken((newToken) => {
@ -757,16 +758,16 @@ function initializeClient(socket, client, token, lastMessage, openChannel) {
} }
function getClientConfiguration() { function getClientConfiguration() {
const config = _.pick(Helper.config, ["public", "lockNetwork", "useHexIp", "prefetch"]); const config = _.pick(Config.values, ["public", "lockNetwork", "useHexIp", "prefetch"]);
config.fileUpload = Helper.config.fileUpload.enable; config.fileUpload = Config.values.fileUpload.enable;
config.ldapEnabled = Helper.config.ldap.enable; config.ldapEnabled = Config.values.ldap.enable;
if (!config.lockNetwork) { if (!config.lockNetwork) {
config.defaults = _.clone(Helper.config.defaults); config.defaults = _.clone(Config.values.defaults);
} else { } else {
// Only send defaults that are visible on the client // Only send defaults that are visible on the client
config.defaults = _.pick(Helper.config.defaults, [ config.defaults = _.pick(Config.values.defaults, [
"name", "name",
"nick", "nick",
"username", "username",
@ -781,8 +782,8 @@ function getClientConfiguration() {
config.version = pkg.version; config.version = pkg.version;
config.gitCommit = Helper.getGitCommit(); config.gitCommit = Helper.getGitCommit();
config.themes = themes.getAll(); config.themes = themes.getAll();
config.defaultTheme = Helper.config.theme; config.defaultTheme = Config.values.theme;
config.defaults.nick = Helper.getDefaultNick(); config.defaults.nick = Config.getDefaultNick();
config.defaults.sasl = ""; config.defaults.sasl = "";
config.defaults.saslAccount = ""; config.defaults.saslAccount = "";
config.defaults.saslPassword = ""; config.defaults.saslPassword = "";
@ -795,7 +796,7 @@ function getClientConfiguration() {
} }
function getServerConfiguration() { function getServerConfiguration() {
const config = _.clone(Helper.config); const config = _.clone(Config.values);
config.stylesheets = packages.getStylesheets(); config.stylesheets = packages.getStylesheets();
@ -833,7 +834,7 @@ function performAuthentication(data) {
}; };
// If webirc is enabled perform reverse dns lookup // If webirc is enabled perform reverse dns lookup
if (Helper.config.webirc === null) { if (Config.values.webirc === null) {
return finalInit(); return finalInit();
} }
@ -844,7 +845,7 @@ function performAuthentication(data) {
}); });
}; };
if (Helper.config.public) { if (Config.values.public) {
client = new Client(manager); client = new Client(manager);
manager.clients.push(client); manager.clients.push(client);

View File

@ -3,7 +3,7 @@
const fs = require("fs"); const fs = require("fs");
const home = require("path").join(__dirname, ".thelounge"); const home = require("path").join(__dirname, ".thelounge");
require("../../src/helper").setHome(home); require("../../src/config").setHome(home);
const STSPolicies = require("../../src/plugins/sts"); // Must be imported *after* setHome const STSPolicies = require("../../src/plugins/sts"); // Must be imported *after* setHome

View File

@ -5,7 +5,7 @@ const Chan = require("../../src/models/chan");
const Msg = require("../../src/models/msg"); const Msg = require("../../src/models/msg");
const User = require("../../src/models/user"); const User = require("../../src/models/user");
const Network = require("../../src/models/network"); const Network = require("../../src/models/network");
const Helper = require("../../src/helper"); const Config = require("../../src/config");
const STSPolicies = require("../../src/plugins/sts"); const STSPolicies = require("../../src/plugins/sts");
const ClientCertificate = require("../../src/plugins/clientCertificate"); const ClientCertificate = require("../../src/plugins/clientCertificate");
@ -126,7 +126,7 @@ describe("Network", function () {
describe("#validate()", function () { describe("#validate()", function () {
it("should set correct defaults", function () { it("should set correct defaults", function () {
Helper.config.defaults.nick = ""; Config.values.defaults.nick = "";
const network = new Network({ const network = new Network({
host: "localhost", host: "localhost",
@ -147,10 +147,10 @@ describe("Network", function () {
}); });
it("should enforce lockNetwork", function () { it("should enforce lockNetwork", function () {
Helper.config.lockNetwork = true; Config.values.lockNetwork = true;
// Make sure we lock in private mode // Make sure we lock in private mode
Helper.config.public = false; Config.values.public = false;
const network = new Network({ const network = new Network({
host: "", host: "",
@ -165,7 +165,7 @@ describe("Network", function () {
expect(network.rejectUnauthorized).to.be.true; expect(network.rejectUnauthorized).to.be.true;
// Make sure we lock in public mode (also resets public=true for other tests) // Make sure we lock in public mode (also resets public=true for other tests)
Helper.config.public = true; Config.values.public = true;
const network2 = new Network({ const network2 = new Network({
host: "some.fake.tld", host: "some.fake.tld",
@ -173,7 +173,7 @@ describe("Network", function () {
expect(network2.validate()).to.be.true; expect(network2.validate()).to.be.true;
expect(network2.host).to.equal("irc.example.com"); expect(network2.host).to.equal("irc.example.com");
Helper.config.lockNetwork = false; Config.values.lockNetwork = false;
}); });
it("should apply STS policies iff they match", function () { it("should apply STS policies iff they match", function () {
@ -204,7 +204,7 @@ describe("Network", function () {
}); });
it("should not remove client certs if TLS is disabled", function () { it("should not remove client certs if TLS is disabled", function () {
Helper.config.public = false; Config.values.public = false;
const client = {idMsg: 1, emit() {}, messageStorage: []}; const client = {idMsg: 1, emit() {}, messageStorage: []};
@ -221,11 +221,11 @@ describe("Network", function () {
expect(ClientCertificate.get(network.uuid)).to.deep.equal(client_cert); // Should be unchanged expect(ClientCertificate.get(network.uuid)).to.deep.equal(client_cert); // Should be unchanged
ClientCertificate.remove(network.uuid); ClientCertificate.remove(network.uuid);
Helper.config.public = true; Config.values.public = true;
}); });
it("should not remove client certs if there is a STS policy", function () { it("should not remove client certs if there is a STS policy", function () {
Helper.config.public = false; Config.values.public = false;
const client = {idMsg: 1, emit() {}, messageStorage: []}; const client = {idMsg: 1, emit() {}, messageStorage: []};
STSPolicies.update("irc.example.com", 7000, 3600); STSPolicies.update("irc.example.com", 7000, 3600);
@ -243,13 +243,13 @@ describe("Network", function () {
expect(ClientCertificate.get(network.uuid)).to.deep.equal(client_cert); // Should be unchanged expect(ClientCertificate.get(network.uuid)).to.deep.equal(client_cert); // Should be unchanged
ClientCertificate.remove(network.uuid); ClientCertificate.remove(network.uuid);
Helper.config.public = true; Config.values.public = true;
}); });
}); });
describe("#createIrcFramework(client)", function () { describe("#createIrcFramework(client)", function () {
it("should generate and use a client certificate when using SASL external", function () { it("should generate and use a client certificate when using SASL external", function () {
Helper.config.public = false; Config.values.public = false;
const client = {idMsg: 1, emit() {}}; const client = {idMsg: 1, emit() {}};
STSPolicies.update("irc.example.com", 7000, 3600); STSPolicies.update("irc.example.com", 7000, 3600);
@ -265,7 +265,7 @@ describe("Network", function () {
expect(network.irc.options.client_certificate).to.not.be.null; expect(network.irc.options.client_certificate).to.not.be.null;
ClientCertificate.remove(network.uuid); ClientCertificate.remove(network.uuid);
Helper.config.public = true; Config.values.public = true;
}); });
}); });

View File

@ -2,7 +2,7 @@
const log = require("../../../src/log"); const log = require("../../../src/log");
const ldapAuth = require("../../../src/plugins/auth/ldap"); const ldapAuth = require("../../../src/plugins/auth/ldap");
const Helper = require("../../../src/helper"); const Config = require("../../../src/config");
const ldap = require("ldapjs"); const ldap = require("ldapjs");
const expect = require("chai").expect; const expect = require("chai").expect;
const stub = require("sinon").stub; const stub = require("sinon").stub;
@ -23,7 +23,7 @@ function normalizeDN(dn) {
function startLdapServer(callback) { function startLdapServer(callback) {
const server = ldap.createServer(); const server = ldap.createServer();
const searchConf = Helper.config.ldap.searchDN; const searchConf = Config.values.ldap.searchDN;
const userDN = primaryKey + "=" + user + "," + baseDN; const userDN = primaryKey + "=" + user + "," + baseDN;
// Two users are authorized: john doe and the root user in case of // Two users are authorized: john doe and the root user in case of
@ -143,34 +143,34 @@ describe("LDAP authentication plugin", function () {
}); });
beforeEach(function () { beforeEach(function () {
Helper.config.public = false; Config.values.public = false;
Helper.config.ldap.enable = true; Config.values.ldap.enable = true;
Helper.config.ldap.url = "ldap://localhost:" + String(serverPort); Config.values.ldap.url = "ldap://localhost:" + String(serverPort);
Helper.config.ldap.primaryKey = primaryKey; Config.values.ldap.primaryKey = primaryKey;
}); });
afterEach(function () { afterEach(function () {
Helper.config.public = true; Config.values.public = true;
Helper.config.ldap.enable = false; Config.values.ldap.enable = false;
}); });
describe("LDAP authentication availability", function () { describe("LDAP authentication availability", function () {
it("checks that the configuration is correctly tied to isEnabled()", function () { it("checks that the configuration is correctly tied to isEnabled()", function () {
Helper.config.ldap.enable = true; Config.values.ldap.enable = true;
expect(ldapAuth.isEnabled()).to.equal(true); expect(ldapAuth.isEnabled()).to.equal(true);
Helper.config.ldap.enable = false; Config.values.ldap.enable = false;
expect(ldapAuth.isEnabled()).to.equal(false); expect(ldapAuth.isEnabled()).to.equal(false);
}); });
}); });
describe("Simple LDAP authentication (predefined DN pattern)", function () { describe("Simple LDAP authentication (predefined DN pattern)", function () {
Helper.config.ldap.baseDN = baseDN; Config.values.ldap.baseDN = baseDN;
testLdapAuth(); testLdapAuth();
}); });
describe("Advanced LDAP authentication (DN found by a prior search query)", function () { describe("Advanced LDAP authentication (DN found by a prior search query)", function () {
delete Helper.config.ldap.baseDN; delete Config.values.ldap.baseDN;
testLdapAuth(); testLdapAuth();
}); });
}); });

View File

@ -4,18 +4,18 @@ const fs = require("fs");
const path = require("path"); const path = require("path");
const {expect} = require("chai"); const {expect} = require("chai");
const ClientCertificate = require("../../src/plugins/clientCertificate"); const ClientCertificate = require("../../src/plugins/clientCertificate");
const Helper = require("../../src/helper"); const Config = require("../../src/config");
describe("ClientCertificate", function () { describe("ClientCertificate", function () {
it("should not generate a client certificate in public mode", function () { it("should not generate a client certificate in public mode", function () {
Helper.config.public = true; Config.values.public = true;
const certificate = ClientCertificate.get("this-is-test-uuid"); const certificate = ClientCertificate.get("this-is-test-uuid");
expect(certificate).to.be.null; expect(certificate).to.be.null;
}); });
it("should generate a client certificate", function () { it("should generate a client certificate", function () {
Helper.config.public = false; Config.values.public = false;
const certificate = ClientCertificate.get("this-is-test-uuid"); const certificate = ClientCertificate.get("this-is-test-uuid");
expect(certificate.certificate).to.match(/^-----BEGIN CERTIFICATE-----/); expect(certificate.certificate).to.match(/^-----BEGIN CERTIFICATE-----/);
@ -25,18 +25,18 @@ describe("ClientCertificate", function () {
expect(certificate2.certificate).to.equal(certificate.certificate); expect(certificate2.certificate).to.equal(certificate.certificate);
expect(certificate2.private_key).to.equal(certificate.private_key); expect(certificate2.private_key).to.equal(certificate.private_key);
Helper.config.public = true; Config.values.public = true;
}); });
it("should remove the client certificate files", function () { it("should remove the client certificate files", function () {
Helper.config.public = false; Config.values.public = false;
const privateKeyPath = path.join( const privateKeyPath = path.join(
Helper.getClientCertificatesPath(), Config.getClientCertificatesPath(),
`this-is-test-uuid.pem` `this-is-test-uuid.pem`
); );
const certificatePath = path.join( const certificatePath = path.join(
Helper.getClientCertificatesPath(), Config.getClientCertificatesPath(),
`this-is-test-uuid.crt` `this-is-test-uuid.crt`
); );
@ -48,6 +48,6 @@ describe("ClientCertificate", function () {
expect(fs.existsSync(privateKeyPath)).to.be.false; expect(fs.existsSync(privateKeyPath)).to.be.false;
expect(fs.existsSync(certificatePath)).to.be.false; expect(fs.existsSync(certificatePath)).to.be.false;
Helper.config.public = true; Config.values.public = true;
}); });
}); });

View File

@ -3,7 +3,7 @@
const path = require("path"); const path = require("path");
const expect = require("chai").expect; const expect = require("chai").expect;
const util = require("../util"); const util = require("../util");
const Helper = require("../../src/helper"); const Config = require("../../src/config");
const link = require("../../src/plugins/irc-events/link.js"); const link = require("../../src/plugins/irc-events/link.js");
describe("Link plugin", function () { describe("Link plugin", function () {
@ -36,7 +36,7 @@ Vivamus bibendum vulputate tincidunt. Sed vitae ligula felis.`;
this.irc = util.createClient(); this.irc = util.createClient();
this.network = util.createNetwork(); this.network = util.createNetwork();
Helper.config.prefetchStorage = false; Config.values.prefetchStorage = false;
}); });
afterEach(function (done) { afterEach(function (done) {
@ -224,11 +224,11 @@ Vivamus bibendum vulputate tincidunt. Sed vitae ligula felis.`;
describe("test disableMediaPreview", function () { describe("test disableMediaPreview", function () {
beforeEach(function (done) { beforeEach(function (done) {
Helper.config.disableMediaPreview = true; Config.values.disableMediaPreview = true;
done(); done();
}); });
afterEach(function (done) { afterEach(function (done) {
Helper.config.disableMediaPreview = false; Config.values.disableMediaPreview = false;
done(); done();
}); });
it("should ignore og:image if disableMediaPreview", function (done) { it("should ignore og:image if disableMediaPreview", function (done) {

View File

@ -5,7 +5,7 @@ const path = require("path");
const expect = require("chai").expect; const expect = require("chai").expect;
const util = require("../util"); const util = require("../util");
const Msg = require("../../src/models/msg"); const Msg = require("../../src/models/msg");
const Helper = require("../../src/helper"); const Config = require("../../src/config");
const MessageStorage = require("../../src/plugins/messageStorage/sqlite.js"); const MessageStorage = require("../../src/plugins/messageStorage/sqlite.js");
describe("SQLite Message Storage", function () { describe("SQLite Message Storage", function () {
@ -13,7 +13,7 @@ describe("SQLite Message Storage", function () {
this.timeout(util.isRunningOnCI() ? 25000 : 5000); this.timeout(util.isRunningOnCI() ? 25000 : 5000);
this.slow(300); this.slow(300);
const expectedPath = path.join(Helper.getHomePath(), "logs", "testUser.sqlite3"); const expectedPath = path.join(Config.getHomePath(), "logs", "testUser.sqlite3");
let store; let store;
before(function (done) { before(function (done) {
@ -34,7 +34,7 @@ describe("SQLite Message Storage", function () {
// After tests run, remove the logs folder // After tests run, remove the logs folder
// so we return to the clean state // so we return to the clean state
fs.unlinkSync(expectedPath); fs.unlinkSync(expectedPath);
fs.rmdir(path.join(Helper.getHomePath(), "logs"), done); fs.rmdir(path.join(Config.getHomePath(), "logs"), done);
}); });
it("should resolve an empty array when disabled", function () { it("should resolve an empty array when disabled", function () {
@ -127,10 +127,10 @@ describe("SQLite Message Storage", function () {
}); });
it("should retrieve latest LIMIT messages in order", function () { it("should retrieve latest LIMIT messages in order", function () {
const originalMaxHistory = Helper.config.maxHistory; const originalMaxHistory = Config.values.maxHistory;
try { try {
Helper.config.maxHistory = 2; Config.values.maxHistory = 2;
for (let i = 0; i < 200; ++i) { for (let i = 0; i < 200; ++i) {
store.index( store.index(
@ -150,15 +150,15 @@ describe("SQLite Message Storage", function () {
expect(messages.map((i) => i.text)).to.deep.equal(["msg 198", "msg 199"]); expect(messages.map((i) => i.text)).to.deep.equal(["msg 198", "msg 199"]);
}); });
} finally { } finally {
Helper.config.maxHistory = originalMaxHistory; Config.values.maxHistory = originalMaxHistory;
} }
}); });
it("should search messages", function () { it("should search messages", function () {
const originalMaxHistory = Helper.config.maxHistory; const originalMaxHistory = Config.values.maxHistory;
try { try {
Helper.config.maxHistory = 2; Config.values.maxHistory = 2;
return store return store
.search({ .search({
@ -177,7 +177,7 @@ describe("SQLite Message Storage", function () {
expect(messages.results.map((i) => i.text)).to.deep.equal(expectedMessages); expect(messages.results.map((i) => i.text)).to.deep.equal(expectedMessages);
}); });
} finally { } finally {
Helper.config.maxHistory = originalMaxHistory; Config.values.maxHistory = originalMaxHistory;
} }
}); });
@ -193,10 +193,10 @@ describe("SQLite Message Storage", function () {
}); });
} }
const originalMaxHistory = Helper.config.maxHistory; const originalMaxHistory = Config.values.maxHistory;
try { try {
Helper.config.maxHistory = 3; Config.values.maxHistory = 3;
store.index( store.index(
{uuid: "this-is-a-network-guid2"}, {uuid: "this-is-a-network-guid2"},
@ -239,7 +239,7 @@ describe("SQLite Message Storage", function () {
.then(() => assertResults("@", ["bar @ baz"])) .then(() => assertResults("@", ["bar @ baz"]))
); );
} finally { } finally {
Helper.config.maxHistory = originalMaxHistory; Config.values.maxHistory = originalMaxHistory;
} }
}); });

View File

@ -5,7 +5,7 @@ const path = require("path");
const crypto = require("crypto"); const crypto = require("crypto");
const expect = require("chai").expect; const expect = require("chai").expect;
const util = require("../util"); const util = require("../util");
const Helper = require("../../src/helper"); const Config = require("../../src/config");
const storage = require("../../src/plugins/storage"); const storage = require("../../src/plugins/storage");
const link = require("../../src/plugins/irc-events/link.js"); const link = require("../../src/plugins/irc-events/link.js");
@ -55,7 +55,7 @@ describe("Image storage", function () {
after(function (done) { after(function (done) {
// After storage tests run, remove the remaining empty // After storage tests run, remove the remaining empty
// storage folder so we return to the clean state // storage folder so we return to the clean state
const dir = Helper.getStoragePath(); const dir = Config.getStoragePath();
fs.rmdir(dir, done); fs.rmdir(dir, done);
}); });
@ -63,11 +63,11 @@ describe("Image storage", function () {
this.irc = util.createClient(); this.irc = util.createClient();
this.network = util.createNetwork(); this.network = util.createNetwork();
Helper.config.prefetchStorage = true; Config.values.prefetchStorage = true;
}); });
afterEach(function () { afterEach(function () {
Helper.config.prefetchStorage = false; Config.values.prefetchStorage = false;
}); });
it("should store the thumbnail", function (done) { it("should store the thumbnail", function (done) {
@ -135,7 +135,7 @@ describe("Image storage", function () {
}); });
it("should clear storage folder", function () { it("should clear storage folder", function () {
const dir = Helper.getStoragePath(); const dir = Config.getStoragePath();
expect(fs.readdirSync(dir)).to.not.be.empty; expect(fs.readdirSync(dir)).to.not.be.empty;
storage.emptyDir(); storage.emptyDir();

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
const log = require("../src/log"); const log = require("../src/log");
const Helper = require("../src/helper"); const Config = require("../src/config");
const expect = require("chai").expect; const expect = require("chai").expect;
const stub = require("sinon").stub; const stub = require("sinon").stub;
const got = require("got"); const got = require("got");
@ -28,7 +28,7 @@ describe("Server", function () {
changelog.checkForUpdates.restore(); changelog.checkForUpdates.restore();
}); });
const webURL = `http://${Helper.config.host}:${Helper.config.port}/`; const webURL = `http://${Config.values.host}:${Config.values.port}/`;
describe("Express", () => { describe("Express", () => {
it("should run a web server on " + webURL, async () => { it("should run a web server on " + webURL, async () => {
@ -84,7 +84,7 @@ describe("Server", function () {
nick: "test-user", nick: "test-user",
join: "#thelounge, #spam", join: "#thelounge, #spam",
name: "Test Network", name: "Test Network",
host: Helper.config.host, host: Config.values.host,
port: 6667, port: 6667,
}); });
}); });

View File

@ -3,7 +3,7 @@
const log = require("../../src/log"); const log = require("../../src/log");
const expect = require("chai").expect; const expect = require("chai").expect;
const stub = require("sinon").stub; const stub = require("sinon").stub;
const mergeConfig = require("../../src/helper").mergeConfig; const Config = require("../../src/config");
const TestUtil = require("../util"); const TestUtil = require("../util");
describe("mergeConfig", function () { describe("mergeConfig", function () {
@ -13,7 +13,7 @@ describe("mergeConfig", function () {
}; };
expect( expect(
mergeConfig(config, { Config._merge_config_objects(config, {
ip: "overridden", ip: "overridden",
}) })
).to.deep.equal({ ).to.deep.equal({
@ -27,7 +27,7 @@ describe("mergeConfig", function () {
it("should merge new properties", function () { it("should merge new properties", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
ip: "default", ip: "default",
newProp: "this should appear too", newProp: "this should appear too",
@ -44,7 +44,7 @@ describe("mergeConfig", function () {
it("should extend objects", function () { it("should extend objects", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
tlsOptions: {}, tlsOptions: {},
}, },
@ -68,7 +68,7 @@ describe("mergeConfig", function () {
stub(log, "warn").callsFake(TestUtil.sanitizeLog((str) => (warning += str))); stub(log, "warn").callsFake(TestUtil.sanitizeLog((str) => (warning += str)));
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
optionOne: 123, optionOne: 123,
}, },
@ -88,7 +88,7 @@ describe("mergeConfig", function () {
it("should not warn for unknown second level keys", function () { it("should not warn for unknown second level keys", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
optionOne: { optionOne: {
subOne: 123, subOne: 123,
@ -111,7 +111,7 @@ describe("mergeConfig", function () {
it("should allow changing nulls", function () { it("should allow changing nulls", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
oidentd: null, oidentd: null,
}, },
@ -126,7 +126,7 @@ describe("mergeConfig", function () {
it("should allow changing nulls with objects", function () { it("should allow changing nulls with objects", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
webirc: null, webirc: null,
}, },
@ -149,7 +149,7 @@ describe("mergeConfig", function () {
const callbackFunction = () => ({}); const callbackFunction = () => ({});
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
webirc: null, webirc: null,
}, },
@ -168,7 +168,7 @@ describe("mergeConfig", function () {
it("should keep new properties inside of objects", function () { it("should keep new properties inside of objects", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
nestedOnce: { nestedOnce: {
ip: "default", ip: "default",
@ -206,7 +206,7 @@ describe("mergeConfig", function () {
it("should not merge arrays", function () { it("should not merge arrays", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
test: ["sqlite", "text"], test: ["sqlite", "text"],
}, },
@ -219,7 +219,7 @@ describe("mergeConfig", function () {
}); });
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
test: ["sqlite", "text"], test: ["sqlite", "text"],
}, },
@ -234,7 +234,7 @@ describe("mergeConfig", function () {
it("should change order in arrays", function () { it("should change order in arrays", function () {
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
test: ["sqlite", "text"], test: ["sqlite", "text"],
}, },
@ -251,7 +251,7 @@ describe("mergeConfig", function () {
stub(log, "warn"); stub(log, "warn");
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
shouldBeObject: { shouldBeObject: {
thing: "yes", thing: "yes",
@ -268,7 +268,7 @@ describe("mergeConfig", function () {
}); });
expect( expect(
mergeConfig( Config._merge_config_objects(
{ {
shouldBeString: "string", shouldBeString: "string",
}, },