diff --git a/src/privileges.js b/src/privileges.js index d10fb32420..5c12365597 100644 --- a/src/privileges.js +++ b/src/privileges.js @@ -5,5 +5,6 @@ var privileges = {}; require('./privileges/categories')(privileges); require('./privileges/topics')(privileges); require('./privileges/posts')(privileges); +require('./privileges/users')(privileges); module.exports = privileges; \ No newline at end of file diff --git a/src/privileges/users.js b/src/privileges/users.js new file mode 100644 index 0000000000..1a0427b766 --- /dev/null +++ b/src/privileges/users.js @@ -0,0 +1,124 @@ + +'use strict'; + +var async = require('async'), + winston = require('winston'), + + db = require('../database'), + topics = require('../topics'), + user = require('../user'), + helpers = require('./helpers'), + groups = require('../groups'), + categories = require('../categories'), + plugins = require('../plugins'); + +module.exports = function(privileges) { + + privileges.users = {}; + + privileges.users.isAdministrator = function(uid, callback) { + if (Array.isArray(uid)) { + groups.isMembers(uid, 'administrators', callback); + } else { + groups.isMember(uid, 'administrators', callback); + } + }; + + privileges.users.isModerator = function(uid, cid, callback) { + if (Array.isArray(cid)) { + isModeratorOfCategories(cid, uid, callback); + } else { + if (Array.isArray(uid)) { + isModeratorsOfCategory(cid, uid, callback); + } else { + isModeratorOfCategory(cid, uid, callback); + } + } + }; + + function isModeratorOfCategories(cids, uid, callback) { + if (!parseInt(uid, 10)) { + return filterIsModerator(null, cids.map(function() {return false;})); + } + + 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 + }), + 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 isMembers = checks.user.map(function(isMember, idx) { + return isMember || checks.group[idx]; + }), + map = {}; + + uniqueCids.forEach(function(cid, index) { + map[cid] = isMembers[index]; + }); + + var isModerator = cids.map(function(cid) { + return map[cid]; + }); + + filterIsModerator(cids, uid, isModerator, callback); + }); + } + + function isModeratorsOfCategory(cid, uids, callback) { + async.parallel([ + 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]; + }); + + filterIsModerator(cid, uids, isModerator, callback); + }); + } + + function isModeratorOfCategory(cid, uid, callback) { + async.parallel([ + 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]; + filterIsModerator(cid, uid, isModerator, 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(data.isModerator) || Array.isArray(cid) && !Array.isArray(data.isModerator)) { + return callback(new Error('filter:user.isModerator - i/o mismatch')); + } + + callback(null, data.isModerator); + }); + } + +}; diff --git a/src/user.js b/src/user.js index 5be73d5f64..7f862599f3 100644 --- a/src/user.js +++ b/src/user.js @@ -11,6 +11,7 @@ var async = require('async'), topics = require('./topics'), groups = require('./groups'), Password = require('./password'), + privileges = require('./privileges'), utils = require('../public/src/utils'); (function(User) { @@ -20,9 +21,11 @@ var async = require('async'), User.reset = require('./user/reset'); User.digest = require('./user/digest'); + require('./user/data')(User); require('./user/auth')(User); require('./user/create')(User); require('./user/posts')(User); + require('./user/categories')(User); require('./user/follow')(User); require('./user/profile')(User); require('./user/admin')(User); @@ -34,113 +37,6 @@ var async = require('async'), require('./user/approval')(User); require('./user/invite')(User); - User.getUserField = function(uid, field, callback) { - User.getUserFields(uid, [field], function(err, user) { - callback(err, user ? user[field] : null); - }); - }; - - User.getUserFields = function(uid, fields, callback) { - User.getMultipleUserFields([uid], fields, function(err, users) { - callback(err, users ? users[0] : null); - }); - }; - - User.getMultipleUserFields = function(uids, fields, callback) { - var fieldsToRemove = []; - function addField(field) { - if (fields.indexOf(field) === -1) { - fields.push(field); - fieldsToRemove.push(field); - } - } - - if (!Array.isArray(uids) || !uids.length) { - return callback(null, []); - } - - var keys = uids.map(function(uid) { - return 'user:' + uid; - }); - - if (fields.indexOf('uid') === -1) { - fields.push('uid'); - } - - if (fields.indexOf('picture') !== -1) { - addField('email'); - addField('gravatarpicture'); - addField('uploadedpicture'); - } - - db.getObjectsFields(keys, fields, function(err, users) { - if (err) { - return callback(err); - } - - modifyUserData(users, fieldsToRemove, callback); - }); - }; - - User.getUserData = function(uid, callback) { - 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); - } - - modifyUserData(users, [], callback); - }); - }; - - function modifyUserData(users, fieldsToRemove, callback) { - users.forEach(function(user) { - if (!user) { - return; - } - - user.username = validator.escape(user.username); - - if (user.password) { - user.password = undefined; - } - - if (!parseInt(user.uid, 10)) { - user.uid = 0; - user.username = '[[global:guest]]'; - user.userslug = ''; - user.picture = User.createGravatarURLFromEmail(''); - } - - if (user.picture) { - if (user.picture === user.uploadedpicture) { - user.picture = user.uploadedpicture = user.picture.startsWith('http') ? user.picture : nconf.get('relative_path') + user.picture; - } else { - user.picture = User.createGravatarURLFromEmail(user.email); - } - } - - for(var i=0; i