Files
NodeBB/src/privileges/helpers.js

162 lines
5.4 KiB
JavaScript
Raw Normal View History

'use strict';
2019-07-20 22:12:22 -04:00
const _ = require('lodash');
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
const groups = require('../groups');
const user = require('../user');
const plugins = require('../plugins');
2019-07-20 22:12:22 -04:00
const helpers = module.exports;
2019-07-20 22:12:22 -04:00
const uidToSystemGroup = {
2018-01-31 15:20:17 -05:00
0: 'guests',
'-1': 'spiders',
};
2019-07-20 22:12:22 -04:00
helpers.isUserAllowedTo = async function (privilege, uid, cid) {
if (Array.isArray(privilege) && !Array.isArray(cid)) {
2019-07-20 22:12:22 -04:00
return await isUserAllowedToPrivileges(privilege, uid, cid);
} else if (Array.isArray(cid) && !Array.isArray(privilege)) {
2019-07-20 22:12:22 -04:00
return await isUserAllowedToCids(privilege, uid, cid);
}
2019-07-20 22:12:22 -04:00
throw new Error('[[error:invalid-data]]');
};
2019-07-20 22:12:22 -04:00
async function isUserAllowedToCids(privilege, uid, cids) {
2018-01-31 15:20:17 -05:00
if (parseInt(uid, 10) <= 0) {
2019-07-20 22:12:22 -04:00
return await isSystemGroupAllowedToCids(privilege, uid, cids);
}
2019-07-20 22:12:22 -04:00
const userKeys = [];
const groupKeys = [];
2017-05-25 21:17:20 -04:00
cids.forEach(function (cid) {
userKeys.push('cid:' + cid + ':privileges:' + privilege);
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
});
2017-05-25 21:17:20 -04:00
2019-07-20 22:12:22 -04:00
return await checkIfAllowed(uid, userKeys, groupKeys);
}
2019-07-20 22:12:22 -04:00
async function isUserAllowedToPrivileges(privileges, uid, cid) {
2018-01-31 15:20:17 -05:00
if (parseInt(uid, 10) <= 0) {
2019-07-20 22:12:22 -04:00
return await isSystemGroupAllowedToPrivileges(privileges, uid, cid);
}
2019-07-20 22:12:22 -04:00
const userKeys = [];
const groupKeys = [];
2017-05-25 21:17:20 -04:00
privileges.forEach(function (privilege) {
userKeys.push('cid:' + cid + ':privileges:' + privilege);
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
});
2019-07-20 22:12:22 -04:00
return await checkIfAllowed(uid, userKeys, groupKeys);
2017-05-25 21:17:20 -04:00
}
2019-07-20 22:12:22 -04:00
async function checkIfAllowed(uid, userKeys, groupKeys) {
const [hasUserPrivilege, hasGroupPrivilege] = await Promise.all([
groups.isMemberOfGroups(uid, userKeys),
groups.isMemberOfGroupsList(uid, groupKeys),
]);
return userKeys.map((key, index) => hasUserPrivilege[index] || hasGroupPrivilege[index]);
}
2019-07-20 22:12:22 -04:00
helpers.isUsersAllowedTo = async function (privilege, uids, cid) {
const [hasUserPrivilege, hasGroupPrivilege] = await Promise.all([
groups.isMembers(uids, 'cid:' + cid + ':privileges:' + privilege),
groups.isMembersOfGroupList(uids, 'cid:' + cid + ':privileges:groups:' + privilege),
]);
return uids.map((uid, index) => hasUserPrivilege[index] || hasGroupPrivilege[index]);
};
2019-07-20 22:12:22 -04:00
async function isSystemGroupAllowedToCids(privilege, uid, cids) {
const groupKeys = cids.map(cid => 'cid:' + cid + ':privileges:groups:' + privilege);
2019-07-20 22:12:22 -04:00
return await groups.isMemberOfGroups(uidToSystemGroup[uid], groupKeys);
}
2019-07-20 22:12:22 -04:00
async function isSystemGroupAllowedToPrivileges(privileges, uid, cid) {
const groupKeys = privileges.map(privilege => 'cid:' + cid + ':privileges:groups:' + privilege);
2019-07-20 22:12:22 -04:00
return await groups.isMemberOfGroups(uidToSystemGroup[uid], groupKeys);
}
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
helpers.getUserPrivileges = async function (cid, hookName, userPrivilegeList) {
const userPrivileges = await plugins.fireHook(hookName, userPrivilegeList.slice());
let memberSets = await groups.getMembersOfGroups(userPrivileges.map(privilege => 'cid:' + cid + ':privileges:' + privilege));
memberSets = memberSets.map(function (set) {
return set.map(uid => parseInt(uid, 10));
});
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
const members = _.uniq(_.flatten(memberSets));
const memberData = await user.getUsersFields(members, ['picture', 'username']);
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
memberData.forEach(function (member) {
member.privileges = {};
for (var x = 0, numPrivs = userPrivileges.length; x < numPrivs; x += 1) {
member.privileges[userPrivileges[x]] = memberSets[x].includes(parseInt(member.uid, 10));
}
});
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
return memberData;
2017-12-20 14:49:20 -05:00
};
2019-07-20 22:12:22 -04:00
helpers.getGroupPrivileges = async function (cid, hookName, groupPrivilegeList) {
const groupPrivileges = await plugins.fireHook(hookName, groupPrivilegeList.slice());
const [memberSets, allGroupNames] = await Promise.all([
groups.getMembersOfGroups(groupPrivileges.map(privilege => 'cid:' + cid + ':privileges:' + privilege)),
groups.getGroups('groups:createtime', 0, -1),
]);
const uniqueGroups = _.uniq(_.flatten(memberSets));
let groupNames = allGroupNames.filter(groupName => !groupName.includes(':privileges:') && uniqueGroups.includes(groupName));
groupNames = groups.ephemeralGroups.concat(groupNames);
moveToFront(groupNames, 'Global Moderators');
moveToFront(groupNames, 'registered-users');
2017-12-20 14:49:20 -05:00
2019-07-20 22:12:22 -04:00
const adminIndex = groupNames.indexOf('administrators');
if (adminIndex !== -1) {
groupNames.splice(adminIndex, 1);
}
const groupData = await groups.getGroupsFields(groupNames, ['private']);
const memberData = groupNames.map(function (member, index) {
const memberPrivs = {};
for (var x = 0, numPrivs = groupPrivileges.length; x < numPrivs; x += 1) {
memberPrivs[groupPrivileges[x]] = memberSets[x].includes(member);
}
return {
name: member,
privileges: memberPrivs,
isPrivate: groupData[index] && !!groupData[index].private,
};
});
return memberData;
2017-12-20 15:19:22 -05:00
};
function moveToFront(groupNames, groupToMove) {
const index = groupNames.indexOf(groupToMove);
if (index !== -1) {
groupNames.splice(0, 0, groupNames.splice(index, 1)[0]);
} else {
groupNames.unshift(groupToMove);
}
}
2019-07-20 22:12:22 -04:00
helpers.giveOrRescind = async function (method, privileges, cids, groupNames) {
groupNames = Array.isArray(groupNames) ? groupNames : [groupNames];
cids = Array.isArray(cids) ? cids : [cids];
2019-07-20 22:12:22 -04:00
for (const groupName of groupNames) {
const groupKeys = [];
fix(style): updated code to follow new eslint recommendations Squashed commit of the following: commit f9ce878b269b3568f0d649309aae1af4dcfdfeef Author: Julian Lam <julian@nodebb.org> Date: Tue Aug 13 14:30:46 2019 -0400 fix(style): updated code to follow new eslint recommendations commit 80dd370e413f22badb96ff2138e7991dfff6d836 Author: Julian Lam <julian@nodebb.org> Date: Tue Aug 13 14:14:58 2019 -0400 fix(deps): update dependency sitemap to v4 Squashed commit of the following: commit f4dd9cabb21e26fdc21f8413be822ea7c64251f8 Author: Julian Lam <julian@nodebb.org> Date: Tue Aug 13 11:33:05 2019 -0400 fix: resolved breaking changes from sitemap v4 upgrade commit 9043415ee16dcc27a8dcc2e4479d1bc5e2d1b60e Merge: e3352b272 72590b346 Author: Julian Lam <julian@nodebb.org> Date: Tue Aug 13 11:09:55 2019 -0400 Merge branch 'master' into renovate/sitemap-4.x commit e3352b272eb9400bdb00774973181397803765e4 Author: Renovate Bot <bot@renovateapp.com> Date: Mon Aug 12 07:59:05 2019 +0000 fix(deps): update dependency sitemap to v4 commit 8e3c0cdcae22acc32d352be8bb72d60e7502dbc5 Author: Renovate Bot <bot@renovateapp.com> Date: Fri Aug 9 00:49:51 2019 +0000 fix(deps): update dependency commander to v3 commit 2104449d38818f2fa4d44b3a58a0a168781acbfb Author: Renovate Bot <bot@renovateapp.com> Date: Tue Aug 13 15:00:27 2019 +0000 fix(deps): update dependency mongodb to v3.3.0 commit d2937f446a21131c070ae5d0ff33d67cfe465b8c Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Tue Aug 13 10:36:48 2019 -0400 feat: async/await admin/controllers commit 1b97e8b199f960dc24e5722702f27499ae049914 Author: Misty (Bot) <deploy@nodebb.org> Date: Tue Aug 13 09:28:39 2019 +0000 Latest translations and fallbacks commit 69a48957a2f0d23c4d194b664bda3a0431179c01 Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Mon Aug 12 21:56:09 2019 -0400 feat: async/await commit b9b2a7e593a452de4bef6d0ab6abe368a3bdb8dd Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Mon Aug 12 20:58:29 2019 -0400 feat: async/await refactor controllers/accounts commit a8d43a175974a0c8ae3dc132bf51a7ed9a4c6305 Author: Baris Usakli <barisusakli@gmail.com> Date: Mon Aug 12 14:49:40 2019 -0400 feat: async/await controllers/accounts commit 2f25aae57bf9dbe98d655276770e56bed9ec023b Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Sun Aug 11 23:09:50 2019 -0400 fix: #7831, fix pagination convert to async/await commit c9e83f2374572264855a04156278eef256b0a20c Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Sun Aug 11 00:14:35 2019 -0400 fix: remove empty line commit 30be91b26c4dd7583412c4e8d56e9c1688e48a44 Author: Barış Soner Uşaklı <barisusakli@gmail.com> Date: Sun Aug 11 00:13:41 2019 -0400 fix: remove useless catchs and empty line commit 2e4a71c0b6104738f15ffbfe3246105b922fdfb3 Author: Renovate Bot <bot@renovateapp.com> Date: Sat Aug 10 06:51:50 2019 +0000 chore(deps): update dependency eslint-config-airbnb-base to v14
2019-08-13 14:33:37 -04:00
cids.forEach(cid => {
privileges.forEach(privilege => {
groupKeys.push('cid:' + cid + ':privileges:groups:' + privilege);
});
});
2019-07-20 22:12:22 -04:00
/* eslint-disable no-await-in-loop */
await method(groupKeys, groupName);
}
};
2019-07-20 22:12:22 -04:00
require('../promisify')(helpers);