From 8db193ff556ac0663400be9ca79f54ad6096b717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 25 May 2017 21:17:20 -0400 Subject: [PATCH] privileges style changes --- src/groups/membership.js | 2 +- src/privileges/categories.js | 223 ++++++++++++++++++----------------- src/privileges/helpers.js | 127 +++++++++----------- src/privileges/posts.js | 151 ++++++++++++------------ src/privileges/topics.js | 111 +++++++++-------- src/privileges/users.js | 173 ++++++++++++++------------- 6 files changed, 384 insertions(+), 403 deletions(-) diff --git a/src/groups/membership.js b/src/groups/membership.js index 1b74badb02..244c3e6695 100644 --- a/src/groups/membership.js +++ b/src/groups/membership.js @@ -323,7 +323,7 @@ module.exports = function (Groups) { }); Groups.isMember = function (uid, groupName, callback) { - if (!uid || parseInt(uid, 10) <= 0) { + if (!uid || parseInt(uid, 10) <= 0 || !groupName) { return setImmediate(callback, null, false); } diff --git a/src/privileges/categories.js b/src/privileges/categories.js index 6678f5d5aa..453203107b 100644 --- a/src/privileges/categories.js +++ b/src/privileges/categories.js @@ -31,126 +31,127 @@ module.exports = function (privileges) { { name: 'Moderate' }, ]; - async.parallel({ - labels: function (next) { + async.waterfall([ + function (next) { async.parallel({ - users: async.apply(plugins.fireHook, 'filter:privileges.list_human', privilegeLabels), - groups: async.apply(plugins.fireHook, 'filter:privileges.groups.list_human', privilegeLabels), - }, next); - }, - users: function (next) { - var userPrivileges; - async.waterfall([ - async.apply(plugins.fireHook, 'filter:privileges.list', privileges.userPrivilegeList), - function (_privs, next) { - userPrivileges = _privs; - groups.getMembersOfGroups(userPrivileges.map(function (privilege) { - return 'cid:' + cid + ':privileges:' + privilege; - }), next); - }, - function (memberSets, next) { - memberSets = memberSets.map(function (set) { - return set.map(function (uid) { - return parseInt(uid, 10); - }); - }); - - var members = _.unique(_.flatten(memberSets)); - - user.getUsersFields(members, ['picture', 'username'], function (err, memberData) { - if (err) { - return next(err); - } - - memberData.forEach(function (member) { - member.privileges = {}; - for (var x = 0, numPrivs = userPrivileges.length; x < numPrivs; x += 1) { - member.privileges[userPrivileges[x]] = memberSets[x].indexOf(parseInt(member.uid, 10)) !== -1; - } - }); - - next(null, memberData); - }); + labels: function (next) { + async.parallel({ + users: async.apply(plugins.fireHook, 'filter:privileges.list_human', privilegeLabels), + groups: async.apply(plugins.fireHook, 'filter:privileges.groups.list_human', privilegeLabels), + }, next); }, - ], next); - }, - groups: function (next) { - var groupPrivileges; - async.waterfall([ - async.apply(plugins.fireHook, 'filter:privileges.groups.list', privileges.groupPrivilegeList), - function (_privs, next) { - groupPrivileges = _privs; - groups.getMembersOfGroups(groupPrivileges.map(function (privilege) { - return 'cid:' + cid + ':privileges:' + privilege; - }), next); + users: function (next) { + var userPrivileges; + var memberSets; + async.waterfall([ + async.apply(plugins.fireHook, 'filter:privileges.list', privileges.userPrivilegeList), + function (_privs, next) { + userPrivileges = _privs; + groups.getMembersOfGroups(userPrivileges.map(function (privilege) { + return 'cid:' + cid + ':privileges:' + privilege; + }), next); + }, + function (_memberSets, next) { + memberSets = _memberSets.map(function (set) { + return set.map(function (uid) { + return parseInt(uid, 10); + }); + }); + + var members = _.unique(_.flatten(memberSets)); + + user.getUsersFields(members, ['picture', 'username'], next); + }, + function (memberData, next) { + memberData.forEach(function (member) { + member.privileges = {}; + for (var x = 0, numPrivs = userPrivileges.length; x < numPrivs; x += 1) { + member.privileges[userPrivileges[x]] = memberSets[x].indexOf(parseInt(member.uid, 10)) !== -1; + } + }); + + next(null, memberData); + }, + ], next); }, - function (memberSets, next) { - var uniqueGroups = _.unique(_.flatten(memberSets)); - - groups.getGroups('groups:createtime', 0, -1, function (err, groupNames) { - if (err) { - return next(err); - } - - groupNames = groupNames.filter(function (groupName) { - return groupName.indexOf(':privileges:') === -1 && uniqueGroups.indexOf(groupName) !== -1; - }); - - groupNames = groups.ephemeralGroups.concat(groupNames); - var registeredUsersIndex = groupNames.indexOf('registered-users'); - if (registeredUsersIndex !== -1) { - groupNames.splice(0, 0, groupNames.splice(registeredUsersIndex, 1)[0]); - } else { - groupNames = ['registered-users'].concat(groupNames); - } - - var adminIndex = groupNames.indexOf('administrators'); - if (adminIndex !== -1) { - groupNames.splice(adminIndex, 1); - } - - var memberPrivs; - - var memberData = groupNames.map(function (member) { - memberPrivs = {}; - - for (var x = 0, numPrivs = groupPrivileges.length; x < numPrivs; x += 1) { - memberPrivs[groupPrivileges[x]] = memberSets[x].indexOf(member) !== -1; + groups: function (next) { + var groupPrivileges; + async.waterfall([ + async.apply(plugins.fireHook, 'filter:privileges.groups.list', privileges.groupPrivilegeList), + function (_privs, next) { + groupPrivileges = _privs; + async.parallel({ + memberSets: function (next) { + groups.getMembersOfGroups(groupPrivileges.map(function (privilege) { + return 'cid:' + cid + ':privileges:' + privilege; + }), next); + }, + groupNames: function (next) { + groups.getGroups('groups:createtime', 0, -1, next); + }, + }, next); + }, + function (results, next) { + var memberSets = results.memberSets; + var uniqueGroups = _.unique(_.flatten(memberSets)); + + var groupNames = results.groupNames.filter(function (groupName) { + return groupName.indexOf(':privileges:') === -1 && uniqueGroups.indexOf(groupName) !== -1; + }); + + groupNames = groups.ephemeralGroups.concat(groupNames); + var registeredUsersIndex = groupNames.indexOf('registered-users'); + if (registeredUsersIndex !== -1) { + groupNames.splice(0, 0, groupNames.splice(registeredUsersIndex, 1)[0]); + } else { + groupNames = ['registered-users'].concat(groupNames); } - return { - name: member, - privileges: memberPrivs, - }; - }); - next(null, memberData); - }); - }, - function (memberData, next) { - // Grab privacy info for the groups as well - async.map(memberData, function (member, next) { - groups.isPrivate(member.name, function (err, isPrivate) { - if (err) { - return next(err); + var adminIndex = groupNames.indexOf('administrators'); + if (adminIndex !== -1) { + groupNames.splice(adminIndex, 1); } - member.isPrivate = isPrivate; - next(null, member); - }); - }, next); + var memberPrivs; + + var memberData = groupNames.map(function (member) { + memberPrivs = {}; + + for (var x = 0, numPrivs = groupPrivileges.length; x < numPrivs; x += 1) { + memberPrivs[groupPrivileges[x]] = memberSets[x].indexOf(member) !== -1; + } + return { + name: member, + privileges: memberPrivs, + }; + }); + + next(null, memberData); + }, + function (memberData, next) { + // Grab privacy info for the groups as well + async.map(memberData, function (member, next) { + async.waterfall([ + function (next) { + groups.isPrivate(member.name, next); + }, + function (isPrivate, next) { + member.isPrivate = isPrivate; + next(); + }, + ], next); + }, next); + }, + ], next); }, - ], next); + }, next); }, - }, function (err, payload) { - if (err) { - return callback(err); - } - - // This is a hack because I can't do {labels.users.length} to echo the count in templates.js - payload.columnCount = payload.labels.users.length + 2; - - callback(null, payload); - }); + function (payload, next) { + // This is a hack because I can't do {labels.users.length} to echo the count in templates.js + payload.columnCount = payload.labels.users.length + 2; + next(null, payload); + }, + ], callback); }; privileges.categories.get = function (cid, uid, callback) { diff --git a/src/privileges/helpers.js b/src/privileges/helpers.js index 9593d60f09..0f56e4f9c8 100644 --- a/src/privileges/helpers.js +++ b/src/privileges/helpers.js @@ -4,7 +4,7 @@ var async = require('async'); var groups = require('../groups'); -var helpers = {}; +var helpers = module.exports; helpers.some = function (tasks, callback) { async.some(tasks, function (task, next) { @@ -29,30 +29,12 @@ function isUserAllowedToCids(privilege, uid, cids, callback) { var userKeys = []; var groupKeys = []; - for (var i = 0; i < cids.length; i += 1) { - userKeys.push('cid:' + cids[i] + ':privileges:' + privilege); - groupKeys.push('cid:' + cids[i] + ':privileges:groups:' + privilege); - } - - async.parallel({ - hasUserPrivilege: function (next) { - groups.isMemberOfGroups(uid, userKeys, next); - }, - hasGroupPrivilege: function (next) { - groups.isMemberOfGroupsList(uid, groupKeys, next); - }, - }, function (err, results) { - if (err) { - return callback(err); - } - - var result = []; - for (var i = 0; i < cids.length; i += 1) { - result.push(results.hasUserPrivilege[i] || results.hasGroupPrivilege[i]); - } - - callback(null, result); + cids.forEach(function (cid) { + userKeys.push('cid:' + cid + ':privileges:' + privilege); + groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege); }); + + checkIfAllowed(uid, userKeys, groupKeys, callback); } function isUserAllowedToPrivileges(privileges, uid, cid, callback) { @@ -62,71 +44,70 @@ function isUserAllowedToPrivileges(privileges, uid, cid, callback) { var userKeys = []; var groupKeys = []; - for (var i = 0; i < privileges.length; i += 1) { - userKeys.push('cid:' + cid + ':privileges:' + privileges[i]); - groupKeys.push('cid:' + cid + ':privileges:groups:' + privileges[i]); - } + privileges.forEach(function (privilege) { + userKeys.push('cid:' + cid + ':privileges:' + privilege); + groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege); + }); - async.parallel({ - hasUserPrivilege: function (next) { - groups.isMemberOfGroups(uid, userKeys, next); - }, - hasGroupPrivilege: function (next) { - groups.isMemberOfGroupsList(uid, groupKeys, next); - }, - }, function (err, results) { - if (err) { - return callback(err); - } + checkIfAllowed(uid, userKeys, groupKeys, callback); +} - var result = []; - for (var i = 0; i < privileges.length; i += 1) { - result.push(results.hasUserPrivilege[i] || results.hasGroupPrivilege[i]); - } +function checkIfAllowed(uid, userKeys, groupKeys, callback) { + async.waterfall([ + function (next) { + async.parallel({ + hasUserPrivilege: function (next) { + groups.isMemberOfGroups(uid, userKeys, next); + }, + hasGroupPrivilege: function (next) { + groups.isMemberOfGroupsList(uid, groupKeys, next); + }, + }, next); + }, + function (results, next) { + var result = userKeys.map(function (key, index) { + return results.hasUserPrivilege[index] || results.hasGroupPrivilege[index]; + }); - callback(null, result); - }); + next(null, result); + }, + ], callback); } - helpers.isUsersAllowedTo = function (privilege, uids, cid, callback) { - async.parallel({ - hasUserPrivilege: function (next) { - groups.isMembers(uids, 'cid:' + cid + ':privileges:' + privilege, next); + async.waterfall([ + function (next) { + async.parallel({ + hasUserPrivilege: function (next) { + groups.isMembers(uids, 'cid:' + cid + ':privileges:' + privilege, next); + }, + hasGroupPrivilege: function (next) { + groups.isMembersOfGroupList(uids, 'cid:' + cid + ':privileges:groups:' + privilege, next); + }, + }, 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 < uids.length; i += 1) { - result.push(results.hasUserPrivilege[i] || results.hasGroupPrivilege[i]); - } + function (results, next) { + var result = uids.map(function (uid, index) { + return results.hasUserPrivilege[index] || results.hasGroupPrivilege[index]; + }); - callback(null, result); - }); + next(null, result); + }, + ], callback); }; function isGuestAllowedToCids(privilege, cids, callback) { - var groupKeys = []; - for (var i = 0; i < cids.length; i += 1) { - groupKeys.push('cid:' + cids[i] + ':privileges:groups:' + privilege); - } + var groupKeys = cids.map(function (cid) { + return 'cid:' + cid + ':privileges:groups:' + privilege; + }); groups.isMemberOfGroups('guests', groupKeys, callback); } function isGuestAllowedToPrivileges(privileges, cid, callback) { - var groupKeys = []; - for (var i = 0; i < privileges.length; i += 1) { - groupKeys.push('cid:' + cid + ':privileges:groups:' + privileges[i]); - } + var groupKeys = privileges.map(function (privilege) { + return 'cid:' + cid + ':privileges:groups:' + privilege; + }); groups.isMemberOfGroups('guests', groupKeys, callback); } - -module.exports = helpers; diff --git a/src/privileges/posts.js b/src/privileges/posts.js index 8a31ad4129..1855098927 100644 --- a/src/privileges/posts.js +++ b/src/privileges/posts.js @@ -32,39 +32,35 @@ module.exports = function (privileges) { 'posts:edit': async.apply(helpers.isUserAllowedTo, 'posts:edit', uid, cids), }, next); }, - ], function (err, results) { - if (err) { - return callback(err); - } - - var privileges = []; - - for (var i = 0; i < pids.length; i += 1) { - var isAdminOrMod = results.isAdmin || results.isModerator[i]; - var editable = isAdminOrMod || (results.isOwner[i] && results['posts:edit'][i]); - - privileges.push({ - editable: editable, - view_deleted: editable, - move: isAdminOrMod, - isAdminOrMod: isAdminOrMod, - 'topics:read': results['topics:read'][i] || isAdminOrMod, - read: results.read[i] || isAdminOrMod, + function (results, next) { + var privileges = pids.map(function (pid, i) { + var isAdminOrMod = results.isAdmin || results.isModerator[i]; + var editable = isAdminOrMod || (results.isOwner[i] && results['posts:edit'][i]); + + return { + editable: editable, + view_deleted: editable, + move: isAdminOrMod, + isAdminOrMod: isAdminOrMod, + 'topics:read': results['topics:read'][i] || isAdminOrMod, + read: results.read[i] || isAdminOrMod, + }; }); - } - callback(null, privileges); - }); + next(null, privileges); + }, + ], callback); }; privileges.posts.can = function (privilege, pid, uid, callback) { - posts.getCidByPid(pid, function (err, cid) { - if (err) { - return callback(err); - } - - privileges.categories.can(privilege, cid, uid, callback); - }); + async.waterfall([ + function (next) { + posts.getCidByPid(pid, next); + }, + function (cid, next) { + privileges.categories.can(privilege, cid, uid, next); + }, + ], callback); }; privileges.posts.filter = function (privilege, pids, uid, callback) { @@ -136,19 +132,21 @@ module.exports = function (privileges) { }; privileges.posts.canEdit = function (pid, uid, callback) { - async.parallel({ - isEditable: async.apply(isPostEditable, pid, uid), - isAdminOrMod: async.apply(isAdminOrMod, pid, uid), - }, function (err, results) { - if (err) { - return callback(err); - } - if (results.isAdminOrMod) { - return callback(null, { flag: true }); - } + async.waterfall([ + function (next) { + async.parallel({ + isEditable: async.apply(isPostEditable, pid, uid), + isAdminOrMod: async.apply(isAdminOrMod, pid, uid), + }, next); + }, + function (results, next) { + if (results.isAdminOrMod) { + return next(null, { flag: true }); + } - callback(null, results.isEditable); - }); + next(null, results.isEditable); + }, + ], callback); }; privileges.posts.canDelete = function (pid, uid, callback) { @@ -166,40 +164,42 @@ module.exports = function (privileges) { 'posts:delete': async.apply(privileges.posts.can, 'posts:delete', pid, uid), }, next); }, - ], function (err, results) { - if (err) { - return callback(err); - } - - if (results.isAdminOrMod) { - return callback(null, { flag: true }); - } + function (results, next) { + if (results.isAdminOrMod) { + return next(null, { flag: true }); + } - if (results.isLocked) { - return callback(null, { flag: false, message: '[[error:topic-locked]]' }); - } + if (results.isLocked) { + return next(null, { flag: false, message: '[[error:topic-locked]]' }); + } - if (!results['posts:delete']) { - return callback(null, { flag: false, message: '[[error:no-privileges]]' }); - } + if (!results['posts:delete']) { + return next(null, { flag: false, message: '[[error:no-privileges]]' }); + } - var postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10); - if (postDeleteDuration && (Date.now() - parseInt(postData.timestamp, 10) > postDeleteDuration * 1000)) { - return callback(null, { flag: false, message: '[[error:post-delete-duration-expired, ' + meta.config.postDeleteDuration + ']]' }); - } - var deleterUid = parseInt(postData.deleterUid, 10) || 0; - var flag = results.isOwner && (deleterUid === 0 || deleterUid === parseInt(postData.uid, 10)); - callback(null, { flag: flag, message: '[[error:no-privileges]]' }); - }); + var postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10); + if (postDeleteDuration && (Date.now() - parseInt(postData.timestamp, 10) > postDeleteDuration * 1000)) { + return next(null, { flag: false, message: '[[error:post-delete-duration-expired, ' + meta.config.postDeleteDuration + ']]' }); + } + var deleterUid = parseInt(postData.deleterUid, 10) || 0; + var flag = results.isOwner && (deleterUid === 0 || deleterUid === parseInt(postData.uid, 10)); + next(null, { flag: flag, message: '[[error:no-privileges]]' }); + }, + ], callback); }; privileges.posts.canMove = function (pid, uid, callback) { - posts.isMain(pid, function (err, isMain) { - if (err || isMain) { - return callback(err || new Error('[[error:cant-move-mainpost]]')); - } - isAdminOrMod(pid, uid, callback); - }); + async.waterfall([ + function (next) { + posts.isMain(pid, next); + }, + function (isMain, next) { + if (isMain) { + return next(new Error('[[error:cant-move-mainpost]]')); + } + isAdminOrMod(pid, uid, next); + }, + ], callback); }; privileges.posts.canPurge = function (pid, uid, callback) { @@ -251,13 +251,14 @@ module.exports = function (privileges) { function isAdminOrMod(pid, uid, callback) { helpers.some([ function (next) { - posts.getCidByPid(pid, function (err, cid) { - if (err || !cid) { - return next(err, false); - } - - user.isModerator(uid, cid, next); - }); + async.waterfall([ + function (next) { + posts.getCidByPid(pid, next); + }, + function (cid, next) { + user.isModerator(uid, cid, next); + }, + ], next); }, function (next) { user.isAdministrator(uid, next); diff --git a/src/privileges/topics.js b/src/privileges/topics.js index f44383eed8..1299713ea7 100644 --- a/src/privileges/topics.js +++ b/src/privileges/topics.js @@ -28,37 +28,34 @@ module.exports = function (privileges) { disabled: async.apply(categories.getCategoryField, topic.cid, 'disabled'), }, next); }, - ], function (err, results) { - if (err) { - return callback(err); - } - - var privData = _.object(privs, results.privileges); - var disabled = parseInt(results.disabled, 10) === 1; - var locked = parseInt(topic.locked, 10) === 1; - var deleted = parseInt(topic.deleted, 10) === 1; - var isOwner = !!parseInt(uid, 10) && parseInt(uid, 10) === parseInt(topic.uid, 10); - var isAdminOrMod = results.isAdministrator || results.isModerator; - var editable = isAdminOrMod; - var deletable = isAdminOrMod || (isOwner && privData['topics:delete']); - - plugins.fireHook('filter:privileges.topics.get', { - 'topics:reply': (privData['topics:reply'] && !locked && !deleted) || isAdminOrMod, - 'topics:read': privData['topics:read'] || isAdminOrMod, - 'topics:delete': (isOwner && privData['topics:delete']) || isAdminOrMod, - 'posts:edit': (privData['posts:edit'] && !locked) || isAdminOrMod, - 'posts:delete': (privData['posts:delete'] && !locked) || isAdminOrMod, - read: privData.read || isAdminOrMod, - view_thread_tools: editable || deletable, - editable: editable, - deletable: deletable, - view_deleted: isAdminOrMod || isOwner, - isAdminOrMod: isAdminOrMod, - disabled: disabled, - tid: tid, - uid: uid, - }, callback); - }); + function (results, next) { + var privData = _.object(privs, results.privileges); + var disabled = parseInt(results.disabled, 10) === 1; + var locked = parseInt(topic.locked, 10) === 1; + var deleted = parseInt(topic.deleted, 10) === 1; + var isOwner = !!parseInt(uid, 10) && parseInt(uid, 10) === parseInt(topic.uid, 10); + var isAdminOrMod = results.isAdministrator || results.isModerator; + var editable = isAdminOrMod; + var deletable = isAdminOrMod || (isOwner && privData['topics:delete']); + + plugins.fireHook('filter:privileges.topics.get', { + 'topics:reply': (privData['topics:reply'] && !locked && !deleted) || isAdminOrMod, + 'topics:read': privData['topics:read'] || isAdminOrMod, + 'topics:delete': (isOwner && privData['topics:delete']) || isAdminOrMod, + 'posts:edit': (privData['posts:edit'] && !locked) || isAdminOrMod, + 'posts:delete': (privData['posts:delete'] && !locked) || isAdminOrMod, + read: privData.read || isAdminOrMod, + view_thread_tools: editable || deletable, + editable: editable, + deletable: deletable, + view_deleted: isAdminOrMod || isOwner, + isAdminOrMod: isAdminOrMod, + disabled: disabled, + tid: tid, + uid: uid, + }, next); + }, + ], callback); }; privileges.topics.can = function (privilege, tid, uid, callback) { @@ -194,29 +191,26 @@ module.exports = function (privileges) { 'topics:delete': async.apply(helpers.isUserAllowedTo, 'topics:delete', uid, [topicData.cid]), }, next); }, - ], function (err, results) { - if (err) { - return callback(err); - } - - if (results.isModerator || results.isAdministrator) { - return callback(null, true); - } + function (results, next) { + if (results.isModerator || results.isAdministrator) { + return next(null, true); + } - var preventTopicDeleteAfterReplies = parseInt(meta.config.preventTopicDeleteAfterReplies, 10) || 0; - if (preventTopicDeleteAfterReplies && (topicData.postcount - 1) >= preventTopicDeleteAfterReplies) { - var langKey = preventTopicDeleteAfterReplies > 1 ? - '[[error:cant-delete-topic-has-replies, ' + meta.config.preventTopicDeleteAfterReplies + ']]' : - '[[error:cant-delete-topic-has-reply]]'; - return callback(new Error(langKey)); - } + var preventTopicDeleteAfterReplies = parseInt(meta.config.preventTopicDeleteAfterReplies, 10) || 0; + if (preventTopicDeleteAfterReplies && (topicData.postcount - 1) >= preventTopicDeleteAfterReplies) { + var langKey = preventTopicDeleteAfterReplies > 1 ? + '[[error:cant-delete-topic-has-replies, ' + meta.config.preventTopicDeleteAfterReplies + ']]' : + '[[error:cant-delete-topic-has-reply]]'; + return next(new Error(langKey)); + } - if (!results['topics:delete'][0]) { - return callback(null, false); - } + if (!results['topics:delete'][0]) { + return next(null, false); + } - callback(null, results.isOwner); - }); + next(null, results.isOwner); + }, + ], callback); }; privileges.topics.canEdit = function (tid, uid, callback) { @@ -234,16 +228,17 @@ module.exports = function (privileges) { ], callback); }; - privileges.topics.isAdminOrMod = function (tid, uid, callback) { helpers.some([ function (next) { - topics.getTopicField(tid, 'cid', function (err, cid) { - if (err) { - return next(err); - } - user.isModerator(uid, cid, next); - }); + async.waterfall([ + function (next) { + topics.getTopicField(tid, 'cid', next); + }, + function (cid, next) { + user.isModerator(uid, cid, next); + }, + ], next); }, function (next) { user.isAdministrator(uid, next); diff --git a/src/privileges/users.js b/src/privileges/users.js index 26557a1798..9731a9f37d 100644 --- a/src/privileges/users.js +++ b/src/privileges/users.js @@ -40,36 +40,34 @@ module.exports = function (privileges) { if (!parseInt(uid, 10)) { return filterIsModerator(cids, uid, cids.map(function () { return false; }), callback); } - - privileges.users.isGlobalModerator(uid, function (err, isGlobalModerator) { - if (err) { - return callback(err); - } - if (isGlobalModerator) { - return filterIsModerator(cids, uid, cids.map(function () { return true; }), callback); - } - - - var uniqueCids = cids.filter(function (cid, index, array) { - return array.indexOf(cid) === index; - }); - - var groupNames = uniqueCids.map(function (cid) { - return 'cid:' + cid + ':privileges:mods'; // At some point we should *probably* change this to "moderate" as well - }); - - var groupListNames = uniqueCids.map(function (cid) { - return 'cid:' + cid + ':privileges:groups:moderate'; - }); - - async.parallel({ - user: async.apply(groups.isMemberOfGroups, uid, groupNames), - group: async.apply(groups.isMemberOfGroupsList, uid, groupListNames), - }, function (err, checks) { - if (err) { - return callback(err); + var uniqueCids; + async.waterfall([ + function (next) { + privileges.users.isGlobalModerator(uid, next); + }, + function (isGlobalModerator, next) { + if (isGlobalModerator) { + return filterIsModerator(cids, uid, cids.map(function () { return true; }), callback); } + uniqueCids = cids.filter(function (cid, index, array) { + return array.indexOf(cid) === index; + }); + + var groupNames = uniqueCids.map(function (cid) { + return 'cid:' + cid + ':privileges:mods'; // At some point we should *probably* change this to "moderate" as well + }); + + var groupListNames = uniqueCids.map(function (cid) { + return 'cid:' + cid + ':privileges:groups:moderate'; + }); + + async.parallel({ + user: async.apply(groups.isMemberOfGroups, uid, groupNames), + group: async.apply(groups.isMemberOfGroupsList, uid, groupListNames), + }, next); + }, + function (checks, next) { var isMembers = checks.user.map(function (isMember, idx) { return isMember || checks.group[idx]; }); @@ -83,80 +81,85 @@ module.exports = function (privileges) { return map[cid]; }); - filterIsModerator(cids, uid, isModerator, callback); - }); - }); + filterIsModerator(cids, uid, isModerator, next); + }, + ], callback); } function isModeratorsOfCategory(cid, uids, callback) { - async.parallel([ - async.apply(privileges.users.isGlobalModerator, uids), - async.apply(groups.isMembers, uids, 'cid:' + cid + ':privileges:mods'), - async.apply(groups.isMembersOfGroupList, uids, 'cid:' + cid + ':privileges:groups:moderate'), - ], function (err, checks) { - if (err) { - return callback(err); - } - - var isModerator = checks[0].map(function (isMember, idx) { - return isMember || checks[1][idx] || checks[2][idx]; - }); - - filterIsModerator(cid, uids, isModerator, callback); - }); + async.waterfall([ + function (next) { + async.parallel([ + async.apply(privileges.users.isGlobalModerator, uids), + async.apply(groups.isMembers, uids, 'cid:' + cid + ':privileges:mods'), + async.apply(groups.isMembersOfGroupList, uids, 'cid:' + cid + ':privileges:groups:moderate'), + ], next); + }, + function (checks, next) { + var isModerator = checks[0].map(function (isMember, idx) { + return isMember || checks[1][idx] || checks[2][idx]; + }); + + filterIsModerator(cid, uids, isModerator, next); + }, + ], callback); } function isModeratorOfCategory(cid, uid, callback) { - async.parallel([ - async.apply(privileges.users.isGlobalModerator, uid), - async.apply(groups.isMember, uid, 'cid:' + cid + ':privileges:mods'), - async.apply(groups.isMemberOfGroupList, uid, 'cid:' + cid + ':privileges:groups:moderate'), - ], function (err, checks) { - if (err) { - return callback(err); - } - - var isModerator = checks[0] || checks[1] || checks[2]; - filterIsModerator(cid, uid, isModerator, callback); - }); + async.waterfall([ + function (next) { + async.parallel([ + async.apply(privileges.users.isGlobalModerator, uid), + async.apply(groups.isMember, uid, 'cid:' + cid + ':privileges:mods'), + async.apply(groups.isMemberOfGroupList, uid, 'cid:' + cid + ':privileges:groups:moderate'), + ], next); + }, + function (checks, next) { + var isModerator = checks[0] || checks[1] || checks[2]; + filterIsModerator(cid, uid, isModerator, next); + }, + ], callback); } function filterIsModerator(cid, uid, isModerator, callback) { - plugins.fireHook('filter:user.isModerator', { uid: uid, cid: cid, isModerator: isModerator }, function (err, data) { - if (err) { - return callback(err); - } - if ((Array.isArray(uid) || Array.isArray(cid)) && !Array.isArray(data.isModerator)) { - return callback(new Error('filter:user.isModerator - i/o mismatch')); - } - - callback(null, data.isModerator); - }); + async.waterfall([ + function (next) { + plugins.fireHook('filter:user.isModerator', { uid: uid, cid: cid, isModerator: isModerator }, next); + }, + function (data, next) { + if ((Array.isArray(uid) || Array.isArray(cid)) && !Array.isArray(data.isModerator)) { + return callback(new Error('filter:user.isModerator - i/o mismatch')); + } + + next(null, data.isModerator); + }, + ], callback); } privileges.users.canEdit = function (callerUid, uid, callback) { if (parseInt(callerUid, 10) === parseInt(uid, 10)) { return process.nextTick(callback, null, true); } - - async.parallel({ - isAdmin: function (next) { - privileges.users.isAdministrator(callerUid, next); - }, - isGlobalMod: function (next) { - privileges.users.isGlobalModerator(callerUid, next); - }, - isTargetAdmin: function (next) { - privileges.users.isAdministrator(uid, next); + async.waterfall([ + function (next) { + async.parallel({ + isAdmin: function (next) { + privileges.users.isAdministrator(callerUid, next); + }, + isGlobalMod: function (next) { + privileges.users.isGlobalModerator(callerUid, next); + }, + isTargetAdmin: function (next) { + privileges.users.isAdministrator(uid, next); + }, + }, next); }, - }, function (err, results) { - if (err) { - return callback(err); - } - var canEdit = results.isAdmin || (results.isGlobalMod && !results.isTargetAdmin); + function (results, next) { + var canEdit = results.isAdmin || (results.isGlobalMod && !results.isTargetAdmin); - callback(null, canEdit); - }); + next(null, canEdit); + }, + ], callback); }; privileges.users.canBanUser = function (callerUid, uid, callback) {