diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index a7fd3863..9a7d208c 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -266,8 +266,9 @@ mainInfoFormat19: "|00|10{processUptimeSeconds!durationSeconds}" mainInfoFormat20: "|00|10{totalCalls:>5}" - mainInfoFormat21: "|00|10{totalPosts:>5}" - mainInfoFormat22: "|00|10{totalFiles} |08/ |10{totalFileBytes!sizeWithoutAbbr} |02{totalFileBytes!sizeAbbr}" + mainInfoFormat21: "|00|10{totalPosts:>7}" + mainInfoFormat22: "|00|10{totalUsers:>5}" + mainInfoFormat23: "|00|10{totalFiles} |08/ |10{totalFileBytes!sizeWithoutAbbr} |02{totalFileBytes!sizeAbbr}" quickLogLevel: info quickLogLevelIndicators: { @@ -283,7 +284,7 @@ mci: { TL17: { width: 23 } TL18: { width: 23 } - TL19: { width: 10 } + TL19: { width: 13 } VM1: { height: 5 diff --git a/art/themes/luciano_blocktronics/wfc.ans b/art/themes/luciano_blocktronics/wfc.ans index bf07f2fa..198ba676 100644 Binary files a/art/themes/luciano_blocktronics/wfc.ans and b/art/themes/luciano_blocktronics/wfc.ans differ diff --git a/core/bbs.js b/core/bbs.js index ebcd0c9d..8d5fc2f1 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -354,6 +354,18 @@ function initialize(cb) { }); }); }, + function initUserCount(callback) { + const User = require('./user.js'); + User.getUserCount((err, count) => { + if(err) { + return callback(err); + } + + const StatLog = require('./stat_log'); + StatLog.setNonPersistentSystemStat(SysProps.TotalUserCount, count); + return callback(null); + }); + }, function initMessageStats(callback) { return require('./message_area.js').startup(callback); }, diff --git a/core/predefined_mci.js b/core/predefined_mci.js index b24918b6..364a1e1c 100644 --- a/core/predefined_mci.js +++ b/core/predefined_mci.js @@ -304,6 +304,10 @@ const PREDEFINED_MCI_GENERATORS = { // :TODO: TZ - Average *system* post/call ratio (iNiQUiTY) // :TODO: ?? - Total users on system + TU : function totalSystemUsers() { + return StatLog.getSystemStatNum(SysProps.TotalUserCount) || 1; + }, + LC : function lastCallerUserName() { // Obv/2 const lastLogin = StatLog.getSystemStat(SysProps.LastLogin) || {}; return lastLogin.userName || 'N/A'; diff --git a/core/system_property.js b/core/system_property.js index 67049552..f39b3a27 100644 --- a/core/system_property.js +++ b/core/system_property.js @@ -37,4 +37,6 @@ module.exports = { SystemMemoryStats : 'system_memory_stats', // object { totalBytes, freeBytes }; non-persistent SystemLoadStats : 'system_load_stats', // object { average, current }; non-persistent + + TotalUserCount : 'user_total_count', // non-persistent }; diff --git a/core/user.js b/core/user.js index 4dad3399..99f587c9 100644 --- a/core/user.js +++ b/core/user.js @@ -793,6 +793,19 @@ module.exports = class User { ); } + static getUserCount(cb) { + userDb.get( + `SELECT count() AS user_count + FROM user;`, + (err, row) => { + if(err) { + return cb(err); + } + return cb(null, row.user_count); + } + ); + } + static getUserList(options, cb) { const userList = []; diff --git a/core/wfc.js b/core/wfc.js index a94bfb42..59e398b2 100644 --- a/core/wfc.js +++ b/core/wfc.js @@ -177,7 +177,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { // Totals totalCalls : StatLog.getSystemStatNum(SysProps.LoginCount), totalPosts : StatLog.getSystemStatNum(SysProps.MessageTotalCount), - //totalUsers : + totalUsers : StatLog.getSystemStatNum(SysProps.TotalUserCount), totalFiles : fileAreaStats.totalFiles || 0, totalFileBytes : fileAreaStats.totalFileBytes || 0, diff --git a/docs/_docs/art/mci.md b/docs/_docs/art/mci.md index 3d7a0c19..05fa9dd5 100644 --- a/docs/_docs/art/mci.md +++ b/docs/_docs/art/mci.md @@ -103,6 +103,7 @@ There are many predefined MCI codes that can be used anywhere on the system (pla | `LC` | Last caller to the system (username) | | `LT` | Time of last caller | | `LD` | Date of last caller | +| `TU` | Total number of users on the system | Some additional special case codes also exist: diff --git a/docs/_docs/modding/wfc.md b/docs/_docs/modding/wfc.md index 3f07054a..d4dd73b0 100644 --- a/docs/_docs/modding/wfc.md +++ b/docs/_docs/modding/wfc.md @@ -6,6 +6,24 @@ title: Waiting For Caller (WFC) The `wfc.js` module provides a Waiting For Caller (WFC) type dashboard from a bygone era. ENiGMA½'s WFC can be accessed over secure connections for accounts with the proper ACS. See **Security** information. ## Security +The system allows any user with the proper security to access the WFC / system operator functionality. The security policy is enforced by ACS with the default of `SCAF2ID1GM[wfc]`, meaning the following are true: + +1. Securely Connected (such as SSH or Secure WebSocket, but not Telnet) +2. Auth Factor 2+. That is, the user has 2FA enabled. +3. User ID of 1 (root/admin) +4. The user belongs to the `wfc` group. + +To change the ACS required, specify a alternative `acs` in the `config` block. For example: +```hjson +mainMenuWaitingForCaller: { + // ... + config: { + acs: SCID1GM[sysops] + } +} +``` + +:information_source: ENiGMA½ will enforce ACS of at least `SC` (secure connection) ## Theming The following MCI codes are available: @@ -26,4 +44,5 @@ The following MCI codes are available: * `{now}`: Current date and/or time in `nowDateTimeFormat` format. * `{processUptimeSeconds}`: Process (the BBS) uptime in seconds. * `{totalCalls}`: Total calls to the system. - * `{totalPosts}`: Total posts to the system. \ No newline at end of file + * `{totalPosts}`: Total posts to the system. + * `{totalUsers}`: Total users on the system. \ No newline at end of file