mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat: allow groups to specify which cids to show member posts from (#8875)
* feat: allow groups to specify which cids to show member posts from * docs: fix tests for openapi * fix: test breakage caused by improper conditional * feat: server-side checking of memberPostCids for validity * feat: admin panel template update to select categories to include * refactor: privilege helpers.isUserAllowedTo ... to helpers.isAllowedTo, allowing group names to be passed in
This commit is contained in:
@@ -40,6 +40,8 @@
|
|||||||
"details.member_count": "Member Count",
|
"details.member_count": "Member Count",
|
||||||
"details.creation_date": "Creation Date",
|
"details.creation_date": "Creation Date",
|
||||||
"details.description": "Description",
|
"details.description": "Description",
|
||||||
|
"details.member-post-cids": "Categories to display posts from",
|
||||||
|
"details.member-post-cids-help": "<strong>Note</strong>: Selecting no categories will assume all categories are included. Use <code>ctrl</code> and <code>shift</code> to select multiple options.",
|
||||||
"details.badge_preview": "Badge Preview",
|
"details.badge_preview": "Badge Preview",
|
||||||
"details.change_icon": "Change Icon",
|
"details.change_icon": "Change Icon",
|
||||||
"details.change_label_colour": "Change Label Colour",
|
"details.change_label_colour": "Change Label Colour",
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ GroupFullObject:
|
|||||||
textColor:
|
textColor:
|
||||||
type: string
|
type: string
|
||||||
description: A six-character hexadecimal colour code
|
description: A six-character hexadecimal colour code
|
||||||
|
memberPostCids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: number
|
||||||
|
example: [1, 2, 3]
|
||||||
icon:
|
icon:
|
||||||
type: string
|
type: string
|
||||||
description: A FontAwesome icon string
|
description: A FontAwesome icon string
|
||||||
@@ -56,6 +61,32 @@ GroupFullObject:
|
|||||||
type: string
|
type: string
|
||||||
descriptionParsed:
|
descriptionParsed:
|
||||||
type: string
|
type: string
|
||||||
|
categories:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cid:
|
||||||
|
type: number
|
||||||
|
description: A category identifier
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
level:
|
||||||
|
type: string
|
||||||
|
icon:
|
||||||
|
type: string
|
||||||
|
parentCid:
|
||||||
|
type: number
|
||||||
|
description: The category identifier for the category that is the immediate
|
||||||
|
ancestor of the current category
|
||||||
|
color:
|
||||||
|
type: string
|
||||||
|
bgColor:
|
||||||
|
type: string
|
||||||
|
selected:
|
||||||
|
type: boolean
|
||||||
|
imageClass:
|
||||||
|
type: string
|
||||||
members:
|
members:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@@ -130,4 +161,9 @@ GroupDataObject:
|
|||||||
type: string
|
type: string
|
||||||
description: "`createtime` rendered as an ISO 8601 format"
|
description: "`createtime` rendered as an ISO 8601 format"
|
||||||
cover:position:
|
cover:position:
|
||||||
type: string
|
type: string
|
||||||
|
memberPostCids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: number
|
||||||
|
example: [1, 2, 3]
|
||||||
@@ -64,6 +64,11 @@ get:
|
|||||||
type: string
|
type: string
|
||||||
ownerUid:
|
ownerUid:
|
||||||
type: number
|
type: number
|
||||||
|
memberPostCids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: number
|
||||||
|
example: [1, 2, 3]
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- description
|
- description
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ get:
|
|||||||
type: string
|
type: string
|
||||||
cover:position:
|
cover:position:
|
||||||
type: string
|
type: string
|
||||||
|
memberPostCids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: number
|
||||||
|
example: [1, 2, 3]
|
||||||
members:
|
members:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ post:
|
|||||||
enum: [0, 1]
|
enum: [0, 1]
|
||||||
createtime:
|
createtime:
|
||||||
type: number
|
type: number
|
||||||
|
memberPostCids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: number
|
||||||
|
example: [1, 2, 3]
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
responses:
|
responses:
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ define('admin/manage/group', [
|
|||||||
userTitleEnabled: $('#group-userTitleEnabled').is(':checked'),
|
userTitleEnabled: $('#group-userTitleEnabled').is(':checked'),
|
||||||
private: $('#group-private').is(':checked'),
|
private: $('#group-private').is(':checked'),
|
||||||
hidden: $('#group-hidden').is(':checked'),
|
hidden: $('#group-hidden').is(':checked'),
|
||||||
|
memberPostCids: $('#memberPostCids').val(),
|
||||||
disableJoinRequests: $('#group-disableJoinRequests').is(':checked'),
|
disableJoinRequests: $('#group-disableJoinRequests').is(':checked'),
|
||||||
disableLeave: $('#group-disableLeave').is(':checked'),
|
disableLeave: $('#group-disableLeave').is(':checked'),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ function modifyGroup(group, fields) {
|
|||||||
group.icon = validator.escape(String(group.icon || ''));
|
group.icon = validator.escape(String(group.icon || ''));
|
||||||
group.createtimeISO = utils.toISOString(group.createtime);
|
group.createtimeISO = utils.toISOString(group.createtime);
|
||||||
group.private = ([null, undefined].includes(group.private)) ? 1 : group.private;
|
group.private = ([null, undefined].includes(group.private)) ? 1 : group.private;
|
||||||
|
group.memberPostCids = (group.memberPostCids || '').split(',').map(cid => parseInt(cid, 10)).filter(Boolean);
|
||||||
|
|
||||||
group['cover:thumb:url'] = group['cover:thumb:url'] || group['cover:url'];
|
group['cover:thumb:url'] = group['cover:thumb:url'] || group['cover:url'];
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const user = require('../user');
|
const user = require('../user');
|
||||||
|
const categories = require('../categories');
|
||||||
const db = require('../database');
|
const db = require('../database');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
const slugify = require('../slugify');
|
const slugify = require('../slugify');
|
||||||
@@ -119,9 +120,10 @@ Groups.get = async function (groupName, options) {
|
|||||||
stop = (parseInt(options.userListCount, 10) || 4) - 1;
|
stop = (parseInt(options.userListCount, 10) || 4) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [groupData, members, pending, invited, isMember, isPending, isInvited, isOwner] = await Promise.all([
|
const [groupData, members, selectCategories, pending, invited, isMember, isPending, isInvited, isOwner] = await Promise.all([
|
||||||
Groups.getGroupData(groupName),
|
Groups.getGroupData(groupName),
|
||||||
Groups.getOwnersAndMembers(groupName, options.uid, 0, stop),
|
Groups.getOwnersAndMembers(groupName, options.uid, 0, stop),
|
||||||
|
categories.buildForSelect(groupName, 'topics:read', []),
|
||||||
Groups.getUsersFromSet('group:' + groupName + ':pending', ['username', 'userslug', 'picture']),
|
Groups.getUsersFromSet('group:' + groupName + ':pending', ['username', 'userslug', 'picture']),
|
||||||
Groups.getUsersFromSet('group:' + groupName + ':invited', ['username', 'userslug', 'picture']),
|
Groups.getUsersFromSet('group:' + groupName + ':invited', ['username', 'userslug', 'picture']),
|
||||||
Groups.isMember(options.uid, groupName),
|
Groups.isMember(options.uid, groupName),
|
||||||
@@ -135,6 +137,10 @@ Groups.get = async function (groupName, options) {
|
|||||||
}
|
}
|
||||||
const descriptionParsed = await plugins.fireHook('filter:parse.raw', groupData.description);
|
const descriptionParsed = await plugins.fireHook('filter:parse.raw', groupData.description);
|
||||||
groupData.descriptionParsed = descriptionParsed;
|
groupData.descriptionParsed = descriptionParsed;
|
||||||
|
groupData.categories = selectCategories.map((category) => {
|
||||||
|
category.selected = groupData.memberPostCids.includes(category.cid);
|
||||||
|
return category;
|
||||||
|
});
|
||||||
groupData.members = members;
|
groupData.members = members;
|
||||||
groupData.membersNextStart = stop + 1;
|
groupData.membersNextStart = stop + 1;
|
||||||
groupData.pending = pending.filter(Boolean);
|
groupData.pending = pending.filter(Boolean);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const db = require('../database');
|
const db = require('../database');
|
||||||
|
const groups = require('.');
|
||||||
const privileges = require('../privileges');
|
const privileges = require('../privileges');
|
||||||
const posts = require('../posts');
|
const posts = require('../posts');
|
||||||
|
|
||||||
@@ -13,6 +14,10 @@ module.exports = function (Groups) {
|
|||||||
let groupNames = await Groups.getUserGroupMembership('groups:visible:createtime', [postData.uid]);
|
let groupNames = await Groups.getUserGroupMembership('groups:visible:createtime', [postData.uid]);
|
||||||
groupNames = groupNames[0];
|
groupNames = groupNames[0];
|
||||||
|
|
||||||
|
// Only process those groups that have the cid in its memberPostCids setting (or no setting at all)
|
||||||
|
const groupsCids = await groups.getGroupsFields(groupNames, ['memberPostCids']);
|
||||||
|
groupNames = groupNames.filter((groupName, idx) => !groupsCids[idx].memberPostCids.length || groupsCids[idx].memberPostCids.includes(postData.cid));
|
||||||
|
|
||||||
const keys = groupNames.map(groupName => 'group:' + groupName + ':member:pids');
|
const keys = groupNames.map(groupName => 'group:' + groupName + ':member:pids');
|
||||||
await db.sortedSetsAdd(keys, postData.timestamp, postData.pid);
|
await db.sortedSetsAdd(keys, postData.timestamp, postData.pid);
|
||||||
await Promise.all(groupNames.map(name => truncateMemberPosts(name)));
|
await Promise.all(groupNames.map(name => truncateMemberPosts(name)));
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
|
|
||||||
|
const categories = require('../categories');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
const slugify = require('../slugify');
|
const slugify = require('../slugify');
|
||||||
const db = require('../database');
|
const db = require('../database');
|
||||||
@@ -18,11 +19,10 @@ module.exports = function (Groups) {
|
|||||||
throw new Error('[[error:no-group]]');
|
throw new Error('[[error:no-group]]');
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await plugins.fireHook('filter:group.update', {
|
({ values } = await plugins.fireHook('filter:group.update', {
|
||||||
groupName: groupName,
|
groupName: groupName,
|
||||||
values: values,
|
values: values,
|
||||||
});
|
}));
|
||||||
values = result.values;
|
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
description: values.description || '',
|
description: values.description || '',
|
||||||
@@ -66,6 +66,12 @@ module.exports = function (Groups) {
|
|||||||
if (values.hasOwnProperty('hidden')) {
|
if (values.hasOwnProperty('hidden')) {
|
||||||
await updateVisibility(groupName, values.hidden);
|
await updateVisibility(groupName, values.hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.hasOwnProperty('memberPostCids')) {
|
||||||
|
const validCids = await categories.getCidsByPrivilege('categories:cid', groupName, 'topics:read');
|
||||||
|
payload.memberPostCids = values.memberPostCids.filter(cid => validCids.includes(cid)).join(',') || '';
|
||||||
|
}
|
||||||
|
|
||||||
await db.setObject('group:' + groupName, payload);
|
await db.setObject('group:' + groupName, payload);
|
||||||
await Groups.renameGroup(groupName, values.name);
|
await Groups.renameGroup(groupName, values.name);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const utils = require('../utils');
|
|||||||
|
|
||||||
module.exports = function (Plugins) {
|
module.exports = function (Plugins) {
|
||||||
Plugins.deprecatedHooks = {
|
Plugins.deprecatedHooks = {
|
||||||
|
'filter:privileges:isUserAllowedTo': 'filter:privileges:isAllowedTo',
|
||||||
};
|
};
|
||||||
|
|
||||||
Plugins.internals = {
|
Plugins.internals = {
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ module.exports = function (privileges) {
|
|||||||
|
|
||||||
privileges.admin.get = async function (uid) {
|
privileges.admin.get = async function (uid) {
|
||||||
const [userPrivileges, isAdministrator] = await Promise.all([
|
const [userPrivileges, isAdministrator] = await Promise.all([
|
||||||
helpers.isUserAllowedTo(privileges.admin.userPrivilegeList, uid, 0),
|
helpers.isAllowedTo(privileges.admin.userPrivilegeList, uid, 0),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ module.exports = function (privileges) {
|
|||||||
|
|
||||||
privileges.admin.can = async function (privilege, uid) {
|
privileges.admin.can = async function (privilege, uid) {
|
||||||
const [isUserAllowedTo, isAdministrator] = await Promise.all([
|
const [isUserAllowedTo, isAdministrator] = await Promise.all([
|
||||||
helpers.isUserAllowedTo(privilege, uid, [0]),
|
helpers.isAllowedTo(privilege, uid, [0]),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
]);
|
]);
|
||||||
return isAdministrator || isUserAllowedTo[0];
|
return isAdministrator || isUserAllowedTo[0];
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module.exports = function (privileges) {
|
|||||||
const privs = ['topics:create', 'topics:read', 'topics:tag', 'read'];
|
const privs = ['topics:create', 'topics:read', 'topics:tag', 'read'];
|
||||||
|
|
||||||
const [userPrivileges, isAdministrator, isModerator] = await Promise.all([
|
const [userPrivileges, isAdministrator, isModerator] = await Promise.all([
|
||||||
helpers.isUserAllowedTo(privs, uid, cid),
|
helpers.isAllowedTo(privs, uid, cid),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
user.isModerator(uid, cid),
|
user.isModerator(uid, cid),
|
||||||
]);
|
]);
|
||||||
@@ -80,7 +80,7 @@ module.exports = function (privileges) {
|
|||||||
if (!cid) {
|
if (!cid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const results = await helpers.isUserAllowedTo(privilege, uid, Array.isArray(cid) ? cid : [cid]);
|
const results = await helpers.isAllowedTo(privilege, uid, Array.isArray(cid) ? cid : [cid]);
|
||||||
|
|
||||||
if (Array.isArray(results) && results.length) {
|
if (Array.isArray(results) && results.length) {
|
||||||
return Array.isArray(cid) ? results : results[0];
|
return Array.isArray(cid) ? results : results[0];
|
||||||
@@ -113,8 +113,8 @@ module.exports = function (privileges) {
|
|||||||
privileges.categories.getBase = async function (privilege, cids, uid) {
|
privileges.categories.getBase = async function (privilege, cids, uid) {
|
||||||
return await utils.promiseParallel({
|
return await utils.promiseParallel({
|
||||||
categories: categories.getCategoriesFields(cids, ['disabled']),
|
categories: categories.getCategoriesFields(cids, ['disabled']),
|
||||||
allowedTo: helpers.isUserAllowedTo(privilege, uid, cids),
|
allowedTo: helpers.isAllowedTo(privilege, uid, cids),
|
||||||
view_deleted: helpers.isUserAllowedTo('posts:view_deleted', uid, cids),
|
view_deleted: helpers.isAllowedTo('posts:view_deleted', uid, cids),
|
||||||
isAdmin: user.isAdministrator(uid),
|
isAdmin: user.isAdministrator(uid),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ module.exports = function (privileges) {
|
|||||||
|
|
||||||
privileges.global.get = async function (uid) {
|
privileges.global.get = async function (uid) {
|
||||||
const [userPrivileges, isAdministrator] = await Promise.all([
|
const [userPrivileges, isAdministrator] = await Promise.all([
|
||||||
helpers.isUserAllowedTo(privileges.global.userPrivilegeList, uid, 0),
|
helpers.isAllowedTo(privileges.global.userPrivilegeList, uid, 0),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ module.exports = function (privileges) {
|
|||||||
privileges.global.can = async function (privilege, uid) {
|
privileges.global.can = async function (privilege, uid) {
|
||||||
const [isAdministrator, isUserAllowedTo] = await Promise.all([
|
const [isAdministrator, isUserAllowedTo] = await Promise.all([
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
helpers.isUserAllowedTo(privilege, uid, [0]),
|
helpers.isAllowedTo(privilege, uid, [0]),
|
||||||
]);
|
]);
|
||||||
return isAdministrator || isUserAllowedTo[0];
|
return isAdministrator || isUserAllowedTo[0];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,26 +26,45 @@ helpers.isUsersAllowedTo = async function (privilege, uids, cid) {
|
|||||||
return result.allowed;
|
return result.allowed;
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers.isUserAllowedTo = async function (privilege, uid, cid) {
|
helpers.isAllowedTo = async function (privilege, uidOrGroupName, cid) {
|
||||||
let allowed;
|
let allowed;
|
||||||
if (Array.isArray(privilege) && !Array.isArray(cid)) {
|
if (Array.isArray(privilege) && !Array.isArray(cid)) {
|
||||||
allowed = await isUserAllowedToPrivileges(privilege, uid, cid);
|
allowed = await isAllowedToPrivileges(privilege, uidOrGroupName, cid);
|
||||||
} else if (Array.isArray(cid) && !Array.isArray(privilege)) {
|
} else if (Array.isArray(cid) && !Array.isArray(privilege)) {
|
||||||
allowed = await isUserAllowedToCids(privilege, uid, cid);
|
allowed = await isAllowedToCids(privilege, uidOrGroupName, cid);
|
||||||
}
|
}
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
const result = await plugins.fireHook('filter:privileges:isUserAllowedTo', { allowed: allowed, privilege: privilege, uid: uid, cid: cid });
|
({ allowed } = await plugins.fireHook('filter:privileges:isUserAllowedTo', { allowed: allowed, privilege: privilege, uid: uidOrGroupName, cid: cid }));
|
||||||
return result.allowed;
|
({ allowed } = await plugins.fireHook('filter:privileges:isAllowedTo', { allowed: allowed, privilege: privilege, uid: uidOrGroupName, cid: cid }));
|
||||||
|
return allowed;
|
||||||
}
|
}
|
||||||
throw new Error('[[error:invalid-data]]');
|
throw new Error('[[error:invalid-data]]');
|
||||||
};
|
};
|
||||||
|
|
||||||
async function isUserAllowedToCids(privilege, uid, cids) {
|
async function isAllowedToCids(privilege, uidOrGroupName, cids) {
|
||||||
if (!privilege) {
|
if (!privilege) {
|
||||||
return cids.map(() => false);
|
return cids.map(() => false);
|
||||||
}
|
}
|
||||||
if (parseInt(uid, 10) <= 0) {
|
|
||||||
return await isSystemGroupAllowedToCids(privilege, uid, cids);
|
// Group handling
|
||||||
|
if (isNaN(parseInt(uidOrGroupName, 10)) && (uidOrGroupName || '').length) {
|
||||||
|
const groupKeys = [];
|
||||||
|
cids.forEach(function (cid) {
|
||||||
|
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
||||||
|
});
|
||||||
|
const sets = await Promise.all([
|
||||||
|
groups.isMemberOfGroups(uidOrGroupName, groupKeys),
|
||||||
|
groups.isMemberOfGroups('registered-users', groupKeys),
|
||||||
|
]);
|
||||||
|
return sets[0].reduce((memo, cur, idx) => {
|
||||||
|
memo.push(cur || sets[1][idx]);
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
// User handling
|
||||||
|
if (parseInt(uidOrGroupName, 10) <= 0) {
|
||||||
|
return await isSystemGroupAllowedToCids(privilege, uidOrGroupName, cids);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userKeys = [];
|
const userKeys = [];
|
||||||
@@ -55,12 +74,29 @@ async function isUserAllowedToCids(privilege, uid, cids) {
|
|||||||
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
||||||
});
|
});
|
||||||
|
|
||||||
return await checkIfAllowed(uid, userKeys, groupKeys);
|
return await checkIfAllowed(uidOrGroupName, userKeys, groupKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isUserAllowedToPrivileges(privileges, uid, cid) {
|
async function isAllowedToPrivileges(privileges, uidOrGroupName, cid) {
|
||||||
if (parseInt(uid, 10) <= 0) {
|
// Group handling
|
||||||
return await isSystemGroupAllowedToPrivileges(privileges, uid, cid);
|
if (isNaN(parseInt(uidOrGroupName, 10)) && (uidOrGroupName || '').length) {
|
||||||
|
const groupKeys = [];
|
||||||
|
privileges.forEach(function (privilege) {
|
||||||
|
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
||||||
|
});
|
||||||
|
const sets = await Promise.all([
|
||||||
|
groups.isMemberOfGroups(uidOrGroupName, groupKeys),
|
||||||
|
groups.isMemberOfGroups('registered-users', groupKeys),
|
||||||
|
]);
|
||||||
|
return sets[0].reduce((memo, cur, idx) => {
|
||||||
|
memo.push(cur || sets[1][idx]);
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
// User handling
|
||||||
|
if (parseInt(uidOrGroupName, 10) <= 0) {
|
||||||
|
return await isSystemGroupAllowedToPrivileges(privileges, uidOrGroupName, cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userKeys = [];
|
const userKeys = [];
|
||||||
@@ -70,7 +106,7 @@ async function isUserAllowedToPrivileges(privileges, uid, cid) {
|
|||||||
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
|
||||||
});
|
});
|
||||||
|
|
||||||
return await checkIfAllowed(uid, userKeys, groupKeys);
|
return await checkIfAllowed(uidOrGroupName, userKeys, groupKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkIfAllowed(uid, userKeys, groupKeys) {
|
async function checkIfAllowed(uid, userKeys, groupKeys) {
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ module.exports = function (privileges) {
|
|||||||
isAdmin: user.isAdministrator(uid),
|
isAdmin: user.isAdministrator(uid),
|
||||||
isModerator: user.isModerator(uid, uniqueCids),
|
isModerator: user.isModerator(uid, uniqueCids),
|
||||||
isOwner: posts.isOwner(pids, uid),
|
isOwner: posts.isOwner(pids, uid),
|
||||||
'topics:read': helpers.isUserAllowedTo('topics:read', uid, uniqueCids),
|
'topics:read': helpers.isAllowedTo('topics:read', uid, uniqueCids),
|
||||||
read: helpers.isUserAllowedTo('read', uid, uniqueCids),
|
read: helpers.isAllowedTo('read', uid, uniqueCids),
|
||||||
'posts:edit': helpers.isUserAllowedTo('posts:edit', uid, uniqueCids),
|
'posts:edit': helpers.isAllowedTo('posts:edit', uid, uniqueCids),
|
||||||
'posts:history': helpers.isUserAllowedTo('posts:history', uid, uniqueCids),
|
'posts:history': helpers.isAllowedTo('posts:history', uid, uniqueCids),
|
||||||
'posts:view_deleted': helpers.isUserAllowedTo('posts:view_deleted', uid, uniqueCids),
|
'posts:view_deleted': helpers.isAllowedTo('posts:view_deleted', uid, uniqueCids),
|
||||||
});
|
});
|
||||||
|
|
||||||
const isModerator = _.zipObject(uniqueCids, results.isModerator);
|
const isModerator = _.zipObject(uniqueCids, results.isModerator);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module.exports = function (privileges) {
|
|||||||
];
|
];
|
||||||
const topicData = await topics.getTopicFields(tid, ['cid', 'uid', 'locked', 'deleted']);
|
const topicData = await topics.getTopicFields(tid, ['cid', 'uid', 'locked', 'deleted']);
|
||||||
const [userPrivileges, isAdministrator, isModerator, disabled] = await Promise.all([
|
const [userPrivileges, isAdministrator, isModerator, disabled] = await Promise.all([
|
||||||
helpers.isUserAllowedTo(privs, uid, topicData.cid),
|
helpers.isAllowedTo(privs, uid, topicData.cid),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
user.isModerator(uid, topicData.cid),
|
user.isModerator(uid, topicData.cid),
|
||||||
categories.getCategoryField(topicData.cid, 'disabled'),
|
categories.getCategoryField(topicData.cid, 'disabled'),
|
||||||
@@ -121,7 +121,7 @@ module.exports = function (privileges) {
|
|||||||
user.isModerator(uid, topicData.cid),
|
user.isModerator(uid, topicData.cid),
|
||||||
user.isAdministrator(uid),
|
user.isAdministrator(uid),
|
||||||
topics.isOwner(tid, uid),
|
topics.isOwner(tid, uid),
|
||||||
helpers.isUserAllowedTo('topics:delete', uid, [topicData.cid]),
|
helpers.isAllowedTo('topics:delete', uid, [topicData.cid]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (isAdministrator) {
|
if (isAdministrator) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ module.exports = function (privileges) {
|
|||||||
return await filterIsModerator(cids, uid, cids.map(() => true));
|
return await filterIsModerator(cids, uid, cids.map(() => true));
|
||||||
}
|
}
|
||||||
const uniqueCids = _.uniq(cids);
|
const uniqueCids = _.uniq(cids);
|
||||||
const isAllowed = await helpers.isUserAllowedTo('moderate', uid, uniqueCids);
|
const isAllowed = await helpers.isAllowedTo('moderate', uid, uniqueCids);
|
||||||
|
|
||||||
const cidToIsAllowed = _.zipObject(uniqueCids, isAllowed);
|
const cidToIsAllowed = _.zipObject(uniqueCids, isAllowed);
|
||||||
const isModerator = cids.map(cid => cidToIsAllowed[cid]);
|
const isModerator = cids.map(cid => cidToIsAllowed[cid]);
|
||||||
|
|||||||
@@ -95,6 +95,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="memberPostCids">[[groups:details.member-post-cids]]</label>
|
||||||
|
<select multiple="true" name="memberPostCids" id="memberPostCids" class="form-control" size="15">
|
||||||
|
{{{each group.categories}}}
|
||||||
|
<option value="{categories.cid}"{{{ if ../selected }}} selected{{{ end }}}>
|
||||||
|
{../level}{../name}
|
||||||
|
</option>
|
||||||
|
{{{end}}}
|
||||||
|
</select>
|
||||||
|
<p class="help-block">[[groups:details.member-post-cids-help]]</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
|||||||
Reference in New Issue
Block a user