Merge pull request #198 from NuSkooler/config-get-for-0.0.9-alpha

More Hot-Reload related changes
This commit is contained in:
Bryan Ashby 2018-06-20 20:22:18 -06:00 committed by GitHub
commit 64f65df7fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 320 additions and 273 deletions

View File

@ -10,7 +10,8 @@ This document attempts to track **major** changes and additions in ENiGMA½. For
* Setting the `data` member of an object will cause form submissions to use this value instead of the selected items index. * Setting the `data` member of an object will cause form submissions to use this value instead of the selected items index.
* See the default `luciano_blocktronics` `matrix` menu for example usage. * See the default `luciano_blocktronics` `matrix` menu for example usage.
* You can now set the `sort` property on a menu to sort items. If `true` items are sorted by `text`. If the value is a string, it represents the key in menu objects to sort by. * You can now set the `sort` property on a menu to sort items. If `true` items are sorted by `text`. If the value is a string, it represents the key in menu objects to sort by.
* Hot-reload of configuration files such as menu.hjson, config.hjson, your themes.hjson, etc.: When a file is saved, it will be hot-reloaded into the running system
* Note that any custom modules should make use of the new Config.get() method.
## 0.0.8-alpha ## 0.0.8-alpha
* [Mystic BBS style](http://wiki.mysticbbs.com/doku.php?id=displaycodes) extended pipe color codes. These allow for example, to set "iCE" background colors. * [Mystic BBS style](http://wiki.mysticbbs.com/doku.php?id=displaycodes) extended pipe color codes. These allow for example, to set "iCE" background colors.

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const resolveMimeType = require('./mime_util.js').resolveMimeType; const resolveMimeType = require('./mime_util.js').resolveMimeType;
@ -61,10 +61,11 @@ module.exports = class ArchiveUtil {
// //
// Load configuration // Load configuration
// //
if(_.has(Config, 'archives.archivers')) { const config = Config();
Object.keys(Config.archives.archivers).forEach(archKey => { if(_.has(config, 'archives.archivers')) {
Object.keys(config.archives.archivers).forEach(archKey => {
const archConfig = Config.archives.archivers[archKey]; const archConfig = config.archives.archivers[archKey];
const archiver = new Archiver(archConfig); const archiver = new Archiver(archConfig);
if(!archiver.ok()) { if(!archiver.ok()) {
@ -75,7 +76,7 @@ module.exports = class ArchiveUtil {
}); });
} }
if(_.isObject(Config.fileTypes)) { if(_.isObject(config.fileTypes)) {
const updateSig = (ft) => { const updateSig = (ft) => {
ft.sig = Buffer.from(ft.sig, 'hex'); ft.sig = Buffer.from(ft.sig, 'hex');
ft.offset = ft.offset || 0; ft.offset = ft.offset || 0;
@ -87,8 +88,8 @@ module.exports = class ArchiveUtil {
} }
}; };
Object.keys(Config.fileTypes).forEach(mimeType => { Object.keys(config.fileTypes).forEach(mimeType => {
const fileType = Config.fileTypes[mimeType]; const fileType = config.fileTypes[mimeType];
if(Array.isArray(fileType)) { if(Array.isArray(fileType)) {
fileType.forEach(ft => { fileType.forEach(ft => {
if(ft.sig) { if(ft.sig) {
@ -109,7 +110,8 @@ module.exports = class ArchiveUtil {
return; return;
} }
let fileType = _.get(Config, [ 'fileTypes', mimeType ] ); const config = Config();
let fileType = _.get(config, [ 'fileTypes', mimeType ] );
if(Array.isArray(fileType)) { if(Array.isArray(fileType)) {
if(!justExtention) { if(!justExtention) {
@ -125,7 +127,7 @@ module.exports = class ArchiveUtil {
} }
if(fileType.archiveHandler) { if(fileType.archiveHandler) {
return _.get( Config, [ 'archives', 'archivers', fileType.archiveHandler ] ); return _.get( config, [ 'archives', 'archivers', fileType.archiveHandler ] );
} }
} }
@ -151,7 +153,7 @@ module.exports = class ArchiveUtil {
return cb(err); return cb(err);
} }
const archFormat = _.findKey(Config.fileTypes, fileTypeInfo => { const archFormat = _.findKey(Config().fileTypes, fileTypeInfo => {
const fileTypeInfos = Array.isArray(fileTypeInfo) ? fileTypeInfo : [ fileTypeInfo ]; const fileTypeInfos = Array.isArray(fileTypeInfo) ? fileTypeInfo : [ fileTypeInfo ];
return fileTypeInfos.find(fti => { return fileTypeInfos.find(fti => {
if(!fti.sig || !fti.archiveHandler) { if(!fti.sig || !fti.archiveHandler) {

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const miscUtil = require('./misc_util.js'); const miscUtil = require('./misc_util.js');
const ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
const aep = require('./ansi_escape_parser.js'); const aep = require('./ansi_escape_parser.js');
@ -126,7 +126,7 @@ function getArtFromPath(path, options, cb) {
function getArt(name, options, cb) { function getArt(name, options, cb) {
const ext = paths.extname(name); const ext = paths.extname(name);
options.basePath = miscUtil.valueWithDefault(options.basePath, Config.paths.art); options.basePath = miscUtil.valueWithDefault(options.basePath, Config().paths.art);
options.asAnsi = miscUtil.valueWithDefault(options.asAnsi, true); options.asAnsi = miscUtil.valueWithDefault(options.asAnsi, true);
// :TODO: make use of asAnsi option and convert from supported -> ansi // :TODO: make use of asAnsi option and convert from supported -> ansi

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const StatLog = require('./stat_log.js'); const StatLog = require('./stat_log.js');
// deps // deps
@ -95,7 +95,7 @@ function resolveConfigAsset(spec) {
assert('config' === asset.type); assert('config' === asset.type);
const path = asset.asset.split('.'); const path = asset.asset.split('.');
let conf = Config; let conf = Config();
for(let i = 0; i < path.length; ++i) { for(let i = 0; i < path.length; ++i) {
if(_.isUndefined(conf[path[i]])) { if(_.isUndefined(conf[path[i]])) {
return spec; return spec;

View File

@ -35,7 +35,7 @@
const term = require('./client_term.js'); const term = require('./client_term.js');
const ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
const User = require('./user.js'); const User = require('./user.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const MenuStack = require('./menu_stack.js'); const MenuStack = require('./menu_stack.js');
const ACS = require('./acs.js'); const ACS = require('./acs.js');
const Events = require('./events.js'); const Events = require('./events.js');
@ -400,7 +400,7 @@ function Client(/*input, output*/) {
} }
if(key || ch) { if(key || ch) {
if(Config.logging.traceUserKeyboardInput) { if(Config().logging.traceUserKeyboardInput) {
self.log.trace( { key : key, ch : escape(ch) }, 'User keyboard input'); // jshint ignore:line self.log.trace( { key : key, ch : escape(ch) }, 'User keyboard input'); // jshint ignore:line
} }
@ -440,8 +440,8 @@ Client.prototype.startIdleMonitor = function() {
const nowMs = Date.now(); const nowMs = Date.now();
const idleLogoutSeconds = this.user.isAuthenticated() ? const idleLogoutSeconds = this.user.isAuthenticated() ?
Config.misc.idleLogoutSeconds : Config().misc.idleLogoutSeconds :
Config.misc.preAuthIdleLogoutSeconds; Config().misc.preAuthIdleLogoutSeconds;
if(nowMs - this.lastKeyPressMs >= (idleLogoutSeconds * 1000)) { if(nowMs - this.lastKeyPressMs >= (idleLogoutSeconds * 1000)) {
this.emit('idle timeout'); this.emit('idle timeout');

View File

@ -13,6 +13,8 @@ const assert = require('assert');
exports.init = init; exports.init = init;
exports.getDefaultPath = getDefaultPath; exports.getDefaultPath = getDefaultPath;
let currentConfiguration = {};
function hasMessageConferenceAndArea(config) { function hasMessageConferenceAndArea(config) {
assert(_.isObject(config.messageConferences)); // we create one ourself! assert(_.isObject(config.messageConferences)); // we create one ourself!
@ -67,12 +69,10 @@ function mergeValidateAndFinalize(config, cb) {
return callback(null, mergedConfig); return callback(null, mergedConfig);
}, },
function setIt(mergedConfig, callback) { function setIt(mergedConfig, callback) {
exports.config = mergedConfig; // :TODO: .config property is to be deprecated once conversions are done
exports.config = currentConfiguration = mergedConfig;
exports.config.get = (path) => {
return _.get(exports.config, path);
};
exports.get = () => currentConfiguration;
return callback(null); return callback(null);
} }
], ],

View File

@ -1,7 +1,7 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
const Config = require('./config.js').config; const Config = require('./config.js').get;
const ConfigCache = require('./config_cache.js'); const ConfigCache = require('./config_cache.js');
const Events = require('./events.js'); const Events = require('./events.js');
@ -15,7 +15,7 @@ exports.getFullConfig = getFullConfig;
function getConfigPath(filePath) { function getConfigPath(filePath) {
// |filePath| is assumed to be in the config path if it's only a file name // |filePath| is assumed to be in the config path if it's only a file name
if('.' === paths.dirname(filePath)) { if('.' === paths.dirname(filePath)) {
filePath = paths.join(Config.paths.config, filePath); filePath = paths.join(Config().paths.config, filePath);
} }
return filePath; return filePath;
} }
@ -24,19 +24,20 @@ function init(cb) {
// pre-cache menu.hjson and prompt.hjson + establish events // pre-cache menu.hjson and prompt.hjson + establish events
const changed = ( { fileName, fileRoot } ) => { const changed = ( { fileName, fileRoot } ) => {
const reCachedPath = paths.join(fileRoot, fileName); const reCachedPath = paths.join(fileRoot, fileName);
if(reCachedPath === getConfigPath(Config.general.menuFile)) { if(reCachedPath === getConfigPath(Config().general.menuFile)) {
Events.emit(Events.getSystemEvents().MenusChanged); Events.emit(Events.getSystemEvents().MenusChanged);
} else if(reCachedPath === getConfigPath(Config.general.promptFile)) { } else if(reCachedPath === getConfigPath(Config().general.promptFile)) {
Events.emit(Events.getSystemEvents().PromptsChanged); Events.emit(Events.getSystemEvents().PromptsChanged);
} }
}; };
const config = Config();
async.series( async.series(
[ [
function menu(callback) { function menu(callback) {
return ConfigCache.getConfigWithOptions( return ConfigCache.getConfigWithOptions(
{ {
filePath : getConfigPath(Config.general.menuFile), filePath : getConfigPath(config.general.menuFile),
callback : changed, callback : changed,
}, },
callback callback
@ -45,7 +46,7 @@ function init(cb) {
function prompt(callback) { function prompt(callback) {
return ConfigCache.getConfigWithOptions( return ConfigCache.getConfigWithOptions(
{ {
filePath : getConfigPath(Config.general.promptFile), filePath : getConfigPath(config.general.promptFile),
callback : changed, callback : changed,
}, },
callback callback

View File

@ -1,7 +1,7 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var Config = require('./config.js').config; var Config = require('./config.js').get;
const StatLog = require('./stat_log.js'); const StatLog = require('./stat_log.js');
var fs = require('graceful-fs'); var fs = require('graceful-fs');
@ -29,7 +29,7 @@ function DropFile(client, fileType) {
Object.defineProperty(this, 'fullPath', { Object.defineProperty(this, 'fullPath', {
get : function() { get : function() {
return paths.join(Config.paths.dropFiles, ('node' + self.client.node), self.fileName); return paths.join(Config().paths.dropFiles, ('node' + self.client.node), self.fileName);
} }
}); });
@ -157,7 +157,7 @@ function DropFile(client, fileType) {
// :TODO: Completely broken right now -- This need to be configurable & come from temp socket server most likely // :TODO: Completely broken right now -- This need to be configurable & come from temp socket server most likely
'-1', // self.client.output._handle.fd.toString(), // :TODO: ALWAYS -1 on Windows! '-1', // self.client.output._handle.fd.toString(), // :TODO: ALWAYS -1 on Windows!
'57600', '57600',
Config.general.boardName, Config().general.boardName,
self.client.user.userId.toString(), self.client.user.userId.toString(),
self.client.user.properties.real_name || self.client.user.username, self.client.user.properties.real_name || self.client.user.username,
self.client.user.username, self.client.user.username,
@ -183,7 +183,7 @@ function DropFile(client, fileType) {
var secLevel = self.client.user.getLegacySecurityLevel().toString(); var secLevel = self.client.user.getLegacySecurityLevel().toString();
return iconv.encode( [ return iconv.encode( [
Config.general.boardName, // "The name of the system." Config().general.boardName, // "The name of the system."
opUn, // "The sysop's name up to the first space." opUn, // "The sysop's name up to the first space."
opUn, // "The sysop's name following the first space." opUn, // "The sysop's name following the first space."
'COM1', // "The serial port the modem is connected to, or 0 if logged in on console." 'COM1', // "The serial port the modem is connected to, or 0 if logged in on console."

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
@ -13,13 +13,14 @@ const nodeMailer = require('nodemailer');
exports.sendMail = sendMail; exports.sendMail = sendMail;
function sendMail(message, cb) { function sendMail(message, cb) {
if(!_.has(Config, 'email.transport')) { const config = Config();
if(!_.has(config, 'email.transport')) {
return cb(Errors.MissingConfig('Email "email::transport" configuration missing')); return cb(Errors.MissingConfig('Email "email::transport" configuration missing'));
} }
message.from = message.from || Config.email.defaultFrom; message.from = message.from || config.email.defaultFrom;
const transportOptions = Object.assign( {}, Config.email.transport, { const transportOptions = Object.assign( {}, config.email.transport, {
logger : Log, logger : Log,
}); });

View File

@ -2,14 +2,14 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
// deps // deps
const assert = require('assert'); const assert = require('assert');
module.exports = function(condition, message) { module.exports = function(condition, message) {
if(Config.debug.assertsEnabled) { if(Config().debug.assertsEnabled) {
assert.apply(this, arguments); assert.apply(this, arguments);
} else if(!(condition)) { } else if(!(condition)) {
const stack = new Error().stack; const stack = new Error().stack;

View File

@ -3,7 +3,7 @@
// ENiGMA½ // ENiGMA½
const PluginModule = require('./plugin_module.js').PluginModule; const PluginModule = require('./plugin_module.js').PluginModule;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
const _ = require('lodash'); const _ = require('lodash');
@ -155,8 +155,9 @@ class ScheduledEvent {
function EventSchedulerModule(options) { function EventSchedulerModule(options) {
PluginModule.call(this, options); PluginModule.call(this, options);
if(_.has(Config, 'eventScheduler')) { const config = Config();
this.moduleConfig = Config.eventScheduler; if(_.has(config, 'eventScheduler')) {
this.moduleConfig = config.eventScheduler;
} }
const self = this; const self = this;

View File

@ -4,7 +4,7 @@
// ENiGMA½ // ENiGMA½
const MenuModule = require('./menu_module.js').MenuModule; const MenuModule = require('./menu_module.js').MenuModule;
const resetScreen = require('./ansi_term.js').resetScreen; const resetScreen = require('./ansi_term.js').resetScreen;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
const getEnigmaUserAgent = require('./misc_util.js').getEnigmaUserAgent; const getEnigmaUserAgent = require('./misc_util.js').getEnigmaUserAgent;
@ -66,7 +66,7 @@ exports.getModule = class ExodusModule extends MenuModule {
this.config.sshHost = this.config.sshHost || this.config.ticketHost; this.config.sshHost = this.config.sshHost || this.config.ticketHost;
this.config.sshPort = this.config.sshPort || 22; this.config.sshPort = this.config.sshPort || 22;
this.config.sshUser = this.config.sshUser || 'exodus_server'; this.config.sshUser = this.config.sshUser || 'exodus_server';
this.config.sshKeyPem = this.config.sshKeyPem || joinPath(Config.paths.misc, 'exodus.id_rsa'); this.config.sshKeyPem = this.config.sshKeyPem || joinPath(Config().paths.misc, 'exodus.id_rsa');
} }
initSequence() { initSequence() {

View File

@ -12,7 +12,7 @@ const FileArea = require('./file_base_area.js');
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const ErrNotEnabled = require('./enig_error.js').ErrorReasons.NotEnabled; const ErrNotEnabled = require('./enig_error.js').ErrorReasons.NotEnabled;
const ArchiveUtil = require('./archive_util.js'); const ArchiveUtil = require('./archive_util.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const DownloadQueue = require('./download_queue.js'); const DownloadQueue = require('./download_queue.js');
const FileAreaWeb = require('./file_area_web.js'); const FileAreaWeb = require('./file_area_web.js');
const FileBaseFilters = require('./file_base_filter.js'); const FileBaseFilters = require('./file_base_filter.js');
@ -255,7 +255,7 @@ exports.getModule = class FileAreaList extends MenuModule {
const mimeType = resolveMimeType(entryInfo.archiveType); const mimeType = resolveMimeType(entryInfo.archiveType);
let desc; let desc;
if(mimeType) { if(mimeType) {
let fileType = _.get(Config, [ 'fileTypes', mimeType ] ); let fileType = _.get(Config(), [ 'fileTypes', mimeType ] );
if(Array.isArray(fileType)) { if(Array.isArray(fileType)) {
// further refine by extention // further refine by extention
@ -264,7 +264,6 @@ exports.getModule = class FileAreaList extends MenuModule {
desc = fileType && fileType.desc; desc = fileType && fileType.desc;
} }
entryInfo.archiveTypeDesc = desc || mimeType || entryInfo.archiveType; entryInfo.archiveTypeDesc = desc || mimeType || entryInfo.archiveType;
//entryInfo.archiveTypeDesc = mimeType ? _.get(Config, [ 'fileTypes', mimeType, 'desc' ] ) || mimeType : entryInfo.archiveType;
} else { } else {
entryInfo.archiveTypeDesc = 'N/A'; entryInfo.archiveTypeDesc = 'N/A';
} }
@ -510,7 +509,7 @@ exports.getModule = class FileAreaList extends MenuModule {
return callback(null); return callback(null);
} }
const expireTime = moment().add(Config.fileBase.web.expireMinutes, 'minutes'); const expireTime = moment().add(Config().fileBase.web.expireMinutes, 'minutes');
FileAreaWeb.createAndServeTempDownload( FileAreaWeb.createAndServeTempDownload(
self.client, self.client,

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const FileDb = require('./database.js').dbs.file; const FileDb = require('./database.js').dbs.file;
const getISOTimestampString = require('./database.js').getISOTimestampString; const getISOTimestampString = require('./database.js').getISOTimestampString;
const FileEntry = require('./file_entry.js'); const FileEntry = require('./file_entry.js');
@ -31,7 +31,7 @@ function notEnabledError() {
class FileAreaWebAccess { class FileAreaWebAccess {
constructor() { constructor() {
this.hashids = new hashids(Config.general.boardName); this.hashids = new hashids(Config().general.boardName);
this.expireTimers = {}; // hashId->timer this.expireTimers = {}; // hashId->timer
} }
@ -52,7 +52,7 @@ class FileAreaWebAccess {
if(self.isEnabled()) { if(self.isEnabled()) {
const routeAdded = self.webServer.instance.addRoute({ const routeAdded = self.webServer.instance.addRoute({
method : 'GET', method : 'GET',
path : Config.fileBase.web.routePath, path : Config().fileBase.web.routePath,
handler : self.routeWebRequest.bind(self), handler : self.routeWebRequest.bind(self),
}); });
return callback(routeAdded ? null : Errors.General('Failed adding route')); return callback(routeAdded ? null : Errors.General('Failed adding route'));
@ -184,11 +184,11 @@ class FileAreaWebAccess {
buildSingleFileTempDownloadLink(client, fileEntry, hashId) { buildSingleFileTempDownloadLink(client, fileEntry, hashId) {
hashId = hashId || this.getSingleFileHashId(client, fileEntry); hashId = hashId || this.getSingleFileHashId(client, fileEntry);
return this.webServer.instance.buildUrl(`${Config.fileBase.web.path}${hashId}`); return this.webServer.instance.buildUrl(`${Config().fileBase.web.path}${hashId}`);
} }
buildBatchArchiveTempDownloadLink(client, hashId) { buildBatchArchiveTempDownloadLink(client, hashId) {
return this.webServer.instance.buildUrl(`${Config.fileBase.web.path}${hashId}`); return this.webServer.instance.buildUrl(`${Config().fileBase.web.path}${hashId}`);
} }
getExistingTempDownloadServeItem(client, fileEntry, cb) { getExistingTempDownloadServeItem(client, fileEntry, cb) {

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const sortAreasOrConfs = require('./conf_area_util.js').sortAreasOrConfs; const sortAreasOrConfs = require('./conf_area_util.js').sortAreasOrConfs;
const FileEntry = require('./file_entry.js'); const FileEntry = require('./file_entry.js');
@ -66,7 +66,7 @@ function getAvailableFileAreas(client, options) {
options = options || { }; options = options || { };
// perform ACS check per conf & omit internal if desired // perform ACS check per conf & omit internal if desired
const allAreas = _.map(Config.fileBase.areas, (areaInfo, areaTag) => Object.assign(areaInfo, { areaTag : areaTag } )); const allAreas = _.map(Config().fileBase.areas, (areaInfo, areaTag) => Object.assign(areaInfo, { areaTag : areaTag } ));
return _.omitBy(allAreas, areaInfo => { return _.omitBy(allAreas, areaInfo => {
if(!options.includeSystemInternal && isInternalArea(areaInfo.areaTag)) { if(!options.includeSystemInternal && isInternalArea(areaInfo.areaTag)) {
@ -96,16 +96,17 @@ function getSortedAvailableFileAreas(client, options) {
} }
function getDefaultFileAreaTag(client, disableAcsCheck) { function getDefaultFileAreaTag(client, disableAcsCheck) {
let defaultArea = _.findKey(Config.fileBase, o => o.default); const config = Config();
let defaultArea = _.findKey(config.fileBase, o => o.default);
if(defaultArea) { if(defaultArea) {
const area = Config.fileBase.areas[defaultArea]; const area = config.fileBase.areas[defaultArea];
if(true === disableAcsCheck || client.acs.hasFileAreaRead(area)) { if(true === disableAcsCheck || client.acs.hasFileAreaRead(area)) {
return defaultArea; return defaultArea;
} }
} }
// just use anything we can // just use anything we can
defaultArea = _.findKey(Config.fileBase.areas, (area, areaTag) => { defaultArea = _.findKey(config.fileBase.areas, (area, areaTag) => {
return WellKnownAreaTags.MessageAreaAttach !== areaTag && (true === disableAcsCheck || client.acs.hasFileAreaRead(area)); return WellKnownAreaTags.MessageAreaAttach !== areaTag && (true === disableAcsCheck || client.acs.hasFileAreaRead(area));
}); });
@ -113,7 +114,7 @@ function getDefaultFileAreaTag(client, disableAcsCheck) {
} }
function getFileAreaByTag(areaTag) { function getFileAreaByTag(areaTag) {
const areaInfo = Config.fileBase.areas[areaTag]; const areaInfo = Config().fileBase.areas[areaTag];
if(areaInfo) { if(areaInfo) {
areaInfo.areaTag = areaTag; // convienence! areaInfo.areaTag = areaTag; // convienence!
areaInfo.storage = getAreaStorageLocations(areaInfo); areaInfo.storage = getAreaStorageLocations(areaInfo);
@ -157,13 +158,14 @@ function changeFileAreaWithOptions(client, areaTag, options, cb) {
} }
function isValidStorageTag(storageTag) { function isValidStorageTag(storageTag) {
return storageTag in Config.fileBase.storageTags; return storageTag in Config().fileBase.storageTags;
} }
function getAreaStorageDirectoryByTag(storageTag) { function getAreaStorageDirectoryByTag(storageTag) {
const storageLocation = (storageTag && Config.fileBase.storageTags[storageTag]); const config = Config();
const storageLocation = (storageTag && config.fileBase.storageTags[storageTag]);
return paths.resolve(Config.fileBase.areaStoragePrefix, storageLocation || ''); return paths.resolve(config.fileBase.areaStoragePrefix, storageLocation || '');
} }
function getAreaDefaultStorageDirectory(areaInfo) { function getAreaDefaultStorageDirectory(areaInfo) {
@ -176,7 +178,7 @@ function getAreaStorageLocations(areaInfo) {
areaInfo.storageTags : areaInfo.storageTags :
[ areaInfo.storageTags || '' ]; [ areaInfo.storageTags || '' ];
const avail = Config.fileBase.storageTags; const avail = Config().fileBase.storageTags;
return _.compact(storageTags.map(storageTag => { return _.compact(storageTags.map(storageTag => {
if(avail[storageTag]) { if(avail[storageTag]) {
@ -233,7 +235,7 @@ function sliceAtSauceMarker(data) {
function attemptSetEstimatedReleaseDate(fileEntry) { function attemptSetEstimatedReleaseDate(fileEntry) {
// :TODO: yearEstPatterns RegExp's should be cached - we can do this @ Config (re)load time // :TODO: yearEstPatterns RegExp's should be cached - we can do this @ Config (re)load time
const patterns = Config.fileBase.yearEstPatterns.map( p => new RegExp(p, 'gmi')); const patterns = Config().fileBase.yearEstPatterns.map( p => new RegExp(p, 'gmi'));
function getMatch(input) { function getMatch(input) {
if(input) { if(input) {
@ -290,11 +292,11 @@ function extractAndProcessDescFiles(fileEntry, filePath, archiveEntries, cb) {
function extractDescFiles(callback) { function extractDescFiles(callback) {
// :TODO: would be nice if these RegExp's were cached // :TODO: would be nice if these RegExp's were cached
// :TODO: this is long winded... // :TODO: this is long winded...
const config = Config();
const extractList = []; const extractList = [];
const shortDescFile = archiveEntries.find( e => { const shortDescFile = archiveEntries.find( e => {
return Config.fileBase.fileNamePatterns.desc.find( pat => new RegExp(pat, 'i').test(e.fileName) ); return config.fileBase.fileNamePatterns.desc.find( pat => new RegExp(pat, 'i').test(e.fileName) );
}); });
if(shortDescFile) { if(shortDescFile) {
@ -302,7 +304,7 @@ function extractAndProcessDescFiles(fileEntry, filePath, archiveEntries, cb) {
} }
const longDescFile = archiveEntries.find( e => { const longDescFile = archiveEntries.find( e => {
return Config.fileBase.fileNamePatterns.descLong.find( pat => new RegExp(pat, 'i').test(e.fileName) ); return config.fileBase.fileNamePatterns.descLong.find( pat => new RegExp(pat, 'i').test(e.fileName) );
}); });
if(longDescFile) { if(longDescFile) {
@ -334,6 +336,7 @@ function extractAndProcessDescFiles(fileEntry, filePath, archiveEntries, cb) {
}); });
}, },
function readDescFiles(descFiles, callback) { function readDescFiles(descFiles, callback) {
const config = Config();
async.each(Object.keys(descFiles), (descType, next) => { async.each(Object.keys(descFiles), (descType, next) => {
const path = descFiles[descType]; const path = descFiles[descType];
if(!path) { if(!path) {
@ -347,9 +350,8 @@ function extractAndProcessDescFiles(fileEntry, filePath, archiveEntries, cb) {
// skip entries that are too large // skip entries that are too large
const maxFileSizeKey = `max${_.upperFirst(descType)}FileByteSize`; const maxFileSizeKey = `max${_.upperFirst(descType)}FileByteSize`;
if(config.fileBase[maxFileSizeKey] && stats.size > config.fileBase[maxFileSizeKey]) {
if(Config.fileBase[maxFileSizeKey] && stats.size > Config.fileBase[maxFileSizeKey]) { logDebug( { byteSize : stats.size, maxByteSize : config.fileBase[maxFileSizeKey] }, `Skipping "${descType}"; Too large` );
logDebug( { byteSize : stats.size, maxByteSize : Config.fileBase[maxFileSizeKey] }, `Skipping "${descType}"; Too large` );
return next(null); return next(null);
} }
@ -488,7 +490,8 @@ function populateFileEntryWithArchive(fileEntry, filePath, stepInfo, iterator, c
} }
function getInfoExtractUtilForDesc(mimeType, filePath, descType) { function getInfoExtractUtilForDesc(mimeType, filePath, descType) {
let fileType = _.get(Config, [ 'fileTypes', mimeType ] ); const config = Config();
let fileType = _.get(config, [ 'fileTypes', mimeType ] );
if(Array.isArray(fileType)) { if(Array.isArray(fileType)) {
// further refine by extention // further refine by extention
@ -504,7 +507,7 @@ function getInfoExtractUtilForDesc(mimeType, filePath, descType) {
return; return;
} }
util = _.get(Config, [ 'infoExtractUtils', util ]); util = _.get(config, [ 'infoExtractUtils', util ]);
if(!util || !_.isString(util.cmd)) { if(!util || !_.isString(util.cmd)) {
return; return;
} }

View File

@ -5,7 +5,7 @@
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const FileEntry = require('./file_entry.js'); const FileEntry = require('./file_entry.js');
const FileArea = require('./file_base_area.js'); const FileArea = require('./file_base_area.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const { Errors } = require('./enig_error.js'); const { Errors } = require('./enig_error.js');
const { const {
splitTextAtTerms, splitTextAtTerms,
@ -64,12 +64,14 @@ function exportFileList(filterCriteria, options, cb) {
{ name : options.headerTemplate, req : false }, { name : options.headerTemplate, req : false },
{ name : options.entryTemplate, req : true } { name : options.entryTemplate, req : true }
]; ];
const config = Config();
async.map(templateFiles, (template, nextTemplate) => { async.map(templateFiles, (template, nextTemplate) => {
if(!template.name && !template.req) { if(!template.name && !template.req) {
return nextTemplate(null, Buffer.from([])); return nextTemplate(null, Buffer.from([]));
} }
template.name = paths.isAbsolute(template.name) ? template.name : paths.join(Config.paths.misc, template.name); template.name = paths.isAbsolute(template.name) ? template.name : paths.join(config.paths.misc, template.name);
fs.readFile(template.name, (err, data) => { fs.readFile(template.name, (err, data) => {
return nextTemplate(err, data); return nextTemplate(err, data);
}); });
@ -221,7 +223,7 @@ function exportFileList(filterCriteria, options, cb) {
const headerFormatObj = { const headerFormatObj = {
nowTs : moment().format(options.tsFormat), nowTs : moment().format(options.tsFormat),
boardName : Config.general.boardName, boardName : Config().general.boardName,
totalFileCount : totals.fileCount, totalFileCount : totals.fileCount,
totalFileSize : totals.bytes, totalFileSize : totals.bytes,
filterAreaTag : filterCriteria.areaTag || '-ALL-', filterAreaTag : filterCriteria.areaTag || '-ALL-',

View File

@ -11,7 +11,7 @@ const Errors = require('./enig_error.js').Errors;
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const FileAreaWeb = require('./file_area_web.js'); const FileAreaWeb = require('./file_area_web.js');
const ErrNotEnabled = require('./enig_error.js').ErrorReasons.NotEnabled; const ErrNotEnabled = require('./enig_error.js').ErrorReasons.NotEnabled;
const Config = require('./config.js').config; const Config = require('./config.js').get;
// deps // deps
const async = require('async'); const async = require('async');
@ -139,7 +139,7 @@ exports.getModule = class FileBaseWebDownloadQueueManager extends MenuModule {
} }
generateAndDisplayBatchLink(cb) { generateAndDisplayBatchLink(cb) {
const expireTime = moment().add(Config.fileBase.web.expireMinutes, 'minutes'); const expireTime = moment().add(Config().fileBase.web.expireMinutes, 'minutes');
FileAreaWeb.createAndServeTempBatchDownload( FileAreaWeb.createAndServeTempBatchDownload(
this.client, this.client,
@ -183,6 +183,7 @@ exports.getModule = class FileBaseWebDownloadQueueManager extends MenuModule {
function prepareQueueDownloadLinks(callback) { function prepareQueueDownloadLinks(callback) {
const webDlExpireTimeFormat = self.menuConfig.config.webDlExpireTimeFormat || 'YYYY-MMM-DD @ h:mm'; const webDlExpireTimeFormat = self.menuConfig.config.webDlExpireTimeFormat || 'YYYY-MMM-DD @ h:mm';
const config = Config();
async.each(self.dlQueue.items, (fileEntry, nextFileEntry) => { async.each(self.dlQueue.items, (fileEntry, nextFileEntry) => {
FileAreaWeb.getExistingTempDownloadServeItem(self.client, fileEntry, (err, serveItem) => { FileAreaWeb.getExistingTempDownloadServeItem(self.client, fileEntry, (err, serveItem) => {
if(err) { if(err) {
@ -190,7 +191,7 @@ exports.getModule = class FileBaseWebDownloadQueueManager extends MenuModule {
return nextFileEntry(err); // we should have caught this prior return nextFileEntry(err); // we should have caught this prior
} }
const expireTime = moment().add(Config.fileBase.web.expireMinutes, 'minutes'); const expireTime = moment().add(config.fileBase.web.expireMinutes, 'minutes');
FileAreaWeb.createAndServeTempDownload( FileAreaWeb.createAndServeTempDownload(
self.client, self.client,

View File

@ -7,7 +7,7 @@ const {
getISOTimestampString, getISOTimestampString,
sanatizeString sanatizeString
} = require('./database.js'); } = require('./database.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
// deps // deps
const async = require('async'); const async = require('async');
@ -202,7 +202,8 @@ module.exports = class FileEntry {
} }
static getAreaStorageDirectoryByTag(storageTag) { static getAreaStorageDirectoryByTag(storageTag) {
const storageLocation = (storageTag && Config.fileBase.storageTags[storageTag]); const config = Config();
const storageLocation = (storageTag && config.fileBase.storageTags[storageTag]);
// absolute paths as-is // absolute paths as-is
if(storageLocation && '/' === storageLocation.charAt(0)) { if(storageLocation && '/' === storageLocation.charAt(0)) {
@ -210,7 +211,7 @@ module.exports = class FileEntry {
} }
// relative to |areaStoragePrefix| // relative to |areaStoragePrefix|
return paths.join(Config.fileBase.areaStoragePrefix, storageLocation || ''); return paths.join(config.fileBase.areaStoragePrefix, storageLocation || '');
} }
get filePath() { get filePath() {

View File

@ -3,7 +3,7 @@
// enigma-bbs // enigma-bbs
const MenuModule = require('./menu_module.js').MenuModule; const MenuModule = require('./menu_module.js').MenuModule;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const DownloadQueue = require('./download_queue.js'); const DownloadQueue = require('./download_queue.js');
@ -56,9 +56,10 @@ exports.getModule = class TransferFileModule extends MenuModule {
// //
// Most options can be set via extraArgs or config block // Most options can be set via extraArgs or config block
// //
const config = Config();
if(options.extraArgs) { if(options.extraArgs) {
if(options.extraArgs.protocol) { if(options.extraArgs.protocol) {
this.protocolConfig = Config.fileTransferProtocols[options.extraArgs.protocol]; this.protocolConfig = config.fileTransferProtocols[options.extraArgs.protocol];
} }
if(options.extraArgs.direction) { if(options.extraArgs.direction) {
@ -78,7 +79,7 @@ exports.getModule = class TransferFileModule extends MenuModule {
} }
} else { } else {
if(this.config.protocol) { if(this.config.protocol) {
this.protocolConfig = Config.fileTransferProtocols[this.config.protocol]; this.protocolConfig = config.fileTransferProtocols[this.config.protocol];
} }
if(this.config.direction) { if(this.config.direction) {
@ -98,7 +99,7 @@ exports.getModule = class TransferFileModule extends MenuModule {
} }
} }
this.protocolConfig = this.protocolConfig || Config.fileTransferProtocols.zmodem8kSz; // try for *something* this.protocolConfig = this.protocolConfig || config.fileTransferProtocols.zmodem8kSz; // try for *something*
this.direction = this.direction || 'send'; this.direction = this.direction || 'send';
this.sendQueue = this.sendQueue || []; this.sendQueue = this.sendQueue || [];

View File

@ -3,7 +3,7 @@
// enigma-bbs // enigma-bbs
const MenuModule = require('./menu_module.js').MenuModule; const MenuModule = require('./menu_module.js').MenuModule;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const ViewController = require('./view_controller.js').ViewController; const ViewController = require('./view_controller.js').ViewController;
@ -129,7 +129,7 @@ exports.getModule = class FileTransferProtocolSelectModule extends MenuModule {
} }
loadAvailProtocols() { loadAvailProtocols() {
this.protocols = _.map(Config.fileTransferProtocols, (protInfo, protocol) => { this.protocols = _.map(Config().fileTransferProtocols, (protInfo, protocol) => {
return { return {
protocol : protocol, protocol : protocol,
name : protInfo.name, name : protInfo.name,

View File

@ -14,7 +14,7 @@ const StatLog = require('./stat_log.js');
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const MessageAreaConfTempSwitcher = require('./mod_mixins.js').MessageAreaConfTempSwitcher; const MessageAreaConfTempSwitcher = require('./mod_mixins.js').MessageAreaConfTempSwitcher;
const { isAnsi, cleanControlCodes, insert } = require('./string_util.js'); const { isAnsi, cleanControlCodes, insert } = require('./string_util.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const { getAddressedToInfo } = require('./mail_util.js'); const { getAddressedToInfo } = require('./mail_util.js');
// deps // deps
@ -335,7 +335,7 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
// to packetAnsiMsgEncoding (generally cp437) as various boards // to packetAnsiMsgEncoding (generally cp437) as various boards
// really don't like ANSI messages in UTF-8 encoding (they should!) // really don't like ANSI messages in UTF-8 encoding (they should!)
// //
msgOpts.meta = { System : { 'explicit_encoding' : Config.scannerTossers.ftn_bso.packetAnsiMsgEncoding || 'cp437' } }; msgOpts.meta = { System : { 'explicit_encoding' : _.get(Config(), 'scannerTossers.ftn_bso.packetAnsiMsgEncoding', 'cp437') } };
msgOpts.message = `${ansi.reset()}${ansi.eraseData(2)}${ansi.goto(1,1)}\r\n${ansi.up()}${msgOpts.message}`; msgOpts.message = `${ansi.reset()}${ansi.eraseData(2)}${ansi.goto(1,1)}\r\n${ansi.up()}${msgOpts.message}`;
} }
} }

View File

@ -1,18 +1,17 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
let Config = require('./config.js').config; const Config = require('./config.js').get;
let Address = require('./ftn_address.js'); const Address = require('./ftn_address.js');
let FNV1a = require('./fnv1a.js'); const FNV1a = require('./fnv1a.js');
const getCleanEnigmaVersion = require('./misc_util.js').getCleanEnigmaVersion; const getCleanEnigmaVersion = require('./misc_util.js').getCleanEnigmaVersion;
let _ = require('lodash'); const _ = require('lodash');
let iconv = require('iconv-lite'); const iconv = require('iconv-lite');
let moment = require('moment'); const moment = require('moment');
//let uuid = require('node-uuid'); const os = require('os');
let os = require('os');
let packageJson = require('../package.json'); const packageJson = require('../package.json');
// :TODO: Remove "Ftn" from most of these -- it's implied in the module // :TODO: Remove "Ftn" from most of these -- it's implied in the module
exports.stringToNullPaddedBuffer = stringToNullPaddedBuffer; exports.stringToNullPaddedBuffer = stringToNullPaddedBuffer;
@ -199,9 +198,10 @@ function getQuotePrefix(name) {
// http://ftsc.org/docs/fts-0004.001 // http://ftsc.org/docs/fts-0004.001
// //
function getOrigin(address) { function getOrigin(address) {
const origin = _.has(Config, 'messageNetworks.originLine') ? const config = Config();
Config.messageNetworks.originLine : const origin = _.has(config, 'messageNetworks.originLine') ?
Config.general.boardName; config.messageNetworks.originLine :
config.general.boardName;
const addrStr = new Address(address).toString('5D'); const addrStr = new Address(address).toString('5D');
return ` * Origin: ${origin} (${addrStr})`; return ` * Origin: ${origin} (${addrStr})`;

View File

@ -10,7 +10,7 @@ const _ = require('lodash');
module.exports = class Log { module.exports = class Log {
static init() { static init() {
const Config = require('./config.js').config; const Config = require('./config.js').get();
const logPath = Config.paths.logs; const logPath = Config.paths.logs;
const err = this.checkLogPath(logPath); const err = this.checkLogPath(logPath);

View File

@ -6,7 +6,7 @@ const theme = require('./theme.js');
const ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
const ViewController = require('./view_controller.js').ViewController; const ViewController = require('./view_controller.js').ViewController;
const menuUtil = require('./menu_util.js'); const menuUtil = require('./menu_util.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const stringFormat = require('../core/string_format.js'); const stringFormat = require('../core/string_format.js');
const MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView; const MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView;
const Errors = require('../core/enig_error.js').Errors; const Errors = require('../core/enig_error.js').Errors;
@ -29,7 +29,7 @@ exports.MenuModule = class MenuModule extends PluginModule {
this.menuMethods = {}; // methods called from @method's this.menuMethods = {}; // methods called from @method's
this.menuConfig.config = this.menuConfig.config || {}; this.menuConfig.config = this.menuConfig.config || {};
this.cls = _.isBoolean(this.menuConfig.options.cls) ? this.menuConfig.options.cls : Config.menus.cls; this.cls = _.isBoolean(this.menuConfig.options.cls) ? this.menuConfig.options.cls : Config().menus.cls;
this.viewControllers = {}; this.viewControllers = {};
} }

View File

@ -4,7 +4,7 @@
// ENiGMA½ // ENiGMA½
var moduleUtil = require('./module_util.js'); var moduleUtil = require('./module_util.js');
var Log = require('./logger.js').log; var Log = require('./logger.js').log;
var Config = require('./config.js').config; var Config = require('./config.js').get;
var asset = require('./asset.js'); var asset = require('./asset.js');
var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
@ -75,7 +75,7 @@ function loadMenu(options, cb) {
const modLoadOpts = { const modLoadOpts = {
name : modSupplied ? modAsset.asset : 'standard_menu', name : modSupplied ? modAsset.asset : 'standard_menu',
path : (!modSupplied || 'systemModule' === modAsset.type) ? __dirname : Config.paths.mods, path : (!modSupplied || 'systemModule' === modAsset.type) ? __dirname : Config().paths.mods,
category : (!modSupplied || 'systemModule' === modAsset.type) ? null : 'mods', category : (!modSupplied || 'systemModule' === modAsset.type) ? null : 'mods',
}; };
@ -189,7 +189,7 @@ function handleAction(client, formData, conf, cb) {
return callModuleMenuMethod( return callModuleMenuMethod(
client, client,
actionAsset, actionAsset,
paths.join(Config.paths.mods, actionAsset.location), paths.join(Config().paths.mods, actionAsset.location),
formData, formData,
conf.extraArgs, conf.extraArgs,
cb); cb);
@ -234,7 +234,7 @@ function handleNext(client, nextSpec, conf, cb) {
case 'method' : case 'method' :
case 'systemMethod' : case 'systemMethod' :
if(_.isString(nextAsset.location)) { if(_.isString(nextAsset.location)) {
return callModuleMenuMethod(client, nextAsset, paths.join(Config.paths.mods, nextAsset.location), {}, extraArgs, cb); return callModuleMenuMethod(client, nextAsset, paths.join(Config().paths.mods, nextAsset.location), {}, extraArgs, cb);
} else if('systemMethod' === nextAsset.type) { } else if('systemMethod' === nextAsset.type) {
// :TODO: see other notes about system_menu_method.js here // :TODO: see other notes about system_menu_method.js here
return callModuleMenuMethod(client, nextAsset, paths.join(__dirname, 'system_menu_method.js'), {}, extraArgs, cb); return callModuleMenuMethod(client, nextAsset, paths.join(__dirname, 'system_menu_method.js'), {}, extraArgs, cb);

View File

@ -3,7 +3,7 @@
// ENiGMA½ // ENiGMA½
const msgDb = require('./database.js').dbs.message; const msgDb = require('./database.js').dbs.message;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Message = require('./message.js'); const Message = require('./message.js');
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
const msgNetRecord = require('./msg_network.js').recordMessage; const msgNetRecord = require('./msg_network.js').recordMessage;
@ -40,7 +40,7 @@ function getAvailableMessageConferences(client, options) {
assert(client || true === options.noClient); assert(client || true === options.noClient);
// perform ACS check per conf & omit system_internal if desired // perform ACS check per conf & omit system_internal if desired
return _.omitBy(Config.messageConferences, (conf, confTag) => { return _.omitBy(Config().messageConferences, (conf, confTag) => {
if(!options.includeSystemInternal && 'system_internal' === confTag) { if(!options.includeSystemInternal && 'system_internal' === confTag) {
return true; return true;
} }
@ -68,8 +68,9 @@ function getAvailableMessageAreasByConfTag(confTag, options) {
// :TODO: confTag === "" then find default // :TODO: confTag === "" then find default
if(_.has(Config.messageConferences, [ confTag, 'areas' ])) { const config = Config();
const areas = Config.messageConferences[confTag].areas; if(_.has(config.messageConferences, [ confTag, 'areas' ])) {
const areas = config.messageConferences[confTag].areas;
if(!options.client || true === options.noAcsCheck) { if(!options.client || true === options.noAcsCheck) {
// everything - no ACS checks // everything - no ACS checks
@ -109,16 +110,17 @@ function getDefaultMessageConferenceTag(client, disableAcsCheck) {
// //
// Note that built in 'system_internal' is always ommited here // Note that built in 'system_internal' is always ommited here
// //
let defaultConf = _.findKey(Config.messageConferences, o => o.default); const config = Config();
let defaultConf = _.findKey(config.messageConferences, o => o.default);
if(defaultConf) { if(defaultConf) {
const conf = Config.messageConferences[defaultConf]; const conf = config.messageConferences[defaultConf];
if(true === disableAcsCheck || client.acs.hasMessageConfRead(conf)) { if(true === disableAcsCheck || client.acs.hasMessageConfRead(conf)) {
return defaultConf; return defaultConf;
} }
} }
// just use anything we can // just use anything we can
defaultConf = _.findKey(Config.messageConferences, (conf, confTag) => { defaultConf = _.findKey(config.messageConferences, (conf, confTag) => {
return 'system_internal' !== confTag && (true === disableAcsCheck || client.acs.hasMessageConfRead(conf)); return 'system_internal' !== confTag && (true === disableAcsCheck || client.acs.hasMessageConfRead(conf));
}); });
@ -135,8 +137,9 @@ function getDefaultMessageAreaTagByConfTag(client, confTag, disableAcsCheck) {
// //
confTag = confTag || getDefaultMessageConferenceTag(client); confTag = confTag || getDefaultMessageConferenceTag(client);
if(confTag && _.has(Config.messageConferences, [ confTag, 'areas' ])) { const config = Config();
const areaPool = Config.messageConferences[confTag].areas; if(confTag && _.has(config.messageConferences, [ confTag, 'areas' ])) {
const areaPool = config.messageConferences[confTag].areas;
let defaultArea = _.findKey(areaPool, o => o.default); let defaultArea = _.findKey(areaPool, o => o.default);
if(defaultArea) { if(defaultArea) {
const area = areaPool[defaultArea]; const area = areaPool[defaultArea];
@ -154,18 +157,18 @@ function getDefaultMessageAreaTagByConfTag(client, confTag, disableAcsCheck) {
} }
function getMessageConferenceByTag(confTag) { function getMessageConferenceByTag(confTag) {
return Config.messageConferences[confTag]; return Config().messageConferences[confTag];
} }
function getMessageConfTagByAreaTag(areaTag) { function getMessageConfTagByAreaTag(areaTag) {
const confs = Config.messageConferences; const confs = Config().messageConferences;
return Object.keys(confs).find( (confTag) => { return Object.keys(confs).find( (confTag) => {
return _.has(confs, [ confTag, 'areas', areaTag]); return _.has(confs, [ confTag, 'areas', areaTag]);
}); });
} }
function getMessageAreaByTag(areaTag, optionalConfTag) { function getMessageAreaByTag(areaTag, optionalConfTag) {
const confs = Config.messageConferences; const confs = Config().messageConferences;
// :TODO: this could be cached // :TODO: this could be cached
if(_.isString(optionalConfTag)) { if(_.isString(optionalConfTag)) {
@ -535,10 +538,11 @@ function trimMessageAreasScheduledEvent(args, cb) {
let areaInfos = []; let areaInfos = [];
// determine maxMessages & maxAgeDays per area // determine maxMessages & maxAgeDays per area
const config = Config();
areaTags.forEach(areaTag => { areaTags.forEach(areaTag => {
let maxMessages = Config.messageAreaDefaults.maxMessages; let maxMessages = config.messageAreaDefaults.maxMessages;
let maxAgeDays = Config.messageAreaDefaults.maxAgeDays; let maxAgeDays = config.messageAreaDefaults.maxAgeDays;
const area = getMessageAreaByTag(areaTag); // note: we don't know the conf here const area = getMessageAreaByTag(areaTag); // note: we don't know the conf here
if(area) { if(area) {

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
// deps // deps
const fs = require('graceful-fs'); const fs = require('graceful-fs');
@ -64,7 +64,7 @@ function loadModuleEx(options, cb) {
} }
function loadModule(name, category, cb) { function loadModule(name, category, cb) {
const path = Config.paths[category]; const path = Config().paths[category];
if(!_.isString(path)) { if(!_.isString(path)) {
return cb(new Error(`Not sure where to look for "${name}" of category "${category}"`)); return cb(new Error(`Not sure where to look for "${name}" of category "${category}"`));
@ -77,7 +77,7 @@ function loadModule(name, category, cb) {
function loadModulesForCategory(category, iterator, complete) { function loadModulesForCategory(category, iterator, complete) {
fs.readdir(Config.paths[category], (err, files) => { fs.readdir(Config().paths[category], (err, files) => {
if(err) { if(err) {
return iterator(err); return iterator(err);
} }
@ -100,10 +100,11 @@ function loadModulesForCategory(category, iterator, complete) {
} }
function getModulePaths() { function getModulePaths() {
const config = Config();
return [ return [
Config.paths.mods, config.paths.mods,
Config.paths.loginServers, config.paths.loginServers,
Config.paths.contentServers, config.paths.contentServers,
Config.paths.scannerTossers, config.paths.scannerTossers,
]; ];
} }

View File

@ -6,7 +6,7 @@ const MenuModule = require('./menu_module.js').MenuModule;
const User = require('./user.js'); const User = require('./user.js');
const theme = require('./theme.js'); const theme = require('./theme.js');
const login = require('./system_menu_method.js').login; const login = require('./system_menu_method.js').login;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const messageArea = require('./message_area.js'); const messageArea = require('./message_area.js');
exports.moduleInfo = { exports.moduleInfo = {
@ -62,6 +62,7 @@ exports.getModule = class NewUserAppModule extends MenuModule {
// //
submitApplication : function(formData, extraArgs, cb) { submitApplication : function(formData, extraArgs, cb) {
const newUser = new User(); const newUser = new User();
const config = Config();
newUser.username = formData.value.username; newUser.username = formData.value.username;
@ -95,10 +96,10 @@ exports.getModule = class NewUserAppModule extends MenuModule {
// :TODO: should probably have a place to create defaults/etc. // :TODO: should probably have a place to create defaults/etc.
}; };
if('*' === Config.defaults.theme) { if('*' === config.defaults.theme) {
newUser.properties.theme_id = theme.getRandomTheme(); newUser.properties.theme_id = theme.getRandomTheme();
} else { } else {
newUser.properties.theme_id = Config.defaults.theme; newUser.properties.theme_id = config.defaults.theme;
} }
// :TODO: User.create() should validate email uniqueness! // :TODO: User.create() should validate email uniqueness!
@ -118,7 +119,7 @@ exports.getModule = class NewUserAppModule extends MenuModule {
// Cache SysOp information now // Cache SysOp information now
// :TODO: Similar to bbs.js. DRY // :TODO: Similar to bbs.js. DRY
if(newUser.isSysOp()) { if(newUser.isSysOp()) {
Config.general.sysOp = { config.general.sysOp = {
username : formData.value.username, username : formData.value.username,
properties : newUser.properties, properties : newUser.properties,
}; };

View File

@ -333,7 +333,7 @@ function importAreas() {
}, },
function validateAndCollectInput(callback) { function validateAndCollectInput(callback) {
const msgArea = require('../../core/message_area.js'); const msgArea = require('../../core/message_area.js');
const Config = require('../../core/config.js').config; const sysConfig = require('../../core/config.js').get();
let msgConfs = msgArea.getSortedAvailMessageConferences(null, { noClient : true } ); let msgConfs = msgArea.getSortedAvailMessageConferences(null, { noClient : true } );
if(!msgConfs) { if(!msgConfs) {
@ -355,8 +355,8 @@ function importAreas() {
} }
let existingNetworkNames = []; let existingNetworkNames = [];
if(_.has(Config, 'messageNetworks.ftn.networks')) { if(_.has(sysConfig, 'messageNetworks.ftn.networks')) {
existingNetworkNames = Object.keys(Config.messageNetworks.ftn.networks); existingNetworkNames = Object.keys(sysConfig.messageNetworks.ftn.networks);
} }
if(0 === existingNetworkNames.length) { if(0 === existingNetworkNames.length) {
@ -407,9 +407,9 @@ function importAreas() {
}); });
}, },
function confirmWithUser(callback) { function confirmWithUser(callback) {
const Config = require('../../core/config.js').config; const sysConfig = require('../../core/config.js').get();
console.info(`Importing the following for "${confTag}" - (${Config.messageConferences[confTag].name} - ${Config.messageConferences[confTag].desc})`); console.info(`Importing the following for "${confTag}" - (${sysConfig.messageConferences[confTag].name} - ${sysConfig.messageConferences[confTag].desc})`);
importEntries.forEach(ie => { importEntries.forEach(ie => {
console.info(` ${ie.ftnTag} - ${ie.name}`); console.info(` ${ie.ftnTag} - ${ie.name}`);
}); });

View File

@ -390,10 +390,10 @@ function displayFileAreaInfo() {
return initConfigAndDatabases(callback); return initConfigAndDatabases(callback);
}, },
function dumpInfo(callback) { function dumpInfo(callback) {
const Config = require('../../core/config.js').config; const sysConfig = require('../../core/config.js').get();
let suppliedAreas = argv._.slice(2); let suppliedAreas = argv._.slice(2);
if(!suppliedAreas || 0 === suppliedAreas.length) { if(!suppliedAreas || 0 === suppliedAreas.length) {
suppliedAreas = _.map(Config.fileBase.areas, (areaInfo, areaTag) => areaTag); suppliedAreas = _.map(sysConfig.fileBase.areas, (areaInfo, areaTag) => areaTag);
} }
const areaAndStorageInfo = getAreaAndStorage(suppliedAreas); const areaAndStorageInfo = getAreaAndStorage(suppliedAreas);

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
const getMessageAreaByTag = require('./message_area.js').getMessageAreaByTag; const getMessageAreaByTag = require('./message_area.js').getMessageAreaByTag;
const getMessageConferenceByTag = require('./message_area.js').getMessageConferenceByTag; const getMessageConferenceByTag = require('./message_area.js').getMessageConferenceByTag;
@ -56,7 +56,7 @@ const PREDEFINED_MCI_GENERATORS = {
// //
// Board // Board
// //
BN : function boardName() { return Config.general.boardName; }, BN : function boardName() { return Config().general.boardName; },
// ENiGMA // ENiGMA
VL : function versionLabel() { return 'ENiGMA½ v' + packageJson.version; }, VL : function versionLabel() { return 'ENiGMA½ v' + packageJson.version; },

View File

@ -3,7 +3,7 @@
// ENiGMA½ // ENiGMA½
const MessageScanTossModule = require('../msg_scan_toss_module.js').MessageScanTossModule; const MessageScanTossModule = require('../msg_scan_toss_module.js').MessageScanTossModule;
const Config = require('../config.js').config; const Config = require('../config.js').get;
const ftnMailPacket = require('../ftn_mail_packet.js'); const ftnMailPacket = require('../ftn_mail_packet.js');
const ftnUtil = require('../ftn_util.js'); const ftnUtil = require('../ftn_util.js');
const Address = require('../ftn_address.js'); const Address = require('../ftn_address.js');
@ -60,8 +60,9 @@ function FTNMessageScanTossModule() {
this.archUtil = ArchiveUtil.getInstance(); this.archUtil = ArchiveUtil.getInstance();
if(_.has(Config, 'scannerTossers.ftn_bso')) { const config = Config();
this.moduleConfig = Config.scannerTossers.ftn_bso; if(_.has(config, 'scannerTossers.ftn_bso')) {
this.moduleConfig = config.scannerTossers.ftn_bso;
} }
this.getDefaultNetworkName = function() { this.getDefaultNetworkName = function() {
@ -69,19 +70,20 @@ function FTNMessageScanTossModule() {
return this.moduleConfig.defaultNetwork.toLowerCase(); return this.moduleConfig.defaultNetwork.toLowerCase();
} }
const networkNames = Object.keys(Config.messageNetworks.ftn.networks); const networkNames = Object.keys(config.messageNetworks.ftn.networks);
if(1 === networkNames.length) { if(1 === networkNames.length) {
return networkNames[0].toLowerCase(); return networkNames[0].toLowerCase();
} }
}; };
this.getDefaultZone = function(networkName) { this.getDefaultZone = function(networkName) {
if(_.isNumber(Config.messageNetworks.ftn.networks[networkName].defaultZone)) { const config = Config();
return Config.messageNetworks.ftn.networks[networkName].defaultZone; if(_.isNumber(config.messageNetworks.ftn.networks[networkName].defaultZone)) {
return config.messageNetworks.ftn.networks[networkName].defaultZone;
} }
// non-explicit: default to local address zone // non-explicit: default to local address zone
const networkLocalAddress = Config.messageNetworks.ftn.networks[networkName].localAddress; const networkLocalAddress = config.messageNetworks.ftn.networks[networkName].localAddress;
if(networkLocalAddress) { if(networkLocalAddress) {
const addr = Address.fromString(networkLocalAddress); const addr = Address.fromString(networkLocalAddress);
return addr.zone; return addr.zone;
@ -96,14 +98,14 @@ function FTNMessageScanTossModule() {
*/ */
this.getNetworkNameByAddress = function(remoteAddress) { this.getNetworkNameByAddress = function(remoteAddress) {
return _.findKey(Config.messageNetworks.ftn.networks, network => { return _.findKey(Config().messageNetworks.ftn.networks, network => {
const localAddress = Address.fromString(network.localAddress); const localAddress = Address.fromString(network.localAddress);
return !_.isUndefined(localAddress) && localAddress.isEqual(remoteAddress); return !_.isUndefined(localAddress) && localAddress.isEqual(remoteAddress);
}); });
}; };
this.getNetworkNameByAddressPattern = function(remoteAddressPattern) { this.getNetworkNameByAddressPattern = function(remoteAddressPattern) {
return _.findKey(Config.messageNetworks.ftn.networks, network => { return _.findKey(Config().messageNetworks.ftn.networks, network => {
const localAddress = Address.fromString(network.localAddress); const localAddress = Address.fromString(network.localAddress);
return !_.isUndefined(localAddress) && localAddress.isPatternMatch(remoteAddressPattern); return !_.isUndefined(localAddress) && localAddress.isPatternMatch(remoteAddressPattern);
}); });
@ -111,7 +113,7 @@ function FTNMessageScanTossModule() {
this.getLocalAreaTagByFtnAreaTag = function(ftnAreaTag) { this.getLocalAreaTagByFtnAreaTag = function(ftnAreaTag) {
ftnAreaTag = ftnAreaTag.toUpperCase(); // always compare upper ftnAreaTag = ftnAreaTag.toUpperCase(); // always compare upper
return _.findKey(Config.messageNetworks.ftn.areas, areaConf => { return _.findKey(Config().messageNetworks.ftn.areas, areaConf => {
return areaConf.tag.toUpperCase() === ftnAreaTag; return areaConf.tag.toUpperCase() === ftnAreaTag;
}); });
}; };
@ -357,6 +359,7 @@ function FTNMessageScanTossModule() {
let ftnAttribute = ftnMailPacket.Packet.Attribute.Local; // message from our system let ftnAttribute = ftnMailPacket.Packet.Attribute.Local; // message from our system
const config = Config();
if(self.isNetMailMessage(message)) { if(self.isNetMailMessage(message)) {
// //
// Set route and message destination properties -- they may differ // Set route and message destination properties -- they may differ
@ -405,14 +408,14 @@ function FTNMessageScanTossModule() {
// //
// EchoMail requires some additional properties & kludges // EchoMail requires some additional properties & kludges
// //
message.meta.FtnProperty.ftn_area = Config.messageNetworks.ftn.areas[message.areaTag].tag; message.meta.FtnProperty.ftn_area = config.messageNetworks.ftn.areas[message.areaTag].tag;
// //
// When exporting messages, we should create/update SEEN-BY // When exporting messages, we should create/update SEEN-BY
// with remote address(s) we are exporting to. // with remote address(s) we are exporting to.
// //
const seenByAdditions = const seenByAdditions =
[ `${localAddress.net}/${localAddress.node}` ].concat(Config.messageNetworks.ftn.areas[message.areaTag].uplinks); [ `${localAddress.net}/${localAddress.node}` ].concat(config.messageNetworks.ftn.areas[message.areaTag].uplinks);
message.meta.FtnProperty.ftn_seen_by = message.meta.FtnProperty.ftn_seen_by =
ftnUtil.getUpdatedSeenByEntries(message.meta.FtnProperty.ftn_seen_by, seenByAdditions); ftnUtil.getUpdatedSeenByEntries(message.meta.FtnProperty.ftn_seen_by, seenByAdditions);
@ -453,7 +456,7 @@ function FTNMessageScanTossModule() {
// Determine CHRS and actual internal encoding name. If the message has an // Determine CHRS and actual internal encoding name. If the message has an
// explicit encoding set, use it. Otherwise, try to preserve any CHRS/encoding already set. // explicit encoding set, use it. Otherwise, try to preserve any CHRS/encoding already set.
// //
let encoding = options.nodeConfig.encoding || Config.scannerTossers.ftn_bso.packetMsgEncoding || 'utf8'; let encoding = options.nodeConfig.encoding || config.scannerTossers.ftn_bso.packetMsgEncoding || 'utf8';
const explicitEncoding = _.get(message.meta, 'System.explicit_encoding'); const explicitEncoding = _.get(message.meta, 'System.explicit_encoding');
if(explicitEncoding) { if(explicitEncoding) {
encoding = explicitEncoding; encoding = explicitEncoding;
@ -513,7 +516,7 @@ function FTNMessageScanTossModule() {
this.hasValidConfiguration = function() { this.hasValidConfiguration = function() {
if(!_.has(this, 'moduleConfig.nodes') || !_.has(Config, 'messageNetworks.ftn.areas')) { if(!_.has(this, 'moduleConfig.nodes') || !_.has(Config(), 'messageNetworks.ftn.areas')) {
return false; return false;
} }
@ -820,7 +823,7 @@ function FTNMessageScanTossModule() {
// //
// Route full|wildcard -> full adddress/network lookup // Route full|wildcard -> full adddress/network lookup
// //
const routes = _.get(Config, 'scannerTossers.ftn_bso.netMail.routes'); const routes = _.get(Config(), 'scannerTossers.ftn_bso.netMail.routes');
if(!routes) { if(!routes) {
return; return;
} }
@ -860,7 +863,7 @@ function FTNMessageScanTossModule() {
const config = _.find(this.moduleConfig.nodes, (node, nodeAddrWildcard) => { const config = _.find(this.moduleConfig.nodes, (node, nodeAddrWildcard) => {
return routeAddress.isPatternMatch(nodeAddrWildcard); return routeAddress.isPatternMatch(nodeAddrWildcard);
}) || { packetType : '2+', encoding : Config.scannerTossers.ftn_bso.packetMsgEncoding }; }) || { packetType : '2+', encoding : Config().scannerTossers.ftn_bso.packetMsgEncoding };
// we should never be failing here; we may just be using defaults. // we should never be failing here; we may just be using defaults.
return cb( return cb(
@ -899,7 +902,7 @@ function FTNMessageScanTossModule() {
exportOpts.destAddress = dstAddr; exportOpts.destAddress = dstAddr;
exportOpts.routeAddress = routeInfo.routeAddress; exportOpts.routeAddress = routeInfo.routeAddress;
exportOpts.fileCase = routeInfo.config.fileCase || 'lower'; exportOpts.fileCase = routeInfo.config.fileCase || 'lower';
exportOpts.network = Config.messageNetworks.ftn.networks[routeInfo.networkName]; exportOpts.network = Config().messageNetworks.ftn.networks[routeInfo.networkName];
exportOpts.networkName = routeInfo.networkName; exportOpts.networkName = routeInfo.networkName;
exportOpts.outgoingDir = self.getOutgoingEchoMailPacketDir(exportOpts.networkName, exportOpts.destAddress); exportOpts.outgoingDir = self.getOutgoingEchoMailPacketDir(exportOpts.networkName, exportOpts.destAddress);
exportOpts.exportType = self.getExportType(routeInfo.config); exportOpts.exportType = self.getExportType(routeInfo.config);
@ -966,6 +969,7 @@ function FTNMessageScanTossModule() {
}; };
this.exportEchoMailMessagesToUplinks = function(messageUuids, areaConfig, cb) { this.exportEchoMailMessagesToUplinks = function(messageUuids, areaConfig, cb) {
const config = Config();
async.each(areaConfig.uplinks, (uplink, nextUplink) => { async.each(areaConfig.uplinks, (uplink, nextUplink) => {
const nodeConfig = self.getNodeConfigByAddress(uplink); const nodeConfig = self.getNodeConfigByAddress(uplink);
if(!nodeConfig) { if(!nodeConfig) {
@ -974,7 +978,7 @@ function FTNMessageScanTossModule() {
const exportOpts = { const exportOpts = {
nodeConfig, nodeConfig,
network : Config.messageNetworks.ftn.networks[areaConfig.network], network : config.messageNetworks.ftn.networks[areaConfig.network],
destAddress : Address.fromString(uplink), destAddress : Address.fromString(uplink),
networkName : areaConfig.network, networkName : areaConfig.network,
fileCase : nodeConfig.fileCase || 'lower', fileCase : nodeConfig.fileCase || 'lower',
@ -1119,7 +1123,7 @@ function FTNMessageScanTossModule() {
this.getLocalUserNameFromAlias = function(lookup) { this.getLocalUserNameFromAlias = function(lookup) {
lookup = lookup.toLowerCase(); lookup = lookup.toLowerCase();
const aliases = _.get(Config, 'messageNetworks.ftn.netMail.aliases'); const aliases = _.get(Config(), 'messageNetworks.ftn.netMail.aliases');
if(!aliases) { if(!aliases) {
return lookup; // keep orig return lookup; // keep orig
} }
@ -1195,7 +1199,7 @@ function FTNMessageScanTossModule() {
// a random UUID. Otherwise, don't assign the UUID just yet. It will be // a random UUID. Otherwise, don't assign the UUID just yet. It will be
// generated at persist() time and should be consistent across import/exports // generated at persist() time and should be consistent across import/exports
// //
if(true === _.get(Config, [ 'messageNetworks', 'ftn', 'areas', config.localAreaTag, 'allowDupes' ], false)) { if(true === _.get(Config(), [ 'messageNetworks', 'ftn', 'areas', config.localAreaTag, 'allowDupes' ], false)) {
// just generate a UUID & therefor always allow for dupes // just generate a UUID & therefor always allow for dupes
message.uuid = uuidV4(); message.uuid = uuidV4();
} }
@ -1650,7 +1654,8 @@ function FTNMessageScanTossModule() {
}; };
this.getLocalAreaTagsForTic = function() { this.getLocalAreaTagsForTic = function() {
return _.union(Object.keys(Config.scannerTossers.ftn_bso.ticAreas || {} ), Object.keys(Config.fileBase.areas)); const config = Config();
return _.union(Object.keys(config.scannerTossers.ftn_bso.ticAreas || {} ), Object.keys(config.fileBase.areas));
}; };
this.processSingleTicFile = function(ticFileInfo, cb) { this.processSingleTicFile = function(ticFileInfo, cb) {
@ -1659,9 +1664,10 @@ function FTNMessageScanTossModule() {
async.waterfall( async.waterfall(
[ [
function generalValidation(callback) { function generalValidation(callback) {
const sysConfig = Config();
const config = { const config = {
nodes : Config.scannerTossers.ftn_bso.nodes, nodes : sysConfig.scannerTossers.ftn_bso.nodes,
defaultPassword : Config.scannerTossers.ftn_bso.tic.password, defaultPassword : sysConfig.scannerTossers.ftn_bso.tic.password,
localAreaTags : self.getLocalAreaTagsForTic(), localAreaTags : self.getLocalAreaTagsForTic(),
}; };
@ -1672,7 +1678,7 @@ function FTNMessageScanTossModule() {
} }
// We may need to map |localAreaTag| back to real areaTag if it's a mapping/alias // We may need to map |localAreaTag| back to real areaTag if it's a mapping/alias
const mappedLocalAreaTag = _.get(Config.scannerTossers.ftn_bso, [ 'ticAreas', localInfo.areaTag ]); const mappedLocalAreaTag = _.get(Config().scannerTossers.ftn_bso, [ 'ticAreas', localInfo.areaTag ]);
if(mappedLocalAreaTag) { if(mappedLocalAreaTag) {
if(_.isString(mappedLocalAreaTag.areaTag)) { if(_.isString(mappedLocalAreaTag.areaTag)) {
@ -1699,7 +1705,7 @@ function FTNMessageScanTossModule() {
// Lastly, we will only replace if the item is in the same/specified area // Lastly, we will only replace if the item is in the same/specified area
// and that come from the same origin as a previous entry. // and that come from the same origin as a previous entry.
// //
const allowReplace = _.get(Config.scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'allowReplace' ], Config.scannerTossers.ftn_bso.tic.allowReplace); const allowReplace = _.get(Config().scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'allowReplace' ], Config().scannerTossers.ftn_bso.tic.allowReplace);
const replaces = ticFileInfo.getAsString('Replaces'); const replaces = ticFileInfo.getAsString('Replaces');
if(!allowReplace || !replaces) { if(!allowReplace || !replaces) {
@ -1755,7 +1761,7 @@ function FTNMessageScanTossModule() {
short_file_name : ticFileInfo.getAsString('File').toUpperCase(), // upper to ensure no case issues later; this should be a DOS 8.3 name short_file_name : ticFileInfo.getAsString('File').toUpperCase(), // upper to ensure no case issues later; this should be a DOS 8.3 name
tic_origin : ticFileInfo.getAsString('Origin'), tic_origin : ticFileInfo.getAsString('Origin'),
tic_desc : ticFileInfo.getAsString('Desc'), tic_desc : ticFileInfo.getAsString('Desc'),
upload_by_username : _.get(Config.scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'uploadBy' ], Config.scannerTossers.ftn_bso.tic.uploadBy), upload_by_username : _.get(Config().scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'uploadBy' ], Config().scannerTossers.ftn_bso.tic.uploadBy),
} }
}; };
@ -1769,7 +1775,7 @@ function FTNMessageScanTossModule() {
// //
const hashTags = const hashTags =
localInfo.hashTags || localInfo.hashTags ||
_.get(Config.scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'hashTags' ] ); // catch-all*/ _.get(Config().scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'hashTags' ] ); // catch-all*/
if(hashTags) { if(hashTags) {
scanOpts.hashTags = new Set(hashTags.split(/[\s,]+/)); scanOpts.hashTags = new Set(hashTags.split(/[\s,]+/));
@ -1817,8 +1823,8 @@ function FTNMessageScanTossModule() {
// We will still fallback as needed from <priority1> -> <priority2> -> <fromFileName> // We will still fallback as needed from <priority1> -> <priority2> -> <fromFileName>
// //
const descPriority = _.get( const descPriority = _.get(
Config.scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'descPriority' ], Config().scannerTossers.ftn_bso.nodes, [ localInfo.node, 'tic', 'descPriority' ],
Config.scannerTossers.ftn_bso.tic.descPriority Config().scannerTossers.ftn_bso.tic.descPriority
); );
if('tic' === descPriority) { if('tic' === descPriority) {
@ -1926,11 +1932,12 @@ function FTNMessageScanTossModule() {
; ;
// we shouldn't, but be sure we don't try to pick up private mail here // we shouldn't, but be sure we don't try to pick up private mail here
const areaTags = Object.keys(Config.messageNetworks.ftn.areas) const config = Config();
const areaTags = Object.keys(config.messageNetworks.ftn.areas)
.filter(areaTag => Message.WellKnownAreaTags.Private !== areaTag); .filter(areaTag => Message.WellKnownAreaTags.Private !== areaTag);
async.each(areaTags, (areaTag, nextArea) => { async.each(areaTags, (areaTag, nextArea) => {
const areaConfig = Config.messageNetworks.ftn.areas[areaTag]; const areaConfig = config.messageNetworks.ftn.areas[areaTag];
if(!this.isAreaConfigValid(areaConfig)) { if(!this.isAreaConfigValid(areaConfig)) {
return nextArea(); return nextArea();
} }
@ -2336,7 +2343,7 @@ FTNMessageScanTossModule.prototype.record = function(message) {
} else if(message.areaTag) { } else if(message.areaTag) {
Object.assign(info, { type : 'EchoMail' } ); Object.assign(info, { type : 'EchoMail' } );
const areaConfig = Config.messageNetworks.ftn.areas[message.areaTag]; const areaConfig = Config().messageNetworks.ftn.areas[message.areaTag];
if(!this.isAreaConfigValid(areaConfig)) { if(!this.isAreaConfigValid(areaConfig)) {
return; return;
} }

View File

@ -4,7 +4,7 @@
// ENiGMA½ // ENiGMA½
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const { ServerModule } = require('../../server_module.js'); const { ServerModule } = require('../../server_module.js');
const Config = require('../../config.js').config; const Config = require('../../config.js').get;
const { const {
splitTextAtTerms, splitTextAtTerms,
isAnsi, isAnsi,
@ -73,8 +73,9 @@ exports.getModule = class GopherModule extends ServerModule {
return; return;
} }
this.publicHostname = Config.contentServers.gopher.publicHostname; const config = Config();
this.publicPort = Config.contentServers.gopher.publicPort; this.publicHostname = config.contentServers.gopher.publicHostname;
this.publicPort = config.contentServers.gopher.publicPort;
this.addRoute(/^\/?\r\n$/, this.defaultGenerator); this.addRoute(/^\/?\r\n$/, this.defaultGenerator);
this.addRoute(/^\/msgarea(\/[a-z0-9_-]+(\/[a-z0-9_-]+)?(\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(_raw)?)?)?\/?\r\n$/, this.messageAreaGenerator); this.addRoute(/^\/msgarea(\/[a-z0-9_-]+(\/[a-z0-9_-]+)?(\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(_raw)?)?)?\/?\r\n$/, this.messageAreaGenerator);
@ -99,9 +100,10 @@ exports.getModule = class GopherModule extends ServerModule {
return true; // nothing to do, but not an error return true; // nothing to do, but not an error
} }
const port = parseInt(Config.contentServers.gopher.port); const config = Config();
const port = parseInt(config.contentServers.gopher.port);
if(isNaN(port)) { if(isNaN(port)) {
this.log.warn( { port : Config.contentServers.gopher.port, server : ModuleInfo.name }, 'Invalid port' ); this.log.warn( { port : config.contentServers.gopher.port, server : ModuleInfo.name }, 'Invalid port' );
return false; return false;
} }
@ -109,13 +111,14 @@ exports.getModule = class GopherModule extends ServerModule {
} }
get enabled() { get enabled() {
return _.get(Config, 'contentServers.gopher.enabled', false) && this.isConfigured(); return _.get(Config(), 'contentServers.gopher.enabled', false) && this.isConfigured();
} }
isConfigured() { isConfigured() {
// public hostname & port must be set; responses contain them! // public hostname & port must be set; responses contain them!
return _.isString(_.get(Config, 'contentServers.gopher.publicHostname')) && const config = Config();
_.isNumber(_.get(Config, 'contentServers.gopher.publicPort')); return _.isString(_.get(config, 'contentServers.gopher.publicHostname')) &&
_.isNumber(_.get(config, 'contentServers.gopher.publicPort'));
} }
addRoute(selectorRegExp, generatorHandler) { addRoute(selectorRegExp, generatorHandler) {
@ -155,7 +158,7 @@ exports.getModule = class GopherModule extends ServerModule {
defaultGenerator(selectorMatch, cb) { defaultGenerator(selectorMatch, cb) {
this.log.trace( { selector : selectorMatch[0] }, 'Serving default content'); this.log.trace( { selector : selectorMatch[0] }, 'Serving default content');
let bannerFile = _.get(Config, 'contentServers.gopher.bannerFile', 'startup_banner.asc'); let bannerFile = _.get(Config(), 'contentServers.gopher.bannerFile', 'startup_banner.asc');
bannerFile = paths.isAbsolute(bannerFile) ? bannerFile : paths.join(__dirname, '../../../misc', bannerFile); bannerFile = paths.isAbsolute(bannerFile) ? bannerFile : paths.join(__dirname, '../../../misc', bannerFile);
fs.readFile(bannerFile, 'utf8', (err, banner) => { fs.readFile(bannerFile, 'utf8', (err, banner) => {
if(err) { if(err) {
@ -174,7 +177,7 @@ exports.getModule = class GopherModule extends ServerModule {
} }
isAreaAndConfExposed(confTag, areaTag) { isAreaAndConfExposed(confTag, areaTag) {
const conf = _.get(Config, [ 'contentServers', 'gopher', 'messageConferences', confTag ]); const conf = _.get(Config(), [ 'contentServers', 'gopher', 'messageConferences', confTag ]);
return Array.isArray(conf) && conf.includes(areaTag); return Array.isArray(conf) && conf.includes(areaTag);
} }
@ -281,13 +284,14 @@ ${msgBody}
}); });
} else if(selectorMatch[1]) { } else if(selectorMatch[1]) {
// list areas in conf // list areas in conf
const sysConfig = Config();
const confTag = selectorMatch[1].replace(/\r\n|\//g, ''); const confTag = selectorMatch[1].replace(/\r\n|\//g, '');
const conf = _.get(Config, [ 'contentServers', 'gopher', 'messageConferences', confTag ]) && getMessageConferenceByTag(confTag); const conf = _.get(sysConfig, [ 'contentServers', 'gopher', 'messageConferences', confTag ]) && getMessageConferenceByTag(confTag);
if(!conf) { if(!conf) {
return this.notFoundGenerator(selectorMatch, cb); return this.notFoundGenerator(selectorMatch, cb);
} }
const areas = _.get(Config, [ 'contentServers', 'gopher', 'messageConferences', confTag ], {}) const areas = _.get(sysConfig, [ 'contentServers', 'gopher', 'messageConferences', confTag ], {})
.map(areaTag => Object.assign( { areaTag }, getMessageAreaByTag(areaTag))) .map(areaTag => Object.assign( { areaTag }, getMessageAreaByTag(areaTag)))
.filter(area => area && !Message.isPrivateAreaTag(area.areaTag)); .filter(area => area && !Message.isPrivateAreaTag(area.areaTag));
@ -307,7 +311,7 @@ ${msgBody}
return cb(response); return cb(response);
} else { } else {
// message area base (list confs) // message area base (list confs)
const confs = Object.keys(_.get(Config, 'contentServers.gopher.messageConferences', {})) const confs = Object.keys(_.get(Config(), 'contentServers.gopher.messageConferences', {}))
.map(confTag => Object.assign( { confTag }, getMessageConferenceByTag(confTag))) .map(confTag => Object.assign( { confTag }, getMessageConferenceByTag(confTag)))
.filter(conf => conf); // remove any baddies .filter(conf => conf); // remove any baddies

View File

@ -4,7 +4,7 @@
// ENiGMA½ // ENiGMA½
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const ServerModule = require('../../server_module.js').ServerModule; const ServerModule = require('../../server_module.js').ServerModule;
const Config = require('../../config.js').config; const Config = require('../../config.js').get;
// deps // deps
const http = require('http'); const http = require('http');
@ -55,12 +55,13 @@ exports.getModule = class WebServerModule extends ServerModule {
constructor() { constructor() {
super(); super();
this.enableHttp = Config.contentServers.web.http.enabled || false; const config = Config();
this.enableHttps = Config.contentServers.web.https.enabled || false; this.enableHttp = config.contentServers.web.http.enabled || false;
this.enableHttps = config.contentServers.web.https.enabled || false;
this.routes = {}; this.routes = {};
if(this.isEnabled() && Config.contentServers.web.staticRoot) { if(this.isEnabled() && config.contentServers.web.staticRoot) {
this.addRoute({ this.addRoute({
method : 'GET', method : 'GET',
path : '/static/.*$', path : '/static/.*$',
@ -77,25 +78,26 @@ exports.getModule = class WebServerModule extends ServerModule {
// Prefer HTTPS over HTTP. Be explicit about the port // Prefer HTTPS over HTTP. Be explicit about the port
// only if non-standard. Allow users to override full prefix in config. // only if non-standard. Allow users to override full prefix in config.
// //
if(_.isString(Config.contentServers.web.overrideUrlPrefix)) { const config = Config();
return `${Config.contentServers.web.overrideUrlPrefix}${pathAndQuery}`; if(_.isString(config.contentServers.web.overrideUrlPrefix)) {
return `${config.contentServers.web.overrideUrlPrefix}${pathAndQuery}`;
} }
let schema; let schema;
let port; let port;
if(Config.contentServers.web.https.enabled) { if(config.contentServers.web.https.enabled) {
schema = 'https://'; schema = 'https://';
port = (443 === Config.contentServers.web.https.port) ? port = (443 === config.contentServers.web.https.port) ?
'' : '' :
`:${Config.contentServers.web.https.port}`; `:${config.contentServers.web.https.port}`;
} else { } else {
schema = 'http://'; schema = 'http://';
port = (80 === Config.contentServers.web.http.port) ? port = (80 === config.contentServers.web.http.port) ?
'' : '' :
`:${Config.contentServers.web.http.port}`; `:${config.contentServers.web.http.port}`;
} }
return `${schema}${Config.contentServers.web.domain}${port}${pathAndQuery}`; return `${schema}${config.contentServers.web.domain}${port}${pathAndQuery}`;
} }
isEnabled() { isEnabled() {
@ -107,14 +109,15 @@ exports.getModule = class WebServerModule extends ServerModule {
this.httpServer = http.createServer( (req, resp) => this.routeRequest(req, resp) ); this.httpServer = http.createServer( (req, resp) => this.routeRequest(req, resp) );
} }
const config = Config();
if(this.enableHttps) { if(this.enableHttps) {
const options = { const options = {
cert : fs.readFileSync(Config.contentServers.web.https.certPem), cert : fs.readFileSync(config.contentServers.web.https.certPem),
key : fs.readFileSync(Config.contentServers.web.https.keyPem), key : fs.readFileSync(config.contentServers.web.https.keyPem),
}; };
// additional options // additional options
Object.assign(options, Config.contentServers.web.https.options || {} ); Object.assign(options, config.contentServers.web.https.options || {} );
this.httpsServer = https.createServer(options, (req, resp) => this.routeRequest(req, resp) ); this.httpsServer = https.createServer(options, (req, resp) => this.routeRequest(req, resp) );
} }
@ -123,13 +126,14 @@ exports.getModule = class WebServerModule extends ServerModule {
listen() { listen() {
let ok = true; let ok = true;
const config = Config();
[ 'http', 'https' ].forEach(service => { [ 'http', 'https' ].forEach(service => {
const name = `${service}Server`; const name = `${service}Server`;
if(this[name]) { if(this[name]) {
const port = parseInt(Config.contentServers.web[service].port); const port = parseInt(config.contentServers.web[service].port);
if(isNaN(port)) { if(isNaN(port)) {
ok = false; ok = false;
return Log.warn( { port : Config.contentServers.web[service].port, server : ModuleInfo.name }, `Invalid port (${service})` ); return Log.warn( { port : config.contentServers.web[service].port, server : ModuleInfo.name }, `Invalid port (${service})` );
} }
return this[name].listen(port); return this[name].listen(port);
} }
@ -167,7 +171,7 @@ exports.getModule = class WebServerModule extends ServerModule {
} }
respondWithError(resp, code, bodyText, title) { respondWithError(resp, code, bodyText, title) {
const customErrorPage = paths.join(Config.contentServers.web.staticRoot, `${code}.html`); const customErrorPage = paths.join(Config().contentServers.web.staticRoot, `${code}.html`);
fs.readFile(customErrorPage, 'utf8', (err, data) => { fs.readFile(customErrorPage, 'utf8', (err, data) => {
resp.writeHead(code, { 'Content-Type' : 'text/html' } ); resp.writeHead(code, { 'Content-Type' : 'text/html' } );
@ -202,14 +206,14 @@ exports.getModule = class WebServerModule extends ServerModule {
} }
routeIndex(req, resp) { routeIndex(req, resp) {
const filePath = paths.join(Config.contentServers.web.staticRoot, 'index.html'); const filePath = paths.join(Config().contentServers.web.staticRoot, 'index.html');
return this.returnStaticPage(filePath, resp); return this.returnStaticPage(filePath, resp);
} }
routeStaticFile(req, resp) { routeStaticFile(req, resp) {
const fileName = req.url.substr(req.url.indexOf('/', 1)); const fileName = req.url.substr(req.url.indexOf('/', 1));
const filePath = paths.join(Config.contentServers.web.staticRoot, fileName); const filePath = paths.join(Config().contentServers.web.staticRoot, fileName);
return this.returnStaticPage(filePath, resp); return this.returnStaticPage(filePath, resp);
} }

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('../../config.js').config; const Config = require('../../config.js').get;
const baseClient = require('../../client.js'); const baseClient = require('../../client.js');
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const LoginServerModule = require('../../login_server_module.js'); const LoginServerModule = require('../../login_server_module.js');
@ -42,7 +42,8 @@ function SSHClient(clientConn) {
const username = ctx.username || ''; const username = ctx.username || '';
const password = ctx.password || ''; const password = ctx.password || '';
self.isNewUser = (Config.users.newUserNames || []).indexOf(username) > -1; const config = Config();
self.isNewUser = (config.users.newUserNames || []).indexOf(username) > -1;
self.log.trace( { method : ctx.method, username : username, newUser : self.isNewUser }, 'SSH authentication attempt'); self.log.trace( { method : ctx.method, username : username, newUser : self.isNewUser }, 'SSH authentication attempt');
@ -60,7 +61,7 @@ function SSHClient(clientConn) {
// If the system is open and |isNewUser| is true, the login // If the system is open and |isNewUser| is true, the login
// sequence is hijacked in order to start the applicaiton process. // sequence is hijacked in order to start the applicaiton process.
// //
if(false === Config.general.closedSystem && self.isNewUser) { if(false === config.general.closedSystem && self.isNewUser) {
return ctx.accept(); return ctx.accept();
} }
@ -99,7 +100,7 @@ function SSHClient(clientConn) {
return alreadyLoggedIn(username); return alreadyLoggedIn(username);
} }
if(loginAttempts >= Config.general.loginAttempts) { if(loginAttempts >= config.general.loginAttempts) {
return terminateConnection(); return terminateConnection();
} }
@ -113,8 +114,8 @@ function SSHClient(clientConn) {
if(err) { if(err) {
interactivePrompt.prompt = `Access denied\n${ctx.username}'s password: `; interactivePrompt.prompt = `Access denied\n${ctx.username}'s password: `;
} else { } else {
const newUserNameList = _.has(Config, 'users.newUserNames') && Config.users.newUserNames.length > 0 ? const newUserNameList = _.has(config, 'users.newUserNames') && config.users.newUserNames.length > 0 ?
Config.users.newUserNames.map(newName => '"' + newName + '"').join(', ') : config.users.newUserNames.map(newName => '"' + newName + '"').join(', ') :
'(No new user names enabled!)'; '(No new user names enabled!)';
interactivePrompt.prompt = `Access denied\n${stringFormat(artInfo.data, { newUserNames : newUserNameList })}\n${ctx.username}'s password'`; interactivePrompt.prompt = `Access denied\n${stringFormat(artInfo.data, { newUserNames : newUserNameList })}\n${ctx.username}'s password'`;
@ -203,7 +204,7 @@ function SSHClient(clientConn) {
} }
// we're ready! // we're ready!
const firstMenu = self.isNewUser ? Config.loginServers.ssh.firstMenuNewUser : Config.loginServers.ssh.firstMenu; const firstMenu = self.isNewUser ? Config().loginServers.ssh.firstMenuNewUser : Config().loginServers.ssh.firstMenu;
self.emit('ready', { firstMenu : firstMenu } ); self.emit('ready', { firstMenu : firstMenu } );
}); });
@ -239,18 +240,19 @@ exports.getModule = class SSHServerModule extends LoginServerModule {
} }
createServer() { createServer() {
const config = Config();
const serverConf = { const serverConf = {
hostKeys : [ hostKeys : [
{ {
key : fs.readFileSync(Config.loginServers.ssh.privateKeyPem), key : fs.readFileSync(config.loginServers.ssh.privateKeyPem),
passphrase : Config.loginServers.ssh.privateKeyPass, passphrase : config.loginServers.ssh.privateKeyPass,
} }
], ],
ident : 'enigma-bbs-' + enigVersion + '-srv', ident : 'enigma-bbs-' + enigVersion + '-srv',
// Note that sending 'banner' breaks at least EtherTerm! // Note that sending 'banner' breaks at least EtherTerm!
debug : (sshDebugLine) => { debug : (sshDebugLine) => {
if(true === Config.loginServers.ssh.traceConnections) { if(true === config.loginServers.ssh.traceConnections) {
Log.trace(`SSH: ${sshDebugLine}`); Log.trace(`SSH: ${sshDebugLine}`);
} }
}, },
@ -265,9 +267,10 @@ exports.getModule = class SSHServerModule extends LoginServerModule {
} }
listen() { listen() {
const port = parseInt(Config.loginServers.ssh.port); const config = Config();
const port = parseInt(config.loginServers.ssh.port);
if(isNaN(port)) { if(isNaN(port)) {
Log.error( { server : ModuleInfo.name, port : Config.loginServers.ssh.port }, 'Cannot load server (invalid port)' ); Log.error( { server : ModuleInfo.name, port : config.loginServers.ssh.port }, 'Cannot load server (invalid port)' );
return false; return false;
} }

View File

@ -5,7 +5,7 @@
const baseClient = require('../../client.js'); const baseClient = require('../../client.js');
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const LoginServerModule = require('../../login_server_module.js'); const LoginServerModule = require('../../login_server_module.js');
const Config = require('../../config.js').config; const Config = require('../../config.js').get;
const EnigAssert = require('../../enigma_assert.js'); const EnigAssert = require('../../enigma_assert.js');
const { stringFromNullTermBuffer } = require('../../string_util.js'); const { stringFromNullTermBuffer } = require('../../string_util.js');
@ -549,7 +549,7 @@ function TelnetClient(input, output) {
}); });
this.connectionTrace = (info, msg) => { this.connectionTrace = (info, msg) => {
if(Config.loginServers.telnet.traceConnections) { if(Config().loginServers.telnet.traceConnections) {
const logger = self.log || Log; const logger = self.log || Log;
return logger.trace(info, `Telnet: ${msg}`); return logger.trace(info, `Telnet: ${msg}`);
} }
@ -568,7 +568,7 @@ function TelnetClient(input, output) {
this.readyNow = () => { this.readyNow = () => {
if(!this.didReady) { if(!this.didReady) {
this.didReady = true; this.didReady = true;
this.emit('ready', { firstMenu : Config.loginServers.telnet.firstMenu } ); this.emit('ready', { firstMenu : Config().loginServers.telnet.firstMenu } );
} }
}; };
} }
@ -879,9 +879,10 @@ exports.getModule = class TelnetServerModule extends LoginServerModule {
} }
listen() { listen() {
const port = parseInt(Config.loginServers.telnet.port); const config = Config();
const port = parseInt(config.loginServers.telnet.port);
if(isNaN(port)) { if(isNaN(port)) {
Log.error( { server : ModuleInfo.name, port : Config.loginServers.telnet.port }, 'Cannot load server (invalid port)' ); Log.error( { server : ModuleInfo.name, port : config.loginServers.telnet.port }, 'Cannot load server (invalid port)' );
return false; return false;
} }

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('../../config.js').config; const Config = require('../../config.js').get;
const TelnetClient = require('./telnet.js').TelnetClient; const TelnetClient = require('./telnet.js').TelnetClient;
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const LoginServerModule = require('../../login_server_module.js'); const LoginServerModule = require('../../login_server_module.js');
@ -92,7 +92,7 @@ function WebSocketClient(ws, req, serverType) {
// If the config allows it, look for 'x-forwarded-proto' as "https" // If the config allows it, look for 'x-forwarded-proto' as "https"
// to override |isSecure| // to override |isSecure|
// //
if(true === _.get(Config, 'loginServers.webSocket.proxied') && if(true === _.get(Config(), 'loginServers.webSocket.proxied') &&
'https' === req.headers['x-forwarded-proto']) 'https' === req.headers['x-forwarded-proto'])
{ {
Log.debug(`Assuming secure connection due to X-Forwarded-Proto of "${req.headers['x-forwarded-proto']}"`); Log.debug(`Assuming secure connection due to X-Forwarded-Proto of "${req.headers['x-forwarded-proto']}"`);
@ -120,7 +120,7 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
// * insecure websocket (ws://) // * insecure websocket (ws://)
// * secure (tls) websocket (wss://) // * secure (tls) websocket (wss://)
// //
const config = _.get(Config, 'loginServers.webSocket'); const config = _.get(Config(), 'loginServers.webSocket');
if(!_.isObject(config)) { if(!_.isObject(config)) {
return; return;
} }
@ -162,7 +162,7 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
} }
const serverName = `${ModuleInfo.name} (${serverType})`; const serverName = `${ModuleInfo.name} (${serverType})`;
const port = parseInt(_.get(Config, [ 'loginServers', 'webSocket', 'secure' === serverType ? 'wss' : 'ws', 'port' ] )); const port = parseInt(_.get(Config(), [ 'loginServers', 'webSocket', 'secure' === serverType ? 'wss' : 'ws', 'port' ] ));
if(isNaN(port)) { if(isNaN(port)) {
Log.error( { server : serverName, port : port }, 'Cannot load server (invalid port)' ); Log.error( { server : serverName, port : port }, 'Cannot load server (invalid port)' );

View File

@ -5,7 +5,7 @@
const MenuModule = require('./menu_module.js').MenuModule; const MenuModule = require('./menu_module.js').MenuModule;
const Errors = require('../core/enig_error.js').Errors; const Errors = require('../core/enig_error.js').Errors;
const ANSI = require('./ansi_term.js'); const ANSI = require('./ansi_term.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
// deps // deps
const async = require('async'); const async = require('async');
@ -90,7 +90,7 @@ exports.getModule = class ShowArtModule extends MenuModule {
} }
// further resolve key -> file base area art // further resolve key -> file base area art
const artSpec = _.get(Config, [ 'fileBase', 'areas', key, 'art' ]); const artSpec = _.get(Config(), [ 'fileBase', 'areas', key, 'art' ]);
if(!artSpec) { if(!artSpec) {
return cb(Errors.MissingConfig(`No art defined for file base area "${key}"`)); return cb(Errors.MissingConfig(`No art defined for file base area "${key}"`));
} }

View File

@ -3,7 +3,7 @@
// ENiGMA½ // ENiGMA½
const User = require('./user.js'); const User = require('./user.js');
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
const { getAddressedToInfo } = require('./mail_util.js'); const { getAddressedToInfo } = require('./mail_util.js');
const Message = require('./message.js'); const Message = require('./message.js');
@ -30,14 +30,15 @@ function validateMessageSubject(data, cb) {
} }
function validateUserNameAvail(data, cb) { function validateUserNameAvail(data, cb) {
if(!data || data.length < Config.users.usernameMin) { const config = Config();
if(!data || data.length < config.users.usernameMin) {
cb(new Error('Username too short')); cb(new Error('Username too short'));
} else if(data.length > Config.users.usernameMax) { } else if(data.length > config.users.usernameMax) {
// generally should be unreached due to view restraints // generally should be unreached due to view restraints
return cb(new Error('Username too long')); return cb(new Error('Username too long'));
} else { } else {
const usernameRegExp = new RegExp(Config.users.usernamePattern); const usernameRegExp = new RegExp(config.users.usernamePattern);
const invalidNames = Config.users.newUserNames + Config.users.badUserNames; const invalidNames = config.users.newUserNames + config.users.badUserNames;
if(!usernameRegExp.test(data)) { if(!usernameRegExp.test(data)) {
return cb(new Error('Username contains invalid characters')); return cb(new Error('Username contains invalid characters'));
@ -133,12 +134,13 @@ function validateBirthdate(data, cb) {
} }
function validatePasswordSpec(data, cb) { function validatePasswordSpec(data, cb) {
if(!data || data.length < Config.users.passwordMin) { const config = Config();
if(!data || data.length < config.users.passwordMin) {
return cb(new Error('Password too short')); return cb(new Error('Password too short'));
} }
// check badpass, if avail // check badpass, if avail
fs.readFile(Config.users.badPassFile, 'utf8', (err, passwords) => { fs.readFile(config.users.badPassFile, 'utf8', (err, passwords) => {
if(err) { if(err) {
Log.warn( { error : err.message }, 'Cannot read bad pass file'); Log.warn( { error : err.message }, 'Cannot read bad pass file');
return cb(null); return cb(null);

View File

@ -1,7 +1,7 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
const Config = require('./config.js').config; const Config = require('./config.js').get;
const art = require('./art.js'); const art = require('./art.js');
const ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
@ -38,7 +38,7 @@ function refreshThemeHelpers(theme) {
let pwChar = _.get( let pwChar = _.get(
theme, theme,
'customization.defaults.general.passwordChar', 'customization.defaults.general.passwordChar',
Config.defaults.passwordChar Config().defaults.passwordChar
); );
if(_.isString(pwChar)) { if(_.isString(pwChar)) {
@ -50,22 +50,22 @@ function refreshThemeHelpers(theme) {
return pwChar; return pwChar;
}, },
getDateFormat : function(style = 'short') { getDateFormat : function(style = 'short') {
const format = Config.defaults.dateFormat[style] || 'MM/DD/YYYY'; const format = Config().defaults.dateFormat[style] || 'MM/DD/YYYY';
return _.get(theme, `customization.defaults.dateFormat.${style}`, format); return _.get(theme, `customization.defaults.dateFormat.${style}`, format);
}, },
getTimeFormat : function(style = 'short') { getTimeFormat : function(style = 'short') {
const format = Config.defaults.timeFormat[style] || 'h:mm a'; const format = Config().defaults.timeFormat[style] || 'h:mm a';
return _.get(theme, `customization.defaults.timeFormat.${style}`, format); return _.get(theme, `customization.defaults.timeFormat.${style}`, format);
}, },
getDateTimeFormat : function(style = 'short') { getDateTimeFormat : function(style = 'short') {
const format = Config.defaults.dateTimeFormat[style] || 'MM/DD/YYYY h:mm a'; const format = Config().defaults.dateTimeFormat[style] || 'MM/DD/YYYY h:mm a';
return _.get(theme, `customization.defaults.dateTimeFormat.${style}`, format); return _.get(theme, `customization.defaults.dateTimeFormat.${style}`, format);
} }
}; };
} }
function loadTheme(themeId, cb) { function loadTheme(themeId, cb) {
const path = paths.join(Config.paths.themes, themeId, 'theme.hjson'); const path = paths.join(Config().paths.themes, themeId, 'theme.hjson');
const changed = ( { fileName, fileRoot } ) => { const changed = ( { fileName, fileRoot } ) => {
const reCachedPath = paths.join(fileRoot, fileName); const reCachedPath = paths.join(fileRoot, fileName);
@ -262,15 +262,16 @@ function getMergedTheme(menuConfig, promptConfig, theme) {
} }
function reloadTheme(themeId) { function reloadTheme(themeId) {
const config = Config();
async.waterfall( async.waterfall(
[ [
function loadMenuConfig(callback) { function loadMenuConfig(callback) {
getFullConfig(Config.general.menuFile, (err, menuConfig) => { getFullConfig(config.general.menuFile, (err, menuConfig) => {
return callback(err, menuConfig); return callback(err, menuConfig);
}); });
}, },
function loadPromptConfig(menuConfig, callback) { function loadPromptConfig(menuConfig, callback) {
getFullConfig(Config.general.promptFile, (err, promptConfig) => { getFullConfig(config.general.promptFile, (err, promptConfig) => {
return callback(err, menuConfig, promptConfig); return callback(err, menuConfig, promptConfig);
}); });
}, },
@ -312,21 +313,21 @@ function reloadAllThemes()
} }
function initAvailableThemes(cb) { function initAvailableThemes(cb) {
const config = Config();
async.waterfall( async.waterfall(
[ [
function loadMenuConfig(callback) { function loadMenuConfig(callback) {
getFullConfig(Config.general.menuFile, (err, menuConfig) => { getFullConfig(config.general.menuFile, (err, menuConfig) => {
return callback(err, menuConfig); return callback(err, menuConfig);
}); });
}, },
function loadPromptConfig(menuConfig, callback) { function loadPromptConfig(menuConfig, callback) {
getFullConfig(Config.general.promptFile, (err, promptConfig) => { getFullConfig(config.general.promptFile, (err, promptConfig) => {
return callback(err, menuConfig, promptConfig); return callback(err, menuConfig, promptConfig);
}); });
}, },
function getThemeDirectories(menuConfig, promptConfig, callback) { function getThemeDirectories(menuConfig, promptConfig, callback) {
fs.readdir(Config.paths.themes, (err, files) => { fs.readdir(config.paths.themes, (err, files) => {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@ -337,7 +338,7 @@ function initAvailableThemes(cb) {
promptConfig, promptConfig,
files.filter( f => { files.filter( f => {
// sync normally not allowed -- initAvailableThemes() is a startup-only method, however // sync normally not allowed -- initAvailableThemes() is a startup-only method, however
return fs.statSync(paths.join(Config.paths.themes, f)).isDirectory(); return fs.statSync(paths.join(config.paths.themes, f)).isDirectory();
}) })
); );
}); });
@ -394,12 +395,13 @@ function setClientTheme(client, themeId) {
let msg; let msg;
let setThemeId; let setThemeId;
const config = Config();
if(availThemes.has(themeId)) { if(availThemes.has(themeId)) {
msg = 'Set client theme'; msg = 'Set client theme';
setThemeId = themeId; setThemeId = themeId;
} else if(availThemes.has(Config.defaults.theme)) { } else if(availThemes.has(config.defaults.theme)) {
msg = 'Failed setting theme by supplied ID; Using default'; msg = 'Failed setting theme by supplied ID; Using default';
setThemeId = Config.defaults.theme; setThemeId = config.defaults.theme;
} else { } else {
msg = 'Failed setting theme by system default ID; Using the first one we can find'; msg = 'Failed setting theme by system default ID; Using the first one we can find';
setThemeId = availThemes.keys().next().value; setThemeId = availThemes.keys().next().value;
@ -421,10 +423,11 @@ function getThemeArt(options, cb) {
// readSauce // readSauce
// random // random
// //
const config = Config();
if(!options.themeId && _.has(options, 'client.user.properties.theme_id')) { if(!options.themeId && _.has(options, 'client.user.properties.theme_id')) {
options.themeId = options.client.user.properties.theme_id; options.themeId = options.client.user.properties.theme_id;
} else { } else {
options.themeId = Config.defaults.theme; options.themeId = config.defaults.theme;
} }
// :TODO: replace asAnsi stuff with something like retrieveAs = 'ansi' | 'pipe' | ... // :TODO: replace asAnsi stuff with something like retrieveAs = 'ansi' | 'pipe' | ...
@ -465,17 +468,17 @@ function getThemeArt(options, cb) {
return callback(null, artInfo); return callback(null, artInfo);
} }
options.basePath = paths.join(Config.paths.themes, options.themeId); options.basePath = paths.join(config.paths.themes, options.themeId);
art.getArt(options.name, options, (err, artInfo) => { art.getArt(options.name, options, (err, artInfo) => {
return callback(null, artInfo); return callback(null, artInfo);
}); });
}, },
function fromDefaultTheme(artInfo, callback) { function fromDefaultTheme(artInfo, callback) {
if(artInfo || Config.defaults.theme === options.themeId) { if(artInfo || config.defaults.theme === options.themeId) {
return callback(null, artInfo); return callback(null, artInfo);
} }
options.basePath = paths.join(Config.paths.themes, Config.defaults.theme); options.basePath = paths.join(config.paths.themes, config.defaults.theme);
art.getArt(options.name, options, (err, artInfo) => { art.getArt(options.name, options, (err, artInfo) => {
return callback(null, artInfo); return callback(null, artInfo);
}); });
@ -485,7 +488,7 @@ function getThemeArt(options, cb) {
return callback(null, artInfo); return callback(null, artInfo);
} }
options.basePath = Config.paths.art; options.basePath = config.paths.art;
art.getArt(options.name, options, (err, artInfo) => { art.getArt(options.name, options, (err, artInfo) => {
return callback(err, artInfo); return callback(err, artInfo);
}); });

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
const userDb = require('./database.js').dbs.user; const userDb = require('./database.js').dbs.user;
const Config = require('./config.js').config; const Config = require('./config.js').get;
const userGroup = require('./user_group.js'); const userGroup = require('./user_group.js');
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const Events = require('./events.js'); const Events = require('./events.js');
@ -56,7 +56,7 @@ module.exports = class User {
} }
isValid() { isValid() {
if(this.userId <= 0 || this.username.length < Config.users.usernameMin) { if(this.userId <= 0 || this.username.length < Config().users.usernameMin) {
return false; return false;
} }
@ -181,15 +181,16 @@ module.exports = class User {
create(password, cb) { create(password, cb) {
assert(0 === this.userId); assert(0 === this.userId);
const config = Config();
if(this.username.length < Config.users.usernameMin || this.username.length > Config.users.usernameMax) { if(this.username.length < config.users.usernameMin || this.username.length > config.users.usernameMax) {
return cb(Errors.Invalid('Invalid username length')); return cb(Errors.Invalid('Invalid username length'));
} }
const self = this; const self = this;
// :TODO: set various defaults, e.g. default activation status, etc. // :TODO: set various defaults, e.g. default activation status, etc.
self.properties.account_status = Config.users.requireActivation ? User.AccountStatus.inactive : User.AccountStatus.active; self.properties.account_status = config.users.requireActivation ? User.AccountStatus.inactive : User.AccountStatus.active;
async.waterfall( async.waterfall(
[ [
@ -229,7 +230,7 @@ module.exports = class User {
}); });
}, },
function setInitialGroupMembership(trans, callback) { function setInitialGroupMembership(trans, callback) {
self.groups = Config.users.defaultGroups; self.groups = config.users.defaultGroups;
if(User.RootUserID === self.userId) { // root/SysOp? if(User.RootUserID === self.userId) { // root/SysOp?
self.groups.push('sysops'); self.groups.push('sysops');

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const Config = require('./config.js').config; const Config = require('./config.js').get;
const Errors = require('./enig_error.js').Errors; const Errors = require('./enig_error.js').Errors;
const getServer = require('./listening_server.js').getServer; const getServer = require('./listening_server.js').getServer;
const webServerPackageName = require('./servers/content/web.js').moduleInfo.packageName; const webServerPackageName = require('./servers/content/web.js').moduleInfo.packageName;
@ -89,12 +89,13 @@ class WebPasswordReset {
}, },
function getEmailTemplates(user, callback) { function getEmailTemplates(user, callback) {
fs.readFile(Config.contentServers.web.resetPassword.resetPassEmailText, 'utf8', (err, textTemplate) => { const config = Config();
fs.readFile(config.contentServers.web.resetPassword.resetPassEmailText, 'utf8', (err, textTemplate) => {
if(err) { if(err) {
textTemplate = PW_RESET_EMAIL_TEXT_TEMPLATE_DEFAULT; textTemplate = PW_RESET_EMAIL_TEXT_TEMPLATE_DEFAULT;
} }
fs.readFile(Config.contentServers.web.resetPassword.resetPassEmailHtml, 'utf8', (err, htmlTemplate) => { fs.readFile(config.contentServers.web.resetPassword.resetPassEmailHtml, 'utf8', (err, htmlTemplate) => {
return callback(null, user, textTemplate, htmlTemplate); return callback(null, user, textTemplate, htmlTemplate);
}); });
}); });
@ -106,7 +107,7 @@ class WebPasswordReset {
function replaceTokens(s) { function replaceTokens(s) {
return s return s
.replace(/%BOARDNAME%/g, Config.general.boardName) .replace(/%BOARDNAME%/g, Config().general.boardName)
.replace(/%USERNAME%/g, user.username) .replace(/%USERNAME%/g, user.username)
.replace(/%TOKEN%/g, user.properties.email_password_reset_token) .replace(/%TOKEN%/g, user.properties.email_password_reset_token)
.replace(/%RESET_URL%/g, resetUrl) .replace(/%RESET_URL%/g, resetUrl)
@ -229,12 +230,13 @@ class WebPasswordReset {
const postResetUrl = webServer.instance.buildUrl('/reset_password'); const postResetUrl = webServer.instance.buildUrl('/reset_password');
const config = Config();
return webServer.instance.routeTemplateFilePage( return webServer.instance.routeTemplateFilePage(
Config.contentServers.web.resetPassword.resetPageTemplate, config.contentServers.web.resetPassword.resetPageTemplate,
(templateData, preprocessFinished) => { (templateData, preprocessFinished) => {
const finalPage = templateData const finalPage = templateData
.replace(/%BOARDNAME%/g, Config.general.boardName) .replace(/%BOARDNAME%/g, config.general.boardName)
.replace(/%USERNAME%/g, user.username) .replace(/%USERNAME%/g, user.username)
.replace(/%TOKEN%/g, token) .replace(/%TOKEN%/g, token)
.replace(/%RESET_URL%/g, postResetUrl) .replace(/%RESET_URL%/g, postResetUrl)
@ -262,9 +264,10 @@ class WebPasswordReset {
req.on('end', () => { req.on('end', () => {
const formData = querystring.parse(bodyData); const formData = querystring.parse(bodyData);
const config = Config();
if(!formData.token || !formData.password || !formData.confirm_password || if(!formData.token || !formData.password || !formData.confirm_password ||
formData.password !== formData.confirm_password || formData.password !== formData.confirm_password ||
formData.password.length < Config.users.passwordMin || formData.password.length > Config.users.passwordMax) formData.password.length < config.users.passwordMin || formData.password.length > config.users.passwordMax)
{ {
return badRequest(); return badRequest();
} }