@strapi/review-workflows 5.60.0 → 5.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/admin/components/Widgets.js +5 -1
  2. package/dist/admin/components/Widgets.js.map +1 -1
  3. package/dist/admin/components/Widgets.mjs +5 -1
  4. package/dist/admin/components/Widgets.mjs.map +1 -1
  5. package/dist/admin/routes/content-manager/model/components/StageFilter.js +1 -1
  6. package/dist/admin/routes/content-manager/model/components/StageFilter.js.map +1 -1
  7. package/dist/admin/routes/content-manager/model/components/StageFilter.mjs +1 -1
  8. package/dist/admin/routes/content-manager/model/components/StageFilter.mjs.map +1 -1
  9. package/dist/admin/routes/content-manager/model/components/TableColumns.js.map +1 -1
  10. package/dist/admin/routes/content-manager/model/components/TableColumns.mjs.map +1 -1
  11. package/dist/admin/routes/content-manager/model/constants.js +2 -2
  12. package/dist/admin/routes/content-manager/model/constants.js.map +1 -1
  13. package/dist/admin/routes/content-manager/model/constants.mjs +2 -2
  14. package/dist/admin/routes/content-manager/model/constants.mjs.map +1 -1
  15. package/dist/admin/routes/settings/index.js +1 -1
  16. package/dist/admin/routes/settings/index.js.map +1 -1
  17. package/dist/admin/routes/settings/index.mjs +1 -1
  18. package/dist/admin/routes/settings/index.mjs.map +1 -1
  19. package/dist/admin/src/routes/content-manager/model/components/TableColumns.d.ts +1 -6
  20. package/dist/server/constants/workflows.js +2 -1
  21. package/dist/server/constants/workflows.js.map +1 -1
  22. package/dist/server/constants/workflows.mjs +2 -1
  23. package/dist/server/constants/workflows.mjs.map +1 -1
  24. package/dist/server/controllers/stages.js +3 -0
  25. package/dist/server/controllers/stages.js.map +1 -1
  26. package/dist/server/controllers/stages.mjs +3 -0
  27. package/dist/server/controllers/stages.mjs.map +1 -1
  28. package/dist/server/services/document-service-middleware.js +28 -1
  29. package/dist/server/services/document-service-middleware.js.map +1 -1
  30. package/dist/server/services/document-service-middleware.mjs +28 -1
  31. package/dist/server/services/document-service-middleware.mjs.map +1 -1
  32. package/dist/server/services/stages.js +32 -14
  33. package/dist/server/services/stages.js.map +1 -1
  34. package/dist/server/services/stages.mjs +32 -14
  35. package/dist/server/services/stages.mjs.map +1 -1
  36. package/dist/server/services/workflow-content-types.js +7 -1
  37. package/dist/server/services/workflow-content-types.js.map +1 -1
  38. package/dist/server/services/workflow-content-types.mjs +7 -1
  39. package/dist/server/services/workflow-content-types.mjs.map +1 -1
  40. package/dist/server/services/workflows.js +44 -1
  41. package/dist/server/services/workflows.js.map +1 -1
  42. package/dist/server/services/workflows.mjs +45 -2
  43. package/dist/server/services/workflows.mjs.map +1 -1
  44. package/dist/server/src/constants/workflows.d.ts +1 -0
  45. package/dist/server/src/constants/workflows.d.ts.map +1 -1
  46. package/dist/server/src/controllers/index.d.ts +1 -1
  47. package/dist/server/src/controllers/stages.d.ts +1 -1
  48. package/dist/server/src/controllers/stages.d.ts.map +1 -1
  49. package/dist/server/src/index.d.ts +4 -4
  50. package/dist/server/src/index.d.ts.map +1 -1
  51. package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
  52. package/dist/server/src/services/index.d.ts +3 -3
  53. package/dist/server/src/services/index.d.ts.map +1 -1
  54. package/dist/server/src/services/stages.d.ts +3 -4
  55. package/dist/server/src/services/stages.d.ts.map +1 -1
  56. package/dist/server/src/services/workflow-content-types.d.ts.map +1 -1
  57. package/dist/server/src/services/workflows.d.ts +2 -1
  58. package/dist/server/src/services/workflows.d.ts.map +1 -1
  59. package/dist/shared/contracts/homepage.d.ts +5 -1
  60. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  61. package/package.json +8 -8
