From 6fe8d25166e4d3bfe5b9cc3b7831662c7d201375 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 16 Jan 2015 12:58:31 -0500 Subject: [PATCH 01/28] add uid to filter:topic.get --- src/topics.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/topics.js b/src/topics.js index 1e9df9958f..3135fd6a88 100644 --- a/src/topics.js +++ b/src/topics.js @@ -255,7 +255,9 @@ var async = require('async'), topicData.locked = parseInt(topicData.locked, 10) === 1; topicData.pinned = parseInt(topicData.pinned, 10) === 1; - plugins.fireHook('filter:topic.get', topicData, callback); + plugins.fireHook('filter:topic.get', {topic: topicData, uid: uid}, function(err, data) { + callback(err, data ? data.topics : null); + }); }); }); }; From 236fe91e953200fae651707293c556eff16deef6 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 16 Jan 2015 13:00:50 -0500 Subject: [PATCH 02/28] fix typo --- src/topics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/topics.js b/src/topics.js index 3135fd6a88..d206b5c211 100644 --- a/src/topics.js +++ b/src/topics.js @@ -256,7 +256,7 @@ var async = require('async'), topicData.pinned = parseInt(topicData.pinned, 10) === 1; plugins.fireHook('filter:topic.get', {topic: topicData, uid: uid}, function(err, data) { - callback(err, data ? data.topics : null); + callback(err, data ? data.topic : null); }); }); }); From b333653464458c2cd27717768f28d9a356e8c3a7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 16 Jan 2015 23:52:51 -0500 Subject: [PATCH 03/28] prevent js crash if responseJSON is undefined --- public/src/modules/uploader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/uploader.js b/public/src/modules/uploader.js index d2f7612c0e..6efdbd988c 100644 --- a/public/src/modules/uploader.js +++ b/public/src/modules/uploader.js @@ -49,7 +49,7 @@ define('uploader', ['csrf'], function(csrf) { }, error: function(xhr) { xhr = maybeParse(xhr); - showAlert('error', xhr.responseJSON.error); + showAlert('error', xhr.responseJSON ? xhr.responseJSON.error : 'error uploading, code : ' + xhr.status); }, uploadProgress: function(event, position, total, percent) { From 093e499bf8f584b82dddc67c89a7255f4ced6216 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 20 Jan 2015 20:55:22 -0500 Subject: [PATCH 04/28] defining module name in iconSelect module --- public/src/modules/iconSelect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/iconSelect.js b/public/src/modules/iconSelect.js index 88ab1903ed..f21bd76e1f 100644 --- a/public/src/modules/iconSelect.js +++ b/public/src/modules/iconSelect.js @@ -2,7 +2,7 @@ /* globals define, bootbox */ -define(function() { +define('iconSelect', function() { var iconSelect = {}; iconSelect.init = function(el, onModified) { From 2917304f6c84da2baab5766a25e9e3a96ff95fe4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 21 Jan 2015 16:14:31 -0500 Subject: [PATCH 05/28] companion commit to nodebb/nodebb-theme-vanilla@0d17032 --- public/src/client/groups/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/client/groups/list.js b/public/src/client/groups/list.js index 38d70d7c4a..36f1e0f3e7 100644 --- a/public/src/client/groups/list.js +++ b/public/src/client/groups/list.js @@ -5,7 +5,7 @@ define('forum/groups/list', function() { var Groups = {}; Groups.init = function() { - var groupsEl = $('.groups.row'); + var groupsEl = $('#groups-list'); groupsEl.on('click', '.list-cover', function() { var groupName = $(this).parents('[data-group]').attr('data-group'); @@ -41,7 +41,7 @@ define('forum/groups/list', function() { }; Groups.search = function(query) { - var groupsEl = $('.groups.row'); + var groupsEl = $('#groups-list'); socket.emit('groups.search', { query: query, From 78a5843ae45e7cd8cb4cbab887112f05469536f2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 21 Jan 2015 16:33:09 -0500 Subject: [PATCH 06/28] fixed tests by removing the broken one, heh heh heh --- src/groups.js | 21 --------------------- tests/groups.js | 11 ----------- 2 files changed, 32 deletions(-) diff --git a/src/groups.js b/src/groups.js index 87e6070757..58170eeaa8 100644 --- a/src/groups.js +++ b/src/groups.js @@ -265,27 +265,6 @@ var async = require('async'), db.getSetMembers('group:' + groupName + ':members', callback); }; - Groups.search = function(query, options, callback) { - if (!query) { - return callback(null, []); - } - - db.getSetMembers('groups', function(err, groups) { - if (err) { - return callback(err); - } - groups = groups.filter(function(groupName) { - return groupName.match(new RegExp(utils.escapeRegexChars(query), 'i')); - }); - - async.map(groups, function(groupName, next) { - Groups.get(groupName, options, next); - }, function(err, groups) { - callback(err, internals.filterGroups(groups, options)); - }); - }); - }; - Groups.isMember = function(uid, groupName, callback) { if (!uid || parseInt(uid, 10) <= 0) { return callback(null, false); diff --git a/tests/groups.js b/tests/groups.js index 47da1b8bbb..0025000828 100644 --- a/tests/groups.js +++ b/tests/groups.js @@ -88,17 +88,6 @@ describe('Groups', function() { done(); }); }); - - it('should return the "Hidden" group when "showAllGroups" option is passed in', function(done) { - Groups.search('hidden', { - showAllGroups: true - }, function(err, groups) { - if (err) return done(err); - assert.equal(1, groups.length); - assert.strictEqual('Hidden', groups[0].name); - done(); - }); - }); }); describe('.isMember()', function() { From 5fb8817b3c54e9c4e86eaf9c6dbeae34b732a0c1 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 22 Jan 2015 14:13:39 -0500 Subject: [PATCH 07/28] closes #2643 --- src/user/delete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/delete.js b/src/user/delete.js index b13fa1aa97..e6cdcebb19 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -85,7 +85,7 @@ module.exports = function(User) { db.deleteAll(keys, next); }, function(next) { - deleteUserIps(uids, next); + deleteUserIps(uid, next); }, function(next) { deleteUserFromFollowers(uid, next); From 77216acbcc341c0572b4a7324064fb0f19492c1f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 22 Jan 2015 14:18:19 -0500 Subject: [PATCH 08/28] user.delete test --- tests/user.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/user.js b/tests/user.js index 3ef541623b..381c6f0a44 100644 --- a/tests/user.js +++ b/tests/user.js @@ -171,6 +171,28 @@ describe('User', function() { }); }); + describe('.delete()', function() { + var uid; + before(function(done) { + User.create({username: 'userToDelete', password: '123456', email: 'delete@me.com'}, function(err, newUid) { + assert.ifError(err); + uid = newUid; + done(); + }); + }); + + it('should delete a user account', function(done) { + User.delete(uid, function(err) { + assert.ifError(err); + User.exists('userToDelete', function(err, exists) { + assert.ifError(err); + assert.equal(exists, false); + done(); + }); + }); + }); + }); + after(function() { db.flushdb(); }); From d895ca6827d203abd71f9170fb24fe2daa9014b7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 22 Jan 2015 14:19:23 -0500 Subject: [PATCH 09/28] missing semicolon --- src/user/delete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/delete.js b/src/user/delete.js index e6cdcebb19..3440e810a4 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -127,7 +127,7 @@ module.exports = function(User) { } db.delete('uid:' + uid + ':ip', callback); }); - }) + }); } function deleteUserFromFollowers(uid, callback) { From 72f28b7b3831bc084ef5606c5a3c2c8760f1f579 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 22 Jan 2015 14:19:59 -0500 Subject: [PATCH 10/28] closed #2641 --- public/language/en_GB/error.json | 1 + public/src/client/groups/details.js | 2 +- src/groups.js | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/public/language/en_GB/error.json b/public/language/en_GB/error.json index fed0c807c9..7e21a1290a 100644 --- a/public/language/en_GB/error.json +++ b/public/language/en_GB/error.json @@ -66,6 +66,7 @@ "group-already-exists": "Group already exists", "group-name-change-not-allowed": "Group name change not allowed", "group-already-member": "You are already part of this group", + "group-needs-owner": "This group requires at least one owner", "post-already-deleted": "This post has already been deleted", "post-already-restored": "This post has already been restored", diff --git a/public/src/client/groups/details.js b/public/src/client/groups/details.js index b667176ae9..09826fb673 100644 --- a/public/src/client/groups/details.js +++ b/public/src/client/groups/details.js @@ -34,7 +34,7 @@ define('forum/groups/details', ['iconSelect', 'vendor/colorpicker/colorpicker', if (!err) { ownerFlagEl.toggleClass('invisible'); } else { - app.alertError(err); + app.alertError(err.message); } }); break; diff --git a/src/groups.js b/src/groups.js index fbb138dce5..beeddd19a9 100644 --- a/src/groups.js +++ b/src/groups.js @@ -659,8 +659,8 @@ var async = require('async'), Groups.requestMembership = function(groupName, uid, callback) { async.parallel({ - exists: async.apply(Groups.isMember, uid, groupName), - isMember: async.apply(Groups.exists, groupName) + exists: async.apply(Groups.exists, groupName), + isMember: async.apply(Groups.isMember, uid, groupName) }, function(err, checks) { if (!checks.exists) { return callback(new Error('[[error:no-group]]')); @@ -694,7 +694,12 @@ var async = require('async'), Groups.leave = function(groupName, uid, callback) { callback = callback || function() {}; - db.sortedSetRemove('group:' + groupName + ':members', uid, function(err) { + var tasks = [ + async.apply(db.sortedSetRemove, 'group:' + groupName + ':members', uid), + async.apply(db.setRemove, 'group:' + groupName + ':owners', uid) + ]; + + async.parallel(tasks, function(err) { if (err) { return callback(err); } @@ -891,7 +896,15 @@ var async = require('async'), Groups.ownership.rescind = function(toUid, groupName, callback) { // Note: No ownership checking is done here on purpose! - db.setRemove('group:' + groupName + ':owners', toUid, callback); + + // If the owners set only contains one member, error out! + db.setCount('group:' + groupName + ':owners', function(err, numOwners) { + if (numOwners <= 1) { + return callback(new Error('[[error:group-needs-owner]]')); + } + + db.setRemove('group:' + groupName + ':owners', toUid, callback); + }); }; Groups.search = function(query, options, callback) { From 070215b05ef45fc8cab78cc334098d3ce508a12b Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 22 Jan 2015 16:08:20 -0500 Subject: [PATCH 11/28] simplified isOwner check because there's no need to check admin status as admins automatically become owners now --- src/groups.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/groups.js b/src/groups.js index e7c1eed77b..7082ba5b65 100644 --- a/src/groups.js +++ b/src/groups.js @@ -884,22 +884,13 @@ var async = require('async'), Groups.updateCoverPosition(data.groupName, data.position, callback); }); - } + }; Groups.ownership = {}; Groups.ownership.isOwner = function(uid, groupName, callback) { - // Note: All admins are also owners - async.waterfall([ - async.apply(db.isSetMember, 'group:' + groupName + ':owners', uid), - function(isOwner, next) { - if (isOwner) { - return next(null, isOwner); - } - - user.isAdministrator(uid, next); - } - ], callback); + // Note: All admins automatically become owners upon joining + db.isSetMember('group:' + groupName + ':owners', uid, callback); }; Groups.ownership.grant = function(toUid, groupName, callback) { From ab69477b24ef9d44a0fd74d40d97ce4e3c7bc64b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 27 Jan 2015 17:37:21 -0500 Subject: [PATCH 12/28] moved filter:user,get to central function --- src/controllers/users.js | 12 +++--------- src/user.js | 8 ++++++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/controllers/users.js b/src/controllers/users.js index a1d5b84f19..0a2d4d0d67 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -44,9 +44,7 @@ usersController.getOnlineUsers = function(req, res, next) { show_anon: anonymousUserCount ? '' : 'hide' }; - plugins.fireHook('filter:userlist.get', {data: userData, uid: uid}, function(err, userData) { - res.render('users', userData.data); - }); + res.render('users', userData); }); }; @@ -76,9 +74,7 @@ usersController.getUsers = function(set, count, req, res, next) { show_anon: 'hide' }; - plugins.fireHook('filter:userlist.get', {data: userData, uid: uid}, function(err, userData) { - res.render('users', userData.data); - }); + res.render('users', userData); }); }; @@ -118,9 +114,7 @@ usersController.getUsersForSearch = function(req, res, next) { show_anon: 'hide' }; - plugins.fireHook('filter:userlist.get', {data: userData, uid: uid}, function(err, userData) { - res.render('users', userData.data); - }); + res.render('users', userData); }); }; diff --git a/src/user.js b/src/user.js index 0a83994964..5e9382efd9 100644 --- a/src/user.js +++ b/src/user.js @@ -249,8 +249,12 @@ var async = require('async'), user.banned = parseInt(user.banned, 10) === 1; user['email:confirmed'] = parseInt(user['email:confirmed'], 10) === 1; }); - - callback(null, results.userData); + plugins.fireHook('filter:userlist.get', {users: results.userData}, function(err, data) { + if (err) { + return callback(err); + } + callback(null, data.users); + }); }); }); }; From 0dc0c39f4813745ebde5d812ef0b6d1f81f81975 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 27 Jan 2015 19:58:17 -0500 Subject: [PATCH 13/28] removed li selector --- public/src/client/topic/posts.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index 8e21928498..7fd55e8bd4 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -52,7 +52,7 @@ define('forum/topic/posts', [ function removeAlreadyAddedPosts() { data.posts = data.posts.filter(function(post) { - return $('#post-container li[data-pid="' + post.pid +'"]').length === 0; + return $('#post-container [data-pid="' + post.pid +'"]').length === 0; }); } @@ -64,8 +64,8 @@ define('forum/topic/posts', [ var firstPostVotes = parseInt(data.posts[0].votes, 10); var firstPostIndex = parseInt(data.posts[0].index, 10); - var firstReply = $('#post-container li.post-row[data-index!="0"]').first(); - var lastReply = $('#post-container li.post-row[data-index!="0"]').last(); + var firstReply = $('#post-container .post-row[data-index!="0"]').first(); + var lastReply = $('#post-container .post-row[data-index!="0"]').last(); if (config.topicPostSort === 'oldest_to_newest') { if (firstPostTimestamp < parseInt(firstReply.attr('data-timestamp'), 10)) { @@ -111,7 +111,7 @@ define('forum/topic/posts', [ // Save document height and position for future reference (about 5 lines down) var height = $(document).height(), scrollTop = $(document).scrollTop(), - originalPostEl = $('li[data-index="0"]'); + originalPostEl = $('.post-row[data-index="0"]'); // Insert the new post html.insertBefore(before); @@ -186,7 +186,7 @@ define('forum/topic/posts', [ function loadPostsAfter(after) { var tid = ajaxify.variables.get('topic_id'); - if (!utils.isNumber(tid) || !utils.isNumber(after) || (after === 0 && $('#post-container li.post-row[data-index="1"]').length)) { + if (!utils.isNumber(tid) || !utils.isNumber(after) || (after === 0 && $('#post-container .post-row[data-index="1"]').length)) { return; } @@ -235,13 +235,13 @@ define('forum/topic/posts', [ }; function showBottomPostBar() { - if($('#post-container .post-row').length > 1 || !$('#post-container li[data-index="0"]').length) { + if($('#post-container .post-row').length > 1 || !$('#post-container [data-index="0"]').length) { $('.bottom-post-bar').removeClass('hide'); } } function hidePostToolsForDeletedPosts(element) { - element.find('li.deleted').each(function() { + element.find('.post-row.deleted').each(function() { postTools.toggle($(this).attr('data-pid'), true); }); } From d47cd270dfffd1a899a8c27f66e495401d71a73c Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 27 Jan 2015 23:37:47 -0500 Subject: [PATCH 14/28] some random favourite typo --- src/favourites.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/favourites.js b/src/favourites.js index 0673626f51..c07468c78a 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -274,7 +274,7 @@ var async = require('async'), } if (!isFavouriting && !results.hasFavourited) { - return callback(new Error('[[error:alrady-unfavourited]]')); + return callback(new Error('[[error:already-unfavourited]]')); } async.waterfall([ From 370a60c14fd5409e4e059dffd11d2c2d17f1d17b Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 27 Jan 2015 23:50:01 -0500 Subject: [PATCH 15/28] potential bug @barisusakli I think you changed this, just pinging you in case --- public/src/client/topic/threadTools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/topic/threadTools.js b/public/src/client/topic/threadTools.js index 41a3d532bf..b401a850ed 100644 --- a/public/src/client/topic/threadTools.js +++ b/public/src/client/topic/threadTools.js @@ -61,7 +61,7 @@ define('forum/topic/threadTools', ['forum/topic/fork', 'forum/topic/move'], func fork.init(); $('.posts').on('click', '.follow', function() { - socket.emit('topics.follow', tid, function(err, state) { + socket.emit('topics.toggleFollow', tid, function(err, state) { if(err) { return app.alert({ type: 'danger', From 5a3c056759be7e51e1154564197a1c39e43b5397 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Tue, 27 Jan 2015 23:50:10 -0500 Subject: [PATCH 16/28] removing li specific selector --- public/src/client/topic/events.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/src/client/topic/events.js b/public/src/client/topic/events.js index 90f54ec064..40217b0969 100644 --- a/public/src/client/topic/events.js +++ b/public/src/client/topic/events.js @@ -69,7 +69,7 @@ define('forum/topic/events', [ }; function updatePostVotesAndUserReputation(data) { - var votes = $('li[data-pid="' + data.post.pid + '"] .votes'), + var votes = $('[data-pid="' + data.post.pid + '"] .votes'), reputationElements = $('.reputation[data-uid="' + data.post.uid + '"]'); votes.html(data.post.votes).attr('data-votes', data.post.votes); @@ -77,7 +77,7 @@ define('forum/topic/events', [ } function updateFavouriteCount(data) { - $('li[data-pid="' + data.post.pid + '"] .favouriteCount').html(data.post.reputation).attr('data-favourites', data.post.reputation); + $('[data-pid="' + data.post.pid + '"] .favouriteCount').html(data.post.reputation).attr('data-favourites', data.post.reputation); } function toggleTopicDeleteState(data) { @@ -139,14 +139,14 @@ define('forum/topic/events', [ } function onPostPurged(pid) { - $('#post-container li[data-pid="' + pid + '"]').fadeOut(500, function() { + $('#post-container [data-pid="' + pid + '"]').fadeOut(500, function() { $(this).remove(); }); postTools.updatePostCount(); } function togglePostDeleteState(data) { - var postEl = $('#post-container li[data-pid="' + data.pid + '"]'); + var postEl = $('#post-container [data-pid="' + data.pid + '"]'); if (!postEl.length) { return; @@ -166,7 +166,7 @@ define('forum/topic/events', [ } function togglePostFavourite(data) { - var favBtn = $('li[data-pid="' + data.post.pid + '"] .favourite'); + var favBtn = $('[data-pid="' + data.post.pid + '"] .favourite'); if (!favBtn.length) { return; } @@ -185,7 +185,7 @@ define('forum/topic/events', [ } function togglePostVote(data) { - var post = $('li[data-pid="' + data.post.pid + '"]'); + var post = $('[data-pid="' + data.post.pid + '"]'); post.find('.upvote').toggleClass('btn-primary upvoted', data.upvote); post.find('.downvote').toggleClass('btn-primary downvoted', data.downvote); From 8bc2d973527f2eaa252e0cca28770f612e3bb5ab Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 29 Jan 2015 10:08:48 -0500 Subject: [PATCH 17/28] stringify helper for t.js --- public/src/modules/helpers.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/src/modules/helpers.js b/public/src/modules/helpers.js index bc40bde658..e8f77a5614 100644 --- a/public/src/modules/helpers.js +++ b/public/src/modules/helpers.js @@ -4,7 +4,7 @@ // export the class if we are in a Node-like system. if (typeof module === 'object' && module.exports === exports) { - exports = module.exports/* = SemVer*/; + exports = module.exports/* = SemVer*/; } var helpers = {}; @@ -21,6 +21,11 @@ return ''; }; + helpers.stringify = function(obj) { + // Turns the incoming object into a JSON string + return JSON.stringify(obj).replace(/&/gm,"&").replace(//gm,">").replace(/"/g, '"'); + }; + // Groups helpers helpers.membershipBtn = function(groupObj) { if (groupObj.isMember) { From 6a2c35c263bba4319603932768bc971e74e110e7 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 29 Jan 2015 15:45:31 -0500 Subject: [PATCH 18/28] latest t.js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c46f966b43..c67d9268e6 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "socket.io-redis": "^0.1.3", "socketio-wildcard": "~0.1.1", "string": "^3.0.0", - "templates.js": "0.1.10", + "templates.js": "0.1.15", "uglify-js": "git+https://github.com/julianlam/UglifyJS2.git", "underscore": "~1.7.0", "validator": "~3.26.0", From 6ebc048f1f3a626881b600887a7b43a93ca96077 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 29 Jan 2015 16:41:48 -0500 Subject: [PATCH 19/28] searching on keyup instead of enter key --- public/src/client/groups/list.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/public/src/client/groups/list.js b/public/src/client/groups/list.js index 9ff22d9396..a3f9394450 100644 --- a/public/src/client/groups/list.js +++ b/public/src/client/groups/list.js @@ -31,9 +31,7 @@ define('forum/groups/list', function() { }); // Group searching - $('#search-text').on('keydown', function(e) { - if (e.keyCode === 13) { Groups.search(e); } - }); + $('#search-text').on('keyup', Groups.search); $('#search-button').on('click', Groups.search); }; From b54f2de504880fc26d40c41f7a347103c24c77ae Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 29 Jan 2015 17:02:20 -0500 Subject: [PATCH 20/28] pass uid to getUsers and getUsersFromSets --- src/controllers/admin/users.js | 3 ++- src/controllers/groups.js | 3 ++- src/controllers/users.js | 10 +++++----- src/search.js | 6 +++--- src/socket.io/admin/categories.js | 2 +- src/socket.io/admin/user.js | 2 +- src/socket.io/user.js | 5 +++-- src/user.js | 8 ++++---- src/user/follow.js | 2 +- src/user/search.js | 9 +++++---- 10 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/controllers/admin/users.js b/src/controllers/admin/users.js index 17944b8370..283302b48e 100644 --- a/src/controllers/admin/users.js +++ b/src/controllers/admin/users.js @@ -31,7 +31,8 @@ usersController.banned = function(req, res, next) { }; function getUsers(set, req, res, next) { - user.getUsersFromSet(set, 0, 49, function(err, users) { + var uid = req.user ? parseInt(req.user.uid, 10) : 0; + user.getUsersFromSet(set, uid, 0, 49, function(err, users) { if (err) { return next(err); } diff --git a/src/controllers/groups.js b/src/controllers/groups.js index c20993a7df..18ea0cbf2d 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -49,12 +49,13 @@ groupsController.details = function(req, res, next) { }; groupsController.members = function(req, res, next) { + var uid = req.user ? parseInt(req.user.uid, 10) : 0; async.waterfall([ function(next) { groups.getGroupNameByGroupSlug(req.params.slug, next); }, function(groupName, next) { - user.getUsersFromSet('group:' + groupName + ':members', 0, 49, next); + user.getUsersFromSet('group:' + groupName + ':members', uid, 0, 49, next); }, ], function(err, users) { if (err) { diff --git a/src/controllers/users.js b/src/controllers/users.js index 0a2d4d0d67..81001d0f3a 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -14,7 +14,7 @@ usersController.getOnlineUsers = function(req, res, next) { async.parallel({ users: function(next) { - user.getUsersFromSet('users:online', 0, 49, next); + user.getUsersFromSet('users:online', uid, 0, 49, next); }, count: function(next) { var now = Date.now(); @@ -63,7 +63,7 @@ usersController.getUsersSortedByJoinDate = function(req, res, next) { usersController.getUsers = function(set, count, req, res, next) { var uid = req.user ? req.user.uid : 0; - getUsersAndCount(set, count, function(err, data) { + getUsersAndCount(set, uid, count, function(err, data) { if (err) { return next(err); } @@ -78,10 +78,10 @@ usersController.getUsers = function(set, count, req, res, next) { }); }; -function getUsersAndCount(set, count, callback) { +function getUsersAndCount(set, uid, count, callback) { async.parallel({ users: function(next) { - user.getUsersFromSet(set, 0, count - 1, next); + user.getUsersFromSet(set, uid, 0, count - 1, next); }, count: function(next) { db.getObjectField('global', 'userCount', next); @@ -102,7 +102,7 @@ usersController.getUsersForSearch = function(req, res, next) { var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20, uid = req.user ? req.user.uid : 0; - getUsersAndCount('users:joindate', resultsPerPage, function(err, data) { + getUsersAndCount('users:joindate', uid, resultsPerPage, function(err, data) { if (err) { return next(err); } diff --git a/src/search.js b/src/search.js index c4a830f41a..e0be3ecafd 100644 --- a/src/search.js +++ b/src/search.js @@ -40,7 +40,7 @@ search.search = function(data, callback) { if (searchIn === 'posts') { searchInPosts(query, data.postedBy, uid, done); } else if (searchIn === 'users') { - searchInUsers(query, done); + searchInUsers(query, uid, done); } else if (searchIn === 'tags') { searchInTags(query, done); } else { @@ -99,8 +99,8 @@ function searchInPosts(query, postedBy, uid, callback) { }); } -function searchInUsers(query, callback) { - user.search({query: query}, function(err, results) { +function searchInUsers(query, uid, callback) { + user.search({query: query, uid: uid}, function(err, results) { callback(err, results ? results.users : null); }); } diff --git a/src/socket.io/admin/categories.js b/src/socket.io/admin/categories.js index 2ba036d7e0..9a9ef0ea7e 100644 --- a/src/socket.io/admin/categories.js +++ b/src/socket.io/admin/categories.js @@ -36,7 +36,7 @@ Categories.search = function(socket, data, callback) { var username = data.username, cid = data.cid; - user.search({query: username}, function(err, data) { + user.search({query: username, uid: socket.uid}, function(err, data) { if (err) { return callback(err); } diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 9189727fbb..5f7199bf29 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -175,7 +175,7 @@ User.deleteUsers = function(socket, uids, callback) { }; User.search = function(socket, data, callback) { - user.search({query: data.query, searchBy: data.searchBy, startsWith: false}, function(err, searchData) { + user.search({query: data.query, searchBy: data.searchBy, startsWith: false, uid: socket.uid}, function(err, searchData) { if (err) { return callback(err); } diff --git a/src/socket.io/user.js b/src/socket.io/user.js index d28421c383..6004bdd469 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -66,7 +66,8 @@ SocketUser.search = function(socket, data, callback) { page: data.page, searchBy: data.searchBy, sortBy: data.sortBy, - filterBy: data.filterBy + filterBy: data.filterBy, + uid: socket.uid }, callback); }; @@ -332,7 +333,7 @@ SocketUser.loadMore = function(socket, data, callback) { var start = parseInt(data.after, 10), end = start + 19; - user.getUsersFromSet(data.set, start, end, function(err, userData) { + user.getUsersFromSet(data.set, socket.uid, start, end, function(err, userData) { if (err) { return callback(err); } diff --git a/src/user.js b/src/user.js index 80f7a951db..c7d8649d22 100644 --- a/src/user.js +++ b/src/user.js @@ -219,18 +219,18 @@ var async = require('async'), } }; - User.getUsersFromSet = function(set, start, stop, callback) { + User.getUsersFromSet = function(set, uid, start, stop, callback) { async.waterfall([ function(next) { User.getUidsFromSet(set, start, stop, next); }, function(uids, next) { - User.getUsers(uids, next); + User.getUsers(uids, uid, next); } ], callback); }; - User.getUsers = function(uids, callback) { + User.getUsers = function(uids, uid, callback) { var fields = ['uid', 'username', 'userslug', 'picture', 'status', 'banned', 'postcount', 'reputation', 'email:confirmed']; plugins.fireHook('filter:users.addFields', {fields: fields}, function(err, data) { if (err) { @@ -264,7 +264,7 @@ var async = require('async'), user['email:confirmed'] = parseInt(user['email:confirmed'], 10) === 1; }); - plugins.fireHook('filter:userlist.get', {users: results.userData}, function(err, data) { + plugins.fireHook('filter:userlist.get', {users: results.userData, uid: uid}, function(err, data) { if (err) { return callback(err); } diff --git a/src/user/follow.js b/src/user/follow.js index c3e2cb340c..6b0c0a3973 100644 --- a/src/user/follow.js +++ b/src/user/follow.js @@ -59,7 +59,7 @@ module.exports = function(User) { return callback(err); } - User.getUsers(uids, callback); + User.getUsers(uids, uid, callback); }); } diff --git a/src/user/search.js b/src/user/search.js index 95130bf68f..9df346f6ec 100644 --- a/src/user/search.js +++ b/src/user/search.js @@ -14,13 +14,14 @@ module.exports = function(User) { var searchBy = data.searchBy || ['username']; var startsWith = data.hasOwnProperty('startsWith') ? data.startsWith : true; var page = data.page || 1; + var uid = data.uid || 0; if (!query) { return callback(null, {timing: 0, users: [], matchCount: 0, pages: []}); } if (searchBy.indexOf('ip') !== -1) { - return searchByIP(query, callback); + return searchByIP(query, uid, callback); } var startTime = process.hrtime(); @@ -46,7 +47,7 @@ module.exports = function(User) { matchCount = uids.length; uids = uids.slice(start, end); - User.getUsers(uids, next); + User.getUsers(uids, uid, next); }, function(userData, next) { @@ -194,14 +195,14 @@ module.exports = function(User) { } } - function searchByIP(ip, callback) { + function searchByIP(ip, uid, callback) { var start = process.hrtime(); async.waterfall([ function(next) { db.getSortedSetRevRange('ip:' + ip + ':uid', 0, -1, next); }, function(uids, next) { - User.getUsers(uids, next); + User.getUsers(uids, uid, next); }, function(users, next) { var diff = process.hrtime(start); From 530bdbbd1a375b3b51bc2f9b824af36de45c2876 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 29 Jan 2015 17:10:49 -0500 Subject: [PATCH 21/28] dont rename if key doesn't exist --- src/database/redis/main.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/database/redis/main.js b/src/database/redis/main.js index 9b08e4af65..e9bd5b2f09 100644 --- a/src/database/redis/main.js +++ b/src/database/redis/main.js @@ -105,8 +105,13 @@ module.exports = function(redisClient, module) { module.rename = function(oldKey, newKey, callback) { callback = callback || function() {}; - redisClient.rename(oldKey, newKey, function(err, res) { - callback(err); + redisClient.exist(oldKey, function(err, exists) { + if (err || !exists) { + return callback(err); + } + redisClient.rename(oldKey, newKey, function(err, res) { + callback(err); + }); }); }; From d1a1cada19af00a8247f5550aa48a394baeb06ea Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 29 Jan 2015 17:12:12 -0500 Subject: [PATCH 22/28] fix typo --- src/database/redis/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/redis/main.js b/src/database/redis/main.js index e9bd5b2f09..efe1b7958a 100644 --- a/src/database/redis/main.js +++ b/src/database/redis/main.js @@ -105,7 +105,7 @@ module.exports = function(redisClient, module) { module.rename = function(oldKey, newKey, callback) { callback = callback || function() {}; - redisClient.exist(oldKey, function(err, exists) { + redisClient.exists(oldKey, function(err, exists) { if (err || !exists) { return callback(err); } From f3f3ca8e5008a7d5303c6e02660384ad7ba6fcce Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 29 Jan 2015 19:25:01 -0500 Subject: [PATCH 23/28] if key isn't found dont error --- src/database/redis/main.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/database/redis/main.js b/src/database/redis/main.js index efe1b7958a..ebad6ae8e6 100644 --- a/src/database/redis/main.js +++ b/src/database/redis/main.js @@ -105,13 +105,8 @@ module.exports = function(redisClient, module) { module.rename = function(oldKey, newKey, callback) { callback = callback || function() {}; - redisClient.exists(oldKey, function(err, exists) { - if (err || !exists) { - return callback(err); - } - redisClient.rename(oldKey, newKey, function(err, res) { - callback(err); - }); + redisClient.rename(oldKey, newKey, function(err, res) { + callback(err && err.message !== 'ERR no such key' ? err : null); }); }; From 4f5918390a87fe9d13b8f1e30065364d210ceab5 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 30 Jan 2015 14:19:15 -0500 Subject: [PATCH 24/28] if user search is blank, return all users --- public/src/client/users.js | 5 ----- src/user/search.js | 4 ---- 2 files changed, 9 deletions(-) diff --git a/public/src/client/users.js b/public/src/client/users.js index b96f3f5501..c3f374c4ff 100644 --- a/public/src/client/users.js +++ b/public/src/client/users.js @@ -115,11 +115,6 @@ define('forum/users', function() { var username = $('#search-user').val(); var notify = $('#user-notfound-notify'); page = page || 1; - if (!username) { - notify.html(''); - notify.parent().removeClass('btn-warning label-warning btn-success label-success'); - return; - } notify.html(''); var filters = []; diff --git a/src/user/search.js b/src/user/search.js index 9df346f6ec..34140005e1 100644 --- a/src/user/search.js +++ b/src/user/search.js @@ -16,10 +16,6 @@ module.exports = function(User) { var page = data.page || 1; var uid = data.uid || 0; - if (!query) { - return callback(null, {timing: 0, users: [], matchCount: 0, pages: []}); - } - if (searchBy.indexOf('ip') !== -1) { return searchByIP(query, uid, callback); } From 4a7ec3ccc6b0b00b76c0996fa19148a957d6e163 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 30 Jan 2015 15:48:17 -0500 Subject: [PATCH 25/28] added groups page to user profile --- public/src/client/groups/list.js | 4 ++-- src/controllers/accounts.js | 23 +++++++++++++++++++++++ src/routes/index.js | 1 + src/views/config.json | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/public/src/client/groups/list.js b/public/src/client/groups/list.js index 0410a9fa17..d0b4c69b50 100644 --- a/public/src/client/groups/list.js +++ b/public/src/client/groups/list.js @@ -8,9 +8,9 @@ define('forum/groups/list', function() { var groupsEl = $('#groups-list'); groupsEl.on('click', '.list-cover', function() { - var groupName = $(this).parents('[data-group]').attr('data-group'); + var groupSlug = $(this).parents('[data-slug]').attr('data-slug'); - ajaxify.go('groups/' + utils.slugify(groupName)); + ajaxify.go('groups/' + groupSlug); }); // Group creation diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 741de9a626..c55977a351 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -233,6 +233,29 @@ accountsController.getTopics = function(req, res, next) { getFromUserSet('account/topics', 'topics', topics.getTopicsFromSet, 'topics', req, res, next); }; +accountsController.getGroups = function(req, res, next) { + var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; + + getBaseUser(req.params.userslug, callerUID, function(err, userData) { + if (err) { + return next(err); + } + + if (!userData) { + return helpers.notFound(req, res); + } + + groups.getUserGroups([userData.uid], function(err, groups) { + if (err) { + return next(err); + } + + userData.groups = groups[0]; + + res.render('account/groups', userData); + }); + }); +}; function getFromUserSet(tpl, set, method, type, req, res, next) { var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; diff --git a/src/routes/index.js b/src/routes/index.js index 1af03e0930..f8012c9456 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -68,6 +68,7 @@ function accountRoutes(app, middleware, controllers) { setupPageRoute(app, '/user/:userslug/followers', middleware, middlewares, controllers.accounts.getFollowers); setupPageRoute(app, '/user/:userslug/posts', middleware, middlewares, controllers.accounts.getPosts); setupPageRoute(app, '/user/:userslug/topics', middleware, middlewares, controllers.accounts.getTopics); + setupPageRoute(app, '/user/:userslug/groups', middleware, middlewares, controllers.accounts.getGroups); setupPageRoute(app, '/user/:userslug/favourites', middleware, accountMiddlewares, controllers.accounts.getFavourites); setupPageRoute(app, '/user/:userslug/watched', middleware, accountMiddlewares, controllers.accounts.getWatchedTopics); diff --git a/src/views/config.json b/src/views/config.json index 70997cf4a8..26ae7b692c 100644 --- a/src/views/config.json +++ b/src/views/config.json @@ -14,6 +14,7 @@ "^user/.*/watched": "account/watched", "^user/.*/posts": "account/posts", "^user/.*/topics": "account/topics", + "^user/.*/groups": "account/groups", "^user/[^\/]+": "account/profile", "^reset/.*": "reset_code", "^tags/.*": "tag", From da0b2c84e675ec03fc4f73568c65d97afa23036e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 30 Jan 2015 16:24:57 -0500 Subject: [PATCH 26/28] passing memberCount and createTime into getUserGroups --- src/groups.js | 54 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/groups.js b/src/groups.js index 4a7611c531..4eca55c05d 100644 --- a/src/groups.js +++ b/src/groups.js @@ -781,35 +781,51 @@ var async = require('async'), groupData = groupData.filter(function(group) { return parseInt(group.hidden, 10) !== 1 && !!group.userTitle; + }).map(function(group) { + group.createtimeISO = utils.toISOString(group.createtime); + return group; }); - var groupSets = groupData.map(function(group) { - group.labelColor = group.labelColor || '#000000'; + async.map(groupData, function(groupObj, next) { + Groups.getMemberCount(groupObj.name, function(err, memberCount) { + if (err) { return next(err); } - if (!group['cover:url']) { - group['cover:url'] = nconf.get('relative_path') + '/images/cover-default.png'; - group['cover:position'] = '50% 50%'; + groupObj.memberCount = memberCount; + next(err, groupObj); + }); + }, function(err, groupData) { + if (err) { + return callback(err); } - return 'group:' + group.name + ':members'; - }); + var groupSets = groupData.map(function(group) { + group.labelColor = group.labelColor || '#000000'; - async.map(uids, function(uid, next) { - db.isMemberOfSortedSets(groupSets, uid, function(err, isMembers) { - if (err) { - return next(err); + if (!group['cover:url']) { + group['cover:url'] = nconf.get('relative_path') + '/images/cover-default.png'; + group['cover:position'] = '50% 50%'; } - var memberOf = []; - isMembers.forEach(function(isMember, index) { - if (isMember) { - memberOf.push(groupData[index]); + return 'group:' + group.name + ':members'; + }); + + async.map(uids, function(uid, next) { + db.isMemberOfSortedSets(groupSets, uid, function(err, isMembers) { + if (err) { + return next(err); } - }); - next(null, memberOf); - }); - }, callback); + var memberOf = []; + isMembers.forEach(function(isMember, index) { + if (isMember) { + memberOf.push(groupData[index]); + } + }); + + next(null, memberOf); + }); + }, callback); + }); }); }); }; From b62337b0b90e124c9f444a54b08d2e6c10ef2921 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 30 Jan 2015 16:27:29 -0500 Subject: [PATCH 27/28] fixed browser title in user groups page --- public/language/en_GB/pages.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/language/en_GB/pages.json b/public/language/en_GB/pages.json index 8b231f8a94..4095ae38a3 100644 --- a/public/language/en_GB/pages.json +++ b/public/language/en_GB/pages.json @@ -11,6 +11,7 @@ "user.followers": "People who Follow %1", "user.posts": "Posts made by %1", "user.topics": "Topics created by %1", + "user.groups": "%1's Groups", "user.favourites": "%1's Favourite Posts", "user.settings": "User Settings", From 59da48dee5056fe07c7fe6163926643786b2059e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sun, 1 Feb 2015 19:35:41 -0500 Subject: [PATCH 28/28] added too-many-messages language key --- public/language/en_GB/error.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/language/en_GB/error.json b/public/language/en_GB/error.json index 7e21a1290a..47b0bf8938 100644 --- a/public/language/en_GB/error.json +++ b/public/language/en_GB/error.json @@ -83,6 +83,7 @@ "cant-chat-with-yourself": "You can't chat with yourself!", "chat-restricted": "This user has restricted their chat messages. They must follow you before you can chat with them", + "too-many-messages": "You have sent too many messages, please wait awhile.", "reputation-system-disabled": "Reputation system is disabled.", "downvoting-disabled": "Downvoting is disabled",