diff --git a/core/acs.js b/core/acs.js index 54145bcb..df89be9b 100644 --- a/core/acs.js +++ b/core/acs.js @@ -3,6 +3,7 @@ // ENiGMA½ const checkAcs = require('./acs_parser.js').parse; +const Log = require('./logger.js').log; // deps const assert = require('assert'); @@ -16,7 +17,12 @@ class ACS { check(acs, scope, defaultAcs) { acs = acs ? acs[scope] : defaultAcs; acs = acs || defaultAcs; - return checkAcs(acs, { client : this.client } ); + try { + return checkAcs(acs, { client : this.client } ); + } catch(e) { + Log.warn( { exception : e, acs : acs }, 'Exception caught checking ACS'); + return false; + } } hasMessageConfRead(conf) { @@ -33,7 +39,12 @@ class ACS { const matchCond = condArray.find( cond => { if(_.has(cond, 'acs')) { - return checkAcs(cond.acs, { client : this.client } ); + try { + return checkAcs(cond.acs, { client : this.client } ); + } catch(e) { + Log.warn( { exception : e, acs : cond }, 'Exception caught checking ACS'); + return false; + } } else { return true; // no acs check req. } diff --git a/core/user.js b/core/user.js index 7703f8fe..7446c872 100644 --- a/core/user.js +++ b/core/user.js @@ -18,6 +18,8 @@ exports.loadProperties = loadProperties; exports.getUserIdsWithProperty = getUserIdsWithProperty; exports.getUserList = getUserList; +exports.isRootUserId = function(id) { return 1 === id; }; + function User() { var self = this; @@ -28,7 +30,7 @@ function User() { this.isAuthenticated = function() { return true === self.authenticated; - } + }; this.isValid = function() { if(self.userId <= 0 || self.username.length < Config.users.usernameMin) { @@ -58,13 +60,15 @@ function User() { groupNames = [ groupNames ]; } + // :TODO: _.some() + var isMember = false; _.forEach(groupNames, groupName => { - if(-1 !== self.groups.indexOf(groupName)) { - isMember = true; - return false; // stop iteration - } + if(-1 !== self.groups.indexOf(groupName)) { + isMember = true; + return false; // stop iteration + } }); return isMember; @@ -103,9 +107,9 @@ User.prototype.load = function(userId, cb) { }; User.prototype.authenticate = function(username, password, cb) { - var self = this; + const self = this; - var cachedInfo = {}; + const cachedInfo = {}; async.waterfall( [ @@ -178,7 +182,7 @@ User.prototype.authenticate = function(username, password, cb) { self.authenticated = true; } - cb(err); + return cb(err); } ); }; diff --git a/misc/install.sh b/misc/install.sh new file mode 100755 index 00000000..7ef9455e --- /dev/null +++ b/misc/install.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +{ # this ensures the entire script is downloaded before execution + +ENIGMA_NODE_VERSION=${ENIGMA_NODE_VERSION:=4.4} +ENIGMA_INSTALL_DIR=${ENIGMA_INSTALL_DIR:=$HOME/enigma-bbs} +ENIGMA_SOURCE=${ENIGMA_SOURCE:=https://github.com/NuSkooler/enigma-bbs.git} +TIME_FORMAT=`date "+%Y-%m-%d %H:%M:%S"` +WAIT_BEFORE_INSTALL=10 + +enigma_header() { + clear + cat << EndOfMessage + ______ +_____________________ _____ ____________________ __________\\_ / +\\__ ____/\\_ ____ \\ /____/ / _____ __ \\ / ______/ // /___jp! + // __|___// | \\// |// | \\// | | \\// \\ /___ /_____ +/____ _____| __________ ___|__| ____| \\ / _____ \\ +---- \\______\\ -- |______\\ ------ /______/ ---- |______\\ - |______\\ /__/ // ___/ + /__ _\\ + <*> ENiGMA½ // https://github.com/NuSkooler/enigma-bbs <*> /__/ + +ENiGMA½ will be installed to ${ENIGMA_INSTALL_DIR}, from source ${ENIGMA_SOURCE}. + +ENiGMA½ requires Node, v${ENIGMA_NODE_VERSION} will be installed via nvm. If you already have nvm installed, this install script will update it to the latest version. + +If this isn't what you were expecting, hit ctrl-c now. Installation will continue in ${WAIT_BEFORE_INSTALL} seconds... + +EndOfMessage + sleep ${WAIT_BEFORE_INSTALL} +} + +enigma_install_needs() { + command -v $1 >/dev/null 2>&1 || { log_error "ENiGMA½ requires $1 but it's not installed. Please install it and restart the installer."; exit 1; } +} + +log() { + printf "${TIME_FORMAT} %b\n" "$*"; +} + +log_error() { + printf "${TIME_FORMAT} \e[41mERROR:\033[0m %b\n" "$*" >&2; +} + +enigma_install_init() { + log "Checking git installation" + enigma_install_needs git + + log "Checking curl installation" + enigma_install_needs curl +} + +install_nvm() { + log "Installing nvm" + curl -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash +} + +configure_nvm() { + log "Installing Node ${ENIGMA_NODE_VERSION} via nvm" + . ~/.nvm/nvm.sh + nvm install ${ENIGMA_NODE_VERSION} + nvm use ${ENIGMA_NODE_VERSION} +} + +download_enigma_source() { + local INSTALL_DIR + INSTALL_DIR=${ENIGMA_INSTALL_DIR} + + if [ -d "$INSTALL_DIR/.git" ]; then + log "ENiGMA½ is already installed in $INSTALL_DIR, trying to update using git" + command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" fetch 2> /dev/null || { + log_error "Failed to update ENiGMA½, run 'git fetch' in $INSTALL_DIR yourself." + exit 1 + } + else + log "Downloading ENiGMA½ from git to '$INSTALL_DIR'" + mkdir -p "$INSTALL_DIR" + command git clone ${ENIGMA_SOURCE} "$INSTALL_DIR" || { + log_error "Failed to clone ENiGMA½ repo. Please report this!" + exit 1 + } + fi +} + +install_node_packages() { + log "Installing required Node packages" + cd ${ENIGMA_INSTALL_DIR} + npm install + if [ $? -eq 0 ]; then + log "npm package installation complete" + else + log_error "Failed to install ENiGMA½ npm packages. Please report this!" + fi +} + +enigma_footer() { + log "ENiGMA½ installation complete!" + echo -e "\e[33m" + cat << EndOfMessage +If this is the first time you've installed ENiGMA½, you now need to generate a minimal configuration. To do so, run the following commands: + +cd ${ENIGMA_INSTALL_DIR} +./oputil.js config --new + +EndOfMessage + echo -e "\e[39m" +} + +enigma_header +enigma_install_init +install_nvm +configure_nvm +download_enigma_source +install_node_packages +enigma_footer + +} # this ensures the entire script is downloaded before execution \ No newline at end of file diff --git a/mods/last_callers.js b/mods/last_callers.js index bce1cebd..5f9b49b0 100644 --- a/mods/last_callers.js +++ b/mods/last_callers.js @@ -7,6 +7,7 @@ const ViewController = require('../core/view_controller.js').ViewController; const StatLog = require('../core/stat_log.js'); const getUserName = require('../core/user.js').getUserName; const loadProperties = require('../core/user.js').loadProperties; +const isRootUserId = require('../core/user.js').isRootUserId; // deps const moment = require('moment'); @@ -68,6 +69,13 @@ LastCallersModule.prototype.mciReady = function(mciData, cb) { StatLog.getSystemLogEntries('user_login_history', StatLog.Order.TimestampDesc, callersView.dimens.height, (err, lh) => { loginHistory = lh; + + if(self.menuConfig.config.hideSysOpLogin) { + loginHistory = loginHistory.filter(lh => { + return false === isRootUserId(parseInt(lh.log_value)); // log_value=userId + }); + } + return callback(err); }); }, diff --git a/mods/telnet_bridge.js b/mods/telnet_bridge.js index b0fa2363..a8a2d9d3 100644 --- a/mods/telnet_bridge.js +++ b/mods/telnet_bridge.js @@ -50,8 +50,11 @@ class TelnetClientConnection extends EventEmitter { if(!this.pipeRestored) { this.pipeRestored = true; - this.client.term.output.unpipe(this.bridgeConnection); - this.client.term.output.resume(); + // client may have bailed + if(_.has(this, 'client.term.output')) { + this.client.term.output.unpipe(this.bridgeConnection); + this.client.term.output.resume(); + } } }