* WIP on user groups
* Minor changes to user credential prompt
This commit is contained in:
parent
ca3453ecfb
commit
a7f9e3846e
|
@ -86,6 +86,7 @@ function getDefaultConfig() {
|
||||||
passwordMax : 128,
|
passwordMax : 128,
|
||||||
requireActivation : true, // require SysOp activation?
|
requireActivation : true, // require SysOp activation?
|
||||||
invalidUsernames : [],
|
invalidUsernames : [],
|
||||||
|
defaultGroups : [ 'users' ]
|
||||||
},
|
},
|
||||||
|
|
||||||
defaults : {
|
defaults : {
|
||||||
|
|
|
@ -70,4 +70,9 @@ function createInitialValues() {
|
||||||
'INSERT OR IGNORE INTO user_group ' +
|
'INSERT OR IGNORE INTO user_group ' +
|
||||||
'VALUES(1, "users");'
|
'VALUES(1, "users");'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
dbs.user.run(
|
||||||
|
'INSERT OR IGNORE INTO user_group ' +
|
||||||
|
'VALUES(2, "sysops");'
|
||||||
|
);
|
||||||
}
|
}
|
|
@ -13,6 +13,10 @@ var _ = require('lodash');
|
||||||
exports.TextView = TextView;
|
exports.TextView = TextView;
|
||||||
|
|
||||||
function TextView(options) {
|
function TextView(options) {
|
||||||
|
if(options.dimens) {
|
||||||
|
options.dimens.height = 1; // force height of 1 for TextView's & sub classes
|
||||||
|
}
|
||||||
|
|
||||||
View.call(this, options);
|
View.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -36,8 +40,6 @@ function TextView(options) {
|
||||||
this.textMaskChar = options.textMaskChar;
|
this.textMaskChar = options.textMaskChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dimens.height = 1;
|
|
||||||
|
|
||||||
this.drawText = function(s) {
|
this.drawText = function(s) {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
56
core/user.js
56
core/user.js
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
var userDb = require('./database.js').dbs.user;
|
var userDb = require('./database.js').dbs.user;
|
||||||
var Config = require('./config.js').config;
|
var Config = require('./config.js').config;
|
||||||
|
var userGroup = require('./user_group.js');
|
||||||
|
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -116,6 +117,15 @@ User.prototype.authenticate = function(username, password, cb) {
|
||||||
cachedInfo.properties = allProps;
|
cachedInfo.properties = allProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function initGroups(callback) {
|
||||||
|
userGroup.getGroupsForUser(cachedInfo.userId, function groupsLoaded(err, groups) {
|
||||||
|
if(!err) {
|
||||||
|
cachedInfo.groups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,6 +135,7 @@ User.prototype.authenticate = function(username, password, cb) {
|
||||||
self.userId = cachedInfo.userId;
|
self.userId = cachedInfo.userId;
|
||||||
self.username = cachedInfo.username;
|
self.username = cachedInfo.username;
|
||||||
self.properties = cachedInfo.properties;
|
self.properties = cachedInfo.properties;
|
||||||
|
self.groups = cachedInfo.groups;
|
||||||
self.authenticated = true;
|
self.authenticated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +175,8 @@ User.prototype.create = function(options, cb) {
|
||||||
// :TODO: set various defaults, e.g. default activation status, etc.
|
// :TODO: set various defaults, e.g. default activation status, etc.
|
||||||
self.properties.account_status = Config.users.requireActivation ? User.AccountStatus.inactive : User.AccountStatus.active;
|
self.properties.account_status = Config.users.requireActivation ? User.AccountStatus.inactive : User.AccountStatus.active;
|
||||||
|
|
||||||
|
// :TODO: Set default groups from Config.users.defaultGroups[]
|
||||||
|
|
||||||
async.series(
|
async.series(
|
||||||
[
|
[
|
||||||
function beginTransaction(callback) {
|
function beginTransaction(callback) {
|
||||||
|
@ -203,6 +216,16 @@ User.prototype.create = function(options, cb) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
function setInitialGroupMembership(callback) {
|
||||||
|
userGroup.getGroupsByName(Config.users.defaultGroups, function defaultGroups(err, groups) {
|
||||||
|
if(err) {
|
||||||
|
callback(err);
|
||||||
|
} else {
|
||||||
|
self.groups = groups;
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
function saveAll(callback) {
|
function saveAll(callback) {
|
||||||
self.persist(false, function persisted(err) {
|
self.persist(false, function persisted(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
|
@ -245,6 +268,11 @@ User.prototype.persist = function(useTransaction, cb) {
|
||||||
persistProperties(self, function persisted(err) {
|
persistProperties(self, function persisted(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
function saveGroups(callback) {
|
||||||
|
userGroup.addUserToGroups(self.userId, self.groups, function groupsSaved(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
|
@ -452,34 +480,6 @@ function loadProperties(options, cb) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadGroups(userId, cb) {
|
|
||||||
//
|
|
||||||
// user_group
|
|
||||||
// group_id | group_name
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// user_group_member
|
|
||||||
// group_id | user_id
|
|
||||||
//
|
|
||||||
//
|
|
||||||
var sql = '';
|
|
||||||
|
|
||||||
var groups = {}; // id:name
|
|
||||||
|
|
||||||
userDb.each(sql, [ userId ], function dbRow(err, row) {
|
|
||||||
if(err) {
|
|
||||||
cb(err);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
//groups[row.group_id]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function complete() {
|
|
||||||
cb(null, groups);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*function getProperties(userId, propNames, cb) {
|
/*function getProperties(userId, propNames, cb) {
|
||||||
var properties = {};
|
var properties = {};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var userDb = require('./database.js').dbs.user;
|
||||||
|
var Config = require('./config.js').config;
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
|
exports.getGroupsForUser = getGroupsForUser;
|
||||||
|
exports.getGroupsByName = getGroupsByName;
|
||||||
|
exports.addUserToGroup = addUserToGroup;
|
||||||
|
exports.addUserToGroups = addUserToGroups;
|
||||||
|
exports.removeUserFromGroup = removeUserFromGroup;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// user_group
|
||||||
|
// group_id | group_name
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// user_group_member
|
||||||
|
// group_id | user_id
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
function getGroupsForUser(userId, cb) {
|
||||||
|
var sql =
|
||||||
|
'SELECT g.group_id, g.group_name ' +
|
||||||
|
'FROM user_group g, user_group_member gm ' +
|
||||||
|
'WHERE g.group_id = gm.group_id AND gm.user_id = ?;';
|
||||||
|
|
||||||
|
var groups = {}; // id:name
|
||||||
|
|
||||||
|
userDb.each(sql, [ userId ], function dbRow(err, row) {
|
||||||
|
if(err) {
|
||||||
|
cb(err);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.log(row);
|
||||||
|
//groups[row.group_id]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function complete() {
|
||||||
|
cb(null, groups);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGroupsByName(groupNames, cb) {
|
||||||
|
var sql =
|
||||||
|
'SELECT group_id, group_name ' +
|
||||||
|
'FROM user_group ' +
|
||||||
|
'WHERE group_name IN ("' + groupNames.join('","') + '");';
|
||||||
|
|
||||||
|
userDb.all(sql, function allRows(err, rows) {
|
||||||
|
if(err) {
|
||||||
|
cb(err);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
var groups = {};
|
||||||
|
rows.forEach(function row(r) {
|
||||||
|
groups[r.group_id] = r.group_name;
|
||||||
|
});
|
||||||
|
cb(null, groups);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addUserToGroup(userId, groupId, cb) {
|
||||||
|
userDb.run(
|
||||||
|
'REPLACE INTO user_group_member (group_id, user_id) ' +
|
||||||
|
'VALUES(?, ?);',
|
||||||
|
[ groupId, userId ],
|
||||||
|
function complete(err) {
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addUserToGroups(userId, groups, cb) {
|
||||||
|
async.each(Object.keys(groups), function item(groupId, nextItem) {
|
||||||
|
addUserToGroup(userId, groupId, function added(err) {
|
||||||
|
nextItem(err);
|
||||||
|
});
|
||||||
|
}, function complete(err) {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeUserFromGroup(userId, groupId, cb) {
|
||||||
|
|
||||||
|
}
|
|
@ -74,6 +74,7 @@ function submitApplication(callingMenu, formData, extraArgs) {
|
||||||
menuViewController.switchFocus(viewIds[0]);
|
menuViewController.switchFocus(viewIds[0]);
|
||||||
} else {
|
} else {
|
||||||
// Seems legit!
|
// Seems legit!
|
||||||
|
// :TODO: All of this should be a system API, not a mod
|
||||||
var newUser = new user.User();
|
var newUser = new user.User();
|
||||||
|
|
||||||
newUser.username = formData.value.username;
|
newUser.username = formData.value.username;
|
||||||
|
@ -87,6 +88,7 @@ function submitApplication(callingMenu, formData, extraArgs) {
|
||||||
email_address : formData.value.email,
|
email_address : formData.value.email,
|
||||||
web_address : formData.value.web,
|
web_address : formData.value.web,
|
||||||
|
|
||||||
|
// :TODO: This is set in User.create() -- proabbly don't need it here:
|
||||||
account_status : Config.users.requireActivation ? user.User.AccountStatus.inactive : user.User.AccountStatus.active,
|
account_status : Config.users.requireActivation ? user.User.AccountStatus.inactive : user.User.AccountStatus.active,
|
||||||
|
|
||||||
// :TODO: Other defaults
|
// :TODO: Other defaults
|
||||||
|
|
|
@ -56,7 +56,8 @@
|
||||||
"submit" : true,
|
"submit" : true,
|
||||||
"focus" : true,
|
"focus" : true,
|
||||||
// :TODO: need a good way to localize these ... Standard Orig->Lookup seems good.
|
// :TODO: need a good way to localize these ... Standard Orig->Lookup seems good.
|
||||||
"items" : [ "Login", "Apply", "Log Off" ]
|
"items" : [ "Login", "Apply", "Log Off" ],
|
||||||
|
"itemSpacing" : 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"submit" : {
|
"submit" : {
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
{
|
{
|
||||||
"userCredentials" : {
|
"userCredentials" : {
|
||||||
"art" : "USERCRED",
|
"art" : "usercred",
|
||||||
"mci" : {
|
"mci" : {
|
||||||
"ET1" : {
|
"ET1" : {
|
||||||
"argName" : "username"
|
"argName" : "username",
|
||||||
|
"width" : 15,
|
||||||
|
"maxLength" : "@config:users.usernameMax"
|
||||||
},
|
},
|
||||||
"ET2" : {
|
"ET2" : {
|
||||||
"submit" : true,
|
"submit" : true,
|
||||||
"argName" : "password",
|
"argName" : "password",
|
||||||
"password" : true
|
"password" : true,
|
||||||
|
"width" : 15,
|
||||||
|
"maxLength" : "@config:users.passwordMax"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue