diff --git a/public/language/en-GB/admin/manage/categories.json b/public/language/en-GB/admin/manage/categories.json
index 7e49aef36b..1eda6ea080 100644
--- a/public/language/en-GB/admin/manage/categories.json
+++ b/public/language/en-GB/admin/manage/categories.json
@@ -45,7 +45,12 @@
"privileges.search-group": "Add Group",
"privileges.copy-to-children": "Copy to Children",
"privileges.copy-from-category": "Copy from Category",
+ "privileges.copy-privileges-to-all-categories": "Copy to All Categories",
+ "privileges.copy-group-privileges-to-children": "Copy this group's privileges to the children of this category.",
+ "privileges.copy-group-privileges-to-all-categories": "Copy this group's privileges to all categories.",
+ "privileges.copy-group-privileges-from": "Copy this group's privileges from another category.",
"privileges.inherit": "If the registered-users
group is granted a specific privilege, all other groups receive an implicit privilege, even if they are not explicitly defined/checked. This implicit privilege is shown to you because all users are part of the registered-users
user group, and so, privileges for additional groups need not be explicitly granted.",
+ "privileges.copy-success": "Privileges copied!",
"analytics.back": "Back to Categories List",
"analytics.title": "Analytics for \"%1\" category",
diff --git a/public/src/admin/manage/privileges.js b/public/src/admin/manage/privileges.js
index f43ebef04f..86b2351d36 100644
--- a/public/src/admin/manage/privileges.js
+++ b/public/src/admin/manage/privileges.js
@@ -49,8 +49,29 @@ 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);
+ $('.privilege-table-container').on('click', '[data-action="copyToChildren"]', function () {
+ Privileges.copyPrivilegesToChildren(cid, '');
+ });
+ $('.privilege-table-container').on('click', '[data-action="copyToChildrenGroup"]', function () {
+ var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
+ Privileges.copyPrivilegesToChildren(cid, groupName);
+ });
+
+ $('.privilege-table-container').on('click', '[data-action="copyPrivilegesFrom"]', function () {
+ Privileges.copyPrivilegesFromCategory(cid, '');
+ });
+ $('.privilege-table-container').on('click', '[data-action="copyPrivilegesFromGroup"]', function () {
+ var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
+ Privileges.copyPrivilegesFromCategory(cid, groupName);
+ });
+
+ $('.privilege-table-container').on('click', '[data-action="copyToAll"]', function () {
+ Privileges.copyPrivilegesToAllCategories(cid, '');
+ });
+ $('.privilege-table-container').on('click', '[data-action="copyToAllGroup"]', function () {
+ var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
+ Privileges.copyPrivilegesToAllCategories(cid, groupName);
+ });
Privileges.exposeAssumedPrivileges();
};
@@ -168,18 +189,18 @@ define('admin/manage/privileges', [
});
};
- Privileges.copyPrivilegesToChildren = function () {
- socket.emit('admin.categories.copyPrivilegesToChildren', cid, function (err) {
+ Privileges.copyPrivilegesToChildren = function (cid, group) {
+ socket.emit('admin.categories.copyPrivilegesToChildren', { cid: cid, group: group }, function (err) {
if (err) {
return app.alertError(err.message);
}
- app.alertSuccess('Privileges copied!');
+ app.alertSuccess('[[admin/manage/categories:privileges.copy-success]]');
});
};
- Privileges.copyPrivilegesFromCategory = function () {
+ Privileges.copyPrivilegesFromCategory = function (cid, group) {
categorySelector.modal(ajaxify.data.categories.slice(1), function (fromCid) {
- socket.emit('admin.categories.copyPrivilegesFrom', { toCid: cid, fromCid: fromCid }, function (err) {
+ socket.emit('admin.categories.copyPrivilegesFrom', { toCid: cid, fromCid: fromCid, group: group }, function (err) {
if (err) {
return app.alertError(err.message);
}
@@ -188,5 +209,14 @@ define('admin/manage/privileges', [
});
};
+ Privileges.copyPrivilegesToAllCategories = function (cid, group) {
+ socket.emit('admin.categories.copyPrivilegesToAllCategories', { cid: cid, group: group }, function (err) {
+ if (err) {
+ return app.alertError(err.message);
+ }
+ app.alertSuccess('[[admin/manage/categories:privileges.copy-success]]');
+ });
+ };
+
return Privileges;
});
diff --git a/src/categories/create.js b/src/categories/create.js
index 4836db2d0b..3c1c23a354 100644
--- a/src/categories/create.js
+++ b/src/categories/create.js
@@ -208,18 +208,28 @@ module.exports = function (Categories) {
], callback);
}
- Categories.copyPrivilegesFrom = function (fromCid, toCid, callback) {
+ Categories.copyPrivilegesFrom = function (fromCid, toCid, group, callback) {
+ if (typeof group === 'function') {
+ callback = group;
+ group = '';
+ }
+
async.waterfall([
function (next) {
plugins.fireHook('filter:categories.copyPrivilegesFrom', {
privileges: privileges.privilegeList.slice(),
fromCid: fromCid,
toCid: toCid,
+ group: group,
}, next);
},
function (data, next) {
async.each(data.privileges, function (privilege, next) {
- copyPrivilege(privilege, data.fromCid, data.toCid, next);
+ if (group) {
+ copyPrivilegeByGroup(privilege, data.fromCid, data.toCid, group, next);
+ } else {
+ copyPrivilege(privilege, data.fromCid, data.toCid, next);
+ }
}, next);
},
], callback);
@@ -249,4 +259,22 @@ module.exports = function (Categories) {
},
], callback);
}
+
+ function copyPrivilegeByGroup(privilege, fromCid, toCid, group, callback) {
+ async.waterfall([
+ function (next) {
+ groups.leave('cid:' + toCid + ':privileges:' + privilege, group, next);
+ },
+ function (next) {
+ db.isSortedSetMember('group:cid:' + fromCid + ':privileges:' + privilege + ':members', group, next);
+ },
+ function (isMember, next) {
+ if (!isMember) {
+ return callback();
+ }
+
+ groups.join('cid:' + toCid + ':privileges:' + privilege, group, next);
+ },
+ ], callback);
+ }
};
diff --git a/src/socket.io/admin/categories.js b/src/socket.io/admin/categories.js
index d585318f17..9497abed61 100644
--- a/src/socket.io/admin/categories.js
+++ b/src/socket.io/admin/categories.js
@@ -101,25 +101,25 @@ Categories.getPrivilegeSettings = function (socket, cid, callback) {
}
};
-Categories.copyPrivilegesToChildren = function (socket, cid, callback) {
+Categories.copyPrivilegesToChildren = function (socket, data, callback) {
async.waterfall([
function (next) {
- categories.getChildren([cid], socket.uid, next);
+ categories.getChildren([data.cid], socket.uid, next);
},
function (children, next) {
children = children[0];
async.eachSeries(children, function (child, next) {
- copyPrivilegesToChildrenRecursive(cid, child, next);
+ copyPrivilegesToChildrenRecursive(data.cid, child, data.group, next);
}, next);
},
], callback);
};
-function copyPrivilegesToChildrenRecursive(parentCid, category, callback) {
+function copyPrivilegesToChildrenRecursive(parentCid, category, group, callback) {
async.waterfall([
function (next) {
- categories.copyPrivilegesFrom(parentCid, category.cid, next);
+ categories.copyPrivilegesFrom(parentCid, category.cid, group, next);
},
function (next) {
async.eachSeries(category.children, function (child, next) {
@@ -134,5 +134,19 @@ Categories.copySettingsFrom = function (socket, data, callback) {
};
Categories.copyPrivilegesFrom = function (socket, data, callback) {
- categories.copyPrivilegesFrom(data.fromCid, data.toCid, callback);
+ categories.copyPrivilegesFrom(data.fromCid, data.toCid, data.group, callback);
+};
+
+Categories.copyPrivilegesToAllCategories = function (socket, data, callback) {
+ async.waterfall([
+ function (next) {
+ categories.getAllCidsFromSet('categories:cid', next);
+ },
+ function (cids, next) {
+ cids = cids.filter(cid => parseInt(cid, 10) !== parseInt(data.cid, 10));
+ async.eachSeries(cids, function (toCid, next) {
+ categories.copyPrivilegesFrom(data.cid, toCid, data.group, next);
+ }, next);
+ },
+ ], callback);
};
diff --git a/src/views/admin/partials/categories/privileges.tpl b/src/views/admin/partials/categories/privileges.tpl
index 9e0b8632d2..be5d892545 100644
--- a/src/views/admin/partials/categories/privileges.tpl
+++ b/src/views/admin/partials/categories/privileges.tpl
@@ -94,7 +94,18 @@
{privileges.groups.name}
-