diff --git a/src/categories/index.js b/src/categories/index.js index 278f72c498..a1275481e8 100644 --- a/src/categories/index.js +++ b/src/categories/index.js @@ -6,7 +6,7 @@ var _ = require('lodash'); var db = require('../database'); var user = require('../user'); -var Groups = require('../groups'); +var groups = require('../groups'); var plugins = require('../plugins'); var privileges = require('../privileges'); const cache = require('../cache'); @@ -130,10 +130,45 @@ Categories.getCategoriesByPrivilege = function (set, uid, privilege, callback) { Categories.getModerators = function (cid, callback) { async.waterfall([ function (next) { - Groups.getMembers('cid:' + cid + ':privileges:moderate', 0, -1, next); + Categories.getModeratorUids([cid], next); }, function (uids, next) { - user.getUsersFields(uids, ['uid', 'username', 'userslug', 'picture'], next); + user.getUsersFields(uids[0], ['uid', 'username', 'userslug', 'picture'], next); + }, + ], callback); +}; + +Categories.getModeratorUids = function (cids, callback) { + var sets; + async.waterfall([ + function (next) { + var groupNames = cids.reduce(function (memo, cid) { + memo.push('cid:' + cid + ':privileges:moderate'); + memo.push('cid:' + cid + ':privileges:groups:moderate'); + return memo; + }, []); + + groups.getMembersOfGroups(groupNames, next); + }, + function (memberSets, next) { + // Every other set is actually a list of user groups, not uids, so convert those to members + sets = memberSets.reduce(function (memo, set, idx) { + if (idx % 2) { + memo.groupNames.push(set); + } else { + memo.uids.push(set); + } + + return memo; + }, { groupNames: [], uids: [] }); + + groups.getMembersOfGroups(sets.groupNames, next); + }, + function (groupUids, next) { + const moderatorUids = cids.map(function (cid, index) { + return _.union(sets.uids[index].concat(groupUids[index])); + }); + next(null, moderatorUids); }, ], callback); }; diff --git a/src/groups/membership.js b/src/groups/membership.js index 247716a0ab..09b8242202 100644 --- a/src/groups/membership.js +++ b/src/groups/membership.js @@ -134,9 +134,7 @@ module.exports = function (Groups) { }; Groups.getMembersOfGroups = function (groupNames, callback) { - db.getSortedSetsMembers(groupNames.map(function (name) { - return 'group:' + name + ':members'; - }), callback); + db.getSortedSetsMembers(groupNames.map(name => 'group:' + name + ':members'), callback); }; Groups.isMember = function (uid, groupName, callback) { diff --git a/src/posts/queue.js b/src/posts/queue.js index 7dd311aa74..7afddef4b5 100644 --- a/src/posts/queue.js +++ b/src/posts/queue.js @@ -1,11 +1,14 @@ 'use strict'; var async = require('async'); +const _ = require('lodash'); var db = require('../database'); var user = require('../user'); var meta = require('../meta'); +var groups = require('../groups'); var topics = require('../topics'); +var categories = require('../categories'); var notifications = require('../notifications'); var privileges = require('../privileges'); var plugins = require('../plugins'); @@ -18,7 +21,7 @@ module.exports = function (Posts) { user.getUserFields(uid, ['uid', 'reputation', 'postcount'], next); }, function (userData, next) { - var shouldQueue = meta.config.postQueue && (!userData.uid || userData.reputation < 0 || userData.postcount <= 0); + const shouldQueue = meta.config.postQueue && (!userData.uid || userData.reputation < 0 || userData.postcount <= 0); plugins.fireHook('filter:post.shouldQueue', { shouldQueue: shouldQueue, uid: uid, @@ -31,6 +34,44 @@ module.exports = function (Posts) { ], callback); }; + function removeQueueNotification(id, callback) { + async.waterfall([ + function (next) { + notifications.rescind('post-queue-' + id, next); + }, + function (next) { + getParsedObject(id, next); + }, + function (data, next) { + if (!data) { + return callback(); + } + getCid(data.type, data, next); + }, + function (cid, next) { + getNotificationUids(cid, next); + }, + function (uids, next) { + uids.forEach(uid => user.notifications.pushCount(uid)); + next(); + }, + ], callback); + } + + function getNotificationUids(cid, callback) { + async.waterfall([ + function (next) { + async.parallel([ + async.apply(groups.getMembersOfGroups, ['administrators', 'Global Moderators']), + async.apply(categories.getModeratorUids, [cid]), + ], next); + }, + function (results, next) { + next(null, _.union(results)); + }, + ], callback); + } + Posts.addToQueue = function (data, callback) { var type = data.title ? 'topic' : 'reply'; var id = type + '-' + Date.now(); @@ -64,14 +105,21 @@ module.exports = function (Posts) { path: '/post-queue', }, next); }, - cid: function (next) { - getCid(type, data, next); + uids: function (next) { + async.waterfall([ + function (next) { + getCid(type, data, next); + }, + function (cid, next) { + getNotificationUids(cid, next); + }, + ], next); }, }, next); }, function (results, next) { if (results.notification) { - notifications.pushGroups(results.notification, ['administrators', 'Global Moderators', 'cid:' + results.cid + ':privileges:moderate'], next); + notifications.push(results.uids, next); } else { next(); } @@ -128,13 +176,13 @@ module.exports = function (Posts) { Posts.removeFromQueue = function (id, callback) { async.waterfall([ function (next) { - db.sortedSetRemove('post:queue', id, next); + removeQueueNotification(id, next); }, function (next) { - db.delete('post:queue:' + id, next); + db.sortedSetRemove('post:queue', id, next); }, function (next) { - notifications.rescind('post-queue-' + id, next); + db.delete('post:queue:' + id, next); }, ], callback); }; diff --git a/src/user/index.js b/src/user/index.js index d8c19ed705..40fda6ab91 100644 --- a/src/user/index.js +++ b/src/user/index.js @@ -291,32 +291,10 @@ User.getModeratorUids = function (callback) { async.waterfall([ async.apply(categories.getAllCidsFromSet, 'categories:cid'), function (cids, next) { - var groupNames = cids.reduce(function (memo, cid) { - memo.push('cid:' + cid + ':privileges:moderate'); - memo.push('cid:' + cid + ':privileges:groups:moderate'); - return memo; - }, []); - - groups.getMembersOfGroups(groupNames, next); - }, - function (memberSets, next) { - // Every other set is actually a list of user groups, not uids, so convert those to members - var sets = memberSets.reduce(function (memo, set, idx) { - if (idx % 2) { - memo.working.push(set); - } else { - memo.regular.push(set); - } - - return memo; - }, { working: [], regular: [] }); - - groups.getMembersOfGroups(sets.working, function (err, memberSets) { - next(err, sets.regular.concat(memberSets || [])); - }); + categories.getModeratorUids(cids, next); }, - function (memberSets, next) { - next(null, _.union.apply(_, memberSets)); + function (uids, next) { + next(null, _.union(uids)); }, ], callback); }; diff --git a/test/categories.js b/test/categories.js index f5b838066d..5eae36d1f9 100644 --- a/test/categories.js +++ b/test/categories.js @@ -800,6 +800,33 @@ describe('Categories', function () { done(); }); }); + + describe('Categories.getModeratorUids', function () { + before(function (done) { + async.series([ + async.apply(groups.create, { name: 'testGroup' }), + async.apply(groups.join, 'cid:1:privileges:groups:moderate', 'testGroup'), + async.apply(groups.join, 'testGroup', 1), + ], done); + }); + + it('should retrieve all users with moderator bit in category privilege', function (done) { + Categories.getModeratorUids([1, 2], function (err, uids) { + assert.ifError(err); + assert.strictEqual(2, uids.length); + assert.strictEqual(1, parseInt(uids[0], 10)); + assert.strictEqual(0, uids[1].length); + done(); + }); + }); + + after(function (done) { + async.series([ + async.apply(groups.leave, 'cid:1:privileges:groups:moderate', 'testGroup'), + async.apply(groups.destroy, 'testGroup'), + ], done); + }); + }); });