@@ -23,6 +23,16 @@ var stages = (({ strapi })=>{
23
23
  const workflowValidator = index.getService('validation', {
24
24
  strapi
25
25
  });
26
+ /**
27
+ * Returns the table linking the entities of a content type to their stage, or undefined when
28
+ * the content type no longer exists or has no stage attribute
29
+ */ const getEntityStageJoinTable = (contentTypeUID)=>{
30
+ if (strapi.db.metadata.has(contentTypeUID) === false) {
31
+ return undefined;
32
+ }
33
+ const { attributes } = strapi.db.metadata.get(contentTypeUID);
34
+ return attributes[workflows.ENTITY_STAGE_ATTRIBUTE]?.joinTable;
35
+ };
26
36
  return {
27
37
  find ({ workflowId, populate }) {
28
38
  return strapi.db.query(workflows.STAGE_MODEL_UID).findMany({
@@ -32,10 +42,13 @@ var stages = (({ strapi })=>{
32
42
  populate
33
43
  });
34
44
  },
35
- findById (id, { populate } = {}) {
45
+ findById (id, { workflowId, populate } = {}) {
36
46
  return strapi.db.query(workflows.STAGE_MODEL_UID).findOne({
37
- where: {
47
+ where: workflowId === undefined ? {
38
48
  id
49
+ } : {
50
+ id,
51
+ workflow: workflowId
39
52
  },
40
53
  populate
41
54
  });
@@ -178,7 +191,7 @@ var stages = (({ strapi })=>{
178
191
  deleted
179
192
  });
180
193
  // Update stages and assign entity stages
181
- return strapi.db.transaction(async ({ trx })=>{
194
+ return strapi.db.transaction(async ()=>{
182
195
  // Create the new stages
183
196
  const createdStages = await this.createMany(created, {
184
197
  fields: [
@@ -203,13 +216,12 @@ var stages = (({ strapi })=>{
203
216
  return !deleted.find((s)=>s.id === targetStage.id);
204
217
  });
205
218
  // Assign the new stage to entities that had the deleted stage
206
- await utils.async.map(contentTypesToMigrate, (contentTypeUID)=>{
207
- this.updateEntitiesStage(contentTypeUID, {
219
+ // Wait for it: deleting the stage also deletes its links to the entities.
220
+ // `strapi.db.transaction` reuses the current transaction.
221
+ await utils.async.map(contentTypesToMigrate, (contentTypeUID)=>this.updateEntitiesStage(contentTypeUID, {
208
222
  fromStageId: stage.id,
209
- toStageId: nearestStage.id,
210
- trx
211
- });
212
- });
223
+ toStageId: nearestStage.id
224
+ }));
213
225
  return this.delete(stage);
214
226
  });
215
227
  return destStages.map((stage)=>({
@@ -264,11 +276,14 @@ var stages = (({ strapi })=>{
264
276
  * @param {string} contentTypeUID
265
277
  * @param {number | undefined | null} fromStageId
266
278
  * @param {number} toStageId
267
- * @param {import('knex').Knex.Transaction} trx
268
279
  * @returns
269
280
  */ async updateEntitiesStage (contentTypeUID, { fromStageId, toStageId }) {
270
- const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID);
271
- const joinTable = attributes[workflows.ENTITY_STAGE_ATTRIBUTE].joinTable;
281
+ const joinTable = getEntityStageJoinTable(contentTypeUID);
282
+ // No entity can be linked to a stage
283
+ if (joinTable === undefined) {
284
+ return;
285
+ }
286
+ const { tableName } = strapi.db.metadata.get(contentTypeUID);
272
287
  const joinColumn = joinTable.joinColumn.name;
273
288
  const invJoinColumn = joinTable.inverseJoinColumn.name;
274
289
  await workflowValidator.validateWorkflowCount();
@@ -293,8 +308,11 @@ var stages = (({ strapi })=>{
293
308
  * @param {string} contentTypeUID
294
309
  * @returns
295
310
  */ async deleteAllEntitiesStage (contentTypeUID) {
296
- const { attributes } = strapi.db.metadata.get(contentTypeUID);
297
- const joinTable = attributes[workflows.ENTITY_STAGE_ATTRIBUTE].joinTable;
311
+ const joinTable = getEntityStageJoinTable(contentTypeUID);
312
+ // No entity can be linked to a stage
313
+ if (joinTable === undefined) {
314
+ return;
315
+ }
298
316
  // Delete all stage links for the content type
299
317
  return strapi.db.transaction(async ({ trx })=>strapi.db.getConnection().from(joinTable.name).delete().transacting(trx));
300
318
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stages.js","sources":["../../../server/src/services/stages.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\nimport { async, errors } from '@strapi/utils';\nimport { pick, map, isEqual } from 'lodash';\nimport type { StagePermission } from '../../../shared/contracts/review-workflows';\nimport { STAGE_MODEL_UID, ENTITY_STAGE_ATTRIBUTE, ERRORS } from '../constants/workflows';\nimport { getService } from '../utils';\n\ninterface PopulatedPermission {\n role: number | { id: number };\n action: string;\n actionParameters?: { from?: number; to?: number };\n}\n\nconst { ApplicationError, ValidationError } = errors;\nconst sanitizedStageFields = ['id', 'name', 'workflow', 'color'];\nconst sanitizeStageFields = (stage: Record<string, unknown>) => pick(stage, sanitizedStageFields);\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const metrics = getService('workflow-metrics', { strapi });\n const stagePermissionsService = getService('stage-permissions', { strapi });\n const workflowValidator = getService('validation', { strapi });\n\n return {\n find({ workflowId, populate }: any) {\n return strapi.db.query(STAGE_MODEL_UID).findMany({\n where: { workflow: workflowId },\n populate,\n });\n },\n\n findById(id: string | number, { populate }: any = {}) {\n return strapi.db.query(STAGE_MODEL_UID).findOne({\n where: { id },\n populate,\n });\n },\n\n async createMany(stagesList: any, { fields }: any = {}) {\n const params = { select: fields ?? '*' };\n\n const stages = await Promise.all(\n stagesList.map((stage: any) =>\n strapi.db.query(STAGE_MODEL_UID).create({\n data: sanitizeStageFields(stage),\n ...params,\n })\n )\n );\n\n await async.reduce(stagesList)(async (_, stage, idx) => {\n const stageId = stages[idx].id;\n const allPermissionIds: number[] = [];\n\n // Register \"from\" permissions\n if (stage.fromPermissions && stage.fromPermissions.length > 0) {\n const fromPermissions = await async.map(\n stage.fromPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...fromPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n // Register \"to\" permissions\n if (stage.toPermissions && stage.toPermissions.length > 0) {\n const toPermissions = await async.map(\n stage.toPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...toPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n if (allPermissionIds.length > 0) {\n await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n permissions: allPermissionIds,\n },\n });\n }\n }, []);\n\n metrics.sendDidCreateStage();\n\n return stages;\n },\n\n async update(srcStage: any, destStage: any) {\n const stageId = destStage.id;\n const hasPermissionChanges = destStage.fromPermissions || destStage.toPermissions;\n\n let allPermissionIds: number[];\n\n if (hasPermissionChanges) {\n // Delete all old permissions (both from and to) when either type changes\n await this.deleteStagePermissions([srcStage]);\n\n allPermissionIds = [];\n\n const extractRoleId = (p: PopulatedPermission): number =>\n typeof p.role === 'object' ? p.role.id : p.role;\n\n // Re-register \"from\" permissions (fall back to existing \"from\" entries from DB)\n const fromPerms =\n destStage.fromPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.from)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (fromPerms.length > 0) {\n const registered = await async.map(fromPerms, (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n\n // Re-register \"to\" permissions (fall back to existing \"to\" entries from DB)\n const toPerms =\n destStage.toPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.to)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (toPerms.length > 0) {\n const registered = await async.map(toPerms, (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n } else {\n allPermissionIds = (srcStage?.permissions ?? [])\n .map((p: { id: number }) => p.id)\n .filter(Boolean);\n }\n\n const stage = await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n ...destStage,\n permissions: allPermissionIds,\n },\n });\n\n metrics.sendDidEditStage();\n\n return stage;\n },\n\n async delete(stage: any) {\n // Unregister all permissions related to this stage id\n await this.deleteStagePermissions([stage]);\n\n const deletedStage = await strapi.db.query(STAGE_MODEL_UID).delete({\n where: { id: stage.id },\n });\n\n metrics.sendDidDeleteStage();\n\n return deletedStage;\n },\n\n async deleteMany(stages: any) {\n await this.deleteStagePermissions(stages);\n\n return strapi.db.query(STAGE_MODEL_UID).deleteMany({\n where: { id: { $in: stages.map((s: any) => s.id) } },\n });\n },\n\n async deleteStagePermissions(stages: any) {\n const permissions = stages.flatMap((s: any) => s.permissions || []);\n await stagePermissionsService.unregister(permissions || []);\n },\n\n count({ workflowId }: any = {}) {\n const opts = {} as any;\n\n if (workflowId) {\n opts.where = {\n workflow: workflowId,\n };\n }\n\n return strapi.db.query(STAGE_MODEL_UID).count(opts);\n },\n\n async replaceStages(srcStages: any, destStages: any, contentTypesToMigrate = []) {\n const { created, updated, deleted } = getDiffBetweenStages(srcStages, destStages);\n\n assertAtLeastOneStageRemain(srcStages || [], { created, deleted });\n\n // Update stages and assign entity stages\n return strapi.db.transaction(async ({ trx }) => {\n // Create the new stages\n const createdStages = await this.createMany(created, { fields: ['id'] });\n // Put all the newly created stages ids\n const createdStagesIds = map(createdStages, 'id');\n\n // Update the workflow stages\n await async.map(updated, (destStage: any) => {\n const srcStage = srcStages.find((s: any) => s.id === destStage.id);\n\n return this.update(srcStage, destStage);\n });\n\n // Delete the stages that are not in the new stages list\n await async.map(deleted, async (stage: any) => {\n // Find the nearest stage in the workflow and newly created stages\n // that is not deleted, prioritizing the previous stages\n const nearestStage = findNearestMatchingStage(\n [...srcStages, ...createdStages],\n srcStages.findIndex((s: any) => s.id === stage.id),\n (targetStage: any) => {\n return !deleted.find((s: any) => s.id === targetStage.id);\n }\n );\n\n // Assign the new stage to entities that had the deleted stage\n await async.map(contentTypesToMigrate, (contentTypeUID: any) => {\n this.updateEntitiesStage(contentTypeUID, {\n fromStageId: stage.id,\n toStageId: nearestStage.id,\n trx,\n });\n });\n\n return this.delete(stage);\n });\n\n return destStages.map((stage: any) => ({\n ...stage,\n id: stage.id ?? createdStagesIds.shift(),\n }));\n });\n },\n\n /**\n * Update the stage of an entity\n */\n async updateEntity(\n entityToUpdate: {\n id: number | string;\n documentId: string;\n locale: string;\n updatedAt: string;\n },\n model: UID.ContentType,\n stageId: any\n ) {\n const stage = await this.findById(stageId);\n const { documentId, locale } = entityToUpdate;\n\n await workflowValidator.validateWorkflowCount();\n\n if (!stage) {\n throw new ApplicationError(`Selected stage does not exist`);\n }\n\n const entity = await strapi.documents(model).update({\n documentId,\n locale,\n // Stage doesn't have DP or i18n enabled, connecting it through the `id`\n // will be safer than relying on the `documentId` + `locale` + `status` transformation\n data: { [ENTITY_STAGE_ATTRIBUTE]: pick(stage, ['id']) },\n populate: [ENTITY_STAGE_ATTRIBUTE],\n });\n\n // Update the `updated_at` field of the entity, so that the `status` is not considered `Modified`\n // NOTE: `updatedAt` is a protected attribute that can not be modified directly from the query layer\n // hence the knex query builder is used here.\n const { tableName } = strapi.db.metadata.get(model);\n await strapi.db\n .connection(tableName)\n .where({ id: entityToUpdate.id })\n .update({\n updated_at: new Date(entityToUpdate.updatedAt),\n });\n\n metrics.sendDidChangeEntryStage();\n\n return entity;\n },\n\n /**\n * Updates entity stages of a content type:\n * - If fromStageId is undefined, all entities with an existing stage will be assigned the new stage\n * - If fromStageId is null, all entities without a stage will be assigned the new stage\n * - If fromStageId is a number, all entities with that stage will be assigned the new stage\n *\n * For performance reasons we use knex queries directly.\n *\n * @param {string} contentTypeUID\n * @param {number | undefined | null} fromStageId\n * @param {number} toStageId\n * @param {import('knex').Knex.Transaction} trx\n * @returns\n */\n async updateEntitiesStage(contentTypeUID: any, { fromStageId, toStageId }: any) {\n const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID) as any;\n const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;\n const joinColumn = joinTable.joinColumn.name;\n const invJoinColumn = joinTable.inverseJoinColumn.name;\n\n await workflowValidator.validateWorkflowCount();\n\n return strapi.db.transaction(async ({ trx }) => {\n // Update all already existing links to the new stage\n if (fromStageId === undefined) {\n return strapi.db\n .getConnection()\n .from(joinTable.name)\n .update({ [invJoinColumn]: toStageId })\n .transacting(trx);\n }\n\n // Update all links from the specified stage to the new stage\n const selectStatement = strapi.db\n .getConnection()\n .select({ [joinColumn]: 't1.id', [invJoinColumn]: toStageId })\n .from(`${tableName} as t1`)\n .leftJoin(`${joinTable.name} as t2`, `t1.id`, `t2.${joinColumn}`)\n .where(`t2.${invJoinColumn}`, fromStageId)\n .toSQL();\n\n // Insert rows for all entries of the content type that have the specified stage\n return strapi.db\n .getConnection(joinTable.name)\n .insert(\n strapi.db.connection.raw(\n `(${joinColumn}, ${invJoinColumn}) ${selectStatement.sql}`,\n selectStatement.bindings\n )\n )\n .transacting(trx);\n });\n },\n\n /**\n * Deletes all entity stages of a content type\n * @param {string} contentTypeUID\n * @returns\n */\n async deleteAllEntitiesStage(contentTypeUID: any) {\n const { attributes } = strapi.db.metadata.get(contentTypeUID) as any;\n const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;\n\n // Delete all stage links for the content type\n return strapi.db.transaction(async ({ trx }) =>\n strapi.db.getConnection().from(joinTable.name).delete().transacting(trx)\n );\n },\n };\n};\n\nconst normalizeStageForDiff = (stage: {\n name?: string;\n color?: string;\n fromPermissions?: unknown[];\n toPermissions?: unknown[];\n}) => ({\n ...pick(stage, ['name', 'color']),\n fromPermissions: stage.fromPermissions ?? [],\n toPermissions: stage.toPermissions ?? [],\n});\n\n/**\n * Compares two arrays of stages and returns an object indicating the differences.\n *\n * The function compares the `id` properties of each stage in `sourceStages` and `comparisonStages` to determine if the stage is present in both arrays.\n * If a stage with the same `id` is found in both arrays but the `name` property is different, the stage is considered updated.\n * If a stage with a particular `id` is only found in `comparisonStages`, it is considered created.\n * If a stage with a particular `id` is only found in `sourceStages`, it is considered deleted.\n *\n * @typedef {{id: Number, name: String, workflow: Number}} Stage\n * @typedef {{created: Stage[], updated: Stage[], deleted: Stage[]}} DiffStages\n *\n * The DiffStages object has three properties: `created`, `updated`, and `deleted`.\n * `created` is an array of stages that are in `comparisonStages` but not in `sourceStages`.\n * `updated` is an array of stages that have different names in `comparisonStages` and `sourceStages`.\n * `deleted` is an array of stages that are in `sourceStages` but not in `comparisonStages`.\n *\n * @param {Stage[]} sourceStages\n * @param {Stage[]} comparisonStages\n * @returns { DiffStages }\n */\nfunction getDiffBetweenStages(sourceStages: any, comparisonStages: any) {\n const result = comparisonStages.reduce(\n // ...\n\n (acc: any, stageToCompare: any) => {\n const srcStage = sourceStages.find((stage: any) => stage.id === stageToCompare.id);\n\n if (!srcStage) {\n acc.created.push(stageToCompare);\n } else if (!isEqual(normalizeStageForDiff(srcStage), normalizeStageForDiff(stageToCompare))) {\n acc.updated.push(stageToCompare);\n }\n return acc;\n },\n { created: [], updated: [] }\n );\n\n result.deleted = sourceStages.filter(\n (srcStage: any) => !comparisonStages.some((cmpStage: any) => cmpStage.id === srcStage.id)\n );\n\n return result;\n}\n\n/**\n * Asserts that at least one stage remains in the workflow after applying deletions and additions.\n *\n * @param {Array} workflowStages - An array of stages in the current workflow.\n * @param {Object} diffStages - An object containing the stages to be deleted and created.\n * @param {Array} diffStages.deleted - An array of stages that are planned to be deleted from the workflow.\n * @param {Array} diffStages.created - An array of stages that are planned to be created in the workflow.\n *\n * @throws {ValidationError} If the number of remaining stages in the workflow after applying deletions and additions is less than 1.\n */\nfunction assertAtLeastOneStageRemain(workflowStages: any, diffStages: any) {\n const remainingStagesCount =\n workflowStages.length - diffStages.deleted.length + diffStages.created.length;\n if (remainingStagesCount < 1) {\n throw new ValidationError(ERRORS.WORKFLOW_WITHOUT_STAGES);\n }\n}\n\n/**\n * Find the id of the nearest object in an array that matches a condition.\n * Used for searching for the nearest stage that is not deleted.\n * Starts by searching the elements before the index, then the remaining elements in the array.\n *\n * @param {Array} stages\n * @param {Number} startIndex the index to start searching from\n * @param {Function} condition must evaluate to true for the object to be considered a match\n * @returns {Object} stage\n */\nfunction findNearestMatchingStage(stages: any, startIndex: any, condition: any) {\n // Start by searching the elements before the startIndex\n for (let i = startIndex; i >= 0; i -= 1) {\n if (condition(stages[i])) {\n return stages[i];\n }\n }\n\n // If no matching element is found before the startIndex,\n // search the remaining elements in the array\n const remainingArray = stages.slice(startIndex + 1);\n const nearestObject = remainingArray.find(condition);\n return nearestObject;\n}\n"],"names":["ApplicationError","ValidationError","errors","sanitizedStageFields","sanitizeStageFields","stage","pick","strapi","metrics","getService","stagePermissionsService","workflowValidator","find","workflowId","populate","db","query","STAGE_MODEL_UID","findMany","where","workflow","findById","id","findOne","createMany","stagesList","fields","params","select","stages","Promise","all","map","create","data","async","reduce","_","idx","stageId","allPermissionIds","fromPermissions","length","permission","register","roleId","role","action","fromStage","push","flat","p","toPermissions","registerTo","toStage","update","permissions","sendDidCreateStage","srcStage","destStage","hasPermissionChanges","deleteStagePermissions","extractRoleId","fromPerms","filter","actionParameters","from","registered","toPerms","to","Boolean","sendDidEditStage","delete","deletedStage","sendDidDeleteStage","deleteMany","$in","s","flatMap","unregister","count","opts","replaceStages","srcStages","destStages","contentTypesToMigrate","created","updated","deleted","getDiffBetweenStages","assertAtLeastOneStageRemain","transaction","trx","createdStages","createdStagesIds","nearestStage","findNearestMatchingStage","findIndex","targetStage","contentTypeUID","updateEntitiesStage","fromStageId","toStageId","shift","updateEntity","entityToUpdate","model","documentId","locale","validateWorkflowCount","entity","documents","ENTITY_STAGE_ATTRIBUTE","tableName","metadata","get","connection","updated_at","Date","updatedAt","sendDidChangeEntryStage","attributes","joinTable","joinColumn","name","invJoinColumn","inverseJoinColumn","undefined","getConnection","transacting","selectStatement","leftJoin","toSQL","insert","raw","sql","bindings","deleteAllEntitiesStage","normalizeStageForDiff","sourceStages","comparisonStages","result","acc","stageToCompare","isEqual","some","cmpStage","workflowStages","diffStages","remainingStagesCount","ERRORS","WORKFLOW_WITHOUT_STAGES","startIndex","condition","i","remainingArray","slice","nearestObject"],"mappings":"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"}
1
+ {"version":3,"file":"stages.js","sources":["../../../server/src/services/stages.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\nimport { async, errors } from '@strapi/utils';\nimport { pick, map, isEqual } from 'lodash';\nimport type { StagePermission } from '../../../shared/contracts/review-workflows';\nimport { STAGE_MODEL_UID, ENTITY_STAGE_ATTRIBUTE, ERRORS } from '../constants/workflows';\nimport { getService } from '../utils';\n\ninterface PopulatedPermission {\n role: number | { id: number };\n action: string;\n actionParameters?: { from?: number; to?: number };\n}\n\nconst { ApplicationError, ValidationError } = errors;\nconst sanitizedStageFields = ['id', 'name', 'workflow', 'color'];\nconst sanitizeStageFields = (stage: Record<string, unknown>) => pick(stage, sanitizedStageFields);\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const metrics = getService('workflow-metrics', { strapi });\n const stagePermissionsService = getService('stage-permissions', { strapi });\n const workflowValidator = getService('validation', { strapi });\n\n /**\n * Returns the table linking the entities of a content type to their stage, or undefined when\n * the content type no longer exists or has no stage attribute\n */\n const getEntityStageJoinTable = (contentTypeUID: UID.ContentType) => {\n if (strapi.db.metadata.has(contentTypeUID) === false) {\n return undefined;\n }\n\n const { attributes } = strapi.db.metadata.get(contentTypeUID) as any;\n return attributes[ENTITY_STAGE_ATTRIBUTE]?.joinTable;\n };\n\n return {\n find({ workflowId, populate }: any) {\n return strapi.db.query(STAGE_MODEL_UID).findMany({\n where: { workflow: workflowId },\n populate,\n });\n },\n\n findById(id: string | number, { workflowId, populate }: any = {}) {\n return strapi.db.query(STAGE_MODEL_UID).findOne({\n where: workflowId === undefined ? { id } : { id, workflow: workflowId },\n populate,\n });\n },\n\n async createMany(stagesList: any, { fields }: any = {}) {\n const params = { select: fields ?? '*' };\n\n const stages = await Promise.all(\n stagesList.map((stage: any) =>\n strapi.db.query(STAGE_MODEL_UID).create({\n data: sanitizeStageFields(stage),\n ...params,\n })\n )\n );\n\n await async.reduce(stagesList)(async (_, stage, idx) => {\n const stageId = stages[idx].id;\n const allPermissionIds: number[] = [];\n\n // Register \"from\" permissions\n if (stage.fromPermissions && stage.fromPermissions.length > 0) {\n const fromPermissions = await async.map(\n stage.fromPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...fromPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n // Register \"to\" permissions\n if (stage.toPermissions && stage.toPermissions.length > 0) {\n const toPermissions = await async.map(\n stage.toPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...toPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n if (allPermissionIds.length > 0) {\n await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n permissions: allPermissionIds,\n },\n });\n }\n }, []);\n\n metrics.sendDidCreateStage();\n\n return stages;\n },\n\n async update(srcStage: any, destStage: any) {\n const stageId = destStage.id;\n const hasPermissionChanges = destStage.fromPermissions || destStage.toPermissions;\n\n let allPermissionIds: number[];\n\n if (hasPermissionChanges) {\n // Delete all old permissions (both from and to) when either type changes\n await this.deleteStagePermissions([srcStage]);\n\n allPermissionIds = [];\n\n const extractRoleId = (p: PopulatedPermission): number =>\n typeof p.role === 'object' ? p.role.id : p.role;\n\n // Re-register \"from\" permissions (fall back to existing \"from\" entries from DB)\n const fromPerms =\n destStage.fromPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.from)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (fromPerms.length > 0) {\n const registered = await async.map(fromPerms, (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n\n // Re-register \"to\" permissions (fall back to existing \"to\" entries from DB)\n const toPerms =\n destStage.toPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.to)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (toPerms.length > 0) {\n const registered = await async.map(toPerms, (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n } else {\n allPermissionIds = (srcStage?.permissions ?? [])\n .map((p: { id: number }) => p.id)\n .filter(Boolean);\n }\n\n const stage = await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n ...destStage,\n permissions: allPermissionIds,\n },\n });\n\n metrics.sendDidEditStage();\n\n return stage;\n },\n\n async delete(stage: any) {\n // Unregister all permissions related to this stage id\n await this.deleteStagePermissions([stage]);\n\n const deletedStage = await strapi.db.query(STAGE_MODEL_UID).delete({\n where: { id: stage.id },\n });\n\n metrics.sendDidDeleteStage();\n\n return deletedStage;\n },\n\n async deleteMany(stages: any) {\n await this.deleteStagePermissions(stages);\n\n return strapi.db.query(STAGE_MODEL_UID).deleteMany({\n where: { id: { $in: stages.map((s: any) => s.id) } },\n });\n },\n\n async deleteStagePermissions(stages: any) {\n const permissions = stages.flatMap((s: any) => s.permissions || []);\n await stagePermissionsService.unregister(permissions || []);\n },\n\n count({ workflowId }: any = {}) {\n const opts = {} as any;\n\n if (workflowId) {\n opts.where = {\n workflow: workflowId,\n };\n }\n\n return strapi.db.query(STAGE_MODEL_UID).count(opts);\n },\n\n async replaceStages(srcStages: any, destStages: any, contentTypesToMigrate = []) {\n const { created, updated, deleted } = getDiffBetweenStages(srcStages, destStages);\n\n assertAtLeastOneStageRemain(srcStages || [], { created, deleted });\n\n // Update stages and assign entity stages\n return strapi.db.transaction(async () => {\n // Create the new stages\n const createdStages = await this.createMany(created, { fields: ['id'] });\n // Put all the newly created stages ids\n const createdStagesIds = map(createdStages, 'id');\n\n // Update the workflow stages\n await async.map(updated, (destStage: any) => {\n const srcStage = srcStages.find((s: any) => s.id === destStage.id);\n\n return this.update(srcStage, destStage);\n });\n\n // Delete the stages that are not in the new stages list\n await async.map(deleted, async (stage: any) => {\n // Find the nearest stage in the workflow and newly created stages\n // that is not deleted, prioritizing the previous stages\n const nearestStage = findNearestMatchingStage(\n [...srcStages, ...createdStages],\n srcStages.findIndex((s: any) => s.id === stage.id),\n (targetStage: any) => {\n return !deleted.find((s: any) => s.id === targetStage.id);\n }\n );\n\n // Assign the new stage to entities that had the deleted stage\n // Wait for it: deleting the stage also deletes its links to the entities.\n // `strapi.db.transaction` reuses the current transaction.\n await async.map(contentTypesToMigrate, (contentTypeUID: any) =>\n this.updateEntitiesStage(contentTypeUID, {\n fromStageId: stage.id,\n toStageId: nearestStage.id,\n })\n );\n\n return this.delete(stage);\n });\n\n return destStages.map((stage: any) => ({\n ...stage,\n id: stage.id ?? createdStagesIds.shift(),\n }));\n });\n },\n\n /**\n * Update the stage of an entity\n */\n async updateEntity(\n entityToUpdate: {\n id: number | string;\n documentId: string;\n locale: string;\n updatedAt: string;\n },\n model: UID.ContentType,\n stageId: any\n ) {\n const stage = await this.findById(stageId);\n const { documentId, locale } = entityToUpdate;\n\n await workflowValidator.validateWorkflowCount();\n\n if (!stage) {\n throw new ApplicationError(`Selected stage does not exist`);\n }\n\n const entity = await strapi.documents(model).update({\n documentId,\n locale,\n // Stage doesn't have DP or i18n enabled, connecting it through the `id`\n // will be safer than relying on the `documentId` + `locale` + `status` transformation\n data: { [ENTITY_STAGE_ATTRIBUTE]: pick(stage, ['id']) },\n populate: [ENTITY_STAGE_ATTRIBUTE],\n });\n\n // Update the `updated_at` field of the entity, so that the `status` is not considered `Modified`\n // NOTE: `updatedAt` is a protected attribute that can not be modified directly from the query layer\n // hence the knex query builder is used here.\n const { tableName } = strapi.db.metadata.get(model);\n await strapi.db\n .connection(tableName)\n .where({ id: entityToUpdate.id })\n .update({\n updated_at: new Date(entityToUpdate.updatedAt),\n });\n\n metrics.sendDidChangeEntryStage();\n\n return entity;\n },\n\n /**\n * Updates entity stages of a content type:\n * - If fromStageId is undefined, all entities with an existing stage will be assigned the new stage\n * - If fromStageId is null, all entities without a stage will be assigned the new stage\n * - If fromStageId is a number, all entities with that stage will be assigned the new stage\n *\n * For performance reasons we use knex queries directly.\n *\n * @param {string} contentTypeUID\n * @param {number | undefined | null} fromStageId\n * @param {number} toStageId\n * @returns\n */\n async updateEntitiesStage(contentTypeUID: any, { fromStageId, toStageId }: any) {\n const joinTable = getEntityStageJoinTable(contentTypeUID);\n\n // No entity can be linked to a stage\n if (joinTable === undefined) {\n return;\n }\n\n const { tableName } = strapi.db.metadata.get(contentTypeUID);\n const joinColumn = joinTable.joinColumn.name;\n const invJoinColumn = joinTable.inverseJoinColumn.name;\n\n await workflowValidator.validateWorkflowCount();\n\n return strapi.db.transaction(async ({ trx }) => {\n // Update all already existing links to the new stage\n if (fromStageId === undefined) {\n return strapi.db\n .getConnection()\n .from(joinTable.name)\n .update({ [invJoinColumn]: toStageId })\n .transacting(trx);\n }\n\n // Update all links from the specified stage to the new stage\n const selectStatement = strapi.db\n .getConnection()\n .select({ [joinColumn]: 't1.id', [invJoinColumn]: toStageId })\n .from(`${tableName} as t1`)\n .leftJoin(`${joinTable.name} as t2`, `t1.id`, `t2.${joinColumn}`)\n .where(`t2.${invJoinColumn}`, fromStageId)\n .toSQL();\n\n // Insert rows for all entries of the content type that have the specified stage\n return strapi.db\n .getConnection(joinTable.name)\n .insert(\n strapi.db.connection.raw(\n `(${joinColumn}, ${invJoinColumn}) ${selectStatement.sql}`,\n selectStatement.bindings\n )\n )\n .transacting(trx);\n });\n },\n\n /**\n * Deletes all entity stages of a content type\n * @param {string} contentTypeUID\n * @returns\n */\n async deleteAllEntitiesStage(contentTypeUID: any) {\n const joinTable = getEntityStageJoinTable(contentTypeUID);\n\n // No entity can be linked to a stage\n if (joinTable === undefined) {\n return;\n }\n\n // Delete all stage links for the content type\n return strapi.db.transaction(async ({ trx }) =>\n strapi.db.getConnection().from(joinTable.name).delete().transacting(trx)\n );\n },\n };\n};\n\nconst normalizeStageForDiff = (stage: {\n name?: string;\n color?: string;\n fromPermissions?: unknown[];\n toPermissions?: unknown[];\n}) => ({\n ...pick(stage, ['name', 'color']),\n fromPermissions: stage.fromPermissions ?? [],\n toPermissions: stage.toPermissions ?? [],\n});\n\n/**\n * Compares two arrays of stages and returns an object indicating the differences.\n *\n * The function compares the `id` properties of each stage in `sourceStages` and `comparisonStages` to determine if the stage is present in both arrays.\n * If a stage with the same `id` is found in both arrays but the `name` property is different, the stage is considered updated.\n * If a stage with a particular `id` is only found in `comparisonStages`, it is considered created.\n * If a stage with a particular `id` is only found in `sourceStages`, it is considered deleted.\n *\n * @typedef {{id: Number, name: String, workflow: Number}} Stage\n * @typedef {{created: Stage[], updated: Stage[], deleted: Stage[]}} DiffStages\n *\n * The DiffStages object has three properties: `created`, `updated`, and `deleted`.\n * `created` is an array of stages that are in `comparisonStages` but not in `sourceStages`.\n * `updated` is an array of stages that have different names in `comparisonStages` and `sourceStages`.\n * `deleted` is an array of stages that are in `sourceStages` but not in `comparisonStages`.\n *\n * @param {Stage[]} sourceStages\n * @param {Stage[]} comparisonStages\n * @returns { DiffStages }\n */\nfunction getDiffBetweenStages(sourceStages: any, comparisonStages: any) {\n const result = comparisonStages.reduce(\n // ...\n\n (acc: any, stageToCompare: any) => {\n const srcStage = sourceStages.find((stage: any) => stage.id === stageToCompare.id);\n\n if (!srcStage) {\n acc.created.push(stageToCompare);\n } else if (!isEqual(normalizeStageForDiff(srcStage), normalizeStageForDiff(stageToCompare))) {\n acc.updated.push(stageToCompare);\n }\n return acc;\n },\n { created: [], updated: [] }\n );\n\n result.deleted = sourceStages.filter(\n (srcStage: any) => !comparisonStages.some((cmpStage: any) => cmpStage.id === srcStage.id)\n );\n\n return result;\n}\n\n/**\n * Asserts that at least one stage remains in the workflow after applying deletions and additions.\n *\n * @param {Array} workflowStages - An array of stages in the current workflow.\n * @param {Object} diffStages - An object containing the stages to be deleted and created.\n * @param {Array} diffStages.deleted - An array of stages that are planned to be deleted from the workflow.\n * @param {Array} diffStages.created - An array of stages that are planned to be created in the workflow.\n *\n * @throws {ValidationError} If the number of remaining stages in the workflow after applying deletions and additions is less than 1.\n */\nfunction assertAtLeastOneStageRemain(workflowStages: any, diffStages: any) {\n const remainingStagesCount =\n workflowStages.length - diffStages.deleted.length + diffStages.created.length;\n if (remainingStagesCount < 1) {\n throw new ValidationError(ERRORS.WORKFLOW_WITHOUT_STAGES);\n }\n}\n\n/**\n * Find the id of the nearest object in an array that matches a condition.\n * Used for searching for the nearest stage that is not deleted.\n * Starts by searching the elements before the index, then the remaining elements in the array.\n *\n * @param {Array} stages\n * @param {Number} startIndex the index to start searching from\n * @param {Function} condition must evaluate to true for the object to be considered a match\n * @returns {Object} stage\n */\nfunction findNearestMatchingStage(stages: any, startIndex: any, condition: any) {\n // Start by searching the elements before the startIndex\n for (let i = startIndex; i >= 0; i -= 1) {\n if (condition(stages[i])) {\n return stages[i];\n }\n }\n\n // If no matching element is found before the startIndex,\n // search the remaining elements in the array\n const remainingArray = stages.slice(startIndex + 1);\n const nearestObject = remainingArray.find(condition);\n return nearestObject;\n}\n"],"names":["ApplicationError","ValidationError","errors","sanitizedStageFields","sanitizeStageFields","stage","pick","strapi","metrics","getService","stagePermissionsService","workflowValidator","getEntityStageJoinTable","contentTypeUID","db","metadata","has","undefined","attributes","get","ENTITY_STAGE_ATTRIBUTE","joinTable","find","workflowId","populate","query","STAGE_MODEL_UID","findMany","where","workflow","findById","id","findOne","createMany","stagesList","fields","params","select","stages","Promise","all","map","create","data","async","reduce","_","idx","stageId","allPermissionIds","fromPermissions","length","permission","register","roleId","role","action","fromStage","push","flat","p","toPermissions","registerTo","toStage","update","permissions","sendDidCreateStage","srcStage","destStage","hasPermissionChanges","deleteStagePermissions","extractRoleId","fromPerms","filter","actionParameters","from","registered","toPerms","to","Boolean","sendDidEditStage","delete","deletedStage","sendDidDeleteStage","deleteMany","$in","s","flatMap","unregister","count","opts","replaceStages","srcStages","destStages","contentTypesToMigrate","created","updated","deleted","getDiffBetweenStages","assertAtLeastOneStageRemain","transaction","createdStages","createdStagesIds","nearestStage","findNearestMatchingStage","findIndex","targetStage","updateEntitiesStage","fromStageId","toStageId","shift","updateEntity","entityToUpdate","model","documentId","locale","validateWorkflowCount","entity","documents","tableName","connection","updated_at","Date","updatedAt","sendDidChangeEntryStage","joinColumn","name","invJoinColumn","inverseJoinColumn","trx","getConnection","transacting","selectStatement","leftJoin","toSQL","insert","raw","sql","bindings","deleteAllEntitiesStage","normalizeStageForDiff","sourceStages","comparisonStages","result","acc","stageToCompare","isEqual","some","cmpStage","workflowStages","diffStages","remainingStagesCount","ERRORS","WORKFLOW_WITHOUT_STAGES","startIndex","condition","i","remainingArray","slice","nearestObject"],"mappings":"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"}
@@ -21,6 +21,16 @@ var stages = (({ strapi })=>{
21
21
  const workflowValidator = getService('validation', {
22
22
  strapi
23
23
  });
24
+ /**
25
+ * Returns the table linking the entities of a content type to their stage, or undefined when
26
+ * the content type no longer exists or has no stage attribute
27
+ */ const getEntityStageJoinTable = (contentTypeUID)=>{
28
+ if (strapi.db.metadata.has(contentTypeUID) === false) {
29
+ return undefined;
30
+ }
31
+ const { attributes } = strapi.db.metadata.get(contentTypeUID);
32
+ return attributes[ENTITY_STAGE_ATTRIBUTE]?.joinTable;
33
+ };
24
34
  return {
25
35
  find ({ workflowId, populate }) {
26
36
  return strapi.db.query(STAGE_MODEL_UID).findMany({
@@ -30,10 +40,13 @@ var stages = (({ strapi })=>{
30
40
  populate
31
41
  });
32
42
  },
33
- findById (id, { populate } = {}) {
43
+ findById (id, { workflowId, populate } = {}) {
34
44
  return strapi.db.query(STAGE_MODEL_UID).findOne({
35
- where: {
45
+ where: workflowId === undefined ? {
36
46
  id
47
+ } : {
48
+ id,
49
+ workflow: workflowId
37
50
  },
38
51
  populate
39
52
  });
@@ -176,7 +189,7 @@ var stages = (({ strapi })=>{
176
189
  deleted
177
190
  });
178
191
  // Update stages and assign entity stages
179
- return strapi.db.transaction(async ({ trx })=>{
192
+ return strapi.db.transaction(async ()=>{
180
193
  // Create the new stages
181
194
  const createdStages = await this.createMany(created, {
182
195
  fields: [
@@ -201,13 +214,12 @@ var stages = (({ strapi })=>{
201
214
  return !deleted.find((s)=>s.id === targetStage.id);
202
215
  });
203
216
  // Assign the new stage to entities that had the deleted stage
204
- await async.map(contentTypesToMigrate, (contentTypeUID)=>{
205
- this.updateEntitiesStage(contentTypeUID, {
217
+ // Wait for it: deleting the stage also deletes its links to the entities.
218
+ // `strapi.db.transaction` reuses the current transaction.
219
+ await async.map(contentTypesToMigrate, (contentTypeUID)=>this.updateEntitiesStage(contentTypeUID, {
206
220
  fromStageId: stage.id,
207
- toStageId: nearestStage.id,
208
- trx
209
- });
210
- });
221
+ toStageId: nearestStage.id
222
+ }));
211
223
  return this.delete(stage);
212
224
  });
213
225
  return destStages.map((stage)=>({
@@ -262,11 +274,14 @@ var stages = (({ strapi })=>{
262
274
  * @param {string} contentTypeUID
263
275
  * @param {number | undefined | null} fromStageId
264
276
  * @param {number} toStageId
265
- * @param {import('knex').Knex.Transaction} trx
266
277
  * @returns
267
278
  */ async updateEntitiesStage (contentTypeUID, { fromStageId, toStageId }) {
268
- const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID);
269
- const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;
279
+ const joinTable = getEntityStageJoinTable(contentTypeUID);
280
+ // No entity can be linked to a stage
281
+ if (joinTable === undefined) {
282
+ return;
283
+ }
284
+ const { tableName } = strapi.db.metadata.get(contentTypeUID);
270
285
  const joinColumn = joinTable.joinColumn.name;
271
286
  const invJoinColumn = joinTable.inverseJoinColumn.name;
272
287
  await workflowValidator.validateWorkflowCount();
@@ -291,8 +306,11 @@ var stages = (({ strapi })=>{
291
306
  * @param {string} contentTypeUID
292
307
  * @returns
293
308
  */ async deleteAllEntitiesStage (contentTypeUID) {
294
- const { attributes } = strapi.db.metadata.get(contentTypeUID);
295
- const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;
309
+ const joinTable = getEntityStageJoinTable(contentTypeUID);
310
+ // No entity can be linked to a stage
311
+ if (joinTable === undefined) {
312
+ return;
313
+ }
296
314
  // Delete all stage links for the content type
297
315
  return strapi.db.transaction(async ({ trx })=>strapi.db.getConnection().from(joinTable.name).delete().transacting(trx));
298
316
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stages.mjs","sources":["../../../server/src/services/stages.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\nimport { async, errors } from '@strapi/utils';\nimport { pick, map, isEqual } from 'lodash';\nimport type { StagePermission } from '../../../shared/contracts/review-workflows';\nimport { STAGE_MODEL_UID, ENTITY_STAGE_ATTRIBUTE, ERRORS } from '../constants/workflows';\nimport { getService } from '../utils';\n\ninterface PopulatedPermission {\n role: number | { id: number };\n action: string;\n actionParameters?: { from?: number; to?: number };\n}\n\nconst { ApplicationError, ValidationError } = errors;\nconst sanitizedStageFields = ['id', 'name', 'workflow', 'color'];\nconst sanitizeStageFields = (stage: Record<string, unknown>) => pick(stage, sanitizedStageFields);\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const metrics = getService('workflow-metrics', { strapi });\n const stagePermissionsService = getService('stage-permissions', { strapi });\n const workflowValidator = getService('validation', { strapi });\n\n return {\n find({ workflowId, populate }: any) {\n return strapi.db.query(STAGE_MODEL_UID).findMany({\n where: { workflow: workflowId },\n populate,\n });\n },\n\n findById(id: string | number, { populate }: any = {}) {\n return strapi.db.query(STAGE_MODEL_UID).findOne({\n where: { id },\n populate,\n });\n },\n\n async createMany(stagesList: any, { fields }: any = {}) {\n const params = { select: fields ?? '*' };\n\n const stages = await Promise.all(\n stagesList.map((stage: any) =>\n strapi.db.query(STAGE_MODEL_UID).create({\n data: sanitizeStageFields(stage),\n ...params,\n })\n )\n );\n\n await async.reduce(stagesList)(async (_, stage, idx) => {\n const stageId = stages[idx].id;\n const allPermissionIds: number[] = [];\n\n // Register \"from\" permissions\n if (stage.fromPermissions && stage.fromPermissions.length > 0) {\n const fromPermissions = await async.map(\n stage.fromPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...fromPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n // Register \"to\" permissions\n if (stage.toPermissions && stage.toPermissions.length > 0) {\n const toPermissions = await async.map(\n stage.toPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...toPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n if (allPermissionIds.length > 0) {\n await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n permissions: allPermissionIds,\n },\n });\n }\n }, []);\n\n metrics.sendDidCreateStage();\n\n return stages;\n },\n\n async update(srcStage: any, destStage: any) {\n const stageId = destStage.id;\n const hasPermissionChanges = destStage.fromPermissions || destStage.toPermissions;\n\n let allPermissionIds: number[];\n\n if (hasPermissionChanges) {\n // Delete all old permissions (both from and to) when either type changes\n await this.deleteStagePermissions([srcStage]);\n\n allPermissionIds = [];\n\n const extractRoleId = (p: PopulatedPermission): number =>\n typeof p.role === 'object' ? p.role.id : p.role;\n\n // Re-register \"from\" permissions (fall back to existing \"from\" entries from DB)\n const fromPerms =\n destStage.fromPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.from)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (fromPerms.length > 0) {\n const registered = await async.map(fromPerms, (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n\n // Re-register \"to\" permissions (fall back to existing \"to\" entries from DB)\n const toPerms =\n destStage.toPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.to)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (toPerms.length > 0) {\n const registered = await async.map(toPerms, (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n } else {\n allPermissionIds = (srcStage?.permissions ?? [])\n .map((p: { id: number }) => p.id)\n .filter(Boolean);\n }\n\n const stage = await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n ...destStage,\n permissions: allPermissionIds,\n },\n });\n\n metrics.sendDidEditStage();\n\n return stage;\n },\n\n async delete(stage: any) {\n // Unregister all permissions related to this stage id\n await this.deleteStagePermissions([stage]);\n\n const deletedStage = await strapi.db.query(STAGE_MODEL_UID).delete({\n where: { id: stage.id },\n });\n\n metrics.sendDidDeleteStage();\n\n return deletedStage;\n },\n\n async deleteMany(stages: any) {\n await this.deleteStagePermissions(stages);\n\n return strapi.db.query(STAGE_MODEL_UID).deleteMany({\n where: { id: { $in: stages.map((s: any) => s.id) } },\n });\n },\n\n async deleteStagePermissions(stages: any) {\n const permissions = stages.flatMap((s: any) => s.permissions || []);\n await stagePermissionsService.unregister(permissions || []);\n },\n\n count({ workflowId }: any = {}) {\n const opts = {} as any;\n\n if (workflowId) {\n opts.where = {\n workflow: workflowId,\n };\n }\n\n return strapi.db.query(STAGE_MODEL_UID).count(opts);\n },\n\n async replaceStages(srcStages: any, destStages: any, contentTypesToMigrate = []) {\n const { created, updated, deleted } = getDiffBetweenStages(srcStages, destStages);\n\n assertAtLeastOneStageRemain(srcStages || [], { created, deleted });\n\n // Update stages and assign entity stages\n return strapi.db.transaction(async ({ trx }) => {\n // Create the new stages\n const createdStages = await this.createMany(created, { fields: ['id'] });\n // Put all the newly created stages ids\n const createdStagesIds = map(createdStages, 'id');\n\n // Update the workflow stages\n await async.map(updated, (destStage: any) => {\n const srcStage = srcStages.find((s: any) => s.id === destStage.id);\n\n return this.update(srcStage, destStage);\n });\n\n // Delete the stages that are not in the new stages list\n await async.map(deleted, async (stage: any) => {\n // Find the nearest stage in the workflow and newly created stages\n // that is not deleted, prioritizing the previous stages\n const nearestStage = findNearestMatchingStage(\n [...srcStages, ...createdStages],\n srcStages.findIndex((s: any) => s.id === stage.id),\n (targetStage: any) => {\n return !deleted.find((s: any) => s.id === targetStage.id);\n }\n );\n\n // Assign the new stage to entities that had the deleted stage\n await async.map(contentTypesToMigrate, (contentTypeUID: any) => {\n this.updateEntitiesStage(contentTypeUID, {\n fromStageId: stage.id,\n toStageId: nearestStage.id,\n trx,\n });\n });\n\n return this.delete(stage);\n });\n\n return destStages.map((stage: any) => ({\n ...stage,\n id: stage.id ?? createdStagesIds.shift(),\n }));\n });\n },\n\n /**\n * Update the stage of an entity\n */\n async updateEntity(\n entityToUpdate: {\n id: number | string;\n documentId: string;\n locale: string;\n updatedAt: string;\n },\n model: UID.ContentType,\n stageId: any\n ) {\n const stage = await this.findById(stageId);\n const { documentId, locale } = entityToUpdate;\n\n await workflowValidator.validateWorkflowCount();\n\n if (!stage) {\n throw new ApplicationError(`Selected stage does not exist`);\n }\n\n const entity = await strapi.documents(model).update({\n documentId,\n locale,\n // Stage doesn't have DP or i18n enabled, connecting it through the `id`\n // will be safer than relying on the `documentId` + `locale` + `status` transformation\n data: { [ENTITY_STAGE_ATTRIBUTE]: pick(stage, ['id']) },\n populate: [ENTITY_STAGE_ATTRIBUTE],\n });\n\n // Update the `updated_at` field of the entity, so that the `status` is not considered `Modified`\n // NOTE: `updatedAt` is a protected attribute that can not be modified directly from the query layer\n // hence the knex query builder is used here.\n const { tableName } = strapi.db.metadata.get(model);\n await strapi.db\n .connection(tableName)\n .where({ id: entityToUpdate.id })\n .update({\n updated_at: new Date(entityToUpdate.updatedAt),\n });\n\n metrics.sendDidChangeEntryStage();\n\n return entity;\n },\n\n /**\n * Updates entity stages of a content type:\n * - If fromStageId is undefined, all entities with an existing stage will be assigned the new stage\n * - If fromStageId is null, all entities without a stage will be assigned the new stage\n * - If fromStageId is a number, all entities with that stage will be assigned the new stage\n *\n * For performance reasons we use knex queries directly.\n *\n * @param {string} contentTypeUID\n * @param {number | undefined | null} fromStageId\n * @param {number} toStageId\n * @param {import('knex').Knex.Transaction} trx\n * @returns\n */\n async updateEntitiesStage(contentTypeUID: any, { fromStageId, toStageId }: any) {\n const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID) as any;\n const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;\n const joinColumn = joinTable.joinColumn.name;\n const invJoinColumn = joinTable.inverseJoinColumn.name;\n\n await workflowValidator.validateWorkflowCount();\n\n return strapi.db.transaction(async ({ trx }) => {\n // Update all already existing links to the new stage\n if (fromStageId === undefined) {\n return strapi.db\n .getConnection()\n .from(joinTable.name)\n .update({ [invJoinColumn]: toStageId })\n .transacting(trx);\n }\n\n // Update all links from the specified stage to the new stage\n const selectStatement = strapi.db\n .getConnection()\n .select({ [joinColumn]: 't1.id', [invJoinColumn]: toStageId })\n .from(`${tableName} as t1`)\n .leftJoin(`${joinTable.name} as t2`, `t1.id`, `t2.${joinColumn}`)\n .where(`t2.${invJoinColumn}`, fromStageId)\n .toSQL();\n\n // Insert rows for all entries of the content type that have the specified stage\n return strapi.db\n .getConnection(joinTable.name)\n .insert(\n strapi.db.connection.raw(\n `(${joinColumn}, ${invJoinColumn}) ${selectStatement.sql}`,\n selectStatement.bindings\n )\n )\n .transacting(trx);\n });\n },\n\n /**\n * Deletes all entity stages of a content type\n * @param {string} contentTypeUID\n * @returns\n */\n async deleteAllEntitiesStage(contentTypeUID: any) {\n const { attributes } = strapi.db.metadata.get(contentTypeUID) as any;\n const joinTable = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable;\n\n // Delete all stage links for the content type\n return strapi.db.transaction(async ({ trx }) =>\n strapi.db.getConnection().from(joinTable.name).delete().transacting(trx)\n );\n },\n };\n};\n\nconst normalizeStageForDiff = (stage: {\n name?: string;\n color?: string;\n fromPermissions?: unknown[];\n toPermissions?: unknown[];\n}) => ({\n ...pick(stage, ['name', 'color']),\n fromPermissions: stage.fromPermissions ?? [],\n toPermissions: stage.toPermissions ?? [],\n});\n\n/**\n * Compares two arrays of stages and returns an object indicating the differences.\n *\n * The function compares the `id` properties of each stage in `sourceStages` and `comparisonStages` to determine if the stage is present in both arrays.\n * If a stage with the same `id` is found in both arrays but the `name` property is different, the stage is considered updated.\n * If a stage with a particular `id` is only found in `comparisonStages`, it is considered created.\n * If a stage with a particular `id` is only found in `sourceStages`, it is considered deleted.\n *\n * @typedef {{id: Number, name: String, workflow: Number}} Stage\n * @typedef {{created: Stage[], updated: Stage[], deleted: Stage[]}} DiffStages\n *\n * The DiffStages object has three properties: `created`, `updated`, and `deleted`.\n * `created` is an array of stages that are in `comparisonStages` but not in `sourceStages`.\n * `updated` is an array of stages that have different names in `comparisonStages` and `sourceStages`.\n * `deleted` is an array of stages that are in `sourceStages` but not in `comparisonStages`.\n *\n * @param {Stage[]} sourceStages\n * @param {Stage[]} comparisonStages\n * @returns { DiffStages }\n */\nfunction getDiffBetweenStages(sourceStages: any, comparisonStages: any) {\n const result = comparisonStages.reduce(\n // ...\n\n (acc: any, stageToCompare: any) => {\n const srcStage = sourceStages.find((stage: any) => stage.id === stageToCompare.id);\n\n if (!srcStage) {\n acc.created.push(stageToCompare);\n } else if (!isEqual(normalizeStageForDiff(srcStage), normalizeStageForDiff(stageToCompare))) {\n acc.updated.push(stageToCompare);\n }\n return acc;\n },\n { created: [], updated: [] }\n );\n\n result.deleted = sourceStages.filter(\n (srcStage: any) => !comparisonStages.some((cmpStage: any) => cmpStage.id === srcStage.id)\n );\n\n return result;\n}\n\n/**\n * Asserts that at least one stage remains in the workflow after applying deletions and additions.\n *\n * @param {Array} workflowStages - An array of stages in the current workflow.\n * @param {Object} diffStages - An object containing the stages to be deleted and created.\n * @param {Array} diffStages.deleted - An array of stages that are planned to be deleted from the workflow.\n * @param {Array} diffStages.created - An array of stages that are planned to be created in the workflow.\n *\n * @throws {ValidationError} If the number of remaining stages in the workflow after applying deletions and additions is less than 1.\n */\nfunction assertAtLeastOneStageRemain(workflowStages: any, diffStages: any) {\n const remainingStagesCount =\n workflowStages.length - diffStages.deleted.length + diffStages.created.length;\n if (remainingStagesCount < 1) {\n throw new ValidationError(ERRORS.WORKFLOW_WITHOUT_STAGES);\n }\n}\n\n/**\n * Find the id of the nearest object in an array that matches a condition.\n * Used for searching for the nearest stage that is not deleted.\n * Starts by searching the elements before the index, then the remaining elements in the array.\n *\n * @param {Array} stages\n * @param {Number} startIndex the index to start searching from\n * @param {Function} condition must evaluate to true for the object to be considered a match\n * @returns {Object} stage\n */\nfunction findNearestMatchingStage(stages: any, startIndex: any, condition: any) {\n // Start by searching the elements before the startIndex\n for (let i = startIndex; i >= 0; i -= 1) {\n if (condition(stages[i])) {\n return stages[i];\n }\n }\n\n // If no matching element is found before the startIndex,\n // search the remaining elements in the array\n const remainingArray = stages.slice(startIndex + 1);\n const nearestObject = remainingArray.find(condition);\n return nearestObject;\n}\n"],"names":["ApplicationError","ValidationError","errors","sanitizedStageFields","sanitizeStageFields","stage","pick","strapi","metrics","getService","stagePermissionsService","workflowValidator","find","workflowId","populate","db","query","STAGE_MODEL_UID","findMany","where","workflow","findById","id","findOne","createMany","stagesList","fields","params","select","stages","Promise","all","map","create","data","async","reduce","_","idx","stageId","allPermissionIds","fromPermissions","length","permission","register","roleId","role","action","fromStage","push","flat","p","toPermissions","registerTo","toStage","update","permissions","sendDidCreateStage","srcStage","destStage","hasPermissionChanges","deleteStagePermissions","extractRoleId","fromPerms","filter","actionParameters","from","registered","toPerms","to","Boolean","sendDidEditStage","delete","deletedStage","sendDidDeleteStage","deleteMany","$in","s","flatMap","unregister","count","opts","replaceStages","srcStages","destStages","contentTypesToMigrate","created","updated","deleted","getDiffBetweenStages","assertAtLeastOneStageRemain","transaction","trx","createdStages","createdStagesIds","nearestStage","findNearestMatchingStage","findIndex","targetStage","contentTypeUID","updateEntitiesStage","fromStageId","toStageId","shift","updateEntity","entityToUpdate","model","documentId","locale","validateWorkflowCount","entity","documents","ENTITY_STAGE_ATTRIBUTE","tableName","metadata","get","connection","updated_at","Date","updatedAt","sendDidChangeEntryStage","attributes","joinTable","joinColumn","name","invJoinColumn","inverseJoinColumn","undefined","getConnection","transacting","selectStatement","leftJoin","toSQL","insert","raw","sql","bindings","deleteAllEntitiesStage","normalizeStageForDiff","sourceStages","comparisonStages","result","acc","stageToCompare","isEqual","some","cmpStage","workflowStages","diffStages","remainingStagesCount","ERRORS","WORKFLOW_WITHOUT_STAGES","startIndex","condition","i","remainingArray","slice","nearestObject"],"mappings":"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"}
1
+ {"version":3,"file":"stages.mjs","sources":["../../../server/src/services/stages.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\nimport { async, errors } from '@strapi/utils';\nimport { pick, map, isEqual } from 'lodash';\nimport type { StagePermission } from '../../../shared/contracts/review-workflows';\nimport { STAGE_MODEL_UID, ENTITY_STAGE_ATTRIBUTE, ERRORS } from '../constants/workflows';\nimport { getService } from '../utils';\n\ninterface PopulatedPermission {\n role: number | { id: number };\n action: string;\n actionParameters?: { from?: number; to?: number };\n}\n\nconst { ApplicationError, ValidationError } = errors;\nconst sanitizedStageFields = ['id', 'name', 'workflow', 'color'];\nconst sanitizeStageFields = (stage: Record<string, unknown>) => pick(stage, sanitizedStageFields);\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const metrics = getService('workflow-metrics', { strapi });\n const stagePermissionsService = getService('stage-permissions', { strapi });\n const workflowValidator = getService('validation', { strapi });\n\n /**\n * Returns the table linking the entities of a content type to their stage, or undefined when\n * the content type no longer exists or has no stage attribute\n */\n const getEntityStageJoinTable = (contentTypeUID: UID.ContentType) => {\n if (strapi.db.metadata.has(contentTypeUID) === false) {\n return undefined;\n }\n\n const { attributes } = strapi.db.metadata.get(contentTypeUID) as any;\n return attributes[ENTITY_STAGE_ATTRIBUTE]?.joinTable;\n };\n\n return {\n find({ workflowId, populate }: any) {\n return strapi.db.query(STAGE_MODEL_UID).findMany({\n where: { workflow: workflowId },\n populate,\n });\n },\n\n findById(id: string | number, { workflowId, populate }: any = {}) {\n return strapi.db.query(STAGE_MODEL_UID).findOne({\n where: workflowId === undefined ? { id } : { id, workflow: workflowId },\n populate,\n });\n },\n\n async createMany(stagesList: any, { fields }: any = {}) {\n const params = { select: fields ?? '*' };\n\n const stages = await Promise.all(\n stagesList.map((stage: any) =>\n strapi.db.query(STAGE_MODEL_UID).create({\n data: sanitizeStageFields(stage),\n ...params,\n })\n )\n );\n\n await async.reduce(stagesList)(async (_, stage, idx) => {\n const stageId = stages[idx].id;\n const allPermissionIds: number[] = [];\n\n // Register \"from\" permissions\n if (stage.fromPermissions && stage.fromPermissions.length > 0) {\n const fromPermissions = await async.map(\n stage.fromPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...fromPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n // Register \"to\" permissions\n if (stage.toPermissions && stage.toPermissions.length > 0) {\n const toPermissions = await async.map(\n stage.toPermissions,\n (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...toPermissions.flat().map((p: { id: number }) => p.id));\n }\n\n if (allPermissionIds.length > 0) {\n await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n permissions: allPermissionIds,\n },\n });\n }\n }, []);\n\n metrics.sendDidCreateStage();\n\n return stages;\n },\n\n async update(srcStage: any, destStage: any) {\n const stageId = destStage.id;\n const hasPermissionChanges = destStage.fromPermissions || destStage.toPermissions;\n\n let allPermissionIds: number[];\n\n if (hasPermissionChanges) {\n // Delete all old permissions (both from and to) when either type changes\n await this.deleteStagePermissions([srcStage]);\n\n allPermissionIds = [];\n\n const extractRoleId = (p: PopulatedPermission): number =>\n typeof p.role === 'object' ? p.role.id : p.role;\n\n // Re-register \"from\" permissions (fall back to existing \"from\" entries from DB)\n const fromPerms =\n destStage.fromPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.from)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (fromPerms.length > 0) {\n const registered = await async.map(fromPerms, (permission: StagePermission) =>\n stagePermissionsService.register({\n roleId: permission.role,\n action: permission.action,\n fromStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n\n // Re-register \"to\" permissions (fall back to existing \"to\" entries from DB)\n const toPerms =\n destStage.toPermissions ??\n (srcStage?.permissions ?? [])\n .filter((p: PopulatedPermission) => p.actionParameters?.to)\n .map((p: PopulatedPermission) => ({ role: extractRoleId(p), action: p.action }));\n\n if (toPerms.length > 0) {\n const registered = await async.map(toPerms, (permission: StagePermission) =>\n stagePermissionsService.registerTo({\n roleId: permission.role,\n action: permission.action,\n toStage: stageId,\n })\n );\n allPermissionIds.push(...registered.flat().map((p: { id: number }) => p.id));\n }\n } else {\n allPermissionIds = (srcStage?.permissions ?? [])\n .map((p: { id: number }) => p.id)\n .filter(Boolean);\n }\n\n const stage = await strapi.db.query(STAGE_MODEL_UID).update({\n where: { id: stageId },\n data: {\n ...destStage,\n permissions: allPermissionIds,\n },\n });\n\n metrics.sendDidEditStage();\n\n return stage;\n },\n\n async delete(stage: any) {\n // Unregister all permissions related to this stage id\n await this.deleteStagePermissions([stage]);\n\n const deletedStage = await strapi.db.query(STAGE_MODEL_UID).delete({\n where: { id: stage.id },\n });\n\n metrics.sendDidDeleteStage();\n\n return deletedStage;\n },\n\n async deleteMany(stages: any) {\n await this.deleteStagePermissions(stages);\n\n return strapi.db.query(STAGE_MODEL_UID).deleteMany({\n where: { id: { $in: stages.map((s: any) => s.id) } },\n });\n },\n\n async deleteStagePermissions(stages: any) {\n const permissions = stages.flatMap((s: any) => s.permissions || []);\n await stagePermissionsService.unregister(permissions || []);\n },\n\n count({ workflowId }: any = {}) {\n const opts = {} as any;\n\n if (workflowId) {\n opts.where = {\n workflow: workflowId,\n };\n }\n\n return strapi.db.query(STAGE_MODEL_UID).count(opts);\n },\n\n async replaceStages(srcStages: any, destStages: any, contentTypesToMigrate = []) {\n const { created, updated, deleted } = getDiffBetweenStages(srcStages, destStages);\n\n assertAtLeastOneStageRemain(srcStages || [], { created, deleted });\n\n // Update stages and assign entity stages\n return strapi.db.transaction(async () => {\n // Create the new stages\n const createdStages = await this.createMany(created, { fields: ['id'] });\n // Put all the newly created stages ids\n const createdStagesIds = map(createdStages, 'id');\n\n // Update the workflow stages\n await async.map(updated, (destStage: any) => {\n const srcStage = srcStages.find((s: any) => s.id === destStage.id);\n\n return this.update(srcStage, destStage);\n });\n\n // Delete the stages that are not in the new stages list\n await async.map(deleted, async (stage: any) => {\n // Find the nearest stage in the workflow and newly created stages\n // that is not deleted, prioritizing the previous stages\n const nearestStage = findNearestMatchingStage(\n [...srcStages, ...createdStages],\n srcStages.findIndex((s: any) => s.id === stage.id),\n (targetStage: any) => {\n return !deleted.find((s: any) => s.id === targetStage.id);\n }\n );\n\n // Assign the new stage to entities that had the deleted stage\n // Wait for it: deleting the stage also deletes its links to the entities.\n // `strapi.db.transaction` reuses the current transaction.\n await async.map(contentTypesToMigrate, (contentTypeUID: any) =>\n this.updateEntitiesStage(contentTypeUID, {\n fromStageId: stage.id,\n toStageId: nearestStage.id,\n })\n );\n\n return this.delete(stage);\n });\n\n return destStages.map((stage: any) => ({\n ...stage,\n id: stage.id ?? createdStagesIds.shift(),\n }));\n });\n },\n\n /**\n * Update the stage of an entity\n */\n async updateEntity(\n entityToUpdate: {\n id: number | string;\n documentId: string;\n locale: string;\n updatedAt: string;\n },\n model: UID.ContentType,\n stageId: any\n ) {\n const stage = await this.findById(stageId);\n const { documentId, locale } = entityToUpdate;\n\n await workflowValidator.validateWorkflowCount();\n\n if (!stage) {\n throw new ApplicationError(`Selected stage does not exist`);\n }\n\n const entity = await strapi.documents(model).update({\n documentId,\n locale,\n // Stage doesn't have DP or i18n enabled, connecting it through the `id`\n // will be safer than relying on the `documentId` + `locale` + `status` transformation\n data: { [ENTITY_STAGE_ATTRIBUTE]: pick(stage, ['id']) },\n populate: [ENTITY_STAGE_ATTRIBUTE],\n });\n\n // Update the `updated_at` field of the entity, so that the `status` is not considered `Modified`\n // NOTE: `updatedAt` is a protected attribute that can not be modified directly from the query layer\n // hence the knex query builder is used here.\n const { tableName } = strapi.db.metadata.get(model);\n await strapi.db\n .connection(tableName)\n .where({ id: entityToUpdate.id })\n .update({\n updated_at: new Date(entityToUpdate.updatedAt),\n });\n\n metrics.sendDidChangeEntryStage();\n\n return entity;\n },\n\n /**\n * Updates entity stages of a content type:\n * - If fromStageId is undefined, all entities with an existing stage will be assigned the new stage\n * - If fromStageId is null, all entities without a stage will be assigned the new stage\n * - If fromStageId is a number, all entities with that stage will be assigned the new stage\n *\n * For performance reasons we use knex queries directly.\n *\n * @param {string} contentTypeUID\n * @param {number | undefined | null} fromStageId\n * @param {number} toStageId\n * @returns\n */\n async updateEntitiesStage(contentTypeUID: any, { fromStageId, toStageId }: any) {\n const joinTable = getEntityStageJoinTable(contentTypeUID);\n\n // No entity can be linked to a stage\n if (joinTable === undefined) {\n return;\n }\n\n const { tableName } = strapi.db.metadata.get(contentTypeUID);\n const joinColumn = joinTable.joinColumn.name;\n const invJoinColumn = joinTable.inverseJoinColumn.name;\n\n await workflowValidator.validateWorkflowCount();\n\n return strapi.db.transaction(async ({ trx }) => {\n // Update all already existing links to the new stage\n if (fromStageId === undefined) {\n return strapi.db\n .getConnection()\n .from(joinTable.name)\n .update({ [invJoinColumn]: toStageId })\n .transacting(trx);\n }\n\n // Update all links from the specified stage to the new stage\n const selectStatement = strapi.db\n .getConnection()\n .select({ [joinColumn]: 't1.id', [invJoinColumn]: toStageId })\n .from(`${tableName} as t1`)\n .leftJoin(`${joinTable.name} as t2`, `t1.id`, `t2.${joinColumn}`)\n .where(`t2.${invJoinColumn}`, fromStageId)\n .toSQL();\n\n // Insert rows for all entries of the content type that have the specified stage\n return strapi.db\n .getConnection(joinTable.name)\n .insert(\n strapi.db.connection.raw(\n `(${joinColumn}, ${invJoinColumn}) ${selectStatement.sql}`,\n selectStatement.bindings\n )\n )\n .transacting(trx);\n });\n },\n\n /**\n * Deletes all entity stages of a content type\n * @param {string} contentTypeUID\n * @returns\n */\n async deleteAllEntitiesStage(contentTypeUID: any) {\n const joinTable = getEntityStageJoinTable(contentTypeUID);\n\n // No entity can be linked to a stage\n if (joinTable === undefined) {\n return;\n }\n\n // Delete all stage links for the content type\n return strapi.db.transaction(async ({ trx }) =>\n strapi.db.getConnection().from(joinTable.name).delete().transacting(trx)\n );\n },\n };\n};\n\nconst normalizeStageForDiff = (stage: {\n name?: string;\n color?: string;\n fromPermissions?: unknown[];\n toPermissions?: unknown[];\n}) => ({\n ...pick(stage, ['name', 'color']),\n fromPermissions: stage.fromPermissions ?? [],\n toPermissions: stage.toPermissions ?? [],\n});\n\n/**\n * Compares two arrays of stages and returns an object indicating the differences.\n *\n * The function compares the `id` properties of each stage in `sourceStages` and `comparisonStages` to determine if the stage is present in both arrays.\n * If a stage with the same `id` is found in both arrays but the `name` property is different, the stage is considered updated.\n * If a stage with a particular `id` is only found in `comparisonStages`, it is considered created.\n * If a stage with a particular `id` is only found in `sourceStages`, it is considered deleted.\n *\n * @typedef {{id: Number, name: String, workflow: Number}} Stage\n * @typedef {{created: Stage[], updated: Stage[], deleted: Stage[]}} DiffStages\n *\n * The DiffStages object has three properties: `created`, `updated`, and `deleted`.\n * `created` is an array of stages that are in `comparisonStages` but not in `sourceStages`.\n * `updated` is an array of stages that have different names in `comparisonStages` and `sourceStages`.\n * `deleted` is an array of stages that are in `sourceStages` but not in `comparisonStages`.\n *\n * @param {Stage[]} sourceStages\n * @param {Stage[]} comparisonStages\n * @returns { DiffStages }\n */\nfunction getDiffBetweenStages(sourceStages: any, comparisonStages: any) {\n const result = comparisonStages.reduce(\n // ...\n\n (acc: any, stageToCompare: any) => {\n const srcStage = sourceStages.find((stage: any) => stage.id === stageToCompare.id);\n\n if (!srcStage) {\n acc.created.push(stageToCompare);\n } else if (!isEqual(normalizeStageForDiff(srcStage), normalizeStageForDiff(stageToCompare))) {\n acc.updated.push(stageToCompare);\n }\n return acc;\n },\n { created: [], updated: [] }\n );\n\n result.deleted = sourceStages.filter(\n (srcStage: any) => !comparisonStages.some((cmpStage: any) => cmpStage.id === srcStage.id)\n );\n\n return result;\n}\n\n/**\n * Asserts that at least one stage remains in the workflow after applying deletions and additions.\n *\n * @param {Array} workflowStages - An array of stages in the current workflow.\n * @param {Object} diffStages - An object containing the stages to be deleted and created.\n * @param {Array} diffStages.deleted - An array of stages that are planned to be deleted from the workflow.\n * @param {Array} diffStages.created - An array of stages that are planned to be created in the workflow.\n *\n * @throws {ValidationError} If the number of remaining stages in the workflow after applying deletions and additions is less than 1.\n */\nfunction assertAtLeastOneStageRemain(workflowStages: any, diffStages: any) {\n const remainingStagesCount =\n workflowStages.length - diffStages.deleted.length + diffStages.created.length;\n if (remainingStagesCount < 1) {\n throw new ValidationError(ERRORS.WORKFLOW_WITHOUT_STAGES);\n }\n}\n\n/**\n * Find the id of the nearest object in an array that matches a condition.\n * Used for searching for the nearest stage that is not deleted.\n * Starts by searching the elements before the index, then the remaining elements in the array.\n *\n * @param {Array} stages\n * @param {Number} startIndex the index to start searching from\n * @param {Function} condition must evaluate to true for the object to be considered a match\n * @returns {Object} stage\n */\nfunction findNearestMatchingStage(stages: any, startIndex: any, condition: any) {\n // Start by searching the elements before the startIndex\n for (let i = startIndex; i >= 0; i -= 1) {\n if (condition(stages[i])) {\n return stages[i];\n }\n }\n\n // If no matching element is found before the startIndex,\n // search the remaining elements in the array\n const remainingArray = stages.slice(startIndex + 1);\n const nearestObject = remainingArray.find(condition);\n return nearestObject;\n}\n"],"names":["ApplicationError","ValidationError","errors","sanitizedStageFields","sanitizeStageFields","stage","pick","strapi","metrics","getService","stagePermissionsService","workflowValidator","getEntityStageJoinTable","contentTypeUID","db","metadata","has","undefined","attributes","get","ENTITY_STAGE_ATTRIBUTE","joinTable","find","workflowId","populate","query","STAGE_MODEL_UID","findMany","where","workflow","findById","id","findOne","createMany","stagesList","fields","params","select","stages","Promise","all","map","create","data","async","reduce","_","idx","stageId","allPermissionIds","fromPermissions","length","permission","register","roleId","role","action","fromStage","push","flat","p","toPermissions","registerTo","toStage","update","permissions","sendDidCreateStage","srcStage","destStage","hasPermissionChanges","deleteStagePermissions","extractRoleId","fromPerms","filter","actionParameters","from","registered","toPerms","to","Boolean","sendDidEditStage","delete","deletedStage","sendDidDeleteStage","deleteMany","$in","s","flatMap","unregister","count","opts","replaceStages","srcStages","destStages","contentTypesToMigrate","created","updated","deleted","getDiffBetweenStages","assertAtLeastOneStageRemain","transaction","createdStages","createdStagesIds","nearestStage","findNearestMatchingStage","findIndex","targetStage","updateEntitiesStage","fromStageId","toStageId","shift","updateEntity","entityToUpdate","model","documentId","locale","validateWorkflowCount","entity","documents","tableName","connection","updated_at","Date","updatedAt","sendDidChangeEntryStage","joinColumn","name","invJoinColumn","inverseJoinColumn","trx","getConnection","transacting","selectStatement","leftJoin","toSQL","insert","raw","sql","bindings","deleteAllEntitiesStage","normalizeStageForDiff","sourceStages","comparisonStages","result","acc","stageToCompare","isEqual","some","cmpStage","workflowStages","diffStages","remainingStagesCount","ERRORS","WORKFLOW_WITHOUT_STAGES","startIndex","condition","i","remainingArray","slice","nearestObject"],"mappings":"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"}
@@ -12,7 +12,9 @@ var workflowsContentTypesFactory = (({ strapi })=>{
12
12
  });
13
13
  const updateContentTypeConfig = async (uid, reviewWorkflowOption)=>{
14
14
  // Merge options in the configuration as the configuration service use a destructuration merge which doesn't include nested objects
15
- const modelConfig = await contentManagerContentTypeService.findConfiguration(uid);
15
+ const modelConfig = await contentManagerContentTypeService.findConfiguration({
16
+ uid
17
+ });
16
18
  await contentManagerContentTypeService.updateConfiguration({
17
19
  uid
18
20
  }, {
@@ -64,6 +66,10 @@ var workflowsContentTypesFactory = (({ strapi })=>{
64
66
  concurrency: 1
65
67
  });
66
68
  await utils.async.map(deleted, async (uid)=>{
69
+ // A stored UID can outlive its model, which leaves no configuration or stage links to clean up
70
+ if (strapi.db.metadata.has(uid) === false) {
71
+ return;
72
+ }
67
73
  await updateContentTypeConfig(uid, false);
68
74
  await stagesService.deleteAllEntitiesStage(uid, {});
69
75
  });
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-content-types.js","sources":["../../../server/src/services/workflow-content-types.ts"],"sourcesContent":["import type { Core, Data } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { merge, difference } from 'lodash';\nimport { getService } from '../utils';\nimport { WORKFLOW_MODEL_UID } from '../constants/workflows';\n\n/** A workflow that lost content types to another one, as read after the write. */\nexport interface ContentTypeTransfer {\n workflowId: Data.ID;\n name: string;\n before: string[];\n after: string[];\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const contentManagerContentTypeService = strapi\n .plugin('content-manager')\n .service('content-types');\n const stagesService = getService('stages', { strapi });\n\n const updateContentTypeConfig = async (uid: any, reviewWorkflowOption: any) => {\n // Merge options in the configuration as the configuration service use a destructuration merge which doesn't include nested objects\n const modelConfig = await contentManagerContentTypeService.findConfiguration(uid);\n\n await contentManagerContentTypeService.updateConfiguration(\n { uid },\n { options: merge({}, modelConfig.options, { reviewWorkflows: reviewWorkflowOption }) }\n );\n };\n\n return {\n /**\n * Migrates entities stages. Used when a content type is assigned to a workflow.\n * @param {*} options\n * @param {Array<string>} options.srcContentTypes - The content types assigned to the previous workflow\n * @param {Array<string>} options.destContentTypes - The content types assigned to the new workflow\n * @param {Workflow.Stage} options.stageId - The new stage to assign the entities to\n */\n async migrate({\n srcContentTypes = [],\n destContentTypes,\n stageId,\n }: any): Promise<ContentTypeTransfer[]> {\n const workflowsService = getService('workflows', { strapi });\n const { created, deleted } = diffContentTypes(srcContentTypes, destContentTypes);\n const transfers = new Map<Data.ID, ContentTypeTransfer>();\n\n await async.map(\n created,\n async (uid: any) => {\n // Content Types should only be assigned to one workflow\n // However, edge cases can happen, and this handles them\n const srcWorkflows = await workflowsService._getAssignedWorkflows(uid, {});\n\n if (srcWorkflows.length) {\n // Updates all existing entities stages links to the new stage\n await stagesService.updateEntitiesStage(uid, { toStageId: stageId });\n // Transfer content types from the previous workflow(s)\n await async.map(srcWorkflows, async (srcWorkflow: any) => {\n const transfer = await this.transferContentTypes(srcWorkflow, uid);\n const previous = transfers.get(transfer.workflowId);\n transfers.set(transfer.workflowId, {\n ...transfer,\n before: previous?.before ?? transfer.before,\n });\n });\n }\n await updateContentTypeConfig(uid, true);\n\n // Create new stages links to the new stage\n return stagesService.updateEntitiesStage(uid, {\n fromStageId: null,\n toStageId: stageId,\n });\n },\n // transferContentTypes can cause race conditions if called in parallel when updating the same workflow\n { concurrency: 1 }\n );\n\n await async.map(deleted, async (uid: any) => {\n await updateContentTypeConfig(uid, false);\n await stagesService.deleteAllEntitiesStage(uid, {});\n });\n\n return [...transfers.values()];\n },\n\n /**\n * Filters the content types assigned to a workflow\n * @param {Workflow} srcWorkflow - The workflow to transfer from\n * @param {string} uid - The content type uid\n */\n async transferContentTypes(srcWorkflow: any, uid: any): Promise<ContentTypeTransfer> {\n // Update assignedContentTypes of the previous workflow\n const updated = await strapi.db.query(WORKFLOW_MODEL_UID).update({\n where: {\n id: srcWorkflow.id,\n },\n data: {\n contentTypes: srcWorkflow.contentTypes.filter((contentType: any) => contentType !== uid),\n },\n });\n\n return {\n workflowId: updated.id,\n name: updated.name,\n before: srcWorkflow.contentTypes,\n after: updated.contentTypes,\n };\n },\n };\n};\n\nconst diffContentTypes = (srcContentTypes: any, destContentTypes: any) => {\n const created = difference(destContentTypes, srcContentTypes);\n const deleted = difference(srcContentTypes, destContentTypes);\n return { created, deleted };\n};\n"],"names":["strapi","contentManagerContentTypeService","plugin","service","stagesService","getService","updateContentTypeConfig","uid","reviewWorkflowOption","modelConfig","findConfiguration","updateConfiguration","options","merge","reviewWorkflows","migrate","srcContentTypes","destContentTypes","stageId","workflowsService","created","deleted","diffContentTypes","transfers","Map","async","map","srcWorkflows","_getAssignedWorkflows","length","updateEntitiesStage","toStageId","srcWorkflow","transfer","transferContentTypes","previous","get","workflowId","set","before","fromStageId","concurrency","deleteAllEntitiesStage","values","updated","db","query","WORKFLOW_MODEL_UID","update","where","id","data","contentTypes","filter","contentType","name","after","difference"],"mappings":"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"}
1
+ {"version":3,"file":"workflow-content-types.js","sources":["../../../server/src/services/workflow-content-types.ts"],"sourcesContent":["import type { Core, Data, UID } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { merge, difference } from 'lodash';\nimport { getService } from '../utils';\nimport { WORKFLOW_MODEL_UID } from '../constants/workflows';\n\n/** A workflow that lost content types to another one, as read after the write. */\nexport interface ContentTypeTransfer {\n workflowId: Data.ID;\n name: string;\n before: string[];\n after: string[];\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const contentManagerContentTypeService = strapi\n .plugin('content-manager')\n .service('content-types');\n const stagesService = getService('stages', { strapi });\n\n const updateContentTypeConfig = async (uid: UID.ContentType, reviewWorkflowOption: boolean) => {\n // Merge options in the configuration as the configuration service use a destructuration merge which doesn't include nested objects\n const modelConfig = await contentManagerContentTypeService.findConfiguration({ uid });\n\n await contentManagerContentTypeService.updateConfiguration(\n { uid },\n { options: merge({}, modelConfig.options, { reviewWorkflows: reviewWorkflowOption }) }\n );\n };\n\n return {\n /**\n * Migrates entities stages. Used when a content type is assigned to a workflow.\n * @param {*} options\n * @param {Array<string>} options.srcContentTypes - The content types assigned to the previous workflow\n * @param {Array<string>} options.destContentTypes - The content types assigned to the new workflow\n * @param {Workflow.Stage} options.stageId - The new stage to assign the entities to\n */\n async migrate({\n srcContentTypes = [],\n destContentTypes,\n stageId,\n }: any): Promise<ContentTypeTransfer[]> {\n const workflowsService = getService('workflows', { strapi });\n const { created, deleted } = diffContentTypes(srcContentTypes, destContentTypes);\n const transfers = new Map<Data.ID, ContentTypeTransfer>();\n\n await async.map(\n created,\n async (uid: any) => {\n // Content Types should only be assigned to one workflow\n // However, edge cases can happen, and this handles them\n const srcWorkflows = await workflowsService._getAssignedWorkflows(uid, {});\n\n if (srcWorkflows.length) {\n // Updates all existing entities stages links to the new stage\n await stagesService.updateEntitiesStage(uid, { toStageId: stageId });\n // Transfer content types from the previous workflow(s)\n await async.map(srcWorkflows, async (srcWorkflow: any) => {\n const transfer = await this.transferContentTypes(srcWorkflow, uid);\n const previous = transfers.get(transfer.workflowId);\n transfers.set(transfer.workflowId, {\n ...transfer,\n before: previous?.before ?? transfer.before,\n });\n });\n }\n await updateContentTypeConfig(uid, true);\n\n // Create new stages links to the new stage\n return stagesService.updateEntitiesStage(uid, {\n fromStageId: null,\n toStageId: stageId,\n });\n },\n // transferContentTypes can cause race conditions if called in parallel when updating the same workflow\n { concurrency: 1 }\n );\n\n await async.map(deleted, async (uid: any) => {\n // A stored UID can outlive its model, which leaves no configuration or stage links to clean up\n if (strapi.db.metadata.has(uid) === false) {\n return;\n }\n\n await updateContentTypeConfig(uid, false);\n await stagesService.deleteAllEntitiesStage(uid, {});\n });\n\n return [...transfers.values()];\n },\n\n /**\n * Filters the content types assigned to a workflow\n * @param {Workflow} srcWorkflow - The workflow to transfer from\n * @param {string} uid - The content type uid\n */\n async transferContentTypes(srcWorkflow: any, uid: any): Promise<ContentTypeTransfer> {\n // Update assignedContentTypes of the previous workflow\n const updated = await strapi.db.query(WORKFLOW_MODEL_UID).update({\n where: {\n id: srcWorkflow.id,\n },\n data: {\n contentTypes: srcWorkflow.contentTypes.filter((contentType: any) => contentType !== uid),\n },\n });\n\n return {\n workflowId: updated.id,\n name: updated.name,\n before: srcWorkflow.contentTypes,\n after: updated.contentTypes,\n };\n },\n };\n};\n\nconst diffContentTypes = (srcContentTypes: any, destContentTypes: any) => {\n const created = difference(destContentTypes, srcContentTypes);\n const deleted = difference(srcContentTypes, destContentTypes);\n return { created, deleted };\n};\n"],"names":["strapi","contentManagerContentTypeService","plugin","service","stagesService","getService","updateContentTypeConfig","uid","reviewWorkflowOption","modelConfig","findConfiguration","updateConfiguration","options","merge","reviewWorkflows","migrate","srcContentTypes","destContentTypes","stageId","workflowsService","created","deleted","diffContentTypes","transfers","Map","async","map","srcWorkflows","_getAssignedWorkflows","length","updateEntitiesStage","toStageId","srcWorkflow","transfer","transferContentTypes","previous","get","workflowId","set","before","fromStageId","concurrency","db","metadata","has","deleteAllEntitiesStage","values","updated","query","WORKFLOW_MODEL_UID","update","where","id","data","contentTypes","filter","contentType","name","after","difference"],"mappings":"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"}
@@ -10,7 +10,9 @@ var workflowsContentTypesFactory = (({ strapi })=>{
10
10
  });
11
11
  const updateContentTypeConfig = async (uid, reviewWorkflowOption)=>{
12
12
  // Merge options in the configuration as the configuration service use a destructuration merge which doesn't include nested objects
13
- const modelConfig = await contentManagerContentTypeService.findConfiguration(uid);
13
+ const modelConfig = await contentManagerContentTypeService.findConfiguration({
14
+ uid
15
+ });
14
16
  await contentManagerContentTypeService.updateConfiguration({
15
17
  uid
16
18
  }, {
@@ -62,6 +64,10 @@ var workflowsContentTypesFactory = (({ strapi })=>{
62
64
  concurrency: 1
63
65
  });
64
66
  await async.map(deleted, async (uid)=>{
67
+ // A stored UID can outlive its model, which leaves no configuration or stage links to clean up
68
+ if (strapi.db.metadata.has(uid) === false) {
69
+ return;
70
+ }
65
71
  await updateContentTypeConfig(uid, false);
66
72
  await stagesService.deleteAllEntitiesStage(uid, {});
67
73
  });