From 6502f3b55ec7b896b09d18bac25561c1b9a19729 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 8 May 2022 22:15:57 -0600 Subject: [PATCH] Initial support for user status flags (NotAvail, NotVisible, ...) --- core/client_connections.js | 24 +++++++++++++++--------- core/node_msg.js | 2 +- core/user.js | 27 +++++++++++++++++++++++++-- core/wfc.js | 21 ++++++++++++++++++++- core/whos_online.js | 2 +- 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/core/client_connections.js b/core/client_connections.js index ca5061e6..4d73a3ad 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -21,21 +21,24 @@ exports.getConnectionByNodeId = getConnectionByNodeId; const clientConnections = []; exports.clientConnections = clientConnections; -function getActiveConnections(authUsersOnly = false) { +function getActiveConnections(options = { authUsersOnly: true, visibleOnly: true }) { return clientConnections.filter(conn => { - return ((authUsersOnly && conn.user.isAuthenticated()) || !authUsersOnly); + if (options.authUsersOnly && !conn.user.isAuthenticated()) { + return false; + } + if (options.visibleOnly && !conn.user.isVisible()) { + return false; + } + + return true; + //return ((options.authUsersOnly && conn.user.isAuthenticated()) || !options.authUsersOnly); }); } -function getActiveConnectionList(authUsersOnly) { - - if(!_.isBoolean(authUsersOnly)) { - authUsersOnly = true; - } - +function getActiveConnectionList(options = { authUsersOnly: true, visibleOnly: true }) { const now = moment(); - return _.map(getActiveConnections(authUsersOnly), ac => { + return _.map(getActiveConnections(options), ac => { let action; try { // attempting to fetch a bad menu stack item can blow up/assert @@ -51,6 +54,8 @@ function getActiveConnectionList(authUsersOnly) { action : action, serverName : ac.session.serverName, isSecure : ac.session.isSecure, + isVisible : ac.user.isVisible(), + isAvailable : ac.user.isAvailable(), }; // @@ -66,6 +71,7 @@ function getActiveConnectionList(authUsersOnly) { const diff = now.diff(moment(ac.user.properties[UserProps.LastLoginTs]), 'minutes'); entry.timeOn = moment.duration(diff, 'minutes'); } + return entry; }); } diff --git a/core/node_msg.js b/core/node_msg.js index bb64757c..08f67333 100644 --- a/core/node_msg.js +++ b/core/node_msg.js @@ -204,7 +204,7 @@ exports.getModule = class NodeMessageModule extends MenuModule { location : 'N/A', affils : 'N/A', timeOn : 'N/A', - }].concat(getActiveConnectionList(true) + }].concat(getActiveConnectionList() .map(node => Object.assign(node, { text : -1 == node.node ? '-ALL-' : node.node.toString() } )) ).filter(node => node.node !== this.client.node); // remove our client's node this.nodeList.sort( (a, b) => a.node - b.node ); // sort by node diff --git a/core/user.js b/core/user.js index 99f587c9..0206e868 100644 --- a/core/user.js +++ b/core/user.js @@ -23,8 +23,6 @@ const moment = require('moment'); const sanatizeFilename = require('sanitize-filename'); const ssh2 = require('ssh2'); -exports.isRootUserId = function(id) { return 1 === id; }; - module.exports = class User { constructor() { this.userId = 0; @@ -32,6 +30,7 @@ module.exports = class User { this.properties = {}; // name:value this.groups = []; // group membership(s) this.authFactor = User.AuthFactors.None; + this.statusFlags = User.StatusFlags.None; } // static property accessors @@ -73,6 +72,14 @@ module.exports = class User { }; } + static get StatusFlags() { + return { + None : 0x00000000, + NotAvailable : 0x00000001, // Not currently available for chat, message, page, etc. + NotVisible : 0x00000002, // Invisible -- does not show online, last callers, etc. + } + } + isAuthenticated() { return true === this.authenticated; } @@ -121,6 +128,22 @@ module.exports = class User { return sanatizeFilename(name) || `user${this.userId.toString()}`; } + isAvailable() { + return (this.statusFlags & User.StatusFlags.NotAvailable) == 0; + } + + isVisible() { + return (this.statusFlags & User.StatusFlags.NotVisible) == 0; + } + + setVisibility(visible) { + if (visible) { + this.statusFlags &= ~User.StatusFlags.NotVisible; + } else { + this.statusFlags |= User.StatusFlags.NotVisible; + } + } + getLegacySecurityLevel() { if(this.isRoot() || this.isGroupMember('sysops')) { return 100; diff --git a/core/wfc.js b/core/wfc.js index 2c61e7b0..ba66685f 100644 --- a/core/wfc.js +++ b/core/wfc.js @@ -96,6 +96,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { enter() { this.client.stopIdleMonitor(); + this._applyOpVisibility(); super.enter(); } @@ -104,12 +105,30 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { return stream.name === 'wfc-ringbuffer'; }); + this._restoreOpVisibility(); + this._stopRefreshing(); this.client.startIdleMonitor(); super.leave(); } + _applyOpVisibility() { + const vis = this.config.opVisibility || 'current'; + this.restoreUserIsVisible = this.client.user.isVisible(); + + switch (vis) { + case 'hidden' : this.client.user.setVisibility(false); break; + case 'visible' : this.client.user.setVisibility(true); break; + default : break; + } + + } + + _restoreOpVisibility() { + this.client.user.setVisibility(this.restoreUserIsVisible); + } + _startRefreshing() { this.mainRefreshTimer = setInterval( () => { this._refreshAll(); @@ -214,7 +233,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { return cb(null); } - const nodeStatusItems = getActiveConnectionList(false) + const nodeStatusItems = getActiveConnectionList({authUsersOnly: false, visibleOnly: false}) .slice(0, nodeStatusView.dimens.height) .map(ac => { // Handle pre-authenticated diff --git a/core/whos_online.js b/core/whos_online.js index 5910bd29..c634d2bc 100644 --- a/core/whos_online.js +++ b/core/whos_online.js @@ -43,7 +43,7 @@ exports.getModule = class WhosOnlineModule extends MenuModule { return cb(Errors.MissingMci(`Missing online list MCI ${MciViewIds.onlineList}`)); } - const onlineList = getActiveConnectionList(true).slice(0, onlineListView.height).map( + const onlineList = getActiveConnectionList().slice(0, onlineListView.height).map( oe => Object.assign(oe, { text : oe.userName, timeOn : _.upperFirst(oe.timeOn.humanize()) }) );