move privileges to same page

This commit is contained in:
Baris Usakli
2017-12-20 14:49:20 -05:00
parent 63b9255fa1
commit 242dc41aca
12 changed files with 235 additions and 475 deletions

View File

@@ -1,6 +1,4 @@
{
"global": "Global",
"global.description": "You can configure the global privileges in this section. Privileges can be granted on a per-user or a per-group basis. You can add a new user to this table by searching for them in the form below.",
"global.warning": "<strong>Note</strong>: Privilege settings take effect immediately. It is not necessary to save after adjusting these settings.",
"global.no-users": "No user-specific global privileges."
}

View File

@@ -1,6 +1,5 @@
'use strict';
define('admin/manage/category', [
'uploader',
'iconSelect',
@@ -8,8 +7,7 @@ define('admin/manage/category', [
'autocomplete',
'translator',
'categorySelector',
'benchpress',
], function (uploader, iconSelect, colorpicker, autocomplete, translator, categorySelector, Benchpress) {
], function (uploader, iconSelect, colorpicker, autocomplete, translator, categorySelector) {
var Category = {};
var modified_categories = {};
@@ -21,11 +19,7 @@ define('admin/manage/category', [
$('#category-selector').on('change', function () {
var val = $(this).val();
if (val === 'global') {
ajaxify.go('admin/manage/privileges');
} else {
ajaxify.go('admin/manage/categories/' + $(this).val() + window.location.hash);
}
});
function enableColorPicker(idx, inputEl) {
@@ -105,7 +99,7 @@ define('admin/manage/category', [
});
$('.copy-settings').on('click', function () {
selectCategoryModal(function (cid) {
categorySelector.modal(function (cid) {
socket.emit('admin.categories.copySettingsFrom', { fromCid: cid, toCid: ajaxify.data.category.cid }, function (err) {
if (err) {
return app.alertError(err.message);
@@ -174,8 +168,6 @@ define('admin/manage/category', [
$('button[data-action="setParent"]').removeClass('hide');
});
});
Category.setupPrivilegeTable();
};
function modified(el) {
@@ -213,102 +205,12 @@ define('admin/manage/category', [
});
}
Category.setupPrivilegeTable = function () {
$('.privilege-table-container').on('change', 'input[type="checkbox"]', function () {
var checkboxEl = $(this);
var privilege = checkboxEl.parent().attr('data-privilege');
var state = checkboxEl.prop('checked');
var rowEl = checkboxEl.parents('tr');
var member = rowEl.attr('data-group-name') || rowEl.attr('data-uid');
var isPrivate = parseInt(rowEl.attr('data-private') || 0, 10);
var isGroup = rowEl.attr('data-group-name') !== undefined;
if (member) {
if (isGroup && privilege === 'groups:moderate' && !isPrivate && state) {
bootbox.confirm('[[admin/manage/categories:alert.confirm-moderate]]', function (confirm) {
if (confirm) {
Category.setPrivilege(member, privilege, state, checkboxEl);
} else {
checkboxEl.prop('checked', !checkboxEl.prop('checked'));
}
});
} else {
Category.setPrivilege(member, privilege, state, checkboxEl);
}
} else {
app.alertError('[[error:invalid-data]]');
}
});
$('.privilege-table-container').on('click', '[data-action="search.user"]', Category.addUserToPrivilegeTable);
$('.privilege-table-container').on('click', '[data-action="search.group"]', Category.addGroupToPrivilegeTable);
$('.privilege-table-container').on('click', '[data-action="copyToChildren"]', Category.copyPrivilegesToChildren);
$('.privilege-table-container').on('click', '[data-action="copyPrivilegesFrom"]', Category.copyPrivilegesFromCategory);
Category.exposeAssumedPrivileges();
};
Category.refreshPrivilegeTable = function () {
socket.emit('admin.categories.getPrivilegeSettings', ajaxify.data.category.cid, function (err, privileges) {
if (err) {
return app.alertError(err.message);
}
Benchpress.parse('admin/partials/categories/privileges', {
privileges: privileges,
}, function (html) {
translator.translate(html, function (html) {
$('.privilege-table-container').html(html);
Category.exposeAssumedPrivileges();
});
});
});
};
Category.exposeAssumedPrivileges = function () {
/*
If registered-users has a privilege enabled, then all users and groups of that privilege
should be assumed to have that privilege as well, even if not set in the db, so reflect
this arrangement in the table
*/
var privs = [];
$('.privilege-table tr[data-group-name="registered-users"] td input[type="checkbox"]').parent().each(function (idx, el) {
if ($(el).find('input').prop('checked')) {
privs.push(el.getAttribute('data-privilege'));
}
});
for (var x = 0, numPrivs = privs.length; x < numPrivs; x += 1) {
var inputs = $('.privilege-table tr[data-group-name]:not([data-group-name="registered-users"],[data-group-name="guests"]) td[data-privilege="' + privs[x] + '"] input');
inputs.each(function (idx, el) {
if (!el.checked) {
el.indeterminate = true;
}
});
}
};
Category.setPrivilege = function (member, privilege, state, checkboxEl) {
socket.emit('admin.categories.setPrivilege', {
cid: ajaxify.data.category.cid,
privilege: privilege,
set: state,
member: member,
}, function (err) {
if (err) {
return app.alertError(err.message);
}
checkboxEl.replaceWith('<i class="fa fa-spin fa-spinner"></i>');
Category.refreshPrivilegeTable();
});
};
Category.launchParentSelector = function () {
var categories = ajaxify.data.allCategories.filter(function (category) {
return category && !category.disabled && parseInt(category.cid, 10) !== parseInt(ajaxify.data.category.cid, 10);
});
selectCategoryModal(categories, function (parentCid) {
categorySelector.modal(categories, function (parentCid) {
var payload = {};
payload[ajaxify.data.category.cid] = {
@@ -332,117 +234,5 @@ define('admin/manage/category', [
});
};
Category.addUserToPrivilegeTable = function () {
var modal = bootbox.dialog({
title: '[[admin/manage/categories:alert.find-user]]',
message: '<input class="form-control input-lg" placeholder="[[admin/manage/categories:alert.user-search]]" />',
show: true,
});
modal.on('shown.bs.modal', function () {
var inputEl = modal.find('input');
autocomplete.user(inputEl, function (ev, ui) {
socket.emit('admin.categories.setPrivilege', {
cid: ajaxify.data.category.cid,
privilege: ['find', 'read', 'topics:read'],
set: true,
member: ui.item.user.uid,
}, function (err) {
if (err) {
return app.alertError(err.message);
}
Category.refreshPrivilegeTable();
modal.modal('hide');
});
});
});
};
Category.addGroupToPrivilegeTable = function () {
var modal = bootbox.dialog({
title: '[[admin/manage/categories:alert.find-group]]',
message: '<input class="form-control input-lg" placeholder="[[admin/manage/categories:alert.group-search]]" />',
show: true,
});
modal.on('shown.bs.modal', function () {
var inputEl = modal.find('input');
autocomplete.group(inputEl, function (ev, ui) {
socket.emit('admin.categories.setPrivilege', {
cid: ajaxify.data.category.cid,
privilege: ['groups:find', 'groups:read', 'groups:topics:read'],
set: true,
member: ui.item.group.name,
}, function (err) {
if (err) {
return app.alertError(err.message);
}
Category.refreshPrivilegeTable();
modal.modal('hide');
});
});
});
};
Category.copyPrivilegesToChildren = function () {
socket.emit('admin.categories.copyPrivilegesToChildren', ajaxify.data.category.cid, function (err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('Privileges copied!');
});
};
Category.copyPrivilegesFromCategory = function () {
selectCategoryModal(function (cid) {
socket.emit('admin.categories.copyPrivilegesFrom', { toCid: ajaxify.data.category.cid, fromCid: cid }, function (err) {
if (err) {
return app.alertError(err.message);
}
ajaxify.refresh();
});
});
};
function selectCategoryModal(categories, callback) {
if (typeof categories === 'function') {
callback = categories;
categories = ajaxify.data.allCategories;
}
Benchpress.parse('admin/partials/categories/select-category', {
categories: categories,
}, function (html) {
translator.translate(html, function (html) {
var modal = bootbox.dialog({
title: '[[modules:composer.select_category]]',
message: html,
buttons: {
save: {
label: '[[global:select]]',
className: 'btn-primary',
callback: submit,
},
},
});
categorySelector.init(modal.find('[component="category-selector"]'));
function submit(ev) {
ev.preventDefault();
var selectedCategory = categorySelector.getSelectedCategory();
if (selectedCategory) {
callback(selectedCategory.cid);
modal.modal('hide');
}
return false;
}
modal.find('form').on('submit', submit);
});
});
}
return Category;
});

View File

@@ -1,19 +1,21 @@
'use strict';
define('admin/manage/privileges', [
'autocomplete',
'translator',
'benchpress',
], function (autocomplete, translator, Benchpress) {
'categorySelector'
], function (autocomplete, translator, Benchpress, categorySelector) {
var Privileges = {};
var cid;
Privileges.init = function () {
cid = ajaxify.data.cid || 0;
$('#category-selector').on('change', function () {
var val = $(this).val();
if (val !== 'global') {
ajaxify.go('admin/manage/categories/' + $(this).val() + '#privileges');
}
ajaxify.go('admin/manage/privileges/' + (val === 'global' ? '' : $(this).val()));
});
@@ -31,7 +33,17 @@ define('admin/manage/privileges', [
var isGroup = rowEl.attr('data-group-name') !== undefined;
if (member) {
if (isGroup && privilege === 'groups:moderate' && !isPrivate && state) {
bootbox.confirm('[[admin/manage/categories:alert.confirm-moderate]]', function (confirm) {
if (confirm) {
Privileges.setPrivilege(member, privilege, state, checkboxEl);
} else {
checkboxEl.prop('checked', !checkboxEl.prop('checked'));
}
});
} else {
Privileges.setPrivilege(member, privilege, state, checkboxEl);
}
} else {
app.alertError('[[error:invalid-data]]');
}
@@ -39,17 +51,19 @@ define('admin/manage/privileges', [
$('.privilege-table-container').on('click', '[data-action="search.user"]', Privileges.addUserToPrivilegeTable);
$('.privilege-table-container').on('click', '[data-action="search.group"]', Privileges.addGroupToPrivilegeTable);
$('.privilege-table-container').on('click', '[data-action="copyToChildren"]', Privileges.copyPrivilegesToChildren);
$('.privilege-table-container').on('click', '[data-action="copyPrivilegesFrom"]', Privileges.copyPrivilegesFromCategory);
Privileges.exposeAssumedPrivileges();
};
Privileges.refreshPrivilegeTable = function () {
socket.emit('admin.categories.getPrivilegeSettings', function (err, privileges) {
socket.emit('admin.categories.getPrivilegeSettings', cid, function (err, privileges) {
if (err) {
return app.alertError(err.message);
}
Benchpress.parse('admin/partials/global/privileges', {
var tpl = cid ? 'admin/partials/categories/privileges' : 'admin/manage/privileges';
Benchpress.parse(tpl, {
privileges: privileges,
}, function (html) {
translator.translate(html, function (html) {
@@ -84,7 +98,7 @@ define('admin/manage/privileges', [
Privileges.setPrivilege = function (member, privilege, state, checkboxEl) {
socket.emit('admin.categories.setPrivilege', {
cid: 0,
cid: cid,
privilege: privilege,
set: state,
member: member,
@@ -109,9 +123,10 @@ define('admin/manage/privileges', [
var inputEl = modal.find('input');
autocomplete.user(inputEl, function (ev, ui) {
var defaultPrivileges = cid ? ['find', 'read', 'topics:read'] : ['chat'];
socket.emit('admin.categories.setPrivilege', {
cid: 0,
privilege: ['chat'],
cid: cid,
privilege: defaultPrivileges,
set: true,
member: ui.item.user.uid,
}, function (err) {
@@ -137,9 +152,10 @@ define('admin/manage/privileges', [
var inputEl = modal.find('input');
autocomplete.group(inputEl, function (ev, ui) {
var defaultPrivileges = cid ? ['groups:find', 'groups:read', 'groups:topics:read'] : ['groups:chat'];
socket.emit('admin.categories.setPrivilege', {
cid: 0,
privilege: ['groups:chat'],
cid: cid,
privilege: defaultPrivileges,
set: true,
member: ui.item.group.name,
}, function (err) {
@@ -154,5 +170,25 @@ define('admin/manage/privileges', [
});
};
Privileges.copyPrivilegesToChildren = function () {
socket.emit('admin.categories.copyPrivilegesToChildren', cid, function (err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('Privileges copied!');
});
};
Privileges.copyPrivilegesFromCategory = function () {
categorySelector.modal(function (fromCid) {
socket.emit('admin.categories.copyPrivilegesFrom', { toCid: cid, fromCid: fromCid }, function (err) {
if (err) {
return app.alertError(err.message);
}
ajaxify.refresh();
});
});
};
return Privileges;
});

View File

@@ -1,7 +1,6 @@
'use strict';
define('categorySelector', function () {
define('categorySelector', ['benchpress', 'translator'], function (Benchpress, translator) {
var categorySelector = {};
var selectedCategory;
var el;
@@ -29,6 +28,42 @@ define('categorySelector', function () {
el.find('[component="category-selector-selected"]').html(categoryEl.find('[component="category-markup"]').html());
};
categorySelector.modal = function (categories, callback) {
if (typeof categories === 'function') {
callback = categories;
categories = ajaxify.data.allCategories;
}
Benchpress.parse('admin/partials/categories/select-category', {
categories: categories,
}, function (html) {
translator.translate(html, function (html) {
var modal = bootbox.dialog({
title: '[[modules:composer.select_category]]',
message: html,
buttons: {
save: {
label: '[[global:select]]',
className: 'btn-primary',
callback: submit,
},
},
});
categorySelector.init(modal.find('[component="category-selector"]'));
function submit(ev) {
ev.preventDefault();
var selectedCategory = categorySelector.getSelectedCategory();
if (selectedCategory) {
callback(selectedCategory.cid);
modal.modal('hide');
}
return false;
}
modal.find('form').on('submit', submit);
});
});
};
return categorySelector;
});

View File

@@ -15,7 +15,6 @@ categoriesController.get = function (req, res, callback) {
function (next) {
async.parallel({
category: async.apply(categories.getCategories, [req.params.category_id], req.user.uid),
privileges: async.apply(privileges.categories.list, req.params.category_id),
allCategories: async.apply(categories.buildForSelect, req.uid, 'read'),
}, next);
},
@@ -36,7 +35,6 @@ categoriesController.get = function (req, res, callback) {
req: req,
res: res,
category: category,
privileges: data.privileges,
allCategories: data.allCategories,
}, next);
},
@@ -44,7 +42,6 @@ categoriesController.get = function (req, res, callback) {
data.category.name = translator.escape(String(data.category.name));
res.render('admin/manage/category', {
category: data.category,
privileges: data.privileges,
allCategories: data.allCategories,
});
},

View File

@@ -8,17 +8,32 @@ var privileges = require('../../privileges');
var privilegesController = module.exports;
privilegesController.get = function (req, res, callback) {
var cid = req.params.cid ? req.params.cid : 0;
async.waterfall([
function (next) {
async.parallel({
privileges: async.apply(privileges.global.list),
privileges: function (next) {
if (!cid) {
privileges.global.list(next);
} else {
privileges.categories.list(cid, next);
}
},
allCategories: async.apply(categories.buildForSelect, req.uid, 'read'),
}, next);
},
function (data) {
data.allCategories.forEach(function (category) {
if (category) {
category.selected = parseInt(category.cid, 10) === parseInt(cid, 10);
}
});
res.render('admin/manage/privileges', {
privileges: data.privileges,
allCategories: data.allCategories,
cid: cid,
});
},
], callback);

View File

@@ -15,121 +15,20 @@ module.exports = function (privileges) {
privileges.categories.list = function (cid, callback) {
// Method used in admin/category controller to show all users/groups with privs in that given cid
var privilegeLabels = privileges.privilegeLabels.slice();
var userPrivilegeList = privileges.userPrivilegeList.slice();
var groupPrivilegeList = privileges.groupPrivilegeList.slice();
async.waterfall([
function (next) {
async.parallel({
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),
users: async.apply(plugins.fireHook, 'filter:privileges.list_human', privileges.privilegeLabels.slice()),
groups: async.apply(plugins.fireHook, 'filter:privileges.groups.list_human', privileges.privilegeLabels.slice()),
}, next);
},
users: function (next) {
var userPrivileges;
var memberSets;
async.waterfall([
async.apply(plugins.fireHook, 'filter:privileges.list', 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 = _.uniq(_.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);
helpers.getUserPrivileges(cid, 'filter:privileges.list', privileges.userPrivilegeList, next);
},
groups: function (next) {
var groupPrivileges;
async.waterfall([
async.apply(plugins.fireHook, 'filter:privileges.groups.list', 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 = _.uniq(_.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);
}
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;
}
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(null, member);
},
], next);
}, next);
},
], next);
helpers.getGroupPrivileges(cid, 'filter:privileges.groups.list', privileges.groupPrivilegeList, next);
},
}, next);
},

View File

@@ -25,121 +25,20 @@ module.exports = function (privileges) {
});
privileges.global.list = function (callback) {
var privilegeLabels = privileges.global.privilegeLabels.slice();
var userPrivilegeList = privileges.global.userPrivilegeList.slice();
var groupPrivilegeList = privileges.global.groupPrivilegeList.slice();
async.waterfall([
function (next) {
async.parallel({
labels: function (next) {
async.parallel({
users: async.apply(plugins.fireHook, 'filter:privileges.global.list_human', privilegeLabels),
groups: async.apply(plugins.fireHook, 'filter:privileges.global.groups.list_human', privilegeLabels),
users: async.apply(plugins.fireHook, 'filter:privileges.global.list_human', privileges.global.privilegeLabels.slice()),
groups: async.apply(plugins.fireHook, 'filter:privileges.global.groups.list_human', privileges.global.privilegeLabels.slice()),
}, next);
},
users: function (next) {
var userPrivileges;
var memberSets;
async.waterfall([
async.apply(plugins.fireHook, 'filter:privileges.global.list', userPrivilegeList),
function (_privs, next) {
userPrivileges = _privs;
groups.getMembersOfGroups(userPrivileges.map(function (privilege) {
return 'cid:0:privileges:' + privilege;
}), next);
},
function (_memberSets, next) {
memberSets = _memberSets.map(function (set) {
return set.map(function (uid) {
return parseInt(uid, 10);
});
});
var members = _.uniq(_.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);
helpers.getUserPrivileges(0, 'filter:privileges.global.list', privileges.global.userPrivilegeList, next);
},
groups: function (next) {
var groupPrivileges;
async.waterfall([
async.apply(plugins.fireHook, 'filter:privileges.global.groups.list', groupPrivilegeList),
function (_privs, next) {
groupPrivileges = _privs;
async.parallel({
memberSets: function (next) {
groups.getMembersOfGroups(groupPrivileges.map(function (privilege) {
return 'cid:0:privileges:' + privilege;
}), next);
},
groupNames: function (next) {
groups.getGroups('groups:createtime', 0, -1, next);
},
}, next);
},
function (results, next) {
var memberSets = results.memberSets;
var uniqueGroups = _.uniq(_.flatten(memberSets));
var groupNames = results.groupNames.filter(function (groupName) {
return groupName.indexOf(':privileges:') === -1 && uniqueGroups.indexOf(groupName) !== -1;
});
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;
}
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(null, member);
},
], next);
}, next);
},
], next);
helpers.getGroupPrivileges(0, 'filter:privileges.global.groups.list', privileges.global.groupPrivilegeList, next);
},
}, next);
},

View File

@@ -2,7 +2,11 @@
'use strict';
var async = require('async');
var _ = require('lodash');
var groups = require('../groups');
var user = require('../user');
var plugins = require('../plugins');
var helpers = module.exports;
@@ -111,3 +115,109 @@ function isGuestAllowedToPrivileges(privileges, cid, callback) {
groups.isMemberOfGroups('guests', groupKeys, callback);
}
helpers.getUserPrivileges = function (cid, hookName, userPrivilegeList, callback) {
var userPrivileges;
var memberSets;
async.waterfall([
async.apply(plugins.fireHook, hookName, userPrivilegeList.slice()),
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 = _.uniq(_.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);
},
], callback);
};
helpers.getGroupPrivileges = function (cid, hookName, groupPrivilegeList, callback) {
var groupPrivileges;
async.waterfall([
async.apply(plugins.fireHook, hookName, groupPrivilegeList.slice()),
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 = _.uniq(_.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);
}
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;
}
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(null, member);
},
], next);
}, next);
},
], callback);
};

View File

@@ -55,7 +55,7 @@ function addRoutes(router, middleware, controllers) {
router.get('/manage/categories/:category_id', middlewares, controllers.admin.categories.get);
router.get('/manage/categories/:category_id/analytics', middlewares, controllers.admin.categories.getAnalytics);
router.get('/manage/privileges', middlewares, controllers.admin.privileges.get);
router.get('/manage/privileges/:cid?', middlewares, controllers.admin.privileges.get);
router.get('/manage/tags', middlewares, controllers.admin.tags.get);
router.get('/manage/post-queue', middlewares, controllers.admin.postQueue.get);
router.get('/manage/ip-blacklist', middlewares, controllers.admin.blacklist.get);

View File

@@ -2,18 +2,8 @@
<form role="form" class="category" data-cid="{category.cid}">
<div class="row">
<div class="col-md-9">
<ul class="nav nav-pills">
<li class="active"><a href="#category-settings" data-toggle="tab">
[[admin/manage/categories:settings]]
</a></li>
<li><a href="#privileges" data-toggle="tab">[[admin/manage/categories:privileges]]</a></li>
</ul>
</div>
<div class="col-md-3">
<div class="col-md-3 pull-right">
<select id="category-selector" class="form-control">
<option value="global" selected>[[admin/manage/privileges:global]]</option>
<option disabled>_____________</option>
<!-- BEGIN allCategories -->
<option value="{allCategories.value}" <!-- IF allCategories.selected -->selected<!-- ENDIF allCategories.selected -->>{allCategories.text}</option>
<!-- END allCategories -->
@@ -176,19 +166,6 @@
</div>
</div>
</div>
<div class="tab-pane fade col-xs-12" id="privileges">
<p>
[[admin/manage/categories:privileges.description]]
</p>
<p class="text-warning">
[[admin/manage/categories:privileges.warning]]
</p>
<hr />
<div class="privilege-table-container">
<!-- IMPORT admin/partials/categories/privileges.tpl -->
</div>
</div>
</div>
</form>
</div>

View File

@@ -3,10 +3,10 @@
<div class="row">
<div class="col-md-3 pull-right">
<select id="category-selector" class="form-control">
<option value="global" selected>[[admin/manage/privileges:global]]</option>
<option value="global" <!-- IF !cid --> selected <!-- ENDIF !cid -->>[[admin/manage/privileges:global]]</option>
<option disabled>_____________</option>
<!-- BEGIN allCategories -->
<option value="{allCategories.value}">{allCategories.text}</option>
<option value="{allCategories.value}" <!-- IF allCategories.selected -->selected<!-- ENDIF allCategories.selected -->>{allCategories.text}</option>
<!-- END allCategories -->
</select>
</div>
@@ -16,14 +16,18 @@
<div class="">
<p>
[[admin/manage/privileges:global.description]]
[[admin/manage/categories:privileges.description]]
</p>
<p class="text-warning">
[[admin/manage/privileges:global.warning]]
[[admin/manage/categories:privileges.warning]]
</p>
<hr />
<div class="privilege-table-container">
<!-- IF cid -->
<!-- IMPORT admin/partials/categories/privileges.tpl -->
<!-- ELSE -->
<!-- IMPORT admin/partials/global/privileges.tpl -->
<!-- ENDIF cid -->
</div>
</div>
</form>