mirror of
https://github.com/strapi/strapi.git
synced 2025-07-23 09:00:19 +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');
|
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);
|
const sanitizedPermissions = permissions.map(permissionService.sanitizePermission);
|
||||||
|
|
||||||
|
@ -182,7 +182,6 @@ const cleanPermissionsInDatabase = async () => {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createMany,
|
createMany,
|
||||||
update,
|
|
||||||
findMany,
|
findMany,
|
||||||
deleteByRolesIds,
|
deleteByRolesIds,
|
||||||
deleteByIds,
|
deleteByIds,
|
||||||
|
@ -1,22 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const {
|
const { set, omit, pick, prop, isArray, differenceWith, differenceBy } = require('lodash/fp');
|
||||||
set,
|
|
||||||
omit,
|
|
||||||
pick,
|
|
||||||
prop,
|
|
||||||
isArray,
|
|
||||||
differenceWith,
|
|
||||||
differenceBy,
|
|
||||||
flow,
|
|
||||||
map,
|
|
||||||
} = require('lodash/fp');
|
|
||||||
const deepEqual = require('fast-deep-equal');
|
const deepEqual = require('fast-deep-equal');
|
||||||
const {
|
const {
|
||||||
generateTimestampCode,
|
generateTimestampCode,
|
||||||
stringIncludes,
|
stringIncludes,
|
||||||
mapAsync,
|
|
||||||
hooks: { createAsyncSeriesWaterfallHook },
|
hooks: { createAsyncSeriesWaterfallHook },
|
||||||
} = require('@strapi/utils');
|
} = require('@strapi/utils');
|
||||||
const { ApplicationError } = require('@strapi/utils').errors;
|
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
|
* Assign permissions to a role
|
||||||
* @param {string|int} roleId - role ID
|
* @param {string|int} roleId - role ID
|
||||||
@ -406,6 +323,13 @@ const partialPermissionUpdate = async (roleId, permissions = {}) => {
|
|||||||
const assignPermissions = async (roleId, permissions = []) => {
|
const assignPermissions = async (roleId, permissions = []) => {
|
||||||
await validatePermissionsExist(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 superAdmin = await getService('role').getSuperAdmin();
|
||||||
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
||||||
const assignRole = set('role', roleId);
|
const assignRole = set('role', roleId);
|
||||||
@ -425,13 +349,13 @@ const assignPermissions = async (roleId, permissions = []) => {
|
|||||||
arePermissionsEqual,
|
arePermissionsEqual,
|
||||||
permissionsWithRole,
|
permissionsWithRole,
|
||||||
existingPermissions
|
existingPermissions
|
||||||
);
|
).filter((permission) => !internalActions.includes(permission.action));
|
||||||
|
|
||||||
const permissionsToDelete = differenceWith(
|
const permissionsToDelete = differenceWith(
|
||||||
arePermissionsEqual,
|
arePermissionsEqual,
|
||||||
existingPermissions,
|
existingPermissions,
|
||||||
permissionsWithRole
|
permissionsWithRole
|
||||||
);
|
).filter((permission) => !internalActions.includes(permission.action));
|
||||||
|
|
||||||
const permissionsToReturn = differenceBy('id', permissionsToDelete, existingPermissions);
|
const permissionsToReturn = differenceBy('id', permissionsToDelete, existingPermissions);
|
||||||
|
|
||||||
@ -463,22 +387,6 @@ const addPermissions = async (roleId, permissions) => {
|
|||||||
return createMany(permissionsWithRole);
|
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;
|
const isContentTypeAction = (action) => action.section === CONTENT_TYPE_SECTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -554,7 +462,6 @@ module.exports = {
|
|||||||
displayWarningIfNoSuperAdmin,
|
displayWarningIfNoSuperAdmin,
|
||||||
addPermissions,
|
addPermissions,
|
||||||
hasSuperAdminRole,
|
hasSuperAdminRole,
|
||||||
partialPermissionUpdate,
|
|
||||||
assignPermissions,
|
assignPermissions,
|
||||||
resetSuperAdminPermissions,
|
resetSuperAdminPermissions,
|
||||||
checkRolesIdForDeletion,
|
checkRolesIdForDeletion,
|
||||||
|
@ -4,21 +4,6 @@ const { yup, validateYupSchema } = require('@strapi/utils');
|
|||||||
const { getService } = require('../utils');
|
const { getService } = require('../utils');
|
||||||
const validators = require('./common-validators');
|
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({
|
const checkPermissionsSchema = yup.object().shape({
|
||||||
permissions: yup.array().of(
|
permissions: yup.array().of(
|
||||||
yup
|
yup
|
||||||
@ -61,9 +46,8 @@ const actionsExistSchema = yup
|
|||||||
.test('actions-exist', '', checkPermissionsExist);
|
.test('actions-exist', '', checkPermissionsExist);
|
||||||
|
|
||||||
// exports
|
// exports
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validatedUpdatePermissionsInput: validateYupSchema(updatePermissions),
|
validatedUpdatePermissionsInput: validateYupSchema(validators.updatePermissions),
|
||||||
validatePermissionsExist: validateYupSchema(actionsExistSchema),
|
validatePermissionsExist: validateYupSchema(actionsExistSchema),
|
||||||
validateCheckPermissionsInput: validateYupSchema(checkPermissionsSchema),
|
validateCheckPermissionsInput: validateYupSchema(checkPermissionsSchema),
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user