2020-05-29 17:23:42 +02:00
|
|
|
'use strict';
|
|
|
|
|
2020-06-11 10:54:26 +02:00
|
|
|
const _ = require('lodash');
|
2020-05-28 13:02:06 +02:00
|
|
|
const { createPermission } = require('../domain/permission');
|
2020-06-22 13:00:21 +02:00
|
|
|
const actionProvider = require('./permission/action-provider');
|
2020-06-09 17:45:53 +02:00
|
|
|
const { validatePermissionsExist } = require('../validation/permission');
|
2020-06-09 19:00:57 +02:00
|
|
|
const createConditionProvider = require('./permission/condition-provider');
|
|
|
|
const createPermissionEngine = require('./permission/engine');
|
|
|
|
|
2020-06-16 11:13:01 +02:00
|
|
|
const conditionProvider = createConditionProvider();
|
2020-06-09 19:00:57 +02:00
|
|
|
const engine = createPermissionEngine(conditionProvider);
|
2020-05-28 13:02:06 +02:00
|
|
|
|
2020-06-22 13:00:21 +02:00
|
|
|
const fieldsToCompare = ['action', 'subject', 'fields', 'conditions'];
|
2020-06-23 16:31:16 +02:00
|
|
|
const getPermissionWithSortedFields = perm => {
|
|
|
|
const sortedPerm = _.cloneDeep(perm);
|
|
|
|
if (Array.isArray(sortedPerm.fields)) {
|
|
|
|
sortedPerm.fields.sort();
|
|
|
|
}
|
|
|
|
return sortedPerm;
|
|
|
|
};
|
2020-06-22 13:00:21 +02:00
|
|
|
const arePermissionsEqual = (perm1, perm2) =>
|
2020-06-23 16:31:16 +02:00
|
|
|
_.isEqual(
|
|
|
|
_.pick(getPermissionWithSortedFields(perm1), fieldsToCompare),
|
|
|
|
_.pick(getPermissionWithSortedFields(perm2), fieldsToCompare)
|
|
|
|
);
|
2020-06-22 13:00:21 +02:00
|
|
|
|
2020-05-29 17:23:42 +02:00
|
|
|
/**
|
|
|
|
* Delete permissions of roles in database
|
2020-06-08 15:13:26 +02:00
|
|
|
* @param rolesIds ids of roles
|
2020-05-29 17:23:42 +02:00
|
|
|
* @returns {Promise<array>}
|
|
|
|
*/
|
2020-05-29 11:09:17 +02:00
|
|
|
const deleteByRolesIds = rolesIds => {
|
|
|
|
return strapi.query('permission', 'admin').delete({ role_in: rolesIds });
|
|
|
|
};
|
|
|
|
|
2020-06-08 15:13:26 +02:00
|
|
|
/**
|
|
|
|
* Delete permissions
|
|
|
|
* @param ids ids of permissions
|
|
|
|
* @returns {Promise<array>}
|
|
|
|
*/
|
|
|
|
const deleteByIds = ids => {
|
|
|
|
return strapi.query('permission', 'admin').delete({ id_in: ids });
|
|
|
|
};
|
|
|
|
|
2020-05-28 11:29:59 +02:00
|
|
|
/**
|
|
|
|
* Find assigned permissions in the database
|
|
|
|
* @param params query params to find the permissions
|
|
|
|
* @returns {Promise<array<Object>>}
|
|
|
|
*/
|
|
|
|
const find = (params = {}) => {
|
|
|
|
return strapi.query('permission', 'admin').find(params, []);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2020-06-01 11:00:00 +02:00
|
|
|
* Assign permissions to a role
|
2020-06-15 19:11:36 +02:00
|
|
|
* @param {string|int} roleId - role ID
|
2020-05-28 11:29:59 +02:00
|
|
|
* @param {Array<Permission{action,subject,fields,conditions}>} permissions - permissions to assign to the role
|
|
|
|
*/
|
2020-06-15 19:11:36 +02:00
|
|
|
const assign = async (roleId, permissions = []) => {
|
2020-06-09 17:45:53 +02:00
|
|
|
try {
|
|
|
|
await validatePermissionsExist(permissions);
|
|
|
|
} catch (err) {
|
|
|
|
throw strapi.errors.badRequest('ValidationError', err);
|
2020-06-04 18:30:26 +02:00
|
|
|
}
|
2020-05-28 11:29:59 +02:00
|
|
|
|
2020-06-22 13:00:21 +02:00
|
|
|
const permissionsWithRole = permissions.map(permission =>
|
|
|
|
createPermission({ ...permission, role: roleId })
|
|
|
|
);
|
|
|
|
|
|
|
|
const existingPermissions = await find({ role: roleId, _limit: -1 });
|
|
|
|
const permissionsToAdd = _.differenceWith(
|
|
|
|
permissionsWithRole,
|
|
|
|
existingPermissions,
|
|
|
|
arePermissionsEqual
|
|
|
|
);
|
|
|
|
const permissionsToDelete = _.differenceWith(
|
|
|
|
existingPermissions,
|
|
|
|
permissionsWithRole,
|
|
|
|
arePermissionsEqual
|
|
|
|
);
|
2020-06-23 16:31:16 +02:00
|
|
|
const permissionsToReturn = _.differenceBy(existingPermissions, permissionsToDelete, 'id');
|
2020-06-22 13:00:21 +02:00
|
|
|
|
|
|
|
if (permissionsToDelete.length > 0) {
|
|
|
|
await deleteByIds(permissionsToDelete.map(p => p.id));
|
|
|
|
}
|
|
|
|
if (permissionsToAdd.length > 0) {
|
2020-06-23 16:31:16 +02:00
|
|
|
const createdPermissions = await strapi
|
|
|
|
.query('permission', 'admin')
|
|
|
|
.createMany(permissionsToAdd);
|
|
|
|
permissionsToReturn.push(...createdPermissions.map(p => ({ ...p, role: p.role.id })));
|
2020-06-22 13:00:21 +02:00
|
|
|
}
|
2020-05-28 11:29:59 +02:00
|
|
|
|
2020-06-23 16:31:16 +02:00
|
|
|
return permissionsToReturn;
|
2020-05-28 11:29:59 +02:00
|
|
|
};
|
|
|
|
|
2020-06-12 10:28:14 +02:00
|
|
|
/**
|
|
|
|
* Find all permissions for a user
|
|
|
|
* @param roles
|
|
|
|
* @returns {Promise<*[]|*>}
|
|
|
|
*/
|
2020-06-11 10:54:26 +02:00
|
|
|
const findUserPermissions = async ({ roles }) => {
|
|
|
|
if (!_.isArray(roles)) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2020-06-22 13:00:21 +02:00
|
|
|
return strapi
|
|
|
|
.query('permission', 'admin')
|
|
|
|
.find({ role_in: roles.map(_.property('id')), _limit: -1 });
|
2020-06-11 10:54:26 +02:00
|
|
|
};
|
|
|
|
|
2020-06-12 10:28:14 +02:00
|
|
|
/**
|
|
|
|
* Removes unwanted fields from a permission
|
|
|
|
* @param permission
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
2020-06-11 10:54:26 +02:00
|
|
|
const sanitizePermission = permission =>
|
|
|
|
_.pick(permission, ['action', 'subject', 'fields', 'conditions']);
|
|
|
|
|
2020-06-23 16:31:16 +02:00
|
|
|
/**
|
|
|
|
* Removes permissions in database that don't exist anymore
|
2020-06-24 14:09:43 +02:00
|
|
|
* @returns {Promise<>}
|
2020-06-23 16:31:16 +02:00
|
|
|
*/
|
|
|
|
const cleanPermissionInDatabase = async () => {
|
|
|
|
const dbPermissions = await find();
|
|
|
|
const allActionsMap = actionProvider.getAllByMap();
|
|
|
|
const permissionsToRemoveIds = [];
|
|
|
|
|
|
|
|
dbPermissions.forEach(perm => {
|
|
|
|
if (
|
|
|
|
!allActionsMap.has(perm.action) ||
|
|
|
|
(Array.isArray(allActionsMap.get(perm.action).subjects) &&
|
|
|
|
!allActionsMap.get(perm.action).subjects.includes(perm.subject))
|
|
|
|
) {
|
|
|
|
permissionsToRemoveIds.push(perm.id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
await deleteByIds(permissionsToRemoveIds);
|
|
|
|
};
|
|
|
|
|
2020-06-24 14:09:43 +02:00
|
|
|
/**
|
|
|
|
* Reset super admin permissions (giving it all permissions)
|
|
|
|
* @returns {Promise<>}
|
|
|
|
*/
|
|
|
|
const resetSuperAdminPermissions = async () => {
|
|
|
|
const superAdminRole = await strapi.admin.services.role.getSuperAdmin();
|
|
|
|
if (!superAdminRole) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const allActions = strapi.admin.services.permission.actionProvider.getAll();
|
|
|
|
const contentTypesActions = allActions.filter(a => a.section === 'contentTypes');
|
|
|
|
|
|
|
|
const permissions = strapi.admin.services[
|
|
|
|
'content-type'
|
|
|
|
].getPermissionsWithNestedFields(contentTypesActions, 1, {
|
|
|
|
fieldsNullFor: ['plugins::content-manager.explorer.delete'],
|
|
|
|
});
|
|
|
|
|
|
|
|
const otherActions = allActions.filter(a => a.section !== 'contentTypes');
|
|
|
|
otherActions.forEach(action => {
|
|
|
|
if (action.subjects) {
|
|
|
|
const newPerms = action.subjects.map(subject =>
|
|
|
|
createPermission({ action: action.actionId, subject })
|
|
|
|
);
|
|
|
|
permissions.push(...newPerms);
|
|
|
|
} else {
|
|
|
|
permissions.push(createPermission({ action: action.actionId }));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
await assign(superAdminRole.id, permissions);
|
|
|
|
};
|
|
|
|
|
2020-05-29 11:09:17 +02:00
|
|
|
module.exports = {
|
2020-05-28 11:29:59 +02:00
|
|
|
find,
|
2020-05-29 11:09:17 +02:00
|
|
|
deleteByRolesIds,
|
2020-06-08 15:13:26 +02:00
|
|
|
deleteByIds,
|
2020-05-28 11:29:59 +02:00
|
|
|
assign,
|
2020-06-11 10:54:26 +02:00
|
|
|
sanitizePermission,
|
|
|
|
findUserPermissions,
|
2020-06-09 19:00:57 +02:00
|
|
|
actionProvider,
|
|
|
|
engine,
|
|
|
|
conditionProvider,
|
2020-06-23 16:31:16 +02:00
|
|
|
cleanPermissionInDatabase,
|
2020-06-24 14:09:43 +02:00
|
|
|
resetSuperAdminPermissions,
|
2020-05-29 11:09:17 +02:00
|
|
|
};
|