mirror of
https://github.com/strapi/strapi.git
synced 2025-07-23 00:51:17 +00:00
feat: filter out internal actions instead of doing partial updates
This commit is contained in:
parent
71ab6118cf
commit
37a9af1953
@ -146,7 +146,7 @@ module.exports = {
|
||||
return ctx.notFound('role.notFound');
|
||||
}
|
||||
|
||||
const permissions = await roleService.partialPermissionUpdate(role.id, input.permissions);
|
||||
const permissions = await roleService.assignPermissions(role.id, input.permissions);
|
||||
|
||||
const sanitizedPermissions = permissions.map(permissionService.sanitizePermission);
|
||||
|
||||
|
@ -182,7 +182,6 @@ const cleanPermissionsInDatabase = async () => {
|
||||
|
||||
module.exports = {
|
||||
createMany,
|
||||
update,
|
||||
findMany,
|
||||
deleteByRolesIds,
|
||||
deleteByIds,
|
||||
|
@ -1,22 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
set,
|
||||
omit,
|
||||
pick,
|
||||
prop,
|
||||
isArray,
|
||||
differenceWith,
|
||||
differenceBy,
|
||||
flow,
|
||||
map,
|
||||
} = require('lodash/fp');
|
||||
const { set, omit, pick, prop, isArray, differenceWith, differenceBy } = require('lodash/fp');
|
||||
const deepEqual = require('fast-deep-equal');
|
||||
const {
|
||||
generateTimestampCode,
|
||||
stringIncludes,
|
||||
mapAsync,
|
||||
hooks: { createAsyncSeriesWaterfallHook },
|
||||
} = require('@strapi/utils');
|
||||
const { ApplicationError } = require('@strapi/utils').errors;
|
||||
@ -326,78 +315,6 @@ const displayWarningIfNoSuperAdmin = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Partially update a role permissions in database.
|
||||
* Permissions will use the format of:
|
||||
* {
|
||||
* connect: [permission1, permission2],
|
||||
* disconnect: [permission3, permission4]
|
||||
* }
|
||||
*
|
||||
* @param {*} roleId
|
||||
* @param {*} permissions
|
||||
*/
|
||||
const partialPermissionUpdate = async (roleId, permissions = {}) => {
|
||||
const superAdmin = await getService('role').getSuperAdmin();
|
||||
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
||||
const permissionsWithRole = flow(
|
||||
map(set('role', roleId)), // Assign role
|
||||
map(permissionDomain.create) // Map permission to domain
|
||||
);
|
||||
|
||||
const connect = permissionsWithRole(permissions.connect) || [];
|
||||
const disconnect = permissionsWithRole(permissions.disconnect) || [];
|
||||
|
||||
await validatePermissionsExist(connect);
|
||||
|
||||
const permissionsToCreate = connect.filter((permission) => !permission.id);
|
||||
const permissionsToUpdate = connect.filter((permission) => permission.id);
|
||||
const permissionsToDelete = disconnect;
|
||||
|
||||
const existingPermissions = await getService('permission').findMany({
|
||||
where: { role: { id: roleId } },
|
||||
populate: ['role'],
|
||||
});
|
||||
|
||||
// Find permissions that do not exist in db
|
||||
const invalidUpdatePermissions = differenceBy('id', permissionsToUpdate, existingPermissions);
|
||||
const invalidDeletePermissions = differenceBy('id', permissionsToDelete, existingPermissions);
|
||||
|
||||
if (invalidUpdatePermissions.length !== 0) {
|
||||
throw new ApplicationError('Some permissions to update do not exist');
|
||||
}
|
||||
|
||||
if (invalidDeletePermissions.length !== 0) {
|
||||
throw new ApplicationError('Some permissions to delete do not exist');
|
||||
}
|
||||
|
||||
// Array of final permissions to return
|
||||
const permissionsToReturn = differenceBy('id', existingPermissions, [
|
||||
...permissionsToDelete,
|
||||
...permissionsToUpdate,
|
||||
]);
|
||||
|
||||
if (permissionsToDelete.length > 0) {
|
||||
await getService('permission').deleteByIds(permissionsToDelete.map(prop('id')));
|
||||
}
|
||||
|
||||
if (permissionsToCreate.length > 0) {
|
||||
const newPermissions = await addPermissions(roleId, permissionsToCreate);
|
||||
permissionsToReturn.push(...newPermissions);
|
||||
}
|
||||
|
||||
if (permissionsToUpdate.length > 0) {
|
||||
const updatedPermissions = await updatePermissions(roleId, permissionsToUpdate);
|
||||
permissionsToReturn.push(...updatedPermissions);
|
||||
}
|
||||
|
||||
if (!isSuperAdmin && (connect.length || disconnect.length)) {
|
||||
await getService('metrics').sendDidUpdateRolePermissions();
|
||||
}
|
||||
|
||||
return permissionsToReturn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign permissions to a role
|
||||
* @param {string|int} roleId - role ID
|
||||
@ -406,6 +323,13 @@ const partialPermissionUpdate = async (roleId, permissions = {}) => {
|
||||
const assignPermissions = async (roleId, permissions = []) => {
|
||||
await validatePermissionsExist(permissions);
|
||||
|
||||
// Internal actions are not handled by the role service, so any permission
|
||||
// with an internal action is filtered out
|
||||
const internalActions = getService('permission')
|
||||
.actionProvider.values()
|
||||
.filter((action) => action.section === 'internal')
|
||||
.map((action) => action.actionId);
|
||||
|
||||
const superAdmin = await getService('role').getSuperAdmin();
|
||||
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
||||
const assignRole = set('role', roleId);
|
||||
@ -425,13 +349,13 @@ const assignPermissions = async (roleId, permissions = []) => {
|
||||
arePermissionsEqual,
|
||||
permissionsWithRole,
|
||||
existingPermissions
|
||||
);
|
||||
).filter((permission) => !internalActions.includes(permission.action));
|
||||
|
||||
const permissionsToDelete = differenceWith(
|
||||
arePermissionsEqual,
|
||||
existingPermissions,
|
||||
permissionsWithRole
|
||||
);
|
||||
).filter((permission) => !internalActions.includes(permission.action));
|
||||
|
||||
const permissionsToReturn = differenceBy('id', permissionsToDelete, existingPermissions);
|
||||
|
||||
@ -463,22 +387,6 @@ const addPermissions = async (roleId, permissions) => {
|
||||
return createMany(permissionsWithRole);
|
||||
};
|
||||
|
||||
const updatePermissions = async (roleId, permissions) => {
|
||||
// TODO: Update many
|
||||
const { conditionProvider, update } = getService('permission');
|
||||
const { sanitizeConditions } = permissionDomain;
|
||||
|
||||
const permissionsWithRole = permissions
|
||||
.map(set('role', roleId))
|
||||
.map(sanitizeConditions(conditionProvider))
|
||||
.map(permissionDomain.create);
|
||||
|
||||
return mapAsync(permissionsWithRole, (permission) => {
|
||||
const { id, ...attributes } = permission;
|
||||
return update({ id }, attributes);
|
||||
});
|
||||
};
|
||||
|
||||
const isContentTypeAction = (action) => action.section === CONTENT_TYPE_SECTION;
|
||||
|
||||
/**
|
||||
@ -554,7 +462,6 @@ module.exports = {
|
||||
displayWarningIfNoSuperAdmin,
|
||||
addPermissions,
|
||||
hasSuperAdminRole,
|
||||
partialPermissionUpdate,
|
||||
assignPermissions,
|
||||
resetSuperAdminPermissions,
|
||||
checkRolesIdForDeletion,
|
||||
|
@ -4,21 +4,6 @@ const { yup, validateYupSchema } = require('@strapi/utils');
|
||||
const { getService } = require('../utils');
|
||||
const validators = require('./common-validators');
|
||||
|
||||
const updatePermissions = yup.object().shape({
|
||||
permissions: yup
|
||||
.object()
|
||||
.shape({
|
||||
connect: yup.array().of(
|
||||
yup.object().shape({
|
||||
id: yup.strapiID(), // If id is not provided, it will be generated
|
||||
...validators.permission.fields,
|
||||
})
|
||||
),
|
||||
disconnect: yup.array().of(yup.object().shape({ id: yup.strapiID().required() })),
|
||||
})
|
||||
.required(),
|
||||
});
|
||||
|
||||
const checkPermissionsSchema = yup.object().shape({
|
||||
permissions: yup.array().of(
|
||||
yup
|
||||
@ -61,9 +46,8 @@ const actionsExistSchema = yup
|
||||
.test('actions-exist', '', checkPermissionsExist);
|
||||
|
||||
// exports
|
||||
|
||||
module.exports = {
|
||||
validatedUpdatePermissionsInput: validateYupSchema(updatePermissions),
|
||||
validatedUpdatePermissionsInput: validateYupSchema(validators.updatePermissions),
|
||||
validatePermissionsExist: validateYupSchema(actionsExistSchema),
|
||||
validateCheckPermissionsInput: validateYupSchema(checkPermissionsSchema),
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user