diff --git a/core/menu_module.js b/core/menu_module.js index 8c811cab..e0845eac 100644 --- a/core/menu_module.js +++ b/core/menu_module.js @@ -4,6 +4,7 @@ var PluginModule = require('./plugin_module.js').PluginModule; var theme = require('./theme.js'); var Log = require('./logger.js').log; +var ansi = require('./ansi_term.js'); var async = require('async'); var assert = require('assert'); @@ -15,6 +16,7 @@ function MenuModule(options) { var self = this; this.menuConfig = options.menuConfig; + this.menuConfig.options = options.menuConfig.options || {}; this.menuMethods = {}; this.viewControllers = []; @@ -76,6 +78,10 @@ MenuModule.prototype.addViewController = function(vc) { }; MenuModule.prototype.beforeArt = function() { + if(this.menuConfig.options.clearScreen) { + this.client.term.write(ansi.resetScreen()); + } + }; MenuModule.prototype.mciReady = function(mciMap) { diff --git a/core/user.js b/core/user.js index b4474573..fae0dc66 100644 --- a/core/user.js +++ b/core/user.js @@ -5,6 +5,7 @@ var userDb = require('./database.js').dbs.user; var crypto = require('crypto'); var assert = require('assert'); var async = require('async'); +var _ = require('lodash'); exports.User = User; exports.getUserIdAndName = getUserIdAndName; @@ -114,9 +115,10 @@ User.prototype.authenticate = function(username, password, cb) { ], function complete(err) { if(!err) { - self.userId = cachedInfo.userId; - self.username = cachedInfo.username; - self.properties = cachedInfo.properties; + self.userId = cachedInfo.userId; + self.username = cachedInfo.username; + self.properties = cachedInfo.properties; + self.authenticated = true; } cb(err); @@ -144,6 +146,110 @@ function getUserIdAndName(username, cb) { ); } +User.prototype.create = function(options, cb) { + assert(0 === this.userId); + assert(this.username.length > 0); // :TODO: Min username length? Max? + assert(_.isObject(options)); + assert(_.isString(options.password)); + + var self = this; + + async.series( + [ + function beginTransaction(callback) { + userDb.run('BEGIN;', function transBegin(err) { + callback(err); + }); + }, + function createUserRec(callback) { + userDb.run( + 'INSERT INTO user (user_name) ' + + 'VALUES (?);', + [ self.username ], + function userInsert(err) { + if(err) { + callback(err); + } else { + self.userId = this.lastID; + callback(null); + } + } + ); + }, + function genAuthCredentials(callback) { + generatePasswordDerivedKeySalt(options.password, function dkAndSalt(err, info) { + if(err) { + callback(err); + } else { + self.properties.pw_pbkdf2_salt = info.salt; + self.properties.pw_pbkdf2_dk = info.dk; + callback(null); + } + }); + }, + function saveAll(callback) { + // :TODO: persist all data - props/etc. + callback(null); + } + ], + function complete(err) { + if(err) { + var originalError = err; + userDb.run('ROLLBACK;', function rollback(err) { + assert(!err); + cb(originalError); + }); + } else { + userDb.run('COMMIT;', function commited(err) { + cb(err); + }); + } + } + ); +}; + +User.prototype.persist = function(useTransaction, cb) { + assert(this.userId > 0); + + async.series( + [ + function beginTransaction(callback) { + if(useTransaction) { + userDb.run('BEGIN;', function transBegin(err) { + callback(err); + }); + } else { + callback(null); + } + }, + function saveProps(callback) { + persistProperties(this, function persisted(err) { + callback(err); + }); + } + ], + function complete(err) { + if(err) { + if(useTransaction) { + userDb.run('ROLLBACK;', function rollback(err) { + cb(err); + }); + } else { + cb(err); + } + } else { + if(useTransaction) { + userDb.run('COMMIT;', function commited(err) { + cb(err); + }); + } else { + cb(null); + } + } + } + ); +}; + function createNew(user, cb) { assert(user.username && user.username.length > 1, 'Invalid userName'); diff --git a/core/view_controller.js b/core/view_controller.js index a4fd8104..cc98e376 100644 --- a/core/view_controller.js +++ b/core/view_controller.js @@ -216,6 +216,8 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { var initialFocusId; var formConfig; + var mciRegEx = /([A-Z]{2})([0-9]{1,2})/; + // :TODO: remove all the passing of fromConfig - use local // :TODO: break all of this up ... a lot @@ -256,7 +258,8 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { function applyFormConfig(callback) { if(formConfig) { async.each(Object.keys(formConfig.mci), function onMciConf(mci, eachCb) { - var viewId = parseInt(mci[2]); // :TODO: what about auto-generated ID's? Do they simply not apply to menu configs? + var mciMatch = mci.match(mciRegEx); // :TODO: what about auto-generated IDs? Do they simply not apply to menu configs? + var viewId = parseInt(mciMatch[2]); var view = self.getView(viewId); var mciConf = formConfig.mci[mci]; diff --git a/mods/apply.js b/mods/apply.js index 62559456..66207311 100644 --- a/mods/apply.js +++ b/mods/apply.js @@ -42,8 +42,6 @@ ApplyModule.prototype.enter = function(client) { ApplyModule.prototype.beforeArt = function() { ApplyModule.super_.prototype.beforeArt.call(this); - - this.client.term.write(ansi.resetScreen()); }; ApplyModule.prototype.mciReady = function(mciMap) { diff --git a/mods/login.js b/mods/login.js index 5198f2ed..4cafbc14 100644 --- a/mods/login.js +++ b/mods/login.js @@ -72,7 +72,7 @@ LoginModule.prototype.enter = function(client) { LoginModule.prototype.beforeArt = function() { LoginModule.super_.prototype.beforeArt.call(this); - this.client.term.write(ansi.resetScreen()); + //this.client.term.write(ansi.resetScreen()); }; LoginModule.prototype.mciReady = function(mciMap) { diff --git a/mods/menu.json b/mods/menu.json index 05ab7759..b161e1e2 100644 --- a/mods/menu.json +++ b/mods/menu.json @@ -14,6 +14,8 @@ "normal" : ..., "focus" : ... } + + ..note that script/methods should be part of a *theme* - or at least checked first with fallback } } */ @@ -48,6 +50,9 @@ } } } + }, + "options" : { + "clearScreen" : true } }, "login" : { @@ -86,6 +91,9 @@ } } } + }, + "options" : { + "clearScreen" : true } }, "logoff" : { @@ -97,14 +105,23 @@ "module" : "apply", "form" : { "0" : { - "ET1ET2ET3ET4ET5ET6ET7ET8ET9TL10TL11TL12" : { + "BN13BN14ET1ET2ET3ET4ET5ET6ET7ET8ET9TL10TL11TL12" : { "mci" : { "ET1" : { "focus" : true + }, + "BN13" : { + "text" : "Apply" + }, + "BN14" : { + "text" : "Cancel" } } } } + }, + "options" : { + "clearScreen" : true } } } \ No newline at end of file diff --git a/mods/standard_menu.js b/mods/standard_menu.js index afae7fe8..925fe1e5 100644 --- a/mods/standard_menu.js +++ b/mods/standard_menu.js @@ -27,8 +27,6 @@ StandardMenuModule.prototype.enter = function(client) { StandardMenuModule.prototype.beforeArt = function() { StandardMenuModule.super_.prototype.beforeArt.call(this); - - this.client.term.write(ansi.resetScreen()); // :TODO: this should be optional }; StandardMenuModule.prototype.mciReady = function(mciMap) {