Remains of the sandboxed CKEditor - will be removed, but the version here may be useful for another editor that is prone to XSS (like Summernote).
645 lines
24 KiB
JavaScript
645 lines
24 KiB
JavaScript
'use strict';
|
|
|
|
const knex = require('../lib/knex');
|
|
const config = require('config');
|
|
const { enforce } = require('../lib/helpers');
|
|
const dtHelpers = require('../lib/dt-helpers');
|
|
const entitySettings = require('../lib/entity-settings');
|
|
const interoperableErrors = require('../shared/interoperable-errors');
|
|
const log = require('../lib/log');
|
|
const {getGlobalNamespaceId} = require('../shared/namespaces');
|
|
const {getAdminId} = require('../shared/users');
|
|
|
|
// TODO: This would really benefit from some permission cache connected to rebuildPermissions
|
|
// A bit of the problem is that the cache would have to expunged as the result of other processes modifying entites/permissions
|
|
|
|
|
|
async function listByEntityDTAjax(context, entityTypeId, entityId, params) {
|
|
return await knex.transaction(async (tx) => {
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
await enforceEntityPermissionTx(tx, context, entityTypeId, entityId, 'share');
|
|
|
|
return await dtHelpers.ajaxListTx(
|
|
tx,
|
|
params,
|
|
builder => builder
|
|
.from(entityType.sharesTable)
|
|
.innerJoin('users', entityType.sharesTable + '.user', 'users.id')
|
|
.innerJoin('generated_role_names', 'generated_role_names.role', 'users.role')
|
|
.where('generated_role_names.entity_type', entityTypeId)
|
|
.where(`${entityType.sharesTable}.entity`, entityId),
|
|
['users.username', 'users.name', 'generated_role_names.name', 'users.id', entityType.sharesTable + '.auto']
|
|
);
|
|
});
|
|
}
|
|
|
|
async function listByUserDTAjax(context, entityTypeId, userId, params) {
|
|
return await knex.transaction(async (tx) => {
|
|
const user = await tx('users').where('id', userId).first();
|
|
if (!user) {
|
|
shares.throwPermissionDenied();
|
|
}
|
|
|
|
await enforceEntityPermissionTx(tx, context, 'namespace', user.namespace, 'manageUsers');
|
|
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
|
|
return await dtHelpers.ajaxListWithPermissionsTx(
|
|
tx,
|
|
context,
|
|
[{entityTypeId}],
|
|
params,
|
|
builder => builder
|
|
.from(entityType.sharesTable)
|
|
.innerJoin(entityType.entitiesTable, entityType.sharesTable + '.entity', entityType.entitiesTable + '.id')
|
|
.innerJoin('generated_role_names', 'generated_role_names.role', entityType.sharesTable + '.role')
|
|
.where('generated_role_names.entity_type', entityTypeId)
|
|
.where(entityType.sharesTable + '.user', userId),
|
|
[entityType.entitiesTable + '.name', 'generated_role_names.name', entityType.entitiesTable + '.id', entityType.sharesTable + '.auto']
|
|
);
|
|
});
|
|
}
|
|
|
|
async function listUnassignedUsersDTAjax(context, entityTypeId, entityId, params) {
|
|
return await knex.transaction(async (tx) => {
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
|
|
await enforceEntityPermissionTx(tx, context, entityTypeId, entityId, 'share');
|
|
|
|
return await dtHelpers.ajaxListTx(
|
|
tx,
|
|
params,
|
|
builder => builder
|
|
.from('users')
|
|
.whereNotExists(function () {
|
|
return this
|
|
.select('*')
|
|
.from(entityType.sharesTable)
|
|
.whereRaw(`users.id = ${entityType.sharesTable}.user`)
|
|
.andWhere(`${entityType.sharesTable}.entity`, entityId);
|
|
}),
|
|
['users.id', 'users.username', 'users.name']
|
|
);
|
|
});
|
|
}
|
|
|
|
async function listRolesDTAjax(entityTypeId, params) {
|
|
return await dtHelpers.ajaxList(
|
|
params,
|
|
builder => builder
|
|
.from('generated_role_names')
|
|
.where({entity_type: entityTypeId}),
|
|
['role', 'name', 'description']
|
|
);
|
|
}
|
|
|
|
async function assign(context, entityTypeId, entityId, userId, role) {
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
|
|
await knex.transaction(async tx => {
|
|
await enforceEntityPermissionTx(tx, context, entityTypeId, entityId, 'share');
|
|
|
|
enforce(await tx('users').where('id', userId).select('id').first(), 'Invalid user id');
|
|
enforce(await tx(entityType.entitiesTable).where('id', entityId).select('id').first(), 'Invalid entity id');
|
|
|
|
const entry = await tx(entityType.sharesTable).where({user: userId, entity: entityId}).select('role').first();
|
|
|
|
if (entry) {
|
|
if (!role) {
|
|
await tx(entityType.sharesTable).where({user: userId, entity: entityId}).del();
|
|
} else if (entry.role !== role) {
|
|
await tx(entityType.sharesTable).where({user: userId, entity: entityId}).update('role', role);
|
|
}
|
|
} else {
|
|
await tx(entityType.sharesTable).insert({
|
|
user: userId,
|
|
entity: entityId,
|
|
role
|
|
});
|
|
}
|
|
|
|
await tx(entityType.permissionsTable).where({user: userId, entity: entityId}).del();
|
|
if (entityTypeId === 'namespace') {
|
|
await rebuildPermissionsTx(tx, {userId});
|
|
} else if (role) {
|
|
await rebuildPermissionsTx(tx, { entityTypeId, entityId, userId });
|
|
}
|
|
});
|
|
}
|
|
|
|
async function rebuildPermissionsTx(tx, restriction) {
|
|
restriction = restriction || {};
|
|
|
|
const namespaceEntityType = entitySettings.getEntityType('namespace');
|
|
|
|
// Collect entity types we care about
|
|
let restrictedEntityTypes;
|
|
if (restriction.entityTypeId) {
|
|
const entityType = entitySettings.getEntityType(restriction.entityTypeId);
|
|
restrictedEntityTypes = {
|
|
[restriction.entityTypeId]: entityType
|
|
};
|
|
} else {
|
|
restrictedEntityTypes = entitySettings.getEntityTypesWithPermissions();
|
|
}
|
|
|
|
|
|
// To prevent users locking out themselves, we consider user with id 1 to be the admin and always assign it
|
|
// the admin role. The admin role is a global role that has admin===true
|
|
// If this behavior is not desired, it is enough to delete the user with id 1.
|
|
const adminUser = await tx('users').where('id', getAdminId()).first();
|
|
if (adminUser) {
|
|
let adminRole;
|
|
for (const role in config.roles.global) {
|
|
if (config.roles.global[role].admin) {
|
|
adminRole = role;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (adminRole) {
|
|
await tx('users').update('role', adminRole).where('id', getAdminId());
|
|
}
|
|
}
|
|
|
|
|
|
// Reset root and own namespace shares as per the user roles
|
|
const usersWithRoleInOwnNamespaceQuery = tx('users')
|
|
.leftJoin(namespaceEntityType.sharesTable, {
|
|
'users.id': `${namespaceEntityType.sharesTable}.user`,
|
|
'users.namespace': `${namespaceEntityType.sharesTable}.entity`
|
|
})
|
|
.select(['users.id', 'users.namespace', 'users.role as userRole', `${namespaceEntityType.sharesTable}.role`]);
|
|
if (restriction.userId) {
|
|
usersWithRoleInOwnNamespaceQuery.where('users.id', restriction.userId);
|
|
}
|
|
const usersWithRoleInOwnNamespace = await usersWithRoleInOwnNamespaceQuery;
|
|
|
|
for (const user of usersWithRoleInOwnNamespace) {
|
|
const roleConf = config.roles.global[user.userRole];
|
|
|
|
if (roleConf) {
|
|
const desiredRole = roleConf.ownNamespaceRole;
|
|
if (desiredRole && user.role !== desiredRole) {
|
|
await tx(namespaceEntityType.sharesTable).where({ user: user.id, entity: user.namespace }).del();
|
|
await tx(namespaceEntityType.sharesTable).insert({ user: user.id, entity: user.namespace, role: desiredRole, auto: true });
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const usersWithRoleInRootNamespaceQuery = tx('users')
|
|
.leftJoin(namespaceEntityType.sharesTable, {
|
|
'users.id': `${namespaceEntityType.sharesTable}.user`,
|
|
[`${namespaceEntityType.sharesTable}.entity`]: getGlobalNamespaceId()
|
|
})
|
|
.select(['users.id', 'users.role as userRole', `${namespaceEntityType.sharesTable}.role`]);
|
|
if (restriction.userId) {
|
|
usersWithRoleInRootNamespaceQuery.andWhere('users.id', restriction.userId);
|
|
}
|
|
const usersWithRoleInRootNamespace = await usersWithRoleInRootNamespaceQuery;
|
|
|
|
for (const user of usersWithRoleInRootNamespace) {
|
|
const roleConf = config.roles.global[user.userRole];
|
|
|
|
if (roleConf) {
|
|
const desiredRole = roleConf.rootNamespaceRole;
|
|
if (desiredRole && user.role !== desiredRole) {
|
|
await tx(namespaceEntityType.sharesTable).where({ user: user.id, entity: getGlobalNamespaceId() }).del();
|
|
await tx(namespaceEntityType.sharesTable).insert({ user: user.id, entity: getGlobalNamespaceId(), role: desiredRole, auto: 1 });
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Build the map of all namespaces
|
|
// nsMap is a map of namespaces - each of the following shape:
|
|
// .id - id of the namespace
|
|
// .namespace - id of the parent or null if no parent
|
|
// .userPermissions - Map userId -> [entityTypeId] -> array of permissions
|
|
// .transitiveUserPermissions - the same as above, but taking into account transitive permission obtained from namespace parents
|
|
|
|
const namespaces = await tx('namespaces').select(['id', 'namespace']);
|
|
|
|
const nsMap = new Map();
|
|
for (const namespace of namespaces) {
|
|
namespace.userPermissions = new Map();
|
|
nsMap.set(namespace.id, namespace);
|
|
}
|
|
|
|
// This populates .userPermissions
|
|
const nsSharesQuery = tx(namespaceEntityType.sharesTable).select(['entity', 'user', 'role']);
|
|
if (restriction.userId) {
|
|
nsSharesQuery.where('user', restriction.userId);
|
|
}
|
|
|
|
const nsShares = await nsSharesQuery;
|
|
for (const nsShare of nsShares) {
|
|
const ns = nsMap.get(nsShare.entity);
|
|
|
|
const userPerms = {};
|
|
ns.userPermissions.set(nsShare.user, userPerms);
|
|
|
|
for (const entityTypeId in restrictedEntityTypes) {
|
|
if (config.roles.namespace[nsShare.role] &&
|
|
config.roles.namespace[nsShare.role].children &&
|
|
config.roles.namespace[nsShare.role].children[entityTypeId]) {
|
|
|
|
userPerms[entityTypeId] = new Set(config.roles.namespace[nsShare.role].children[entityTypeId]);
|
|
|
|
} else {
|
|
userPerms[entityTypeId] = new Set();
|
|
}
|
|
}
|
|
}
|
|
|
|
// This computes .transitiveUserPermissions
|
|
for (const ns of nsMap.values()) {
|
|
ns.transitiveUserPermissions = new Map();
|
|
|
|
for (const userPermsPair of ns.userPermissions) {
|
|
const userPerms = {};
|
|
ns.transitiveUserPermissions.set(userPermsPair[0], userPerms);
|
|
|
|
for (const entityTypeId in restrictedEntityTypes) {
|
|
userPerms[entityTypeId] = new Set(userPermsPair[1][entityTypeId]);
|
|
}
|
|
}
|
|
|
|
let parentId = ns.namespace;
|
|
while (parentId) {
|
|
const parent = nsMap.get(parentId);
|
|
|
|
for (const userPermsPair of parent.userPermissions) {
|
|
const user = userPermsPair[0];
|
|
|
|
if (ns.transitiveUserPermissions.has(user)) {
|
|
const userPerms = ns.transitiveUserPermissions.get(user);
|
|
|
|
for (const entityTypeId in restrictedEntityTypes) {
|
|
for (const perm of userPermsPair[1][entityTypeId]) {
|
|
userPerms[entityTypeId].add(perm);
|
|
}
|
|
}
|
|
} else {
|
|
const userPerms = {};
|
|
ns.transitiveUserPermissions.set(user, userPerms);
|
|
|
|
for (const entityTypeId in restrictedEntityTypes) {
|
|
userPerms[entityTypeId] = new Set(userPermsPair[1][entityTypeId]);
|
|
}
|
|
}
|
|
}
|
|
|
|
parentId = parent.namespace;
|
|
}
|
|
}
|
|
|
|
|
|
// This reads direct shares from DB, joins each with the permissions from namespaces and stores the permissions into DB
|
|
for (const entityTypeId in restrictedEntityTypes) {
|
|
const entityType = restrictedEntityTypes[entityTypeId];
|
|
|
|
const expungeQuery = tx(entityType.permissionsTable).del();
|
|
if (restriction.entityId) {
|
|
expungeQuery.where('entity', restriction.entityId);
|
|
}
|
|
if (restriction.userId) {
|
|
expungeQuery.where('user', restriction.userId);
|
|
}
|
|
await expungeQuery;
|
|
|
|
const entitiesQuery = tx(entityType.entitiesTable).select(['id', 'namespace']);
|
|
if (restriction.entityId) {
|
|
entitiesQuery.where('id', restriction.entityId);
|
|
}
|
|
const entities = await entitiesQuery;
|
|
|
|
for (const entity of entities) {
|
|
const permsPerUser = new Map();
|
|
|
|
if (entity.namespace) { // The root namespace has not parent namespace, thus the test
|
|
const transitiveUserPermissions = nsMap.get(entity.namespace).transitiveUserPermissions;
|
|
for (const transitivePermsPair of transitiveUserPermissions.entries()) {
|
|
permsPerUser.set(transitivePermsPair[0], new Set(transitivePermsPair[1][entityTypeId]));
|
|
}
|
|
}
|
|
|
|
const directSharesQuery = tx(entityType.sharesTable).select(['user', 'role']).where('entity', entity.id);
|
|
if (restriction.userId) {
|
|
directSharesQuery.andWhere('user', restriction.userId);
|
|
}
|
|
const directShares = await directSharesQuery;
|
|
|
|
for (const share of directShares) {
|
|
let userPerms;
|
|
if (permsPerUser.has(share.user)) {
|
|
userPerms = permsPerUser.get(share.user);
|
|
} else {
|
|
userPerms = new Set();
|
|
permsPerUser.set(share.user, userPerms);
|
|
}
|
|
|
|
if (config.roles[entityTypeId][share.role] &&
|
|
config.roles[entityTypeId][share.role].permissions) {
|
|
|
|
for (const perm of config.roles[entityTypeId][share.role].permissions) {
|
|
userPerms.add(perm);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const userPermsPair of permsPerUser.entries()) {
|
|
const data = [];
|
|
|
|
for (const operation of userPermsPair[1]) {
|
|
data.push({user: userPermsPair[0], entity: entity.id, operation});
|
|
}
|
|
|
|
if (data.length > 0) {
|
|
await tx(entityType.permissionsTable).insert(data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function rebuildPermissions(restriction) {
|
|
await knex.transaction(async tx => {
|
|
await rebuildPermissionsTx(tx, restriction);
|
|
});
|
|
}
|
|
|
|
async function regenerateRoleNamesTable() {
|
|
await knex.transaction(async tx => {
|
|
await tx('generated_role_names').del();
|
|
|
|
const entityTypeIds = ['global', ...Object.keys(entitySettings.getEntityTypesWithPermissions())];
|
|
|
|
for (const entityTypeId of entityTypeIds) {
|
|
const roles = config.roles[entityTypeId];
|
|
|
|
for (const role in roles) {
|
|
await tx('generated_role_names').insert({
|
|
entity_type: entityTypeId,
|
|
role,
|
|
name: roles[role].name,
|
|
description: roles[role].description,
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
function throwPermissionDenied() {
|
|
throw new interoperableErrors.PermissionDeniedError('Permission denied');
|
|
}
|
|
|
|
async function removeDefaultShares(tx, user) {
|
|
const namespaceEntityType = entitySettings.getEntityType('namespace');
|
|
|
|
const roleConf = config.roles.global[user.role];
|
|
|
|
if (roleConf) {
|
|
const desiredRole = roleConf.rootNamespaceRole;
|
|
|
|
if (roleConf.ownNamespaceRole) {
|
|
await tx(namespaceEntityType.sharesTable).where({ user: user.id, entity: user.namespace }).del();
|
|
}
|
|
|
|
if (roleConf.rootNamespaceRole) {
|
|
await tx(namespaceEntityType.sharesTable).where({ user: user.id, entity: getGlobalNamespaceId() }).del();
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkGlobalPermission(context, requiredOperations) {
|
|
if (!context.user) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof requiredOperations === 'string') {
|
|
requiredOperations = [ requiredOperations ];
|
|
}
|
|
|
|
if (context.user.restrictedAccessHandler) {
|
|
const originalRequiredOperations = requiredOperations;
|
|
const allowedPerms = context.user.restrictedAccessHandler.globalPermissions;
|
|
if (allowedPerms) {
|
|
requiredOperations = requiredOperations.filter(perm => allowedPerms.has(perm));
|
|
} else {
|
|
requiredOperations = [];
|
|
}
|
|
log.verbose('check global permissions with restrictedAccessHandler -- requiredOperations: [' + originalRequiredOperations + '] -> [' + requiredOperations + ']');
|
|
}
|
|
|
|
if (requiredOperations.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
if (context.user.admin) { // This handles the getAdminContext() case
|
|
return true;
|
|
}
|
|
|
|
const roleSpec = config.roles.global[context.user.role];
|
|
let success = false;
|
|
if (roleSpec) {
|
|
for (const requiredOperation of requiredOperations) {
|
|
if (roleSpec.permissions.includes(requiredOperation)) {
|
|
success = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
function enforceGlobalPermission(context, requiredOperations) {
|
|
if (!checkGlobalPermission(context, requiredOperations)) {
|
|
throwPermissionDenied();
|
|
}
|
|
}
|
|
|
|
async function _checkPermissionTx(tx, context, entityTypeId, entityId, requiredOperations) {
|
|
if (!context.user) {
|
|
return false;
|
|
}
|
|
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
|
|
if (typeof requiredOperations === 'string') {
|
|
requiredOperations = [ requiredOperations ];
|
|
}
|
|
|
|
if (context.user.restrictedAccessHandler) {
|
|
const originalRequiredOperations = requiredOperations;
|
|
if (context.user.restrictedAccessHandler.permissions) {
|
|
const entityPerms = context.user.restrictedAccessHandler.permissions[entityTypeId];
|
|
|
|
if (!entityPerms) {
|
|
requiredOperations = [];
|
|
} else if (entityPerms === true) {
|
|
// no change to require operations
|
|
} else if (entityPerms instanceof Set) {
|
|
requiredOperations = requiredOperations.filter(perm => entityPerms.has(perm));
|
|
} else {
|
|
const allowedPerms = entityPerms[entityId];
|
|
if (allowedPerms) {
|
|
requiredOperations = requiredOperations.filter(perm => allowedPerms.has(perm));
|
|
} else {
|
|
requiredOperations = [];
|
|
}
|
|
}
|
|
} else {
|
|
requiredOperations = [];
|
|
}
|
|
log.verbose('check permissions with restrictedAccessHandler -- entityTypeId: ' + entityTypeId + ' entityId: ' + entityId + ' requiredOperations: [' + originalRequiredOperations + '] -> [' + requiredOperations + ']');
|
|
}
|
|
|
|
if (requiredOperations.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
if (context.user.admin) { // This handles the getAdminContext() case. In this case we don't check the permission, but just the existence.
|
|
const existsQuery = tx(entityType.entitiesTable);
|
|
|
|
if (entityId) {
|
|
existsQuery.where('id', entityId);
|
|
}
|
|
|
|
const exists = await existsQuery.first();
|
|
|
|
return !!exists;
|
|
|
|
} else {
|
|
const permsQuery = tx(entityType.permissionsTable)
|
|
.where('user', context.user.id)
|
|
.whereIn('operation', requiredOperations);
|
|
|
|
if (entityId) {
|
|
permsQuery.andWhere('entity', entityId);
|
|
}
|
|
|
|
const perms = await permsQuery.first();
|
|
|
|
return !!perms;
|
|
}
|
|
}
|
|
|
|
async function checkEntityPermission(context, entityTypeId, entityId, requiredOperations) {
|
|
if (!entityId) {
|
|
return false;
|
|
}
|
|
|
|
return await knex.transaction(async tx => {
|
|
return await _checkPermissionTx(tx, context, entityTypeId, entityId, requiredOperations);
|
|
});
|
|
}
|
|
|
|
async function checkEntityPermissionTx(tx, context, entityTypeId, entityId, requiredOperations) {
|
|
if (!entityId) {
|
|
return false;
|
|
}
|
|
|
|
return await _checkPermissionTx(tx, context, entityTypeId, entityId, requiredOperations);
|
|
}
|
|
|
|
async function checkTypePermission(context, entityTypeId, requiredOperations) {
|
|
return await knex.transaction(async tx => {
|
|
return await _checkPermissionTx(tx, context, entityTypeId, null, requiredOperations);
|
|
});
|
|
}
|
|
|
|
async function enforceEntityPermission(context, entityTypeId, entityId, requiredOperations) {
|
|
if (!entityId) {
|
|
throwPermissionDenied();
|
|
}
|
|
await knex.transaction(async tx => {
|
|
const result = await _checkPermissionTx(tx, context, entityTypeId, entityId, requiredOperations);
|
|
if (!result) {
|
|
log.info(`Denying permission ${entityTypeId}.${entityId} ${requiredOperations}`);
|
|
throwPermissionDenied();
|
|
}
|
|
});
|
|
}
|
|
|
|
async function enforceEntityPermissionTx(tx, context, entityTypeId, entityId, requiredOperations) {
|
|
if (!entityId) {
|
|
throwPermissionDenied();
|
|
}
|
|
const result = await _checkPermissionTx(tx, context, entityTypeId, entityId, requiredOperations);
|
|
if (!result) {
|
|
log.info(`Denying permission ${entityTypeId}.${entityId} ${requiredOperations}`);
|
|
throwPermissionDenied();
|
|
}
|
|
}
|
|
|
|
async function enforceTypePermission(context, entityTypeId, requiredOperations) {
|
|
await knex.transaction(async tx => {
|
|
const result = await _checkPermissionTx(tx, context, entityTypeId, null, requiredOperations);
|
|
if (!result) {
|
|
log.info(`Denying permission ${entityTypeId} ${requiredOperations}`);
|
|
throwPermissionDenied();
|
|
}
|
|
});
|
|
}
|
|
|
|
async function enforceTypePermissionTx(tx, context, entityTypeId, requiredOperations) {
|
|
const result = await _checkPermissionTx(tx, context, entityTypeId, null, requiredOperations);
|
|
if (!result) {
|
|
log.info(`Denying permission ${entityTypeId} ${requiredOperations}`);
|
|
throwPermissionDenied();
|
|
}
|
|
}
|
|
|
|
function getGlobalPermissions(context) {
|
|
if (!context.user) {
|
|
return [];
|
|
}
|
|
|
|
enforce(!context.user.admin, 'getPermissions is not supposed to be called by assumed admin');
|
|
|
|
return (config.roles.global[context.user.role] || {}).permissions || [];
|
|
}
|
|
|
|
async function getPermissionsTx(tx, context, entityTypeId, entityId) {
|
|
if (!context.user) {
|
|
return [];
|
|
}
|
|
|
|
enforce(!context.user.admin, 'getPermissions is not supposed to be called by assumed admin');
|
|
|
|
const entityType = entitySettings.getEntityType(entityTypeId);
|
|
|
|
const rows = await tx(entityType.permissionsTable)
|
|
.select('operation')
|
|
.where('entity', entityId)
|
|
.where('user', context.user.id);
|
|
|
|
return rows.map(x => x.operation);
|
|
}
|
|
|
|
module.exports.listByEntityDTAjax = listByEntityDTAjax;
|
|
module.exports.listByUserDTAjax = listByUserDTAjax;
|
|
module.exports.listUnassignedUsersDTAjax = listUnassignedUsersDTAjax;
|
|
module.exports.listRolesDTAjax = listRolesDTAjax;
|
|
module.exports.assign = assign;
|
|
module.exports.rebuildPermissionsTx = rebuildPermissionsTx;
|
|
module.exports.rebuildPermissions = rebuildPermissions;
|
|
module.exports.removeDefaultShares = removeDefaultShares;
|
|
module.exports.enforceEntityPermission = enforceEntityPermission;
|
|
module.exports.enforceEntityPermissionTx = enforceEntityPermissionTx;
|
|
module.exports.enforceTypePermission = enforceTypePermission;
|
|
module.exports.enforceTypePermissionTx = enforceTypePermissionTx;
|
|
module.exports.checkEntityPermissionTx = checkEntityPermissionTx;
|
|
module.exports.checkEntityPermission = checkEntityPermission;
|
|
module.exports.checkTypePermission = checkTypePermission;
|
|
module.exports.enforceGlobalPermission = enforceGlobalPermission;
|
|
module.exports.checkGlobalPermission = checkGlobalPermission;
|
|
module.exports.throwPermissionDenied = throwPermissionDenied;
|
|
module.exports.regenerateRoleNamesTable = regenerateRoleNamesTable;
|
|
module.exports.getGlobalPermissions = getGlobalPermissions;
|
|
module.exports.getPermissionsTx = getPermissionsTx;
|