diff --git a/src/categories.js b/src/categories.js index 315f6e8c4f..0d33631437 100644 --- a/src/categories.js +++ b/src/categories.js @@ -216,7 +216,7 @@ var db = require('./database'), return callback(null, []); } - privileges.categories.filter(privilege, cids, uid, function(err, cids) { + privileges.categories.filterCids(privilege, cids, uid, function(err, cids) { if (err) { return callback(err); } @@ -402,7 +402,7 @@ var db = require('./database'), async.waterfall([ async.apply(db.getSortedSetRange, 'categories:cid', 0, -1), function(cids, next) { - privileges.categories.filter('find', cids, uid, next); + privileges.categories.filterCids('find', cids, uid, next); }, function (cids, next) { Categories.getCategoriesData(cids, next); diff --git a/src/groups.js b/src/groups.js index 06c03bcffa..3b5c6e8318 100644 --- a/src/groups.js +++ b/src/groups.js @@ -173,6 +173,9 @@ Groups.isMemberOfGroupList = function(uid, groupListKey, callback) { db.getSetMembers('group:' + groupListKey + ':members', function(err, groupNames) { + if (err) { + return callback(err); + } groupNames = internals.removeEphemeralGroups(groupNames); if (groupNames.length === 0) { return callback(null, null); @@ -180,11 +183,7 @@ async.some(groupNames, function(groupName, next) { Groups.isMember(uid, groupName, function(err, isMember) { - if (!err && isMember) { - next(true); - } else { - next(false); - } + next(!err && isMember); }); }, function(result) { callback(null, result); @@ -192,6 +191,38 @@ }); }; + Groups.isMembersOfGroupList = function(uids, groupListKey, callback) { + db.getSetMembers('group:' + groupListKey + ':members', function(err, groupNames) { + if (err) { + return callback(err); + } + groupNames = internals.removeEphemeralGroups(groupNames); + if (groupNames.length === 0) { + return callback(null, null); + } + var results = []; + uids.forEach(function() { + results.push(false); + }); + + async.each(groupNames, function(groupName, next) { + Groups.isMembers(uids, groupName, function(err, isMembers) { + if (err) { + return next(err); + } + results.forEach(function(isMember, index) { + if (!isMember && isMembers[index]) { + results[index] = true; + } + }); + next(); + }); + }, function(err) { + callback(err, results); + }); + }); + }; + Groups.exists = function(name, callback) { if (Array.isArray(name)) { db.isSetMembers('groups', name, callback); diff --git a/src/privileges/categories.js b/src/privileges/categories.js index e7572888f7..a6e1ce7204 100644 --- a/src/privileges/categories.js +++ b/src/privileges/categories.js @@ -16,10 +16,10 @@ module.exports = function(privileges) { privileges.categories.get = function(cid, uid, callback) { async.parallel({ 'topics:create': function(next) { - helpers.allowedTo('topics:create', uid, [cid], next); + helpers.isUserAllowedTo('topics:create', uid, [cid], next); }, read: function(next) { - helpers.allowedTo('read', uid, [cid], next); + helpers.isUserAllowedTo('read', uid, [cid], next); }, isAdministrator: function(next) { user.isAdministrator(uid, next); @@ -55,7 +55,7 @@ module.exports = function(privileges) { helpers.some([ function(next) { - helpers.allowedTo(privilege, uid, [cid], function(err, results) { + helpers.isUserAllowedTo(privilege, uid, [cid], function(err, results) { next(err, Array.isArray(results) && results.length ? results[0] : false); }); }, @@ -69,7 +69,7 @@ module.exports = function(privileges) { }); }; - privileges.categories.filter = function(privilege, cids, uid, callback) { + privileges.categories.filterCids = function(privilege, cids, uid, callback) { if (!cids.length) { return callback(null, []); } @@ -80,7 +80,7 @@ module.exports = function(privileges) { async.parallel({ allowedTo: function(next) { - helpers.allowedTo(privilege, uid, cids, next); + helpers.isUserAllowedTo(privilege, uid, cids, next); }, isModerators: function(next) { user.isModerator(uid, cids, next); @@ -104,6 +104,37 @@ module.exports = function(privileges) { }); }; + privileges.categories.filterUids = function(privilege, cid, uids, callback) { + if (!uids.length) { + return callback(null, []); + } + + uids = uids.filter(function(uid, index, array) { + return array.indexOf(uid) === index; + }); + + async.parallel({ + allowedTo: function(next) { + helpers.isUsersAllowedTo(privilege, uids, cid, next); + }, + isModerators: function(next) { + user.isModerator(uids, cid, next); + }, + isAdmin: function(next) { + user.isAdministrator(uids, next); + } + }, function(err, results) { + if (err) { + return callback(err); + } + + uids = uids.filter(function(uid, index) { + return results.allowedTo[index] || results.isModerators[index] || results.isAdmin[index]; + }); + callback(null, uids); + }); + }; + privileges.categories.isAdminOrMod = function(cids, uid, callback) { async.parallel({ isModerators: function(next) { diff --git a/src/privileges/helpers.js b/src/privileges/helpers.js index ee6583b408..17a8eee1eb 100644 --- a/src/privileges/helpers.js +++ b/src/privileges/helpers.js @@ -20,7 +20,7 @@ helpers.some = function(tasks, callback) { }); }; -helpers.allowedTo = function(privilege, uid, cids, callback) { +helpers.isUserAllowedTo = function(privilege, uid, cids, callback) { if (parseInt(uid, 10) === 0) { return isGuestAllowedTo(privilege, cids, callback); } @@ -61,6 +61,35 @@ helpers.allowedTo = function(privilege, uid, cids, callback) { }); }; +helpers.isUsersAllowedTo = function(privilege, uids, cid, callback) { + async.parallel({ + userPrivilegeExists: function(next) { + groups.exists('cid:' + cid + ':privileges:' + privilege, next); + }, + groupPrivilegeExists: function(next) { + groups.exists('cid:' + cid + ':privileges:groups:' + privilege, next); + }, + hasUserPrivilege: function(next) { + groups.isMembers(uids, 'cid:' + cid + ':privileges:' + privilege, next); + }, + hasGroupPrivilege: function(next) { + groups.isMembersOfGroupList(uids, 'cid:' + cid + ':privileges:groups:' + privilege, next); + } + }, function(err, results) { + if (err) { + return callback(err); + } + + var result = []; + + for(var i=0; i