Merge remote-tracking branch 'origin/master' into develop
commit
d1ccd78ac2
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"administrators": "Administrators",
|
||||||
|
"global-moderators": "Global Moderators",
|
||||||
|
"no-global-moderators": "No Global Moderators",
|
||||||
|
"moderators-of-category": "%1 Moderators",
|
||||||
|
"no-moderators": "No Moderators",
|
||||||
|
"add-administrator": "Add Administrator",
|
||||||
|
"add-global-moderator": "Add Global Moderator",
|
||||||
|
"add-moderator": "Add Moderator"
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"global": "Global",
|
||||||
|
"global.no-users": "No user-specific global privileges."
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"success": "Riuscito",
|
"success": "Riuscito",
|
||||||
"topic-post": "Hai postato correttamente.",
|
"topic-post": "Hai postato correttamente.",
|
||||||
"post-queued": "Your post is queued for approval.",
|
"post-queued": "La tua discussione è in attesa di approvazione.",
|
||||||
"authentication-successful": "Autenticazione Riuscita",
|
"authentication-successful": "Autenticazione Riuscita",
|
||||||
"settings-saved": "Impostazioni salvate!"
|
"settings-saved": "Impostazioni salvate!"
|
||||||
}
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
.admins-mods {
|
||||||
|
.user-card {
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-user-icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-depth-1 {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
.category-depth-2 {
|
||||||
|
margin-left: 60px;
|
||||||
|
}
|
||||||
|
.category-depth-3 {
|
||||||
|
margin-left: 90px;
|
||||||
|
}
|
||||||
|
.category-depth-4 {
|
||||||
|
margin-left: 120px;
|
||||||
|
}
|
||||||
|
.category-depth-5 {
|
||||||
|
margin-left: 150px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define('admin/manage/admins-mods', ['translator', 'benchpress', 'autocomplete'], function (translator, Benchpress, autocomplete) {
|
||||||
|
var AdminsMods = {};
|
||||||
|
|
||||||
|
AdminsMods.init = function () {
|
||||||
|
autocomplete.user($('#admin-search'), function (ev, ui) {
|
||||||
|
socket.emit('admin.user.makeAdmins', [ui.item.user.uid], function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.make-admin-success]]');
|
||||||
|
$('#admin-search').val('');
|
||||||
|
|
||||||
|
if ($('.administrator-area [data-uid="' + ui.item.user.uid + '"]').length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.parseAndTranslate('admin/manage/admins-mods', 'admins.members', { admins: { members: [ui.item.user] } }, function (html) {
|
||||||
|
$('.administrator-area').prepend(html);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.administrator-area').on('click', '.remove-user-icon', function () {
|
||||||
|
var userCard = $(this).parents('[data-uid]');
|
||||||
|
var uid = userCard.attr('data-uid');
|
||||||
|
if (parseInt(uid, 10) === parseInt(app.user.uid, 10)) {
|
||||||
|
return app.alertError('[[admin/manage/users:alerts.no-remove-yourself-admin]]');
|
||||||
|
}
|
||||||
|
bootbox.confirm('[[admin/manage/users:alerts.confirm-remove-admin]]', function (confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
socket.emit('admin.user.removeAdmins', [uid], function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.remove-admin-success]]');
|
||||||
|
userCard.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
autocomplete.user($('#global-mod-search'), function (ev, ui) {
|
||||||
|
socket.emit('admin.groups.join', {
|
||||||
|
groupName: 'Global Moderators',
|
||||||
|
uid: ui.item.user.uid,
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.make-global-mod-success]]');
|
||||||
|
$('#global-mod-search').val('');
|
||||||
|
|
||||||
|
if ($('.global-moderator-area [data-uid="' + ui.item.user.uid + '"]').length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.parseAndTranslate('admin/manage/admins-mods', 'globalMods.members', { globalMods: { members: [ui.item.user] } }, function (html) {
|
||||||
|
$('.global-moderator-area').prepend(html);
|
||||||
|
$('#no-global-mods-warning').addClass('hidden');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.global-moderator-area').on('click', '.remove-user-icon', function () {
|
||||||
|
var userCard = $(this).parents('[data-uid]');
|
||||||
|
var uid = userCard.attr('data-uid');
|
||||||
|
|
||||||
|
bootbox.confirm('[[admin/manage/users:alerts.confirm-remove-global-mod]]', function (confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
socket.emit('admin.groups.leave', { uid: uid, groupName: 'Global Moderators' }, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.remove-global-mod-success]]');
|
||||||
|
userCard.remove();
|
||||||
|
if (!$('.global-moderator-area').children().length) {
|
||||||
|
$('#no-global-mods-warning').removeClass('hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
autocomplete.user($('.moderator-search'), function (ev, ui) {
|
||||||
|
var input = $(ev.target);
|
||||||
|
var cid = $(ev.target).attr('data-cid');
|
||||||
|
socket.emit('admin.categories.setPrivilege', {
|
||||||
|
cid: cid,
|
||||||
|
privilege: ['moderate'],
|
||||||
|
set: true,
|
||||||
|
member: ui.item.user.uid,
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.make-moderator-success]]');
|
||||||
|
input.val('');
|
||||||
|
|
||||||
|
if ($('.moderator-area[data-cid="' + cid + '"] [data-uid="' + ui.item.user.uid + '"]').length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.parseAndTranslate('admin/manage/admins-mods', 'globalMods', { globalMods: [ui.item.user] }, function (html) {
|
||||||
|
$('.moderator-area[data-cid="' + cid + '"]').prepend(html);
|
||||||
|
$('.no-moderator-warning[data-cid="' + cid + '"]').addClass('hidden');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.moderator-area').on('click', '.remove-user-icon', function () {
|
||||||
|
var moderatorArea = $(this).parents('[data-cid]');
|
||||||
|
var cid = moderatorArea.attr('data-cid');
|
||||||
|
var userCard = $(this).parents('[data-uid]');
|
||||||
|
var uid = userCard.attr('data-uid');
|
||||||
|
|
||||||
|
bootbox.confirm('[[admin/manage/users:alerts.confirm-remove-moderator]]', function (confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
socket.emit('admin.categories.setPrivilege', {
|
||||||
|
cid: cid,
|
||||||
|
privilege: ['moderate'],
|
||||||
|
set: false,
|
||||||
|
member: uid,
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/users:alerts.remove-moderator-success]]');
|
||||||
|
userCard.remove();
|
||||||
|
if (!moderatorArea.children().length) {
|
||||||
|
$('.no-moderator-warning[data-cid="' + cid + '"]').removeClass('hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return AdminsMods;
|
||||||
|
});
|
@ -0,0 +1,194 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define('admin/manage/privileges', [
|
||||||
|
'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();
|
||||||
|
ajaxify.go('admin/manage/privileges/' + (val === 'global' ? '' : $(this).val()));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Privileges.setupPrivilegeTable();
|
||||||
|
};
|
||||||
|
|
||||||
|
Privileges.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) {
|
||||||
|
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]]');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.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', cid, function (err, privileges) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
var tpl = cid ? 'admin/partials/categories/privileges' : 'admin/partials/global/privileges';
|
||||||
|
Benchpress.parse(tpl, {
|
||||||
|
privileges: privileges,
|
||||||
|
}, function (html) {
|
||||||
|
translator.translate(html, function (html) {
|
||||||
|
$('.privilege-table-container').html(html);
|
||||||
|
Privileges.exposeAssumedPrivileges();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Privileges.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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Privileges.setPrivilege = function (member, privilege, state, checkboxEl) {
|
||||||
|
socket.emit('admin.categories.setPrivilege', {
|
||||||
|
cid: 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>');
|
||||||
|
Privileges.refreshPrivilegeTable();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Privileges.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) {
|
||||||
|
var defaultPrivileges = cid ? ['find', 'read', 'topics:read'] : ['chat'];
|
||||||
|
socket.emit('admin.categories.setPrivilege', {
|
||||||
|
cid: cid,
|
||||||
|
privilege: defaultPrivileges,
|
||||||
|
set: true,
|
||||||
|
member: ui.item.user.uid,
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Privileges.refreshPrivilegeTable();
|
||||||
|
modal.modal('hide');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Privileges.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) {
|
||||||
|
var defaultPrivileges = cid ? ['groups:find', 'groups:read', 'groups:topics:read'] : ['groups:chat'];
|
||||||
|
socket.emit('admin.categories.setPrivilege', {
|
||||||
|
cid: cid,
|
||||||
|
privilege: defaultPrivileges,
|
||||||
|
set: true,
|
||||||
|
member: ui.item.group.name,
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Privileges.refreshPrivilegeTable();
|
||||||
|
modal.modal('hide');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
@ -0,0 +1,50 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
|
var groups = require('../../groups');
|
||||||
|
var categories = require('../../categories');
|
||||||
|
|
||||||
|
var AdminsMods = module.exports;
|
||||||
|
|
||||||
|
AdminsMods.get = function (req, res, next) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
admins: function (next) {
|
||||||
|
groups.get('administrators', { uid: req.uid }, next);
|
||||||
|
},
|
||||||
|
globalMods: function (next) {
|
||||||
|
groups.get('Global Moderators', { uid: req.uid }, next);
|
||||||
|
},
|
||||||
|
categories: function (next) {
|
||||||
|
getModeratorsOfCategories(req.uid, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results) {
|
||||||
|
res.render('admin/manage/admins-mods', results);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
|
};
|
||||||
|
|
||||||
|
function getModeratorsOfCategories(uid, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
categories.buildForSelect(uid, 'find', next);
|
||||||
|
},
|
||||||
|
function (categoryData, next) {
|
||||||
|
async.map(categoryData, function (category, next) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
categories.getModerators(category.cid, next);
|
||||||
|
},
|
||||||
|
function (moderators, next) {
|
||||||
|
category.moderators = moderators;
|
||||||
|
next(null, category);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
|
var categories = require('../../categories');
|
||||||
|
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: 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);
|
||||||
|
};
|
@ -0,0 +1,128 @@
|
|||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
|
var user = require('../user');
|
||||||
|
var groups = require('../groups');
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
var plugins = require('../plugins');
|
||||||
|
|
||||||
|
module.exports = function (privileges) {
|
||||||
|
privileges.global = {};
|
||||||
|
|
||||||
|
privileges.global.privilegeLabels = [
|
||||||
|
{ name: 'Chat' },
|
||||||
|
{ name: 'Upload Images' },
|
||||||
|
{ name: 'Upload Files' },
|
||||||
|
];
|
||||||
|
|
||||||
|
privileges.global.userPrivilegeList = [
|
||||||
|
'chat',
|
||||||
|
'upload:post:image',
|
||||||
|
'upload:post:file',
|
||||||
|
];
|
||||||
|
|
||||||
|
privileges.global.groupPrivilegeList = privileges.global.userPrivilegeList.map(function (privilege) {
|
||||||
|
return 'groups:' + privilege;
|
||||||
|
});
|
||||||
|
|
||||||
|
privileges.global.list = function (callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
labels: function (next) {
|
||||||
|
async.parallel({
|
||||||
|
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) {
|
||||||
|
helpers.getUserPrivileges(0, 'filter:privileges.global.list', privileges.global.userPrivilegeList, next);
|
||||||
|
},
|
||||||
|
groups: function (next) {
|
||||||
|
helpers.getGroupPrivileges(0, 'filter:privileges.global.groups.list', privileges.global.groupPrivilegeList, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
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.global.get = function (uid, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
privileges: function (next) {
|
||||||
|
helpers.isUserAllowedTo(privileges.global.userPrivilegeList, uid, 0, next);
|
||||||
|
},
|
||||||
|
isAdministrator: function (next) {
|
||||||
|
user.isAdministrator(uid, next);
|
||||||
|
},
|
||||||
|
isGlobalModerator: function (next) {
|
||||||
|
user.isGlobalModerator(uid, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
var privData = _.zipObject(privileges.global.userPrivilegeList, results.privileges);
|
||||||
|
var isAdminOrMod = results.isAdministrator || results.isGlobalModerator;
|
||||||
|
|
||||||
|
plugins.fireHook('filter:privileges.global.get', {
|
||||||
|
chat: privData.chat || isAdminOrMod,
|
||||||
|
'upload:post:image': privData['upload:post:image'] || isAdminOrMod,
|
||||||
|
'upload:post:file': privData['upload:post:file'] || isAdminOrMod,
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
privileges.global.can = function (privilege, uid, callback) {
|
||||||
|
helpers.some([
|
||||||
|
function (next) {
|
||||||
|
helpers.isUserAllowedTo(privilege, uid, [0], function (err, results) {
|
||||||
|
next(err, Array.isArray(results) && results.length ? results[0] : false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
user.isGlobalModerator(uid, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
user.isAdministrator(uid, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
privileges.global.give = function (privileges, groupName, callback) {
|
||||||
|
helpers.giveOrRescind(groups.join, privileges, 0, groupName, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
privileges.global.rescind = function (privileges, groupName, callback) {
|
||||||
|
helpers.giveOrRescind(groups.leave, privileges, 0, groupName, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
privileges.global.userPrivileges = function (uid, callback) {
|
||||||
|
var tasks = {};
|
||||||
|
|
||||||
|
privileges.global.userPrivilegeList.forEach(function (privilege) {
|
||||||
|
tasks[privilege] = async.apply(groups.isMember, uid, 'cid:0:privileges:' + privilege);
|
||||||
|
});
|
||||||
|
|
||||||
|
async.parallel(tasks, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
privileges.global.groupPrivileges = function (groupName, callback) {
|
||||||
|
var tasks = {};
|
||||||
|
|
||||||
|
privileges.global.groupPrivilegeList.forEach(function (privilege) {
|
||||||
|
tasks[privilege] = async.apply(groups.isMember, groupName, 'cid:0:privileges:' + privilege);
|
||||||
|
});
|
||||||
|
|
||||||
|
async.parallel(tasks, callback);
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,12 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
var groups = require('../../groups');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Give chat privilege to registered-users',
|
||||||
|
timestamp: Date.UTC(2017, 11, 18),
|
||||||
|
method: function (callback) {
|
||||||
|
groups.join('cid:0:privileges:groups:chat', 'registered-users', callback);
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,45 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var groups = require('../../groups');
|
||||||
|
var privileges = require('../../privileges');
|
||||||
|
var db = require('../../database');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Give upload privilege to registered-users globally if it is given on a category',
|
||||||
|
timestamp: Date.UTC(2018, 0, 3),
|
||||||
|
method: function (callback) {
|
||||||
|
db.getSortedSetRange('categories:cid', 0, -1, function (err, cids) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
async.eachSeries(cids, function (cid, next) {
|
||||||
|
getGroupPrivileges(cid, function (err, groupPrivileges) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var privs = [];
|
||||||
|
if (groupPrivileges['groups:upload:post:image']) {
|
||||||
|
privs.push('upload:post:image');
|
||||||
|
}
|
||||||
|
if (groupPrivileges['groups:upload:post:file']) {
|
||||||
|
privs.push('upload:post:file');
|
||||||
|
}
|
||||||
|
privileges.global.give(privs, 'registered-users', next);
|
||||||
|
});
|
||||||
|
}, callback);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getGroupPrivileges(cid, callback) {
|
||||||
|
var tasks = {};
|
||||||
|
|
||||||
|
['groups:upload:post:image', 'groups:upload:post:file'].forEach(function (privilege) {
|
||||||
|
tasks[privilege] = async.apply(groups.isMember, 'registered-users', 'cid:' + cid + ':privileges:' + privilege);
|
||||||
|
});
|
||||||
|
|
||||||
|
async.parallel(tasks, callback);
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<div class="admins-mods">
|
||||||
|
<h4><!-- IF admins.icon --><i class="fa {admins.icon}"></i> <!-- ENDIF admins.icon -->[[admin/manage/admins-mods:administrators]]</h4>
|
||||||
|
<div class="administrator-area">
|
||||||
|
<!-- BEGIN admins.members -->
|
||||||
|
<div class="user-card pull-left" data-uid="{admins.members.uid}">
|
||||||
|
<!-- IF admins.members.picture -->
|
||||||
|
<img class="avatar avatar-sm" src="{admins.members.picture}" />
|
||||||
|
<!-- ELSE -->
|
||||||
|
<div class="avatar avatar-sm" style="background-color: {admins.members.icon:bgColor};">{admins.members.icon:text}</div>
|
||||||
|
<!-- ENDIF admins.members.picture -->
|
||||||
|
<a href="{config.relative_path}/user/{admins.members.userslug}">{admins.members.username}</a>
|
||||||
|
<i class="remove-user-icon fa fa-times" role="button"></i>
|
||||||
|
</div>
|
||||||
|
<!-- END admins.members -->
|
||||||
|
</div>
|
||||||
|
<input id="admin-search" class="form-control" placeholder="[[admin/manage/admins-mods:add-administrator]]" />
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h4><!-- IF globalMods.icon --><i class="fa {globalMods.icon}"></i> <!-- ENDIF globalMods.icon -->[[admin/manage/admins-mods:global-moderators]]</h4>
|
||||||
|
<div class="global-moderator-area">
|
||||||
|
<!-- BEGIN globalMods.members -->
|
||||||
|
<div class="user-card pull-left" data-uid="{globalMods.members.uid}">
|
||||||
|
<!-- IF globalMods.members.picture -->
|
||||||
|
<img class="avatar avatar-sm" src="{globalMods.members.picture}" />
|
||||||
|
<!-- ELSE -->
|
||||||
|
<div class="avatar avatar-sm" style="background-color: {globalMods.members.icon:bgColor};">{globalMods.members.icon:text}</div>
|
||||||
|
<!-- ENDIF globalMods.members.picture -->
|
||||||
|
<a href="{config.relative_path}/user/{globalMods.members.userslug}">{globalMods.members.username}</a>
|
||||||
|
<i class="remove-user-icon fa fa-times" role="button"></i>
|
||||||
|
</div>
|
||||||
|
<!-- END globalMods.members -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="no-global-mods-warning" class="<!-- IF globalMods.members.length -->hidden<!-- ENDIF globalMods.members.length -->">[[admin/manage/admins-mods:no-global-moderators]]</div>
|
||||||
|
|
||||||
|
<input id="global-mod-search" class="form-control" placeholder="[[admin/manage/admins-mods:add-global-moderator]]" />
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<!-- BEGIN categories -->
|
||||||
|
<div class="categories category-wrapper category-depth-{categories.depth}">
|
||||||
|
<h4><!-- IF categories.icon --><i class="fa {categories.icon}"></i> <!-- ENDIF categories.icon -->[[admin/manage/admins-mods:moderators-of-category, {categories.name}]]</h4>
|
||||||
|
<div class="moderator-area" data-cid="{categories.cid}">
|
||||||
|
<!-- BEGIN categories.moderators -->
|
||||||
|
<div class="user-card pull-left" data-uid="{categories.moderators.uid}">
|
||||||
|
<!-- IF categories.moderators.picture -->
|
||||||
|
<img class="avatar avatar-sm" src="{categories.moderators.picture}" />
|
||||||
|
<!-- ELSE -->
|
||||||
|
<div class="avatar avatar-sm" style="background-color: {categories.moderators.icon:bgColor};">{categories.moderators.icon:text}</div>
|
||||||
|
<!-- ENDIF categories.moderators.picture -->
|
||||||
|
<a href="{config.relative_path}/user/{categories.moderators.userslug}">{categories.moderators.username}</a>
|
||||||
|
<i class="remove-user-icon fa fa-times" role="button"></i>
|
||||||
|
</div>
|
||||||
|
<!-- END categories.moderators -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-cid="{categories.cid}" class="no-moderator-warning <!-- IF categories.moderators.length -->hidden<!-- ENDIF categories.moderators.length -->">[[admin/manage/admins-mods:no-moderators]]</div>
|
||||||
|
|
||||||
|
<input data-cid="{categories.cid}" class="form-control moderator-search" placeholder="[[admin/manage/admins-mods:add-moderator]]" />
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<!-- END categories -->
|
||||||
|
</div>
|
@ -0,0 +1,31 @@
|
|||||||
|
<div class="row">
|
||||||
|
<form role="form" class="category">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3 pull-right">
|
||||||
|
<select id="category-selector" class="form-control">
|
||||||
|
<option value="global" <!-- IF !cid --> selected <!-- ENDIF !cid -->>[[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 -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<p>
|
||||||
|
[[admin/manage/categories:privileges.description]]
|
||||||
|
</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>
|
||||||
|
</div>
|
@ -0,0 +1,86 @@
|
|||||||
|
<table class="table table-striped privilege-table">
|
||||||
|
<thead>
|
||||||
|
<tr class="privilege-table-header">
|
||||||
|
<th colspan="3"></th>
|
||||||
|
</tr><tr><!-- zebrastripe reset --></tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">[[admin/manage/categories:privileges.section-user]]</th>
|
||||||
|
<!-- BEGIN privileges.labels.users -->
|
||||||
|
<th class="text-center">{privileges.labels.users.name}</th>
|
||||||
|
<!-- END privileges.labels.users -->
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- IF privileges.users.length -->
|
||||||
|
<!-- BEGIN privileges.users -->
|
||||||
|
<tr data-uid="{privileges.users.uid}">
|
||||||
|
<td>
|
||||||
|
<!-- IF ../picture -->
|
||||||
|
<img class="avatar avatar-sm" src="{privileges.users.picture}" title="{privileges.users.username}" />
|
||||||
|
<!-- ELSE -->
|
||||||
|
<div class="avatar avatar-sm" style="background-color: {../icon:bgColor};">{../icon:text}</div>
|
||||||
|
<!-- ENDIF ../picture -->
|
||||||
|
</td>
|
||||||
|
<td>{privileges.users.username}</td>
|
||||||
|
{function.spawnPrivilegeStates, privileges.users.username, ../privileges}
|
||||||
|
</tr>
|
||||||
|
<!-- END privileges.users -->
|
||||||
|
<tr>
|
||||||
|
<td colspan="{privileges.columnCount}">
|
||||||
|
<button type="button" class="btn btn-primary pull-right" data-ajaxify="false" data-action="search.user">
|
||||||
|
[[admin/manage/categories:privileges.search-user]]
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- ELSE -->
|
||||||
|
<tr>
|
||||||
|
<td colspan="{privileges.columnCount}">
|
||||||
|
[[admin/manage/privileges:global.no-users]]
|
||||||
|
<button type="button" class="btn btn-primary pull-right" data-ajaxify="false" data-action="search.user">
|
||||||
|
[[admin/manage/categories:privileges.search-user]]
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- ENDIF privileges.users.length -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="table table-striped privilege-table">
|
||||||
|
<thead>
|
||||||
|
<tr class="privilege-table-header">
|
||||||
|
<th colspan="3"></th>
|
||||||
|
</tr><tr><!-- zebrastripe reset --></tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">[[admin/manage/categories:privileges.section-group]]</th>
|
||||||
|
<!-- BEGIN privileges.labels.groups -->
|
||||||
|
<th class="text-center">{privileges.labels.groups.name}</th>
|
||||||
|
<!-- END privileges.labels.groups -->
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- BEGIN privileges.groups -->
|
||||||
|
<tr data-group-name="{privileges.groups.name}" data-private="<!-- IF privileges.groups.isPrivate -->1<!-- ELSE -->0<!-- ENDIF privileges.groups.isPrivate -->">
|
||||||
|
<td>
|
||||||
|
<!-- IF privileges.groups.isPrivate -->
|
||||||
|
<i class="fa fa-lock text-muted" title="[[admin/manage/categories:privileges.group-private]]"></i>
|
||||||
|
<!-- ENDIF privileges.groups.isPrivate -->
|
||||||
|
{privileges.groups.name}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
{function.spawnPrivilegeStates, privileges.groups.name, ../privileges}
|
||||||
|
</tr>
|
||||||
|
<!-- END privileges.groups -->
|
||||||
|
<tr>
|
||||||
|
<td colspan="{privileges.columnCount}">
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
<button type="button" class="btn btn-primary pull-right" data-ajaxify="false" data-action="search.group">
|
||||||
|
[[admin/manage/categories:privileges.search-group]]
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="help-block">
|
||||||
|
[[admin/manage/categories:privileges.inherit]]
|
||||||
|
</div>
|
Loading…
Reference in New Issue