+ Introduction of WIP asset system - menus, prompts, art, etc. @type:location/asset

This commit is contained in:
Bryan Ashby 2015-04-05 01:15:04 -06:00
parent 113e16df0d
commit 3336caeec9
6 changed files with 95 additions and 26 deletions

31
core/asset.js Normal file
View File

@ -0,0 +1,31 @@
/* jslint node: true */
'use strict';
exports.parseAsset = parseAsset;
var ALL_ASSETS = [
'art',
'menu',
'method',
'prompt',
];
// \@(art|menu|method)\:([\w\.]*)(?:\/?([\w\d\_]+))*
var ASSET_RE = new RegExp('\\@(' + ALL_ASSETS.join('|') + ')\\:([\\w\\.]*)(?:\\?/([\\w\\d\\_]+))*');
function parseAsset(s) {
var m = ASSET_RE.exec(s);
if(m) {
var result = { type : m[1] };
if(m[3]) {
result.location = m[2];
result.asset = m[3];
} else {
result.asset = m[2];
}
return result;
}
}

View File

@ -29,11 +29,11 @@ function SSHClient(input, output) {
if('password' === ctx.method) { if('password' === ctx.method) {
// :TODO: Log attempts // :TODO: Log attempts
user.authenticate(ctx.username, ctx.password, self, function onAuthResult(isAuth) { user.authenticate(ctx.username, ctx.password, self, function onAuthResult(err) {
if(isAuth) { if(err) {
ctx.accept();
} else {
ctx.reject(); ctx.reject();
} else {
ctx.accept();
} }
}); });
} else if('publickey' === ctx.method) { } else if('publickey' === ctx.method) {

View File

@ -303,7 +303,7 @@ function authenticate(userName, password, client, cb) {
], ],
function validateAuth(err, passDk, propsDk) { function validateAuth(err, passDk, propsDk) {
if(err) { if(err) {
cb(false); cb(err);
} else { } else {
// //
// Use constant time comparison here for security feel-goods // Use constant time comparison here for security feel-goods
@ -321,7 +321,7 @@ function authenticate(userName, password, client, cb) {
c |= passDkBuf[i] ^ propsDkBuf[i]; c |= passDkBuf[i] ^ propsDkBuf[i];
} }
cb(0 === c); cb(0 === c ? null : new Error('Invalid password'));
} }
} }
); );

View File

