diff --git a/public/src/forum/users.js b/public/src/forum/users.js index 4106ebde34..f10c739918 100644 --- a/public/src/forum/users.js +++ b/public/src/forum/users.js @@ -111,7 +111,7 @@ define(function() { function onUsersLoaded(users, emptyContainer) { templates.preload_template('users', function() { - templates['useres'].parse({users:[]}); + templates['users'].parse({users:[]}); var html = templates.prepare(templates['users'].blocks['users']).parse({ users: users }); diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 80bf88baa9..71e28308cf 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -130,7 +130,11 @@ accountsController.getAccount = function(req, res, next) { }); } - user.isFollowing(callerUID, userData.theirid, function (isFollowing) { + user.isFollowing(callerUID, userData.theirid, function (err, isFollowing) { + if(err) { + return next(err); + } + posts.getPostsByUid(callerUID, userData.theirid, 0, 9, function (err, userPosts) { if(err) { return next(err); @@ -161,53 +165,39 @@ accountsController.getAccount = function(req, res, next) { }; accountsController.getFollowing = function(req, res, next) { - var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; - - getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) { - if(err) { - return next(err); - } - - if (userData) { - user.getFollowing(userData.uid, function (err, followingData) { - if(err) { - return next(err); - } - userData.following = followingData; - userData.followingCount = followingData.length; - - res.render('following', userData); - }); - - } else { - return userNotFound(); - } - }); + getFollow('following', req, res, next); }; accountsController.getFollowers = function(req, res, next) { + getFollow('followers', req, res, next); +}; + +function getFollow(name, req, res, next) { var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; + var userData; - getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) { + async.waterfall([ + function(next) { + getUserDataByUserSlug(req.params.userslug, callerUID, next); + }, + function(data, next) { + userData = data; + if (!userData) { + return userNotFound(); + } + var method = name === 'following' ? 'getFollowing' : 'getFollowers'; + user[method](userData.uid, next); + } + ], function(err, users) { if(err) { return next(err); } + userData[name] = users; + userData[name + 'Count'] = users.length; - if (userData) { - user.getFollowers(userData.uid, function (err, followersData) { - if(err) { - return next(err); - } - userData.followers = followersData; - userData.followersCount = followersData.length; - - res.render('followers', userData); - }); - } else { - return userNotFound(); - } + res.render(name, userData); }); -}; +} accountsController.getFavourites = function(req, res, next) { var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; @@ -286,7 +276,7 @@ accountsController.accountEdit = function(req, res, next) { if(err) { return next(err); } - + res.render('accountedit', userData); }); }; @@ -323,12 +313,12 @@ accountsController.accountSettings = function(req, res, next) { userData.yourid = req.user.uid; userData.theirid = uid; userData.settings = settings; - + res.render('accountsettings', userData); }); }); - }); + }); }; accountsController.uploadPicture = function (req, res, next) { diff --git a/src/controllers/index.js b/src/controllers/index.js index e43d08a9c1..7caec05855 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -183,6 +183,7 @@ Controllers.login = function(req, res, next) { }; Controllers.register = function(req, res, next) { + var data = {}, login_strategies = auth.get_login_strategies(), num_strategies = login_strategies.length; @@ -206,7 +207,7 @@ Controllers.register = function(req, res, next) { data.maximumUsernameLength = meta.config.maximumUsernameLength; data.minimumPasswordLength = meta.config.minimumPasswordLength; data.termsOfUse = meta.config.termsOfUse; - + res.render('register', data); }; diff --git a/src/controllers/topics.js b/src/controllers/topics.js index b6fe70caac..8edf274e15 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -47,8 +47,8 @@ topicsController.get = function(req, res, next) { if (parseInt(topicData.deleted, 10) === 1 && parseInt(topicData.expose_tools, 10) === 0) { return next(new Error('Topic deleted'), null); } + topicData.currentPage = page; } - topicData.currentPage = page; next(err, topicData); }); }); diff --git a/src/database/mongo.js b/src/database/mongo.js index 78b3914cc2..92a80cebf7 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -100,6 +100,26 @@ return null; } + function fieldToString(field) { + if(field === null || field === undefined) { + return field; + } + + if(typeof field !== 'string') { + field = field.toString(); + } + // if there is a '.' in the field name it inserts subdocument in mongo, replace '.'s with \uff0E + field = field.replace(/\./g, '\uff0E'); + return field; + } + + function toString(value) { + if(value === null || value === undefined) { + return value; + } + + return value.toString(); + } // // Exported functions @@ -235,11 +255,7 @@ module.setObjectField = function(key, field, value, callback) { var data = {}; - if(typeof field !== 'string') { - field = field.toString(); - } - // if there is a '.' in the field name it inserts subdocument in mongo, replace '.'s with \uff0E - field = field.replace(/\./g, '\uff0E'); + field = fieldToString(field); data[field] = value; db.collection('objects').update({_key:key}, {$set:data}, {upsert:true, w: 1}, function(err, result) { if(typeof callback === 'function') { @@ -271,51 +287,69 @@ }; module.getObjectField = function(key, field, callback) { - if(typeof field !== 'string') { - field = field.toString(); - } - field = field.replace(/\./g, '\uff0E'); + field = fieldToString(field); module.getObjectFields(key, [field], function(err, data) { if(err) { return callback(err); } - callback(null, data[field]); + callback(null, data ? data[field] : null); }); }; module.getObjectFields = function(key, fields, callback) { + module.getObjectsFields([key], fields, function(err, items) { + callback(err, items ? items[0] : null); + }); + }; + + module.getObjectsFields = function(keys, fields, callback) { var _fields = { - _id: 0 + _id: 0, + _key: 1 }; - for(var i=0; i 0 + finalText = usernames.join(', ') + (rest_amount > 0 ? " and " + rest_amount + (rest_amount > 1 ? " others" : " other") : ""); - callback(null, usernames); + callback(null, finalText); }); }); }; diff --git a/src/user.js b/src/user.js index 4edf9a77cf..0bb7bbbaac 100644 --- a/src/user.js +++ b/src/user.js @@ -168,32 +168,51 @@ var bcrypt = require('bcryptjs'), }; User.getMultipleUserFields = function(uids, fields, callback) { - if (uids.length === 0) { + + if (!Array.isArray(uids) || !uids.length) { return callback(null, []); } - function getFields(uid, next) { - User.getUserFields(uid, fields, next); - } + var keys = uids.map(function(uid) { + return 'user:' + uid; + }); - async.map(uids, getFields, callback); + db.getObjectsFields(keys, fields, callback); }; User.getUserData = function(uid, callback) { - db.getObject('user:' + uid, function(err, data) { - if(err) { + User.getUsersData([uid], function(err, users) { + callback(err, users ? users[0] : null); + }); + }; + + User.getUsersData = function(uids, callback) { + + if (!Array.isArray(uids) || !uids.length) { + return callback(null, []); + } + + var keys = uids.map(function(uid) { + return 'user:' + uid; + }); + + db.getObjects(keys, function(err, users) { + if (err) { return callback(err); } - if (data) { - if (data.password) { - data.password = null; - data.hasPassword = true; - } else { - data.hasPassword = false; + users.forEach(function(user) { + if (user) { + if (user.password) { + user.password = null; + user.hasPassword = true; + } else { + user.hasPassword = false; + } } - } - callback(err, data); + }); + + callback(null, users); }); }; @@ -508,36 +527,48 @@ var bcrypt = require('bcryptjs'), db.getSortedSetRevRange(set, start, stop, function(err, uids) { if (err) { - return callback(err, null); + return callback(err); } - function getUserData(uid, callback) { - User.getUserData(uid, function(err, userData) { - if(!userData.status) { - userData.status = 'online'; + User.getUsersData(uids, function(err, users) { + if (err) { + return callback(err); + } + + async.map(users, function(user, next) { + if (!user) { + return next(null, user); } - User.isAdministrator(uid, function(err, isAdmin) { - if (userData) { - userData.administrator = isAdmin ? '1':'0'; + if (!user.status) { + user.status = 'online'; + } + + User.isAdministrator(user.uid, function(err, isAdmin) { + if (err) { + return next(err); } + user.administrator = isAdmin ? '1':'0'; + if(set === 'users:online') { - return callback(null, userData); + return next(null, user); } - db.sortedSetScore('users:online', uid, function(err, score) { + db.sortedSetScore('users:online', user.uid, function(err, score) { + if (err) { + return next(err); + } + if(!score) { - userData.status = 'offline'; + user.status = 'offline'; } - callback(null, userData); + next(null, user); }); }); - }); - } - - async.map(uids, getUserData, callback); + }, callback); + }); }); }; @@ -568,24 +599,25 @@ var bcrypt = require('bcryptjs'), }; User.getUsersCSV = function(callback) { - var csvContent = ""; + var csvContent = ''; db.getObjectValues('username:uid', function(err, uids) { - if(err) { + if (err) { return callback(err); } - async.each(uids, function(uid, next) { - User.getUserFields(uid, ['email', 'username'], function(err, userData) { - if(err) { - return next(err); - } + User.getMultipleUserFields(uids, ['email', 'username'], function(err, usersData) { + if (err) { + return callback(err); + } - csvContent += userData.email + ',' + userData.username + ',' + uid + '\n'; - next(); + usersData.forEach(function(user, index) { + if (user) { + csvContent += user.email + ',' + user.username + ',' + uids[index] + '\n'; + } }); - }, function(err) { - callback(err, csvContent); + + callback(null, csvContent); }); }); }; @@ -604,9 +636,9 @@ var bcrypt = require('bcryptjs'), query = query.toLowerCase(); var usernames = Object.keys(usernamesHash), - results = []; + uids = []; - results = usernames.filter(function(username) { + uids = usernames.filter(function(username) { return username.toLowerCase().indexOf(query) === 0; }) .slice(0, 10) @@ -617,7 +649,10 @@ var bcrypt = require('bcryptjs'), return usernamesHash[username]; }); - User.getDataForUsers(results, function(err, userdata) { + 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}); @@ -657,70 +692,48 @@ var bcrypt = require('bcryptjs'), }); }; - User.follow = function(uid, followid, callback) { - db.setAdd('following:' + uid, followid, function(err, data) { - if(err) { - return callback(err); - } + User.follow = function(uid, followuid, callback) { + toggleFollow('follow', uid, followuid, callback); + }; - db.setAdd('followers:' + followid, uid, callback); - }); + User.unfollow = function(uid, unfollowuid, callback) { + toggleFollow('unfollow', uid, unfollowuid, callback); }; - User.unfollow = function(uid, unfollowid, callback) { - db.setRemove('following:' + uid, unfollowid, function(err, data) { + 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.setRemove('followers:' + unfollowid, uid, callback); + db[command]('followers:' + theiruid, uid, callback); }); - }; + } User.getFollowing = function(uid, callback) { - db.getSetMembers('following:' + uid, function(err, userIds) { - if(err) { - return callback(err); - } - - User.getDataForUsers(userIds, callback); - }); + getFollow('following:' + uid, callback); }; User.getFollowers = function(uid, callback) { - db.getSetMembers('followers:' + uid, function(err, userIds) { + getFollow('followers:' + uid, callback); + }; + + function getFollow(set, callback) { + db.getSetMembers(set, function(err, uids) { if(err) { return callback(err); } - User.getDataForUsers(userIds, callback); + User.getUsersData(uids, callback); }); - }; + } User.getFollowingCount = function(uid, callback) { - db.getSetMembers('following:' + uid, function(err, userIds) { - if (err) { - return callback(err); - } - - userIds = userIds.filter(function(value) { - return parseInt(value, 10) !== 0; - }); - callback(null, userIds.length); - }); + db.setCount('following:' + uid, callback); }; User.getFollowerCount = function(uid, callback) { - db.getSetMembers('followers:' + uid, function(err, userIds) { - if(err) { - return callback(err); - } - - userIds = userIds.filter(function(value) { - return parseInt(value, 10) !== 0; - }); - callback(null, userIds.length); - }); + db.setCount('followers:' + uid, callback); }; User.getFollowStats = function (uid, callback) { @@ -734,22 +747,6 @@ var bcrypt = require('bcryptjs'), }, callback); }; - User.getDataForUsers = function(uids, callback) { - - if (!uids || !Array.isArray(uids) || uids.length === 0) { - return callback(null, []); - } - - function getUserData(uid, next) { - if(parseInt(uid, 10) === 0) { - return next(null, null); - } - - User.getUserData(uid, next); - } - - async.map(uids, getUserData, callback); - }; User.sendPostNotificationToFollowers = function(uid, tid, pid) { User.getUserField(uid, 'username', function(err, username) { @@ -773,13 +770,7 @@ var bcrypt = require('bcryptjs'), }; User.isFollowing = function(uid, theirid, callback) { - db.isSetMember('following:' + uid, theirid, function(err, isMember) { - if (!err) { - callback(isMember); - } else { - console.log(err); - } - }); + db.isSetMember('following:' + uid, theirid, callback); }; User.exists = function(userslug, callback) { @@ -809,29 +800,17 @@ var bcrypt = require('bcryptjs'), }; User.getUsernamesByUids = function(uids, callback) { + User.getMultipleUserFields(uids, ['username'], function(err, users) { + if (err) { + return callback(err); + } - if (!Array.isArray(uids)) { - return callback(null, []); - } - - function getUserName(uid, next) { - User.getUserField(uid, 'username', next); - } - - async.map(uids, getUserName, callback); - }; - - User.getUserSlugsByUids = function(uids, callback) { - - if (!Array.isArray(uids)) { - return callback(null, []); - } - - function getUserSlug(uid, next) { - User.getUserField(uid, 'userslug', next); - } + users = users.map(function(user) { + return user.username; + }); - async.map(uids, getUserSlug, callback); + callback(null, users); + }); }; User.getUsernameByUserslug = function(slug, callback) { @@ -846,12 +825,7 @@ var bcrypt = require('bcryptjs'), }; User.getUidByEmail = function(email, callback) { - db.getObjectField('email:uid', email, function(err, data) { - if (err) { - return callback(err); - } - callback(null, data); - }); + db.getObjectField('email:uid', email, callback); }; User.isModerator = function(uid, cid, callback) {