From 67ef155c6007a1ccf644aeb322085c956f9129c1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 12 Mar 2014 20:03:20 -0400 Subject: [PATCH 1/7] fixing image uploads --- src/routes/api.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index 43194ce8cb..909f142863 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -83,7 +83,7 @@ function uploadImage(image, callback) { } else { if (meta.config.allowFileUploads) { - Posts.uploadPostFile(image, callback); + uploadFile(image, callback); } else { callback(new Error('Uploads are disabled!')); } @@ -109,7 +109,7 @@ function uploadFile(file, callback) { } var filename = 'upload-' + utils.generateUUID() + path.extname(file.name); - require('./file').saveFileToLocal(filename, file.path, function(err, upload) { + require('../file').saveFileToLocal(filename, file.path, function(err, upload) { if(err) { return callback(err); } From 90e398e5c9b3ec3ef89c0805c662609f0afc1236 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 12 Mar 2014 20:53:42 -0400 Subject: [PATCH 2/7] user js refactor, category fix if a category that didn't exist was request with category/1231 or api/category/1231 it was crashing. --- public/src/forum/accountedit.js | 4 +- src/categories.js | 50 ++- src/controllers/categories.js | 4 + src/socket.io/index.js | 6 +- src/user.js | 401 ++---------------- src/user/admin.js | 46 ++ src/{useremail.js => user/email.js} | 12 +- src/user/follow.js | 68 +++ .../notifications.js} | 13 +- src/user/profile.js | 196 +++++++++ src/{userreset.js => user/reset.js} | 12 +- src/user/settings.js | 54 +++ 12 files changed, 462 insertions(+), 404 deletions(-) create mode 100644 src/user/admin.js rename src/{useremail.js => user/email.js} (89%) create mode 100644 src/user/follow.js rename src/{usernotifications.js => user/notifications.js} (94%) create mode 100644 src/user/profile.js rename src/{userreset.js => user/reset.js} (90%) create mode 100644 src/user/settings.js diff --git a/public/src/forum/accountedit.js b/public/src/forum/accountedit.js index 207785e846..de9e3708b7 100644 --- a/public/src/forum/accountedit.js +++ b/public/src/forum/accountedit.js @@ -29,8 +29,8 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { return app.alertError(err.message); } - if (!data || !data.success) { - return app.alertError('There was an error updating your profile! ' + err.message); + if (!data) { + return app.alertError('There was an error updating your profile!'); } app.alertSuccess('Your profile has been updated successfully!'); diff --git a/src/categories.js b/src/categories.js index 918ab69d56..c2cddcf744 100644 --- a/src/categories.js +++ b/src/categories.js @@ -57,32 +57,38 @@ var db = require('./database'), Categories.getCategoryById = function(cid, start, end, uid, callback) { - if(parseInt(uid, 10)) { - Categories.markAsRead(cid, uid); - } - - async.parallel({ - category: function(next) { - Categories.getCategoryData(cid, next); - }, - topics: function(next) { - Categories.getCategoryTopics(cid, start, end, uid, next); - }, - pageCount: function(next) { - Categories.getPageCount(cid, uid, next); + CategoryTools.exists(cid, function(err, exists) { + if(err || !exists) { + return callback(err || new Error('category-not-found [' + cid + ']')); } - }, function(err, results) { - if(err) { - return callback(err); + + if(parseInt(uid, 10)) { + Categories.markAsRead(cid, uid); } - var category = results.category; - category.topics = results.topics.topics; - category.nextStart = results.topics.nextStart; - category.pageCount = results.pageCount; - category.topic_row_size = 'col-md-9'; + async.parallel({ + category: function(next) { + Categories.getCategoryData(cid, next); + }, + topics: function(next) { + Categories.getCategoryTopics(cid, start, end, uid, next); + }, + pageCount: function(next) { + Categories.getPageCount(cid, uid, next); + } + }, function(err, results) { + if(err) { + return callback(err); + } + + var category = results.category; + category.topics = results.topics.topics; + category.nextStart = results.topics.nextStart; + category.pageCount = results.pageCount; + category.topic_row_size = 'col-md-9'; - callback(null, category); + callback(null, category); + }); }); }; diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 2f2a1e35a9..9d0a1aae49 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -89,6 +89,10 @@ categoriesController.get = function(req, res, next) { end = start + settings.topicsPerPage - 1; categories.getCategoryById(cid, start, end, uid, function (err, categoryData) { + if (err) { + return next(err); + } + if (categoryData) { if (parseInt(categoryData.disabled, 10) === 1) { return next(new Error('Category disabled'), null); diff --git a/src/socket.io/index.js b/src/socket.io/index.js index d477273649..9d55c874aa 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -186,10 +186,8 @@ Sockets.logoutUser = function(uid) { }; Sockets.emitUserCount = function() { - db.getObjectField('global', 'userCount', function(err, count) { - io.sockets.emit('user.count', err?{message:err.message}:null, { - count: count - }); + user.count(function(err, count) { + io.sockets.emit('user.count', err ? {message:err.message} : null, count); }); }; diff --git a/src/user.js b/src/user.js index 089158e75a..360266e887 100644 --- a/src/user.js +++ b/src/user.js @@ -19,9 +19,14 @@ var bcrypt = require('bcryptjs'), (function(User) { - User.email = require('./useremail'); - User.notifications = require('./usernotifications'); - User.reset = require('./userreset'); + User.email = require('./user/email'); + User.notifications = require('./user/notifications'); + User.reset = require('./user/reset'); + + require('./user/follow')(User); + require('./user/profile')(User); + require('./user/admin')(User); + require('./user/settings')(User); User.create = function(userData, callback) { userData = userData || {}; @@ -224,51 +229,7 @@ var bcrypt = require('bcryptjs'), }); }; - User.getSettings = function(uid, callback) { - function sendDefaultSettings() { - callback(null, { - showemail: false, - usePagination: parseInt(meta.config.usePagination, 10) === 1, - topicsPerPage: parseInt(meta.config.topicsPerPage, 10) || 20, - postsPerPage: parseInt(meta.config.postsPerPage, 10) || 10 - }); - } - - if(!parseInt(uid, 10)) { - return sendDefaultSettings(); - } - - db.getObject('user:' + uid + ':settings', function(err, settings) { - if(err) { - return callback(err); - } - - if(!settings) { - settings = {}; - } - - settings.showemail = settings.showemail ? parseInt(settings.showemail, 10) !== 0 : false; - settings.usePagination = settings.usePagination ? parseInt(settings.usePagination, 10) === 1 : parseInt(meta.config.usePagination, 10) === 1; - settings.topicsPerPage = settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : parseInt(meta.config.topicsPerPage, 10) || 20; - settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10; - - callback(null, settings); - }); - }; - - User.saveSettings = function(uid, data, callback) { - - if(!data.topicsPerPage || !data.postsPerPage || parseInt(data.topicsPerPage, 10) <= 0 || parseInt(data.postsPerPage, 10) <= 0) { - return callback(new Error('Invalid pagination value!')); - } - db.setObject('user:' + uid + ':settings', { - showemail: data.showemail, - usePagination: data.usePagination, - topicsPerPage: data.topicsPerPage, - postsPerPage: data.postsPerPage - }, callback); - }; User.updateLastOnlineTime = function(uid, callback) { User.getUserField(uid, 'status', function(err, status) { @@ -286,157 +247,6 @@ var bcrypt = require('bcryptjs'), }); }; - User.updateProfile = function(uid, data, callback) { - var fields = ['username', 'email', 'fullname', 'website', 'location', 'birthday', 'signature']; - var returnData = { - success: false - }; - - function isSignatureValid(next) { - if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) { - next(new Error('Signature can\'t be longer than ' + meta.config.maximumSignatureLength + ' characters!'), false); - } else { - next(null, true); - } - } - - function isEmailAvailable(next) { - if (!data.email) { - return next(null, true); - } - - User.getUserField(uid, 'email', function(err, email) { - if(email === data.email) { - return next(null, true); - } - - User.email.available(data.email, function(err, available) { - if (err) { - return next(err, null); - } - - if (!available) { - next(new Error('Email not available!'), false); - } else { - next(null, true); - } - }); - }); - } - - function isUsernameAvailable(next) { - User.getUserFields(uid, ['username', 'userslug'], function(err, userData) { - - var userslug = utils.slugify(data.username); - - if(userslug === userData.userslug) { - return next(null, true); - } - - if(!utils.isUserNameValid(data.username) || !userslug) { - return next(new Error('Invalid Username!'), false); - } - - User.exists(userslug, function(err, exists) { - if(err) { - return next(err); - } - - if(exists) { - next(new Error('Username not available!'), false); - } else { - next(null, true); - } - }); - }); - } - - async.series([isSignatureValid, isEmailAvailable, isUsernameAvailable], function(err, results) { - if (err) { - return callback(err, returnData); - } - - async.each(fields, updateField, function(err) { - if (err) { - return callback(err, returnData); - } - - returnData.success = true; - callback(null, returnData); - }); - }); - - function updateField(field, next) { - if (!(data[field] !== undefined && typeof data[field] === 'string')) { - return next(); - } - - data[field] = data[field].trim(); - data[field] = validator.escape(data[field]); - - if (field === 'email') { - User.getUserFields(uid, ['email', 'picture', 'uploadedpicture'], function(err, userData) { - if (err) { - return next(err); - } - - if(userData.email === data.email) { - return next(); - } - - var gravatarpicture = User.createGravatarURLFromEmail(data.email); - User.setUserField(uid, 'gravatarpicture', gravatarpicture); - - db.deleteObjectField('email:uid', userData.email); - db.setObjectField('email:uid', data.email, uid); - User.setUserField(uid, 'email', data.email); - if (userData.picture !== userData.uploadedpicture) { - returnData.picture = gravatarpicture; - User.setUserField(uid, 'picture', gravatarpicture); - } - returnData.gravatarpicture = gravatarpicture; - - events.logEmailChange(uid, userData.email, data.email); - next(); - }); - return; - } else if (field === 'username') { - - User.getUserFields(uid, ['username', 'userslug'], function(err, userData) { - var userslug = utils.slugify(data.username); - - if(data.username !== userData.username) { - User.setUserField(uid, 'username', data.username); - db.deleteObjectField('username:uid', userData.username); - db.setObjectField('username:uid', data.username, uid); - events.logUsernameChange(uid, userData.username, data.username); - } - - if(userslug !== userData.userslug) { - User.setUserField(uid, 'userslug', userslug); - db.deleteObjectField('userslug:uid', userData.userslug); - db.setObjectField('userslug:uid', userslug, uid); - returnData.userslug = userslug; - } - - next(); - }); - - return; - } else if (field === 'signature') { - data[field] = S(data[field]).stripTags().s; - } else if (field === 'website') { - if(data[field].substr(0, 7) !== 'http://' && data[field].substr(0, 8) !== 'https://') { - data[field] = 'http://' + data[field]; - } - } - - User.setUserField(uid, field, data[field]); - - next(); - } - }; - User.isReadyToPost = function(uid, callback) { User.getUserField(uid, 'lastposttime', function(err, lastposttime) { if(err) { @@ -532,52 +342,43 @@ var bcrypt = require('bcryptjs'), }; User.getUsers = function(set, start, stop, callback) { - - db.getSortedSetRevRange(set, start, stop, function(err, uids) { - if (err) { - return callback(err); + function loadUserInfo(user, callback) { + if (!user) { + return callback(null, user); } - User.getUsersData(uids, function(err, users) { - if (err) { - return callback(err); - } - - async.map(users, function(user, next) { - if (!user) { - return next(null, user); + async.waterfall([ + function(next) { + User.isAdministrator(user.uid, next); + }, + function(isAdmin, next) { + user.status = !user.status ? 'online' : ''; + user.administrator = isAdmin ? '1':'0'; + if (set === 'users:online') { + return callback(null, user); } - - if (!user.status) { - user.status = 'online'; + db.sortedSetScore('users:online', user.uid, next); + }, + function(score, next) { + if (!score) { + user.status = 'offline'; } + next(null, user); + } + ], callback); + } - User.isAdministrator(user.uid, function(err, isAdmin) { - if (err) { - return next(err); - } - - user.administrator = isAdmin ? '1':'0'; - - if(set === 'users:online') { - return next(null, user); - } - - db.sortedSetScore('users:online', user.uid, function(err, score) { - if (err) { - return next(err); - } - - if(!score) { - user.status = 'offline'; - } - - next(null, user); - }); - }); - }, callback); - }); - }); + async.waterfall([ + function(next) { + db.getSortedSetRevRange(set, start, stop, next); + }, + function(uids, next) { + User.getUsersData(uids, next); + }, + function(users, next) { + async.map(users, loadUserInfo, next); + } + ], callback); }; User.createGravatarURLFromEmail = function(email) { @@ -597,36 +398,14 @@ var bcrypt = require('bcryptjs'), User.hashPassword = function(password, callback) { if (!password) { - callback(password); - return; + return callback(password); } bcrypt.genSalt(nconf.get('bcrypt_rounds'), function(err, salt) { - bcrypt.hash(password, salt, callback); - }); - }; - - User.getUsersCSV = function(callback) { - var csvContent = ''; - - db.getObjectValues('username:uid', function(err, uids) { if (err) { return callback(err); } - - User.getMultipleUserFields(uids, ['email', 'username'], function(err, usersData) { - if (err) { - return callback(err); - } - - usersData.forEach(function(user, index) { - if (user) { - csvContent += user.email + ',' + user.username + ',' + uids[index] + '\n'; - } - }); - - callback(null, csvContent); - }); + bcrypt.hash(password, salt, callback); }); }; @@ -688,78 +467,8 @@ var bcrypt = require('bcryptjs'), User.getPostIds = function(uid, start, stop, callback) { db.getSortedSetRevRange('uid:' + uid + ':posts', start, stop, function(err, pids) { - if(err) { - return callback(err); - } - - if (pids && pids.length) { - callback(null, pids); - } else { - callback(null, []); - } - }); - }; - - User.follow = function(uid, followuid, callback) { - toggleFollow('follow', uid, followuid, callback); - }; - - User.unfollow = function(uid, unfollowuid, callback) { - toggleFollow('unfollow', uid, unfollowuid, callback); - }; - - function toggleFollow(type, uid, theiruid, callback) { - var command = type === 'follow' ? 'setAdd' : 'setRemove'; - db[command]('following:' + uid, theiruid, function(err) { - if(err) { - return callback(err); - } - db[command]('followers:' + theiruid, uid, callback); - }); - } - - User.getFollowing = function(uid, callback) { - getFollow('following:' + uid, callback); - }; - - User.getFollowers = function(uid, callback) { - getFollow('followers:' + uid, callback); - }; - - function getFollow(set, callback) { - db.getSetMembers(set, function(err, uids) { - if(err) { - return callback(err); - } - - User.getUsersData(uids, callback); + callback(err, Array.isArray(pids) ? pids : []); }); - } - - User.getFollowingCount = function(uid, callback) { - db.setCount('following:' + uid, callback); - }; - - User.getFollowerCount = function(uid, callback) { - db.setCount('followers:' + uid, callback); - }; - - User.getFollowStats = function (uid, callback) { - async.parallel({ - followingCount: function(next) { - User.getFollowingCount(uid, next); - }, - followerCount : function(next) { - User.getFollowerCount(uid, next); - } - }, callback); - }; - - - - - User.isFollowing = function(uid, theirid, callback) { - db.isSetMember('following:' + uid, theirid, callback); }; User.exists = function(userslug, callback) { @@ -770,13 +479,7 @@ var bcrypt = require('bcryptjs'), User.count = function(callback) { db.getObjectField('global', 'userCount', function(err, count) { - if(err) { - return callback(err); - } - - callback(null, { - count: count ? count : 0 - }); + callback(err, count ? count : 0); }); }; @@ -825,21 +528,5 @@ var bcrypt = require('bcryptjs'), groups.isMemberByGroupName(uid, 'administrators', callback); }; - User.logIP = function(uid, ip) { - db.sortedSetAdd('uid:' + uid + ':ip', +new Date(), ip || 'Unknown'); - }; - - User.getIPs = function(uid, end, callback) { - db.getSortedSetRevRange('uid:' + uid + ':ip', 0, end, function(err, ips) { - if(err) { - return callback(err); - } - - callback(null, ips.map(function(ip) { - return {ip:ip}; - })); - }); - }; - }(exports)); diff --git a/src/user/admin.js b/src/user/admin.js new file mode 100644 index 0000000000..6a94c1715b --- /dev/null +++ b/src/user/admin.js @@ -0,0 +1,46 @@ + +'use strict'; + +var async = require('async'), + db = require('./../database'); + +module.exports = function(User) { + + User.logIP = function(uid, ip) { + db.sortedSetAdd('uid:' + uid + ':ip', Date.now(), ip || 'Unknown'); + }; + + User.getIPs = function(uid, end, callback) { + db.getSortedSetRevRange('uid:' + uid + ':ip', 0, end, function(err, ips) { + if(err) { + return callback(err); + } + + callback(null, ips.map(function(ip) { + return {ip:ip}; + })); + }); + }; + + User.getUsersCSV = function(callback) { + var csvContent = ''; + + async.waterfall([ + function(next) { + db.getObjectValues('username:uid', next); + }, + function(uids, next) { + User.getMultipleUserFields(uids, ['uid', 'email', 'username'], next); + }, + function(usersData, next) { + usersData.forEach(function(user, index) { + if (user) { + csvContent += user.email + ',' + user.username + ',' + user.uid + '\n'; + } + }); + + next(null, csvContent); + } + ], callback); + }; +}; \ No newline at end of file diff --git a/src/useremail.js b/src/user/email.js similarity index 89% rename from src/useremail.js rename to src/user/email.js index 603dc7eee0..74aa01db17 100644 --- a/src/useremail.js +++ b/src/user/email.js @@ -5,12 +5,12 @@ var async = require('async'), nconf = require('nconf'), winston = require('winston'), - user = require('./user'), - utils = require('./../public/src/utils'), - plugins = require('./plugins'), - db = require('./database'), - meta = require('./meta'), - emailer = require('./emailer'); + user = require('./../user'), + utils = require('./../../public/src/utils'), + plugins = require('./../plugins'), + db = require('./../database'), + meta = require('./../meta'), + emailer = require('./../emailer'); (function(UserEmail) { diff --git a/src/user/follow.js b/src/user/follow.js new file mode 100644 index 0000000000..4a354521fc --- /dev/null +++ b/src/user/follow.js @@ -0,0 +1,68 @@ + +'use strict'; + +var async = require('async'), + db = require('./../database'); + +module.exports = function(User) { + + User.follow = function(uid, followuid, callback) { + toggleFollow('follow', uid, followuid, callback); + }; + + User.unfollow = function(uid, unfollowuid, callback) { + toggleFollow('unfollow', uid, unfollowuid, callback); + }; + + function toggleFollow(type, uid, theiruid, callback) { + var command = type === 'follow' ? 'setAdd' : 'setRemove'; + db[command]('following:' + uid, theiruid, function(err) { + if(err) { + return callback(err); + } + db[command]('followers:' + theiruid, uid, callback); + }); + } + + User.getFollowing = function(uid, callback) { + getFollow('following:' + uid, callback); + }; + + User.getFollowers = function(uid, callback) { + getFollow('followers:' + uid, callback); + }; + + function getFollow(set, callback) { + db.getSetMembers(set, function(err, uids) { + if(err) { + return callback(err); + } + + User.getUsersData(uids, callback); + }); + } + + User.getFollowingCount = function(uid, callback) { + db.setCount('following:' + uid, callback); + }; + + User.getFollowerCount = function(uid, callback) { + db.setCount('followers:' + uid, callback); + }; + + User.getFollowStats = function (uid, callback) { + async.parallel({ + followingCount: function(next) { + User.getFollowingCount(uid, next); + }, + followerCount : function(next) { + User.getFollowerCount(uid, next); + } + }, callback); + }; + + User.isFollowing = function(uid, theirid, callback) { + db.isSetMember('following:' + uid, theirid, callback); + }; + +}; \ No newline at end of file diff --git a/src/usernotifications.js b/src/user/notifications.js similarity index 94% rename from src/usernotifications.js rename to src/user/notifications.js index 8228074b12..088caa5760 100644 --- a/src/usernotifications.js +++ b/src/user/notifications.js @@ -5,12 +5,11 @@ var async = require('async'), nconf = require('nconf'), winston = require('winston'), - user = require('./user'), - utils = require('./../public/src/utils'), - db = require('./database'), - notifications = require('./notifications'), - topics = require('./topics'), - websockets = require('./socket.io'); + user = require('./../user'), + utils = require('./../../public/src/utils'), + db = require('./../database'), + notifications = require('./../notifications'), + topics = require('./../topics'); (function(UserNotifications) { @@ -161,7 +160,7 @@ var async = require('async'), }; UserNotifications.pushCount = function(uid) { - + var websockets = require('./../socket.io'); UserNotifications.getUnreadCount(uid, function(err, count) { if (err) { return winston.warn('[User.pushNotifCount] Count not retrieve unread notifications count to push to uid ' + uid + '\'s client(s)'); diff --git a/src/user/profile.js b/src/user/profile.js new file mode 100644 index 0000000000..8273cf72de --- /dev/null +++ b/src/user/profile.js @@ -0,0 +1,196 @@ + +'use strict'; + +var async = require('async'), + validator = require('validator'), + S = require('string'), + + utils = require('./../../public/src/utils'), + meta = require('./../meta'), + events = require('./../events'), + db = require('./../database'); + +module.exports = function(User) { + + User.updateProfile = function(uid, data, callback) { + var fields = ['username', 'email', 'fullname', 'website', 'location', 'birthday', 'signature']; + + function isSignatureValid(next) { + if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) { + next(new Error('Signature can\'t be longer than ' + meta.config.maximumSignatureLength + ' characters!')); + } else { + next(); + } + } + + function isEmailAvailable(next) { + if (!data.email) { + return next(); + } + + User.getUserField(uid, 'email', function(err, email) { + if(email === data.email) { + return next(); + } + + User.email.available(data.email, function(err, available) { + if (err) { + return next(err); + } + + next(!available ? new Error('Email not available!') : null); + + }); + }); + } + + function isUsernameAvailable(next) { + User.getUserFields(uid, ['username', 'userslug'], function(err, userData) { + + var userslug = utils.slugify(data.username); + + if(userslug === userData.userslug) { + return next(); + } + + if(!utils.isUserNameValid(data.username) || !userslug) { + return next(new Error('Invalid Username!')); + } + + User.exists(userslug, function(err, exists) { + if(err) { + return next(err); + } + + next(exists ? new Error('Username not available!') : null); + }); + }); + } + + async.series([isSignatureValid, isEmailAvailable, isUsernameAvailable], function(err, results) { + if (err) { + return callback(err); + } + + async.each(fields, updateField, function(err) { + if (err) { + return callback(err); + } + + User.getUserFields(uid, ['userslug', 'picture', 'gravatarpicture'], callback); + }); + }); + + function updateField(field, next) { + if (!(data[field] !== undefined && typeof data[field] === 'string')) { + return next(); + } + + data[field] = data[field].trim(); + data[field] = validator.escape(data[field]); + + if (field === 'email') { + return updateEmail(uid, data.email, next); + } else if (field === 'username') { + return updateUsername(uid, data.username, next); + } else if (field === 'signature') { + data[field] = S(data[field]).stripTags().s; + } else if (field === 'website') { + if(data[field].substr(0, 7) !== 'http://' && data[field].substr(0, 8) !== 'https://') { + data[field] = 'http://' + data[field]; + } + } + + User.setUserField(uid, field, data[field]); + + next(); + } + }; + + function updateEmail(uid, newEmail, callback) { + User.getUserFields(uid, ['email', 'picture', 'uploadedpicture'], function(err, userData) { + if (err) { + return callback(err); + } + + if(userData.email === newEmail) { + return callback(); + } + + db.deleteObjectField('email:uid', userData.email, function(err) { + if (err) { + return callback(err); + } + + events.logEmailChange(uid, userData.email, newEmail); + + var gravatarpicture = User.createGravatarURLFromEmail(newEmail); + async.parallel([ + function(next) { + User.setUserField(uid, 'gravatarpicture', gravatarpicture, next); + }, + function(next) { + db.setObjectField('email:uid', newEmail, uid, next); + }, + function(next) { + User.setUserField(uid, 'email', newEmail, next); + }, + function(next) { + if (userData.picture !== userData.uploadedpicture) { + User.setUserField(uid, 'picture', gravatarpicture, next); + } + }, + ], callback); + }); + }); + } + + function updateUsername(uid, newUsername, callback) { + User.getUserFields(uid, ['username', 'userslug'], function(err, userData) { + function update(field, object, value, callback) { + async.parallel([ + function(next) { + User.setUserField(uid, field, value, next); + }, + function(next) { + db.setObjectField(object, value, uid, next); + } + ], callback); + } + + if (err) { + return callback(err); + } + var userslug = utils.slugify(newUsername); + + async.parallel([ + function(next) { + if (newUsername === userData.username) { + return next(); + } + + db.deleteObjectField('username:uid', userData.username, function(err) { + if (err) { + return next(err); + } + events.logUsernameChange(uid, userData.username, newUsername); + update('username', 'username:uid', newUsername, next); + }); + }, + function(next) { + if (userslug === userData.userslug) { + return next(); + } + + db.deleteObjectField('userslug:uid', userData.userslug, function(err) { + if (err) { + return next(err); + } + update('userslug', 'userslug:uid', userslug, next); + }); + } + ], callback); + }); + } + +}; \ No newline at end of file diff --git a/src/userreset.js b/src/user/reset.js similarity index 90% rename from src/userreset.js rename to src/user/reset.js index 9561a1b48e..330f49c843 100644 --- a/src/userreset.js +++ b/src/user/reset.js @@ -4,13 +4,13 @@ var async = require('async'), nconf = require('nconf'), - user = require('./user'), - utils = require('./../public/src/utils'), + user = require('./../user'), + utils = require('./../../public/src/utils'), - db = require('./database'), - meta = require('./meta'), - events = require('./events'), - emailer = require('./emailer'); + db = require('./../database'), + meta = require('./../meta'), + events = require('./../events'), + emailer = require('./../emailer'); (function(UserReset) { diff --git a/src/user/settings.js b/src/user/settings.js new file mode 100644 index 0000000000..af1bf9e81b --- /dev/null +++ b/src/user/settings.js @@ -0,0 +1,54 @@ + +'use strict'; + +var meta = require('./../meta'), + db = require('./../database'); + +module.exports = function(User) { + + User.getSettings = function(uid, callback) { + function sendDefaultSettings() { + callback(null, { + showemail: false, + usePagination: parseInt(meta.config.usePagination, 10) === 1, + topicsPerPage: parseInt(meta.config.topicsPerPage, 10) || 20, + postsPerPage: parseInt(meta.config.postsPerPage, 10) || 10 + }); + } + + if(!parseInt(uid, 10)) { + return sendDefaultSettings(); + } + + db.getObject('user:' + uid + ':settings', function(err, settings) { + if(err) { + return callback(err); + } + + if(!settings) { + settings = {}; + } + + settings.showemail = settings.showemail ? parseInt(settings.showemail, 10) !== 0 : false; + settings.usePagination = settings.usePagination ? parseInt(settings.usePagination, 10) === 1 : parseInt(meta.config.usePagination, 10) === 1; + settings.topicsPerPage = settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : parseInt(meta.config.topicsPerPage, 10) || 20; + settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10; + + callback(null, settings); + }); + }; + + User.saveSettings = function(uid, data, callback) { + + if(!data.topicsPerPage || !data.postsPerPage || parseInt(data.topicsPerPage, 10) <= 0 || parseInt(data.postsPerPage, 10) <= 0) { + return callback(new Error('Invalid pagination value!')); + } + + db.setObject('user:' + uid + ':settings', { + showemail: data.showemail, + usePagination: data.usePagination, + topicsPerPage: data.topicsPerPage, + postsPerPage: data.postsPerPage + }, callback); + }; +}; \ No newline at end of file From 970639274e79512b4dff4f4ada31c30e80d2bdb6 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 12 Mar 2014 21:18:39 -0400 Subject: [PATCH 3/7] fixes image uploads if images had special regex characters in them upload text was failing --- public/src/modules/composer.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 01538a6275..a10006a123 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -110,7 +110,6 @@ define(['taskbar'], function(taskbar) { } function removeDraft(save_id) { - console.log('removing draft'); return localStorage.removeItem(save_id); } @@ -273,6 +272,10 @@ define(['taskbar'], function(taskbar) { }); } + function escapeRegExp(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }; + function uploadContentFiles(params) { var files = params.files, post_uuid = params.post_uuid, @@ -299,10 +302,15 @@ define(['taskbar'], function(taskbar) { textarea.val(text); uploadForm.off('submit').submit(function() { + function updateTextArea(filename, text) { + var current = textarea.val(); + var re = new RegExp(escapeRegExp(filename) + "]\\([^)]+\\)", 'g'); + textarea.val(current.replace(re, filename + '](' + text + ')')); + } $(this).find('#postUploadCsrf').val($('#csrf_token').val()); - if(formData) { + if (formData) { formData.append('_csrf', $('#csrf_token').val()); } @@ -317,15 +325,14 @@ define(['taskbar'], function(taskbar) { xhr = maybeParse(xhr); app.alertError('Error uploading file!\nStatus : ' + xhr.status + '\nMessage : ' + xhr.responseText); - if (typeof callback == 'function') + if (typeof callback === 'function') { callback(xhr); + } }, uploadProgress: function(event, position, total, percent) { - var current = textarea.val(); for(var i=0; i < files.length; ++i) { - var re = new RegExp(files[i].name + "]\\([^)]+\\)", 'g'); - textarea.val(current.replace(re, files[i].name+'](uploading ' + percent + '%)')); + updateTextArea(files[i].name, 'uploading' + percent + '%'); } }, @@ -334,15 +341,14 @@ define(['taskbar'], function(taskbar) { if(uploads && uploads.length) { for(var i=0; i Date: Wed, 12 Mar 2014 21:41:53 -0400 Subject: [PATCH 4/7] categories refactor --- src/categories.js | 127 +------------------------------- src/categories/activeusers.js | 83 +++++++++++++++++++++ src/categories/recentreplies.js | 62 ++++++++++++++++ 3 files changed, 148 insertions(+), 124 deletions(-) create mode 100644 src/categories/activeusers.js create mode 100644 src/categories/recentreplies.js diff --git a/src/categories.js b/src/categories.js index c2cddcf744..134fea78f2 100644 --- a/src/categories.js +++ b/src/categories.js @@ -17,6 +17,9 @@ var db = require('./database'), (function(Categories) { + require('./categories/activeusers')(Categories); + require('./categories/recentreplies')(Categories); + Categories.create = function(data, callback) { db.incrObjectField('global', 'nextCid', function(err, cid) { if (err) { @@ -56,7 +59,6 @@ var db = require('./database'), }; Categories.getCategoryById = function(cid, start, end, uid, callback) { - CategoryTools.exists(cid, function(err, exists) { if(err || !exists) { return callback(err || new Error('category-not-found [' + cid + ']')); @@ -226,56 +228,6 @@ var db = require('./database'), db.isSetMember('cid:' + cid + ':read_by_uid', uid, callback); }; - Categories.getRecentReplies = function(cid, uid, count, callback) { - if(count === 0 || !count) { - return callback(null, []); - } - - CategoryTools.privileges(cid, uid, function(err, privileges) { - if(err) { - return callback(err); - } - - if (!privileges.read) { - return callback(null, []); - } - - db.getSortedSetRevRange('categories:recent_posts:cid:' + cid, 0, count - 1, function(err, pids) { - if (err) { - return callback(err, []); - } - - if (!pids || !pids.length) { - return callback(null, []); - } - - posts.getPostSummaryByPids(pids, true, callback); - }); - }); - }; - - Categories.moveRecentReplies = function(tid, oldCid, cid, callback) { - function movePost(pid, callback) { - posts.getPostField(pid, 'timestamp', function(err, timestamp) { - if(err) { - return callback(err); - } - - db.sortedSetRemove('categories:recent_posts:cid:' + oldCid, pid); - db.sortedSetAdd('categories:recent_posts:cid:' + cid, timestamp, pid); - callback(); - }); - } - - topics.getPids(tid, function(err, pids) { - if(err) { - return callback(err); - } - - async.each(pids, movePost, callback); - }); - }; - Categories.getCategoryData = function(cid, callback) { Categories.getCategoriesData([cid], function(err, categories) { callback(err, categories ? categories[0] : null); @@ -351,79 +303,6 @@ var db = require('./database'), }); }; - Categories.isUserActiveIn = function(cid, uid, callback) { - - db.getSortedSetRange('uid:' + uid + ':posts', 0, -1, function(err, pids) { - if (err) { - return callback(err); - } - - var index = 0, - active = false; - - async.whilst( - function() { - return active === false && index < pids.length; - }, - function(callback) { - posts.getCidByPid(pids[index], function(err, postCid) { - if (err) { - return callback(err); - } - - if (postCid === cid) { - active = true; - } - - ++index; - callback(); - }); - }, - function(err) { - callback(err, active); - } - ); - }); - }; - - Categories.addActiveUser = function(cid, uid, timestamp) { - if(parseInt(uid, 10)) { - db.sortedSetAdd('cid:' + cid + ':active_users', timestamp, uid); - } - }; - - Categories.removeActiveUser = function(cid, uid) { - db.sortedSetRemove('cid:' + cid + ':active_users', uid); - }; - - Categories.getActiveUsers = function(cid, callback) { - db.getSortedSetRevRange('cid:' + cid + ':active_users', 0, 23, callback); - }; - - Categories.moveActiveUsers = function(tid, oldCid, cid, callback) { - function updateUser(uid, timestamp) { - Categories.addActiveUser(cid, uid, timestamp); - Categories.isUserActiveIn(oldCid, uid, function(err, active) { - - if (!err && !active) { - Categories.removeActiveUser(oldCid, uid); - } - }); - } - - topics.getTopicField(tid, 'timestamp', function(err, timestamp) { - if(!err) { - topics.getUids(tid, function(err, uids) { - if (!err && uids) { - for (var i = 0; i < uids.length; ++i) { - updateUser(uids[i], timestamp); - } - } - }); - } - }); - }; - Categories.onNewPostMade = function(uid, tid, pid, timestamp) { topics.getTopicFields(tid, ['cid', 'pinned'], function(err, topicData) { diff --git a/src/categories/activeusers.js b/src/categories/activeusers.js new file mode 100644 index 0000000000..059432f3e5 --- /dev/null +++ b/src/categories/activeusers.js @@ -0,0 +1,83 @@ +'use strict'; + +var async = require('async'), + + db = require('./../database'), + posts = require('./../posts'), + topics = require('./../topics'); + +module.exports = function(Categories) { + + Categories.isUserActiveIn = function(cid, uid, callback) { + + db.getSortedSetRange('uid:' + uid + ':posts', 0, -1, function(err, pids) { + if (err) { + return callback(err); + } + + var index = 0, + active = false; + + async.whilst( + function() { + return active === false && index < pids.length; + }, + function(callback) { + posts.getCidByPid(pids[index], function(err, postCid) { + if (err) { + return callback(err); + } + + if (postCid === cid) { + active = true; + } + + ++index; + callback(); + }); + }, + function(err) { + callback(err, active); + } + ); + }); + }; + + Categories.addActiveUser = function(cid, uid, timestamp) { + if(parseInt(uid, 10)) { + db.sortedSetAdd('cid:' + cid + ':active_users', timestamp, uid); + } + }; + + Categories.removeActiveUser = function(cid, uid) { + db.sortedSetRemove('cid:' + cid + ':active_users', uid); + }; + + Categories.getActiveUsers = function(cid, callback) { + db.getSortedSetRevRange('cid:' + cid + ':active_users', 0, 23, callback); + }; + + Categories.moveActiveUsers = function(tid, oldCid, cid, callback) { + function updateUser(uid, timestamp) { + Categories.addActiveUser(cid, uid, timestamp); + Categories.isUserActiveIn(oldCid, uid, function(err, active) { + + if (!err && !active) { + Categories.removeActiveUser(oldCid, uid); + } + }); + } + + topics.getTopicField(tid, 'timestamp', function(err, timestamp) { + if(!err) { + topics.getUids(tid, function(err, uids) { + if (!err && uids) { + for (var i = 0; i < uids.length; ++i) { + updateUser(uids[i], timestamp); + } + } + }); + } + }); + }; +}; \ No newline at end of file diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js new file mode 100644 index 0000000000..a5dd10bc4e --- /dev/null +++ b/src/categories/recentreplies.js @@ -0,0 +1,62 @@ + +'use strict'; + +var async = require('async'), + db = require('./../database'), + posts = require('./../posts'), + topics = require('./../topics'), + CategoryTools = require('./../categoryTools'); + +module.exports = function(Categories) { + Categories.getRecentReplies = function(cid, uid, count, callback) { + if(count === 0 || !count) { + return callback(null, []); + } + + CategoryTools.privileges(cid, uid, function(err, privileges) { + if(err) { + return callback(err); + } + + if (!privileges.read) { + return callback(null, []); + } + + db.getSortedSetRevRange('categories:recent_posts:cid:' + cid, 0, count - 1, function(err, pids) { + if (err) { + return callback(err, []); + } + + if (!pids || !pids.length) { + return callback(null, []); + } + + posts.getPostSummaryByPids(pids, true, callback); + }); + }); + }; + + Categories.moveRecentReplies = function(tid, oldCid, cid, callback) { + function movePost(pid, callback) { + posts.getPostField(pid, 'timestamp', function(err, timestamp) { + if(err) { + return callback(err); + } + + db.sortedSetRemove('categories:recent_posts:cid:' + oldCid, pid); + db.sortedSetAdd('categories:recent_posts:cid:' + cid, timestamp, pid); + callback(); + }); + } + + topics.getPids(tid, function(err, pids) { + if(err) { + return callback(err); + } + + async.each(pids, movePost, callback); + }); + }; +}; + + From 383b68e7fc53777dad680ddd3a16e2fb5ba25ed1 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 12 Mar 2014 21:57:25 -0400 Subject: [PATCH 5/7] user js refactor --- src/user.js | 71 --------------------------------------------- src/user/admin.js | 8 +++++ src/user/profile.js | 62 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 72 deletions(-) diff --git a/src/user.js b/src/user.js index 360266e887..78184bdbdd 100644 --- a/src/user.js +++ b/src/user.js @@ -159,14 +159,6 @@ var bcrypt = require('bcryptjs'), }); }; - User.ban = function(uid, callback) { - User.setUserField(uid, 'banned', 1, callback); - }; - - User.unban = function(uid, callback) { - User.setUserField(uid, 'banned', 0, callback); - }; - User.getUserField = function(uid, field, callback) { db.getObjectField('user:' + uid, field, callback); }; @@ -229,8 +221,6 @@ var bcrypt = require('bcryptjs'), }); }; - - User.updateLastOnlineTime = function(uid, callback) { User.getUserField(uid, 'status', function(err, status) { function cb(err) { @@ -264,67 +254,6 @@ var bcrypt = require('bcryptjs'), }); }; - User.changePassword = function(uid, data, callback) { - if(!data || !data.uid) { - return callback(new Error('invalid-uid')); - } - - function hashAndSetPassword(callback) { - User.hashPassword(data.newPassword, function(err, hash) { - if(err) { - return callback(err); - } - - User.setUserField(data.uid, 'password', hash, function(err) { - if(err) { - return callback(err); - } - - if(parseInt(uid, 10) === parseInt(data.uid, 10)) { - events.logPasswordChange(data.uid); - } else { - events.logAdminChangeUserPassword(uid, data.uid); - } - - callback(); - }); - }); - } - - if (!utils.isPasswordValid(data.newPassword)) { - return callback(new Error('Invalid password!')); - } - - if(parseInt(uid, 10) !== parseInt(data.uid, 10)) { - User.isAdministrator(uid, function(err, isAdmin) { - if(err || !isAdmin) { - return callback(err || new Error('not-allowed')); - } - - hashAndSetPassword(callback); - }); - } else { - User.getUserField(uid, 'password', function(err, currentPassword) { - if(err) { - return callback(err); - } - - if (currentPassword !== null) { - bcrypt.compare(data.currentPassword, currentPassword, function(err, res) { - if (err || !res) { - return callback(err || new Error('Your current password is not correct!')); - } - - hashAndSetPassword(callback); - }); - } else { - // No password in account (probably SSO login) - hashAndSetPassword(callback); - } - }); - } - }; - User.setUserField = function(uid, field, value, callback) { db.setObjectField('user:' + uid, field, value, callback); }; diff --git a/src/user/admin.js b/src/user/admin.js index 6a94c1715b..ece5b56cf3 100644 --- a/src/user/admin.js +++ b/src/user/admin.js @@ -43,4 +43,12 @@ module.exports = function(User) { } ], callback); }; + + User.ban = function(uid, callback) { + User.setUserField(uid, 'banned', 1, callback); + }; + + User.unban = function(uid, callback) { + User.setUserField(uid, 'banned', 0, callback); + }; }; \ No newline at end of file diff --git a/src/user/profile.js b/src/user/profile.js index 8273cf72de..e1fc6284d4 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -1,7 +1,8 @@ 'use strict'; -var async = require('async'), +var bcrypt = require('bcryptjs'), + async = require('async'), validator = require('validator'), S = require('string'), @@ -193,4 +194,63 @@ module.exports = function(User) { }); } + User.changePassword = function(uid, data, callback) { + if(!data || !data.uid) { + return callback(new Error('invalid-uid')); + } + + function hashAndSetPassword(callback) { + User.hashPassword(data.newPassword, function(err, hash) { + if(err) { + return callback(err); + } + + User.setUserField(data.uid, 'password', hash, function(err) { + if(err) { + return callback(err); + } + + if(parseInt(uid, 10) === parseInt(data.uid, 10)) { + events.logPasswordChange(data.uid); + } else { + events.logAdminChangeUserPassword(uid, data.uid); + } + + callback(); + }); + }); + } + + if (!utils.isPasswordValid(data.newPassword)) { + return callback(new Error('Invalid password!')); + } + + if(parseInt(uid, 10) !== parseInt(data.uid, 10)) { + User.isAdministrator(uid, function(err, isAdmin) { + if(err || !isAdmin) { + return callback(err || new Error('not-allowed')); + } + + hashAndSetPassword(callback); + }); + } else { + User.getUserField(uid, 'password', function(err, currentPassword) { + if(err) { + return callback(err); + } + + if (!currentPassword) { + return hashAndSetPassword(callback); + } + + bcrypt.compare(data.currentPassword, currentPassword, function(err, res) { + if (err || !res) { + return callback(err || new Error('Your current password is not correct!')); + } + hashAndSetPassword(callback); + }); + }); + } + }; + }; \ No newline at end of file From d8e00f95a2027e9e87379a0d6fa34f9d5175ec4b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 12 Mar 2014 22:11:48 -0400 Subject: [PATCH 6/7] moved user search to its own file --- src/socket.io/user.js | 5 ++++- src/user.js | 39 +------------------------------------ src/user/search.js | 45 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 src/user/search.js diff --git a/src/socket.io/user.js b/src/socket.io/user.js index f62e95ccfd..c3094fbcff 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -1,3 +1,5 @@ +'use strict'; + var async = require('async'), user = require('../user'), topics = require('../topics'), @@ -93,8 +95,9 @@ SocketUser.updateProfile = function(socket, data, callback) { if(err) { return callback(err); } + if(!isAdmin) { - return callback(new Error('not allowed!')) + return callback(new Error('not allowed!')); } user.updateProfile(data.uid, data, callback); diff --git a/src/user.js b/src/user.js index 78184bdbdd..fcabfbb0de 100644 --- a/src/user.js +++ b/src/user.js @@ -27,6 +27,7 @@ var bcrypt = require('bcryptjs'), require('./user/profile')(User); require('./user/admin')(User); require('./user/settings')(User); + require('./user/search')(User); User.create = function(userData, callback) { userData = userData || {}; @@ -338,44 +339,6 @@ var bcrypt = require('bcryptjs'), }); }; - User.search = function(query, callback) { - if (!query || query.length === 0) { - return callback(null, {timing:0, users:[]}); - } - var start = process.hrtime(); - - db.getObject('username:uid', function(err, usernamesHash) { - if (err) { - return callback(null, {timing: 0, users:[]}); - } - - query = query.toLowerCase(); - - var usernames = Object.keys(usernamesHash), - uids = []; - - uids = usernames.filter(function(username) { - return username.toLowerCase().indexOf(query) === 0; - }) - .slice(0, 10) - .sort(function(a, b) { - return a > b; - }) - .map(function(username) { - return usernamesHash[username]; - }); - - User.getUsersData(uids, function(err, userdata) { - if (err) { - return callback(err); - } - var diff = process.hrtime(start); - var timing = (diff[0] * 1e3 + diff[1] / 1e6).toFixed(1); - callback(null, {timing: timing, users: userdata}); - }); - }); - }; - User.onNewPostMade = function(uid, tid, pid, timestamp) { User.addPostIdToUser(uid, pid, timestamp); diff --git a/src/user/search.js b/src/user/search.js new file mode 100644 index 0000000000..587f175352 --- /dev/null +++ b/src/user/search.js @@ -0,0 +1,45 @@ + +'use strict'; + +var db = require('./../database'); + +module.exports = function(User) { + User.search = function(query, callback) { + if (!query || query.length === 0) { + return callback(null, {timing:0, users:[]}); + } + var start = process.hrtime(); + + db.getObject('username:uid', function(err, usernamesHash) { + if (err) { + return callback(null, {timing: 0, users:[]}); + } + + query = query.toLowerCase(); + + var usernames = Object.keys(usernamesHash), + uids = []; + + uids = usernames.filter(function(username) { + return username.toLowerCase().indexOf(query) === 0; + }) + .slice(0, 10) + .sort(function(a, b) { + return a > b; + }) + .map(function(username) { + return usernamesHash[username]; + }); + + User.getUsersData(uids, function(err, userdata) { + if (err) { + return callback(err); + } + var diff = process.hrtime(start); + var timing = (diff[0] * 1e3 + diff[1] / 1e6).toFixed(1); + callback(null, {timing: timing, users: userdata}); + }); + }); + }; +}; + From 7668b95c66a1265786347b1aa0c947043573009a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 12 Mar 2014 23:18:54 -0400 Subject: [PATCH 7/7] register.js cleanup --- public/src/forum/register.js | 243 ++++++++++++++++++----------------- 1 file changed, 127 insertions(+), 116 deletions(-) diff --git a/public/src/forum/register.js b/public/src/forum/register.js index 674f53af6e..6d189cdad3 100644 --- a/public/src/forum/register.js +++ b/public/src/forum/register.js @@ -1,151 +1,162 @@ -define(function() { - var Register = {}; +'use strict'; - Register.init = function() { - var username = $('#username'), - password = $('#password'), - password_confirm = $('#password-confirm'), - register = $('#register'), - emailEl = $('#email'), - username_notify = $('#username-notify'), - email_notify = $('#email-notify'), - password_notify = $('#password-notify'), - password_confirm_notify = $('#password-confirm-notify'), - agreeTerms = $('#agree-terms'), - validationError = false, - successIcon = ''; +/* globals define, app, utils, socket, config */ - $('#referrer').val(app.previousUrl); - function showError(element, msg) { - element.html(msg); - element.parent() - .removeClass('alert-success') - .addClass('alert-danger'); - element.show(); +define(function() { + var Register = {}, + validationError = false, + successIcon = ''; + + function showError(element, msg) { + element.html(msg); + element.parent() + .removeClass('alert-success') + .addClass('alert-danger'); + element.show(); + validationError = true; + } + + function showSuccess(element, msg) { + element.html(msg); + element.parent() + .removeClass('alert-danger') + .addClass('alert-success'); + element.show(); + } + + function validateEmail(email) { + var email_notify = $('#email-notify'); + + if (!email) { validationError = true; + return; } - function showSuccess(element, msg) { - element.html(msg); - element.parent() - .removeClass('alert-danger') - .addClass('alert-success'); - element.show(); + if (!utils.isEmailValid(email)) { + showError(email_notify, 'Invalid email address.'); + return; } - function validateEmail() { - if (!emailEl.val()) { - validationError = true; - return; + socket.emit('user.emailExists', { + email: email + }, function(err, exists) { + if(err) { + return app.alertError(err.message); } - if (!utils.isEmailValid(emailEl.val())) { - showError(email_notify, 'Invalid email address.'); + if (exists) { + showError(email_notify, 'Email address already taken!'); } else { - socket.emit('user.emailExists', { - email: emailEl.val() - }, function(err, exists) { - if(err) { - return app.alertError(err.message); - } - - if (exists) { - showError(email_notify, 'Email address already taken!'); - } else { - showSuccess(email_notify, successIcon); - } - }); + showSuccess(email_notify, successIcon); } - } - - emailEl.on('blur', function() { - validateEmail(); }); + } - function validateUsername() { - if (!username.val()) { - validationError = true; - return; - } + function validateUsername(username) { + var username_notify = $('#username-notify'); - if (username.val().length < config.minimumUsernameLength) { - showError(username_notify, 'Username too short!'); - } else if (username.val().length > config.maximumUsernameLength) { - showError(username_notify, 'Username too long!'); - } else if (!utils.isUserNameValid(username.val()) || !utils.slugify(username.val())) { - showError(username_notify, 'Invalid username!'); - } else { - socket.emit('user.exists', { - username: username.val() - }, function(err, exists) { - if(err) { - return app.alertError(err.message); - } - - if (exists) { - showError(username_notify, 'Username already taken!'); - } else { - showSuccess(username_notify, successIcon); - } - }); - } + if (!username) { + validationError = true; + return; } - username.on('keyup', function() { - $('#yourUsername').html(this.value.length > 0 ? this.value : 'username'); - }); + if (username.length < config.minimumUsernameLength) { + showError(username_notify, 'Username too short!'); + } else if (username.length > config.maximumUsernameLength) { + showError(username_notify, 'Username too long!'); + } else if (!utils.isUserNameValid(username) || !utils.slugify(username)) { + showError(username_notify, 'Invalid username!'); + } else { + socket.emit('user.exists', { + username: username + }, function(err, exists) { + if(err) { + return app.alertError(err.message); + } - username.on('blur', function() { - validateUsername(); - }); + if (exists) { + showError(username_notify, 'Username already taken!'); + } else { + showSuccess(username_notify, successIcon); + } + }); + } + } - function validatePassword() { - if (!password.val()) { - validationError = true; - return; - } + function validatePassword(password, password_confirm) { + if (!password) { + validationError = true; + return; + } + var password_notify = $('#password-notify'), + password_confirm_notify = $('#password-confirm-notify'); + + if (password.length < config.minimumPasswordLength) { + showError(password_notify, 'Password too short!'); + } else if (!utils.isPasswordValid(password)) { + showError(password_notify, 'Invalid password!'); + } else { + showSuccess(password_notify, successIcon); + } - if (password.val().length < config.minimumPasswordLength) { - showError(password_notify, 'Password too short!'); - } else if (!utils.isPasswordValid(password.val())) { - showError(password_notify, 'Invalid password!'); - } else { - showSuccess(password_notify, successIcon); - } + if (password !== password_confirm && password_confirm !== '') { + showError(password_confirm_notify, 'Passwords must match!'); + } + } - if (password.val() !== password_confirm.val() && password_confirm.val() !== '') { - showError(password_confirm_notify, 'Passwords must match!'); - } + function validatePasswordConfirm(password, password_confirm) { + var password_notify = $('#password-notify'), + password_confirm_notify = $('#password-confirm-notify'); + + if (!password || password_notify.hasClass('alert-error')) { + return; } - $(password).on('blur', function() { - validatePassword(); + if (password !== password_confirm) { + showError(password_confirm_notify, 'Passwords must match!'); + } else { + showSuccess(password_confirm_notify, successIcon); + } + } + + Register.init = function() { + var email = $('#email'), + username = $('#username'), + password = $('#password'), + password_confirm = $('#password-confirm'), + register = $('#register'), + agreeTerms = $('#agree-terms'); + + $('#referrer').val(app.previousUrl); + + email.on('blur', function() { + validateEmail(email.val()); }); - function validatePasswordConfirm() { - if (!password.val() || password_notify.hasClass('alert-error')) { - return; - } + username.on('keyup', function() { + $('#yourUsername').html(this.value.length > 0 ? this.value : 'username'); + }); - if (password.val() !== password_confirm.val()) { - showError(password_confirm_notify, 'Passwords must match!'); - } else { - showSuccess(password_confirm_notify, successIcon); - } - } + username.on('blur', function() { + validateUsername(username.val()); + }); + + password.on('blur', function() { + validatePassword(password.val(), password_confirm.val()); + }); - $(password_confirm).on('blur', function() { - validatePasswordConfirm(); + password_confirm.on('blur', function() { + validatePasswordConfirm(password.val(), password_confirm.val()); }); function validateForm() { validationError = false; - validateEmail(); - validateUsername(); - validatePassword(); - validatePasswordConfirm(); + validateEmail(email.val()); + validateUsername(username.val()); + validatePassword(password.val(), password_confirm.val()); + validatePasswordConfirm(password.val(), password_confirm.val()); return validationError; }