diff --git a/core/asset.js b/core/asset.js new file mode 100644 index 00000000..b239f185 --- /dev/null +++ b/core/asset.js @@ -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; + } +} \ No newline at end of file diff --git a/core/servers/ssh.js b/core/servers/ssh.js index 88a3d1db..918286c2 100644 --- a/core/servers/ssh.js +++ b/core/servers/ssh.js @@ -29,11 +29,11 @@ function SSHClient(input, output) { if('password' === ctx.method) { // :TODO: Log attempts - user.authenticate(ctx.username, ctx.password, self, function onAuthResult(isAuth) { - if(isAuth) { - ctx.accept(); - } else { + user.authenticate(ctx.username, ctx.password, self, function onAuthResult(err) { + if(err) { ctx.reject(); + } else { + ctx.accept(); } }); } else if('publickey' === ctx.method) { diff --git a/core/user.js b/core/user.js index d61840e7..110b0b85 100644 --- a/core/user.js +++ b/core/user.js @@ -303,7 +303,7 @@ function authenticate(userName, password, client, cb) { ], function validateAuth(err, passDk, propsDk) { if(err) { - cb(false); + cb(err); } else { // // Use constant time comparison here for security feel-goods @@ -321,7 +321,7 @@ function authenticate(userName, password, client, cb) { c |= passDkBuf[i] ^ propsDkBuf[i]; } - cb(0 === c); + cb(0 === c ? null : new Error('Invalid password')); } } ); diff --git a/core/view_controller.js b/core/view_controller.js index 19175161..2d7059ea 100644 --- a/core/view_controller.js +++ b/core/view_controller.js @@ -5,6 +5,7 @@ var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; var menuUtil = require('./menu_util.js'); var Log = require('./logger.js').log; +var asset = require('./asset.js'); var events = require('events'); var util = require('util'); @@ -215,6 +216,7 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { var initialFocusId; // :TODO: remove all the passing of fromConfig - use local + // :TODO: break all of this up ... a lot async.waterfall( [ @@ -285,6 +287,8 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { // and map the various entries to menus/etc. // 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) { Log.debug( { formData : formData }, 'Submit form'); @@ -328,13 +332,31 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { conf = confForFormId[c]; if(_.isEqual(formData.value, conf.value, formValueCompare)) { + if(!conf.action) { + continue; + } + var formattedArgs; if(conf.args) { formattedArgs = self.formatMenuArgs(conf.args); } - - self.client.gotoMenuModule( { name : conf.menu, args : formattedArgs } ); - break; + + var actionAsset = asset.parseAsset(conf.action); + 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) { var self = this; - return _.forIn(args, function onArg(value, key) { + return _.mapValues(args, function val(value) { if('string' === typeof value) { - args[key] = self.formatMCIString(value); + return self.formatMCIString(value); } + return value; }); }; \ No newline at end of file diff --git a/mods/login.js b/mods/login.js index 55557e65..084f105c 100644 --- a/mods/login.js +++ b/mods/login.js @@ -23,6 +23,20 @@ exports.getModule = LoginModule; function LoginModule(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); diff --git a/mods/menu.json b/mods/menu.json index 16a9ad6b..111dcee3 100644 --- a/mods/menu.json +++ b/mods/menu.json @@ -7,12 +7,18 @@ "BN1" : { ... "draw" : "@script:blah.js/drawButton" + // @method:scriptName[.js]/methodName (foreign .js) + // @art:artName + // @method:/methodName (local to module.js) + "draw" : { + "normal" : ..., + "focus" : ... + } } } */ "matrix" : { "art" : "matrix", - // :TODO: Not currently supporting more than form 0. Should probably do that! "form" : { "0" : { "VM1" : { @@ -28,16 +34,15 @@ "*" : [ { "value" : { "1" : 0 }, - "menu" : "loginForm", - "args" : { "reason" : "show_form" } + "action" : "@menu:login" }, { "value" : { "1" : 1 }, - "menu" : "apply" + "action" : "@menu:apply" }, { "value" : { "1" : 2 }, - "menu" : "logoff" + "action" : "@menu:logoff" } ] } @@ -45,7 +50,7 @@ } } }, - "loginForm" : { + "login" : { "art" : "login", // TODO: rename to login_form "module" : "login", "form" : { @@ -67,15 +72,15 @@ "submit" : { "3" : [ // Login { - "value" : { "3" : null }, - "menu" : "attemptLogin", - "args" : { "reason" : "attempt_login", "username" : "{1}", "password" : "{2}" } + "value" : { "3" : null }, + "action" : "@method:attemptLogin", + "args" : { "username" : "{1}", "password" : "{2}" } // :TODO: rename to actionArgs ? } ], "4" : [ // cancel { - "value" : { "4" : null }, - "menu" : "matrix" + "value" : { "4" : null }, + "action" : "@menu:matrix" } ] } @@ -83,10 +88,6 @@ } } }, - "attemptLogin" : { - "art" : "login", - "module" : "login" - }, "logoff" : { "art" : "logoff", "module" : "logoff"