System allows non-unique email addresses #7

This commit is contained in:
Bryan Ashby 2015-11-27 22:26:00 -07:00
parent d7c35911e8
commit a1f1578048
2 changed files with 98 additions and 3 deletions

View File

@ -15,6 +15,7 @@ exports.User = User;
exports.getUserIdAndName = getUserIdAndName; exports.getUserIdAndName = getUserIdAndName;
exports.getUserName = getUserName; exports.getUserName = getUserName;
exports.loadProperties = loadProperties; exports.loadProperties = loadProperties;
exports.getUserIdsWithProperty = getUserIdsWithProperty;
exports.getUserList = getUserList; exports.getUserList = getUserList;
function User() { function User() {
@ -494,6 +495,26 @@ function loadProperties(options, cb) {
}); });
} }
// :TODO: make this much more flexible - propValue should allow for case-insensitive compare, etc.
function getUserIdsWithProperty(propName, propValue, cb) {
var userIds = [];
userDb.each(
'SELECT user_id ' +
'FROM user_property ' +
'WHERE prop_name = ? AND prop_value = ?;',
[ propName, propValue ],
function rowEntry(err, row) {
if(!err) {
userIds.push(row.user_id);
}
},
function complete() {
cb(null, userIds);
}
);
}
function getUserList(options, cb) { function getUserList(options, cb) {
var userList = []; var userList = [];

View File

@ -13,10 +13,12 @@ var sysMenuMethod = require('../core/system_menu_method.js');
var getDefaultMessageArea = require('../core/message_area.js').getDefaultMessageArea; var getDefaultMessageArea = require('../core/message_area.js').getDefaultMessageArea;
var util = require('util'); var util = require('util');
var async = require('async');
exports.submitApplication = submitApplication; exports.submitApplication = submitApplication;
function validateApplicationData(formData, cb) { function validateApplicationData(formData, cb) {
/*
if(formData.value.username.length < Config.users.usernameMin) { if(formData.value.username.length < Config.users.usernameMin) {
cb('Handle too short!', [ 1 ]); cb('Handle too short!', [ 1 ]);
return; return;
@ -62,6 +64,77 @@ function validateApplicationData(formData, cb) {
cb(null); cb(null);
} }
}); });
*/
// :TODO: This entire section should be replaced with a generic form validation system!!
async.waterfall(
[
function basics(callback) {
if(formData.value.username.length < Config.users.usernameMin) {
cb(new Error('Handle too short!'), [ 1 ]);
return;
}
if(formData.value.username.length > Config.users.usernameMax) {
cb(new Error('Handle too long!'), [ 1 ]);
return;
}
var re = new RegExp(Config.users.usernamePattern);
if(!re.test(formData.value.username)) {
cb(new Error('Handle contains invalid characters!'), [ 1 ] );
return;
}
var invalidNames = Config.users.newUserNames + Config.users.badUserNames;
if(invalidNames.indexOf(formData.value.username.toLowerCase()) > -1) {
cb(new Error('Handle is blacklisted!'), [ 1 ] );
return;
}
if(isNaN(Date.parse(formData.value.birthdate))) {
cb(new Error('Invalid birthdate!'), [ 3 ] );
return;
}
if(formData.value.password.length < Config.users.passwordMin) {
cb(new Error('Password too short!'), [ 9, 10 ]);
return;
}
if(formData.value.password !== formData.value.passwordConfirm) {
cb(new Error('Passwords do not match!'), [ 9, 10 ]);
return;
}
callback(null);
},
function email(callback) {
user.getUserIdsWithProperty('email_address', formData.value.email, function userIdsWithEmail(err, uids) {
if(err) {
callback(new Error('Internal system error: ' + err.toString()), [ 1 ]);
} else if(uids.length > 0) {
callback(new Error('Email address not unique!'), [ 7 ] );
} else {
callback(null);
}
});
},
function userName(callback) {
user.getUserIdAndName(formData.value.username, function userIdAndName(err) {
var alreadyExists = !err;
if(alreadyExists) {
callback(new Error('Username unavailable!'), [ 1 ] );
} else {
cb(null);
}
});
}
],
function complete(err, viewIds) {
cb(err, viewIds);
}
);
} }
function submitApplication(callingMenu, formData, extraArgs) { function submitApplication(callingMenu, formData, extraArgs) {
@ -76,9 +149,9 @@ function submitApplication(callingMenu, formData, extraArgs) {
errorMsg : menuViewController.getView(11) errorMsg : menuViewController.getView(11)
}; };
validateApplicationData(formData, function validationResult(errorMsg, viewIds) { validateApplicationData(formData, function validationResult(err, viewIds) {
if(errorMsg) { if(err) {
views.errorMsg.setText(errorMsg); views.errorMsg.setText(err.toString().replace('Error: ', ''));
viewIds.forEach(function formId(id) { viewIds.forEach(function formId(id) {
menuViewController.getView(id).clearText(''); menuViewController.getView(id).clearText('');
@ -120,6 +193,7 @@ function submitApplication(callingMenu, formData, extraArgs) {
newUser.properties.theme_id = Config.defaults.theme; newUser.properties.theme_id = Config.defaults.theme;
} }
// :TODO: .create() should also validate email uniqueness!
newUser.create( { password : formData.value.password }, function created(err) { newUser.create( { password : formData.value.password }, function created(err) {
if(err) { if(err) {
Log.info( { error : err, username : formData.value.username }, 'New user creation failed'); Log.info( { error : err, username : formData.value.username }, 'New user creation failed');