From 2495b5b89b6f9b44e07ee31ca235b3f4537f124e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 8 Jan 2014 21:24:43 -0500 Subject: [PATCH] refactored group category permissions, removed getCategoryAccess method call --- public/src/forum/admin/categories.js | 35 ++++++------ src/categoryTools.js | 80 ++++++++++++++++++++++------ src/groups.js | 28 ++++++++-- src/routes/api.js | 36 ++++--------- src/websockets.js | 15 ++---- 5 files changed, 124 insertions(+), 70 deletions(-) diff --git a/public/src/forum/admin/categories.js b/public/src/forum/admin/categories.js index c2efea477d..c7404f3279 100644 --- a/public/src/forum/admin/categories.js +++ b/public/src/forum/admin/categories.js @@ -213,7 +213,7 @@ define(['uploader'], function(uploader) { var modal = $('#category-permissions-modal'), searchEl = modal.find('#permission-search'), resultsEl = modal.find('.search-results'), - groupsResultsEl = modal.find('.groups-results'), + groupsResultsEl = modal.find('.groups-results'), searchDelay; searchEl.off().on('keyup', function() { @@ -266,22 +266,23 @@ define(['uploader'], function(uploader) { searchEl.keyup(); }); - // User Groups and privileges - socket.emit('api:admin.categories.groupsearch', cid, function(err, results) { + // User Groups and privileges + socket.emit('api:admin.categories.groupsList', cid, function(err, results) { var groupsFrag = document.createDocumentFragment(), - trEl = document.createElement('tr'); - var numResults = results.length, + numResults = results.length, + trEl = document.createElement('tr'), resultObj; for(var x=0;x' + - '
' + - '' + - '' + - '
' + - ''; + trEl.innerHTML = '

' + resultObj.name + '

' + + '' + + '
' + + '' + + '' + + '
' + + ''; groupsFrag.appendChild(trEl.cloneNode(true)); } @@ -290,12 +291,14 @@ define(['uploader'], function(uploader) { }); groupsResultsEl.off().on('click', '[data-gpriv]', function(e) { - var btnEl = $(this), - gid = btnEl.parents('li[data-gid]').attr('data-gid'), - privilege = this.getAttribute('data-gpriv'); + var btnEl = $(this), + gid = btnEl.parents('tr[data-gid]').attr('data-gid'), + privilege = this.getAttribute('data-gpriv'); e.preventDefault(); - socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err, privileges) { - btnEl.toggleClass('active', privileges[privilege]); + socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err) { + if (!err) { + btnEl.toggleClass('active'); + } }); }) diff --git a/src/categoryTools.js b/src/categoryTools.js index e1f79e8c07..bdce420460 100644 --- a/src/categoryTools.js +++ b/src/categoryTools.js @@ -47,6 +47,46 @@ CategoryTools.privileges = function(cid, uid, callback) { } }); }, + "g+r": function(next) { + var key = 'cid:' + cid + ':privileges:g+r'; + Groups.exists(key, function(err, exists) { + if (exists) { + async.parallel({ + isMember: function(next) { + Groups.isMemberOfGroupAny(uid, key, next); + }, + isEmpty: function(next) { + Groups.isEmptyByGroupName(key, next); + } + }, next); + } else { + next(null, { + isMember: false, + isEmpty: true + }); + } + }); + }, + "g+w": function(next) { + var key = 'cid:' + cid + ':privileges:g+w'; + Groups.exists(key, function(err, exists) { + if (exists) { + async.parallel({ + isMember: function(next) { + Groups.isMemberOfGroupAny(uid, key, next); + }, + isEmpty: function(next) { + Groups.isEmptyByGroupName(key, next); + } + }, next); + } else { + next(null, { + isMember: false, + isEmpty: true + }); + } + }); + }, moderator: function(next) { User.isModerator(uid, cid, next); }, @@ -57,8 +97,24 @@ CategoryTools.privileges = function(cid, uid, callback) { callback(err, !privileges ? null : { "+r": privileges['+r'].isMember, "+w": privileges['+w'].isMember, - read: (privileges['+r'].isMember || privileges['+r'].isEmpty) || privileges.moderator || privileges.admin, - write: (privileges['+w'].isMember || privileges['+w'].isEmpty) || privileges.moderator || privileges.admin, + "g+r": privileges['g+r'].isMember, + "g+w": privileges['g+w'].isMember, + read: ( + ( + (privileges['+r'].isMember || privileges['+r'].isEmpty) && + (privileges['g+r'].isMember || privileges['g+r'].isEmpty) + ) || + privileges.moderator || + privileges.admin + ), + write: ( + ( + (privileges['+w'].isMember || privileges['+w'].isEmpty) && + (privileges['g+w'].isMember || privileges['g+w'].isEmpty) + ) || + privileges.moderator || + privileges.admin + ), editable: privileges.moderator || privileges.admin, view_deleted: privileges.moderator || privileges.admin }); @@ -67,16 +123,13 @@ CategoryTools.privileges = function(cid, uid, callback) { CategoryTools.groupPrivileges = function(cid, gid, callback) { async.parallel({ - "+gr": function(next) { - var key = 'cid:' + cid + ':privileges:+gr'; + "g+r": function(next) { + var key = 'cid:' + cid + ':privileges:g+r'; Groups.exists(key, function(err, exists) { if (exists) { async.parallel({ isMember: function(next) { Groups.isMemberByGroupName(gid, key, next); - }, - isEmpty: function(next) { - Groups.isEmptyByGroupName(key, next); } }, next); } else { @@ -87,16 +140,13 @@ CategoryTools.groupPrivileges = function(cid, gid, callback) { } }); }, - "+gw": function(next) { - var key = 'cid:' + cid + ':privileges:+gw'; + "g+w": function(next) { + var key = 'cid:' + cid + ':privileges:g+w'; Groups.exists(key, function(err, exists) { if (exists) { async.parallel({ isMember: function(next) { Groups.isMemberByGroupName(gid, key, next); - }, - isEmpty: function(next) { - Groups.isEmptyByGroupName(key, next); } }, next); } else { @@ -109,10 +159,8 @@ CategoryTools.groupPrivileges = function(cid, gid, callback) { } }, function(err, privileges) { callback(err, !privileges ? null : { - "+gr": privileges['+gr'].isMember, - "+gw": privileges['+gw'].isMember, - read: (privileges['+gr'].isMember || privileges['+gr'].isEmpty), - write: (privileges['+gw'].isMember || privileges['+gw'].isEmpty), + "g+r": privileges['g+r'].isMember, + "g+w": privileges['g+w'].isMember }); }); }; diff --git a/src/groups.js b/src/groups.js index dc235fd26b..de931c3887 100644 --- a/src/groups.js +++ b/src/groups.js @@ -106,6 +106,28 @@ }); }; + Groups.isMemberOfGroupAny = function(uid, groupListKey, callback) { + Groups.getGidFromName(groupListKey, function(err, gid) { + if (err || !gid) { + return callback(new Error('error-checking-group')); + } + + db.getSetMembers('gid:' + gid + ':members', function(err, gids) { + async.some(gids, function(gid, next) { + Groups.isMember(uid, gid, function(err, isMember) { + if (!err && isMember) { + next(true); + } else { + next(false); + } + }); + }, function(result) { + callback(null, result); + }); + }); + }) + }; + Groups.isEmpty = function(gid, callback) { db.setCount('gid:' + gid + ':members', function(err, numMembers) { callback(err, numMembers === 0); @@ -266,7 +288,7 @@ // check user group read access level async.series([function(callback){ // get groups with read permission - db.getObjectField('group:gid', 'cid:' + cid + ':privileges:+gr', function(err, gid){ + db.getObjectField('group:gid', 'cid:' + cid + ':privileges:g+r', function(err, gid){ // get the user groups that belong to this read group db.getSetMembers('gid:' + gid + ':members', function (err, gids) { // check if user belong to any of these user groups @@ -285,10 +307,10 @@ // has access or not. async.series(groups_check, function(err, results){ callback(null, results); - }); + }); }); }); - + }], function(err, results){ // if the read group is empty we will asume that read access has been granted to ALL diff --git a/src/routes/api.js b/src/routes/api.js index 680cb159ee..33156ea955 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -132,15 +132,8 @@ var path = require('path'), if (parseInt(data.deleted, 10) === 1 && parseInt(data.expose_tools, 10) === 0) { return res.json(404, {}); } - // get the category this post belongs to and check category access - var cid = data.category_slug.split("/")[0]; - groups.getCategoryAccess(cid, uid, function(err, access){ - if (access){ - res.json(data); - } else { - res.send(403); - } - }) + + res.json(data); } else next(); }); } else { @@ -155,24 +148,17 @@ var path = require('path'), // Category Whitelisting categoryTools.privileges(req.params.id, uid, function(err, privileges) { if (!err && privileges.read) { - groups.getCategoryAccess(req.params.id, uid, function(err, access){ - if (access){ - categories.getCategoryById(req.params.id, uid, function (err, data) { - if(err) { - return next(err); - } - - if (data && parseInt(data.disabled, 10) === 0) { - res.json(data); - } else { - next(); - } - }, req.params.id, uid); - } else { - res.send(403); + categories.getCategoryById(req.params.id, uid, function (err, data) { + if(err) { + return next(err); } - }); + if (data && parseInt(data.disabled, 10) === 0) { + res.json(data); + } else { + next(); + } + }, req.params.id, uid); } else { res.send(403); } diff --git a/src/websockets.js b/src/websockets.js index b908f459a4..b52807b23b 100644 --- a/src/websockets.js +++ b/src/websockets.js @@ -1136,32 +1136,27 @@ websockets.init = function(io) { }); socket.on('api:admin.categories.setGroupPrivilege', function(cid, gid, privilege, set, callback) { - var cb = function(err) { - CategoryTools.groupPrivileges(cid, gid, callback); - }; - if (set) { - groups.joinByGroupName('cid:' + cid + ':privileges:' + privilege, gid, cb); + groups.joinByGroupName('cid:' + cid + ':privileges:' + privilege, gid, callback); } else { - groups.leaveByGroupName('cid:' + cid + ':privileges:' + privilege, gid, cb); + groups.leaveByGroupName('cid:' + cid + ':privileges:' + privilege, gid, callback); } }); - socket.on('api:admin.categories.groupsearch', function(cid, callback) { + socket.on('api:admin.categories.groupsList', function(cid, callback) { groups.list({expand:false}, function(err, data){ async.map(data, function(groupObj, next) { CategoryTools.groupPrivileges(cid, groupObj.gid, function(err, privileges) { if (!err) { groupObj.privileges = privileges; } else { - winston.error('[socket api:admin.categories.groupsearch] Could not retrieve permissions'); + winston.error('[socket api:admin.categories.groupsList] Could not retrieve permissions'); } next(null, groupObj); }); }, function(err, data) { - if (!callback) socket.emit('api:admin.categories.groupsearch', data); - else callback(null, data); + callback(null, data); }); }); });