@ -5,6 +5,7 @@
var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
var menuUtil = require('./menu_util.js'); var menuUtil = require('./menu_util.js');
var Log = require('./logger.js').log; var Log = require('./logger.js').log;
var asset = require('./asset.js');
var events = require('events'); var events = require('events');
var util = require('util'); var util = require('util');
@ -215,6 +216,7 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
var initialFocusId; var initialFocusId;
// :TODO: remove all the passing of fromConfig - use local // :TODO: remove all the passing of fromConfig - use local
// :TODO: break all of this up ... a lot
async.waterfall( async.waterfall(
[ [
@ -285,6 +287,8 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
// and map the various entries to menus/etc. // and map the various entries to menus/etc.
// //
if(_.isObject(formConfig.submit)) { if(_.isObject(formConfig.submit)) {
// :TODO: If this model is kept, formData does not need to include actual data, just form ID & submitID
// we can get the rest here via each view in form -> getViewData()
self.on('submit', function onSubmit(formData) { self.on('submit', function onSubmit(formData) {
Log.debug( { formData : formData }, 'Submit form'); Log.debug( { formData : formData }, 'Submit form');
@ -328,13 +332,31 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
conf = confForFormId[c]; conf = confForFormId[c];
if(_.isEqual(formData.value, conf.value, formValueCompare)) { if(_.isEqual(formData.value, conf.value, formValueCompare)) {
if(!conf.action) {
continue;
}
var formattedArgs; var formattedArgs;
if(conf.args) { if(conf.args) {
formattedArgs = self.formatMenuArgs(conf.args); formattedArgs = self.formatMenuArgs(conf.args);
} }
self.client.gotoMenuModule( { name : conf.menu, args : formattedArgs } ); var actionAsset = asset.parseAsset(conf.action);
break; assert(_.isObject(actionAsset));
if('method' === actionAsset.type) {
if(actionAsset.location) {
// :TODO: call with (client, args, ...) at least.
} else {
// local to current module
var currentMod = self.client.currentMenuModule;
if(currentMod.menuMethods[actionAsset.asset]) {
currentMod.menuMethods[actionAsset.asset](formattedArgs);
}
}
} else if('menu' === actionAsset.type) {
self.client.gotoMenuModule( { name : actionAsset.asset, args : formattedArgs } );
}
} }
} }
}); });
@ -377,9 +399,10 @@ ViewController.prototype.formatMCIString = function(format) {
ViewController.prototype.formatMenuArgs = function(args) { ViewController.prototype.formatMenuArgs = function(args) {
var self = this; var self = this;
return _.forIn(args, function onArg(value, key) { return _.mapValues(args, function val(value) {
if('string' === typeof value) { if('string' === typeof value) {
args[key] = self.formatMCIString(value); return self.formatMCIString(value);
} }
return value;
}); });
}; };

View File

@ -23,6 +23,20 @@ exports.getModule = LoginModule;
function LoginModule(menuConfig) { function LoginModule(menuConfig) {
MenuModule.call(this, menuConfig); MenuModule.call(this, menuConfig);
var self = this;
this.menuMethods = {
attemptLogin : function(args) {
user.authenticate(args.username, args.password, self.client, function onAuth(err) {
if(err) {
console.log(err);
} else {
console.log('logged in!')
}
});
}
};
} }
require('util').inherits(LoginModule, MenuModule); require('util').inherits(LoginModule, MenuModule);

View File

@ -7,12 +7,18 @@
"BN1" : { "BN1" : {
... ...
"draw" : "@script:blah.js/drawButton" "draw" : "@script:blah.js/drawButton"
// @method:scriptName[.js]/methodName (foreign .js)
// @art:artName
// @method:/methodName (local to module.js)
"draw" : {
"normal" : ...,
"focus" : ...
}
} }
} }
*/ */
"matrix" : { "matrix" : {
"art" : "matrix", "art" : "matrix",
// :TODO: Not currently supporting more than form 0. Should probably do that!
"form" : { "form" : {
"0" : { "0" : {
"VM1" : { "VM1" : {
@ -28,16 +34,15 @@
"*" : [ "*" : [
{ {
"value" : { "1" : 0 }, "value" : { "1" : 0 },
"menu" : "loginForm", "action" : "@menu:login"
"args" : { "reason" : "show_form" }
}, },
{ {
"value" : { "1" : 1 }, "value" : { "1" : 1 },
"menu" : "apply" "action" : "@menu:apply"
}, },
{ {
"value" : { "1" : 2 }, "value" : { "1" : 2 },
"menu" : "logoff" "action" : "@menu:logoff"
} }
] ]
} }
@ -45,7 +50,7 @@
} }
} }
}, },
"loginForm" : { "login" : {
"art" : "login", // TODO: rename to login_form "art" : "login", // TODO: rename to login_form
"module" : "login", "module" : "login",
"form" : { "form" : {
@ -67,15 +72,15 @@
"submit" : { "submit" : {
"3" : [ // Login "3" : [ // Login
{ {
"value" : { "3" : null }, "value" : { "3" : null },
"menu" : "attemptLogin", "action" : "@method:attemptLogin",
"args" : { "reason" : "attempt_login", "username" : "{1}", "password" : "{2}" } "args" : { "username" : "{1}", "password" : "{2}" } // :TODO: rename to actionArgs ?
} }
], ],
"4" : [ // cancel "4" : [ // cancel
{ {
"value" : { "4" : null }, "value" : { "4" : null },
"menu" : "matrix" "action" : "@menu:matrix"
} }
] ]
} }
@ -83,10 +88,6 @@
} }
} }
}, },
"attemptLogin" : {
"art" : "login",
"module" : "login"
},
"logoff" : { "logoff" : {
"art" : "logoff", "art" : "logoff",
"module" : "logoff" "module" : "logoff"