* Some more JSON -> HJSON cleanup

* More work on ACS system conditional matching. Now functional within menus. Still more work to go on various ACS checks themselves.
* Use ACS for new user path: If new user requires activation, they will see 'DONE' then get logged off
This commit is contained in:
Bryan Ashby 2015-11-14 12:22:21 -07:00
parent 03f9ad4789
commit 688e46bc47
9 changed files with 93 additions and 68 deletions

View File

@ -792,6 +792,7 @@ module.exports = (function() {
var user = options.client.user; var user = options.client.user;
var _ = require('lodash'); var _ = require('lodash');
var assert = require('assert');
function checkAccess(acsCode, value) { function checkAccess(acsCode, value) {
try { try {
@ -802,6 +803,18 @@ module.exports = (function() {
AG : function ageGreaterOrEqualThan() { AG : function ageGreaterOrEqualThan() {
return !isNaN(value) && user.getAge() >= value; return !isNaN(value) && user.getAge() >= value;
}, },
AS : function accountStatus() {
if(_.isNumber(value)) {
value = [ value ];
}
assert(_.isArray(value));
return _.findIndex(value, function cmp(accStatus) {
return parseInt(accStatus, 10) === parseInt(user.properties.account_status, 10);
}) > -1;
},
EC : function isEncoding() { EC : function isEncoding() {
switch(value) { switch(value) {
case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase(); case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase();
@ -814,13 +827,9 @@ module.exports = (function() {
return false; return false;
} }
value.forEach(function grpEntry(groupName) { return _.findIndex(value, function cmp(groupName) {
if(user.isGroupMember(groupName)) { return user.isGroupMember(groupName);
return true; }) > - 1;
}
});
return false;
}, },
NN : function isNode() { NN : function isNode() {
return client.node === value; return client.node === value;

View File

@ -14,11 +14,11 @@ function getConditionalValue(client, condArray, memberName) {
assert(_.isArray(condArray)); assert(_.isArray(condArray));
assert(_.isString(memberName)); assert(_.isString(memberName));
console.log(condArray) var matchCond = _.find(condArray, function cmp(cond) {
return acsParser.parse(cond.acs, { client : client } );
condArray.forEach(function cond(c) {
if(acsParser.parse(c.acs, { client : client })) {
return c[memberName];
}
}); });
if(matchCond) {
return matchCond[memberName];
}
} }

View File

@ -146,7 +146,7 @@ function MenuModule(options) {
this.autoNextMenu = function() { this.autoNextMenu = function() {
function goNext() { function goNext() {
if(_.isString(self.menuConfig.next)) { if(_.isString(self.menuConfig.next) || _.isArray(self.menuConfig.next)) {
menuUtil.handleNext(self.client, self.menuConfig.next); menuUtil.handleNext(self.client, self.menuConfig.next);
} else { } else {
self.prevMenu(); self.prevMenu();
@ -179,6 +179,10 @@ function MenuModule(options) {
} }
} }
}; };
this.haveNext = function() {
return (_.isString(this.menuConfig.next) || _.isArray(this.menuConfig.next));
};
} }
require('util').inherits(MenuModule, PluginModule); require('util').inherits(MenuModule, PluginModule);
@ -215,6 +219,14 @@ MenuModule.prototype.restoreSavedState = function(savedState) {
}; };
MenuModule.prototype.nextMenu = function(cb) { MenuModule.prototype.nextMenu = function(cb) {
//
// If we don't actually have |next|, we'll go previous
//
if(!this.haveNext()) {
this.prevMenu(cb);
return;
}
// :TODO: this, prevMenu(), and gotoMenu() need a default |cb| handler if none is supplied. // :TODO: this, prevMenu(), and gotoMenu() need a default |cb| handler if none is supplied.
// ...if the error is that we do not meet ACS requirements and did not get a match, then what? // ...if the error is that we do not meet ACS requirements and did not get a match, then what?
if(!cb) { if(!cb) {

View File

@ -46,24 +46,10 @@ MenuStack.prototype.next = function(cb) {
assert(currentModuleInfo, 'Empty menu stack!'); assert(currentModuleInfo, 'Empty menu stack!');
var menuConfig = currentModuleInfo.instance.menuConfig; var menuConfig = currentModuleInfo.instance.menuConfig;
/*
:TODO: next should allow for conditionals based on ACS
next: [
{ acs: "GM[sysops]|U1", next: theNextMenu },
...
]
acsUtil.getAcsConditionMatch(cond, memberName) -> value | undefined
(memberName = "next")
*/
var next; var next;
if(_.isArray(menuConfig.next)) { if(_.isArray(menuConfig.next)) {
next = acsUtil.getConditionalValue(this.client, menuConfig.next, 'next'); next = acsUtil.getConditionalValue(this.client, menuConfig.next, 'next');
console.log('conditional next: ' + next);
if(!next) { if(!next) {
cb(new Error('No matching condition for \'next\'!')); cb(new Error('No matching condition for \'next\'!'));
return; return;
@ -75,12 +61,12 @@ MenuStack.prototype.next = function(cb) {
return; return;
} }
if(menuConfig.next === currentModuleInfo.name) { if(next === currentModuleInfo.name) {
cb(new Error('Menu config \'next\' specifies current menu!')); cb(new Error('Menu config \'next\' specifies current menu!'));
return; return;
} }
this.goto(menuConfig.next, { }, cb); this.goto(next, { }, cb);
}; };
MenuStack.prototype.prev = function(cb) { MenuStack.prototype.prev = function(cb) {

View File

@ -10,6 +10,7 @@ var asset = require('./asset.js');
var theme = require('./theme.js'); var theme = require('./theme.js');
var configCache = require('./config_cache.js'); var configCache = require('./config_cache.js');
var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
var acsUtil = require('./acs_util.js');
var fs = require('fs'); var fs = require('fs');
var paths = require('path'); var paths = require('path');
@ -220,7 +221,11 @@ function handleAction(client, formData, conf) {
} }
function handleNext(client, nextSpec, conf) { function handleNext(client, nextSpec, conf) {
assert(_.isString(nextSpec)); assert(_.isString(nextSpec) || _.isArray(nextSpec));
if(_.isArray(nextSpec)) {
nextSpec = acsUtil.getConditionalValue(client, nextSpec, 'next');
}
var nextAsset = asset.getAssetWithShorthand(nextSpec, 'menu'); var nextAsset = asset.getAssetWithShorthand(nextSpec, 'menu');

View File

@ -85,9 +85,9 @@ User.StandardPropertyGroups = {
}; };
User.AccountStatus = { User.AccountStatus = {
disabled : -1, disabled : 0,
inactive : 0, inactive : 1,
active : 1, active : 2,
}; };
User.prototype.load = function(userId, cb) { User.prototype.load = function(userId, cb) {

View File

@ -4,6 +4,7 @@
var user = options.client.user; var user = options.client.user;
var _ = require('lodash'); var _ = require('lodash');
var assert = require('assert');
function checkAccess(acsCode, value) { function checkAccess(acsCode, value) {
try { try {
@ -14,6 +15,18 @@
AG : function ageGreaterOrEqualThan() { AG : function ageGreaterOrEqualThan() {
return !isNaN(value) && user.getAge() >= value; return !isNaN(value) && user.getAge() >= value;
}, },
AS : function accountStatus() {
if(_.isNumber(value)) {
value = [ value ];
}
assert(_.isArray(value));
return _.findIndex(value, function cmp(accStatus) {
return parseInt(accStatus, 10) === parseInt(user.properties.account_status, 10);
}) > -1;
},
EC : function isEncoding() { EC : function isEncoding() {
switch(value) { switch(value) {
case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase(); case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase();
@ -26,13 +39,9 @@
return false; return false;
} }
value.forEach(function grpEntry(groupName) { return _.findIndex(value, function cmp(groupName) {
if(user.isGroupMember(groupName)) { return user.isGroupMember(groupName);
return true; }) > - 1;
}
});
return false;
}, },
NN : function isNode() { NN : function isNode() {
return client.node === value; return client.node === value;

View File

@ -119,8 +119,6 @@
next: @systemMethod:logoff next: @systemMethod:logoff
} }
/* /*
nua -> send sysop mail -> { active } -> matrix
-> you must active -> matrix
TODO: display PRINT before this (Obv/2) or NEWUSER1 (Mystic) TODO: display PRINT before this (Obv/2) or NEWUSER1 (Mystic)
*/ */
newUserApplication: { newUserApplication: {
@ -305,9 +303,16 @@
newUserFeedbackToSysOp: { newUserFeedbackToSysOp: {
status: Feedback to SysOp status: Feedback to SysOp
module: msg_area_post_fse module: msg_area_post_fse
// :TODO: If the user is auto-approved, login seq. else, DONE.ANS -> Logoff next: [
// :TODO: client.nextOrFallback(): go next or fallback. Use in MenuModule base also {
fallback: fullLoginSequenceLoginArt acs: AS2
next: fullLoginSequenceLoginArt
}
{
acs: !AS2
next: newUserInactiveDone
}
]
config: { config: {
art: { art: {
header: MSGEHDR header: MSGEHDR
@ -413,6 +418,13 @@
} }
} }
newUserInactiveDone: {
desc: Finished with NUA
art: DONE
options: { pause: true }
next: @menu:logoff
}
fullLoginSequenceLoginArt: { fullLoginSequenceLoginArt: {
desc: Logging In desc: Logging In
art: WELCOME art: WELCOME
@ -448,12 +460,8 @@
prompt: menuCommand prompt: menuCommand
submit: [ submit: [
{ {
"value" : { "command" : "G" }, value: { command: "G" }
"action" : "@menu:logoff" action: @menu:logoff
},
{
"value" : { "command" : "O" },
"action" : "@menu:doorPimpWars"
} }
{ {
value: { command: "D" } value: { command: "D" }
@ -464,21 +472,17 @@
action: @menu:mainMenuUserList action: @menu:mainMenuUserList
} }
{ {
value: { command: "E" } value: { command: "L" }
action: @menu:doorTestExample action: @menu:mainMenuLastCallers
} }
{ {
"value" : { "command" : "L" }, value: { command: "Y" }
"action" : "@menu:mainMenuLastCallers" action: @menu:mainMenuUserStats
}, }
{ {
"value" : { "command" : "Y" }, value: { command: "M" }
"action" : "@menu:mainMenuUserStats" action: @menu:messageArea
}, }
{
"value" : { "command" : "M" },
"action" : "@menu:messageArea"
},
{ {
value: { command: "C" } value: { command: "C" }
action: @menu:mainMenuUserConfig action: @menu:mainMenuUserConfig
@ -488,8 +492,8 @@
action: @menu:mainMenuSystemStats action: @menu:mainMenuSystemStats
} }
{ {
"value" : 1, value: 1
"action" : "@menu:mainMenu" action: @menu:mainMenu
} }
] ]
} }

View File

@ -48,7 +48,7 @@ function AreaPostFSEModule(options) {
console.log(msg); console.log(msg);
} }
self.prevMenu(); self.nextMenu();
} }
); );
}; };