From e53cb36ee2f408f3bc85711ccd2e2b464efa223c Mon Sep 17 00:00:00 2001 From: Jamie Howard Date: Tue, 12 Sep 2023 15:40:23 +0100 Subject: [PATCH] feature(ee): migrate stages into RBAC versions --- .../review-workflows-stages-roles.js | 54 +++++++++++++++++++ packages/core/admin/ee/server/register.js | 2 + .../review-workflows/stage-permissions.js | 2 +- .../services/review-workflows/stages.js | 12 ++++- 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 packages/core/admin/ee/server/migrations/review-workflows-stages-roles.js diff --git a/packages/core/admin/ee/server/migrations/review-workflows-stages-roles.js b/packages/core/admin/ee/server/migrations/review-workflows-stages-roles.js new file mode 100644 index 0000000000..596428e450 --- /dev/null +++ b/packages/core/admin/ee/server/migrations/review-workflows-stages-roles.js @@ -0,0 +1,54 @@ +'use strict'; + +const { STAGE_TRANSITION_UID, STAGE_MODEL_UID } = require('../constants/workflows'); +const { getService } = require('../utils'); + +async function migrateReviewWorkflowStagesRoles({ oldContentTypes, contentTypes }) { + const stageUID = 'admin::workflow-stage'; + const hadRolePermissions = !!oldContentTypes?.[stageUID]?.attributes?.permissions; + const hasRolePermissions = !!contentTypes?.[stageUID]?.attributes?.permissions; + + // If the stage content type did not have permissions in the previous version + // then we set the permissions of every stage to be every current role in the app. + // This ensures consistent behaviour when upgrading to a strapi version with review workflows RBAC. + if (!hadRolePermissions && hasRolePermissions) { + const stagePermissionsService = getService('stage-permissions'); + + const stages = await strapi.query(stageUID).findMany(); + const roles = await strapi.query('admin::role').findMany(); + + // Collect the permissions to add and group them by stage id. + const groupedPermissions = {}; + roles + .map((role) => role.id) + .forEach((id) => { + stages + .map((stage) => stage.id) + .forEach((stageId) => { + if (!groupedPermissions[stageId]) { + groupedPermissions[stageId] = []; + } + + groupedPermissions[stageId].push({ + roleId: id, + fromStage: stageId, + action: STAGE_TRANSITION_UID, + }); + }); + }); + + for (const [stageId, permissions] of Object.entries(groupedPermissions)) { + // Register the permissions for this stage + const stagePermissions = await stagePermissionsService.registerMany(permissions); + + // Update the stage with its new permissions + await strapi.entityService.update(STAGE_MODEL_UID, Number(stageId), { + data: { + permissions: stagePermissions.flat().map((p) => p.id), + }, + }); + } + } +} + +module.exports = migrateReviewWorkflowStagesRoles; diff --git a/packages/core/admin/ee/server/register.js b/packages/core/admin/ee/server/register.js index e700b2ec34..1aa236c4a8 100644 --- a/packages/core/admin/ee/server/register.js +++ b/packages/core/admin/ee/server/register.js @@ -4,6 +4,7 @@ const { features } = require('@strapi/strapi/lib/utils/ee'); const executeCERegister = require('../../server/register'); const migrateAuditLogsTable = require('./migrations/audit-logs-table'); const migrateReviewWorkflowStagesColor = require('./migrations/review-workflows-stages-color'); +const migrateReviewWorkflowStagesRoles = require('./migrations/review-workflows-stages-roles'); const migrateReviewWorkflowName = require('./migrations/review-workflows-workflow-name'); const migrateWorkflowsContentTypes = require('./migrations/review-workflows-content-types'); const migrateStageAttribute = require('./migrations/review-workflows-stage-attribute'); @@ -26,6 +27,7 @@ module.exports = async ({ strapi }) => { strapi .hook('strapi::content-types.afterSync') .register(migrateReviewWorkflowStagesColor) + .register(migrateReviewWorkflowStagesRoles) .register(migrateReviewWorkflowName) .register(migrateWorkflowsContentTypes) .register(migrateDeletedCTInWorkflows); diff --git a/packages/core/admin/ee/server/services/review-workflows/stage-permissions.js b/packages/core/admin/ee/server/services/review-workflows/stage-permissions.js index 15035c74eb..4c15ee51ae 100644 --- a/packages/core/admin/ee/server/services/review-workflows/stage-permissions.js +++ b/packages/core/admin/ee/server/services/review-workflows/stage-permissions.js @@ -15,7 +15,7 @@ module.exports = ({ strapi }) => { const permissionService = getService('permission'); return { - async register(roleId, action, fromStage) { + async register({ roleId, action, fromStage }) { if (!validActions.includes(action)) { throw new ApplicationError(`Invalid action ${action}`); } diff --git a/packages/core/admin/ee/server/services/review-workflows/stages.js b/packages/core/admin/ee/server/services/review-workflows/stages.js index 4661a5db8f..79128168d4 100644 --- a/packages/core/admin/ee/server/services/review-workflows/stages.js +++ b/packages/core/admin/ee/server/services/review-workflows/stages.js @@ -61,7 +61,11 @@ module.exports = ({ strapi }) => { stagePermissions, // Register each stage permission (permission) => - stagePermissionsService.register(permission.role, permission.action, stageId) + stagePermissionsService.register({ + roleId: permission.role, + action: permission.action, + fromStage: stageId, + }) ); // Update stage with the new permissions @@ -85,7 +89,11 @@ module.exports = ({ strapi }) => { await this.deleteStagePermissions([srcStage]); const permissions = await mapAsync(destStage.permissions, (permission) => - stagePermissionsService.register(permission.role, permission.action, stageId) + stagePermissionsService.register({ + roleId: permission.role, + action: permission.action, + fromStage: stageId, + }) ); stagePermissions = permissions.flat().map((p) => p.id); }