@strapi/review-workflows 0.0.0-experimental.f31889311d753b5f7d95198ae84d8fce1d156cd6 → 0.0.0-experimental.f49f46a1c17445a39e8af3f63124bcccf73842e6
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.
- package/dist/_chunks/{Layout-Cwbb9usb.js → Layout-B4fpKB9J.js} +8 -9
- package/dist/_chunks/Layout-B4fpKB9J.js.map +1 -0
- package/dist/_chunks/{Layout-BpMLb-Oo.mjs → Layout-Dko22Aly.mjs} +8 -9
- package/dist/_chunks/Layout-Dko22Aly.mjs.map +1 -0
- package/dist/_chunks/{en-xcewH2pC.js → en-CYgjfSep.js} +5 -2
- package/dist/_chunks/en-CYgjfSep.js.map +1 -0
- package/dist/_chunks/{en-D9ZrQAV6.mjs → en-D9dxziEb.mjs} +5 -2
- package/dist/_chunks/en-D9dxziEb.mjs.map +1 -0
- package/dist/_chunks/{_id-p9NnvlMP.js → id-BKq7JAqZ.js} +82 -49
- package/dist/_chunks/id-BKq7JAqZ.js.map +1 -0
- package/dist/_chunks/{_id-KpezMzxO.mjs → id-DINFSsrh.mjs} +82 -49
- package/dist/_chunks/id-DINFSsrh.mjs.map +1 -0
- package/dist/_chunks/{index-DqT_oXGP.js → index-BpIILEs0.js} +9 -29
- package/dist/_chunks/index-BpIILEs0.js.map +1 -0
- package/dist/_chunks/{index-BTr8zF-9.js → index-BpL7C1EG.js} +54 -71
- package/dist/_chunks/index-BpL7C1EG.js.map +1 -0
- package/dist/_chunks/{index-DtJI5ZoC.mjs → index-DAcEdoqJ.mjs} +55 -72
- package/dist/_chunks/index-DAcEdoqJ.mjs.map +1 -0
- package/dist/_chunks/{index-BxkGN0Yj.mjs → index-ZcZKwmTD.mjs} +11 -31
- package/dist/_chunks/index-ZcZKwmTD.mjs.map +1 -0
- package/dist/_chunks/{router-B8G2sh6V.mjs → router-BPH_u176.mjs} +3 -3
- package/dist/_chunks/router-BPH_u176.mjs.map +1 -0
- package/dist/_chunks/{router-Bqj-105s.js → router-DeEgX8Ao.js} +3 -3
- package/dist/_chunks/router-DeEgX8Ao.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/services/settings.d.ts +1737 -7
- package/dist/server/index.js +180 -108
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +180 -108
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/constants/workflows.d.ts +1 -0
- package/dist/server/src/constants/workflows.d.ts.map +1 -1
- package/dist/server/src/content-types/index.d.ts +6 -0
- package/dist/server/src/content-types/index.d.ts.map +1 -1
- package/dist/server/src/content-types/workflow/index.d.ts +6 -0
- package/dist/server/src/content-types/workflow/index.d.ts.map +1 -1
- package/dist/server/src/controllers/assignees.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +0 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/stages.d.ts.map +1 -1
- package/dist/server/src/controllers/workflows.d.ts +0 -7
- package/dist/server/src/controllers/workflows.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +28 -7
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/review-workflows.d.ts.map +1 -1
- package/dist/server/src/services/assignees.d.ts +8 -4
- package/dist/server/src/services/assignees.d.ts.map +1 -1
- package/dist/server/src/services/document-service-middleware.d.ts +1 -0
- package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +16 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/metrics/index.d.ts +4 -4
- package/dist/server/src/services/metrics/index.d.ts.map +1 -1
- package/dist/server/src/services/metrics/weekly-metrics.d.ts.map +1 -1
- package/dist/server/src/services/stages.d.ts +7 -7
- package/dist/server/src/services/stages.d.ts.map +1 -1
- package/dist/server/src/services/workflows.d.ts.map +1 -1
- package/dist/server/src/validation/review-workflows.d.ts +4 -0
- package/dist/server/src/validation/review-workflows.d.ts.map +1 -1
- package/dist/shared/contracts/review-workflows.d.ts +9 -17
- package/dist/shared/contracts/review-workflows.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/_chunks/Layout-BpMLb-Oo.mjs.map +0 -1
- package/dist/_chunks/Layout-Cwbb9usb.js.map +0 -1
- package/dist/_chunks/_id-KpezMzxO.mjs.map +0 -1
- package/dist/_chunks/_id-p9NnvlMP.js.map +0 -1
- package/dist/_chunks/en-D9ZrQAV6.mjs.map +0 -1
- package/dist/_chunks/en-xcewH2pC.js.map +0 -1
- package/dist/_chunks/index-BTr8zF-9.js.map +0 -1
- package/dist/_chunks/index-BxkGN0Yj.mjs.map +0 -1
- package/dist/_chunks/index-DqT_oXGP.js.map +0 -1
- package/dist/_chunks/index-DtJI5ZoC.mjs.map +0 -1
- package/dist/_chunks/router-B8G2sh6V.mjs.map +0 -1
- package/dist/_chunks/router-Bqj-105s.js.map +0 -1
- package/strapi-server.js +0 -3
- /package/dist/admin/src/routes/settings/{:id.d.ts → id.d.ts} +0 -0
package/dist/server/index.mjs
CHANGED
|
@@ -6386,7 +6386,8 @@ const WORKFLOW_POPULATE = {
|
|
|
6386
6386
|
}
|
|
6387
6387
|
}
|
|
6388
6388
|
}
|
|
6389
|
-
}
|
|
6389
|
+
},
|
|
6390
|
+
stageRequiredToPublish: true
|
|
6390
6391
|
};
|
|
6391
6392
|
function checkVersionThreshold(startVersion, currentVersion, thresholdVersion) {
|
|
6392
6393
|
return semver$1.gte(currentVersion, thresholdVersion) && semver$1.lt(startVersion, thresholdVersion);
|
|
@@ -6561,8 +6562,40 @@ function extendReviewWorkflowContentTypes({ strapi: strapi2 }) {
|
|
|
6561
6562
|
});
|
|
6562
6563
|
}
|
|
6563
6564
|
}
|
|
6565
|
+
function persistRWOnDowngrade({ strapi: strapi2 }) {
|
|
6566
|
+
const { removePersistedTablesWithSuffix, persistTables } = getAdminService("persist-tables");
|
|
6567
|
+
return async ({ contentTypes: contentTypes2 }) => {
|
|
6568
|
+
const getStageTableToPersist = (contentTypeUID) => {
|
|
6569
|
+
const { attributes, tableName } = strapi2.db.metadata.get(contentTypeUID);
|
|
6570
|
+
const joinTableName = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable.name;
|
|
6571
|
+
return {
|
|
6572
|
+
name: joinTableName,
|
|
6573
|
+
dependsOn: [{ name: tableName }]
|
|
6574
|
+
};
|
|
6575
|
+
};
|
|
6576
|
+
const getAssigneeTableToPersist = (contentTypeUID) => {
|
|
6577
|
+
const { attributes, tableName } = strapi2.db.metadata.get(contentTypeUID);
|
|
6578
|
+
const joinTableName = attributes[ENTITY_ASSIGNEE_ATTRIBUTE].joinTable.name;
|
|
6579
|
+
return {
|
|
6580
|
+
name: joinTableName,
|
|
6581
|
+
dependsOn: [{ name: tableName }]
|
|
6582
|
+
};
|
|
6583
|
+
};
|
|
6584
|
+
const enabledRWContentTypes = fp.pipe([
|
|
6585
|
+
getVisibleContentTypesUID,
|
|
6586
|
+
fp.filter((uid) => hasStageAttribute(contentTypes2[uid]))
|
|
6587
|
+
])(contentTypes2);
|
|
6588
|
+
const stageJoinTablesToPersist = enabledRWContentTypes.map(getStageTableToPersist);
|
|
6589
|
+
await removePersistedTablesWithSuffix("_strapi_stage_lnk");
|
|
6590
|
+
await persistTables(stageJoinTablesToPersist);
|
|
6591
|
+
const assigneeJoinTablesToPersist = enabledRWContentTypes.map(getAssigneeTableToPersist);
|
|
6592
|
+
await removePersistedTablesWithSuffix("_strapi_assignee_lnk");
|
|
6593
|
+
await persistTables(assigneeJoinTablesToPersist);
|
|
6594
|
+
};
|
|
6595
|
+
}
|
|
6564
6596
|
const register = async ({ strapi: strapi2 }) => {
|
|
6565
6597
|
strapi2.hook("strapi::content-types.beforeSync").register(migrateStageAttribute);
|
|
6598
|
+
strapi2.hook("strapi::content-types.afterSync").register(persistRWOnDowngrade({ strapi: strapi2 }));
|
|
6566
6599
|
strapi2.hook("strapi::content-types.afterSync").register(migrateReviewWorkflowStagesColor).register(migrateReviewWorkflowStagesRoles).register(migrateReviewWorkflowName).register(migrateWorkflowsContentTypes).register(migrateDeletedCTInWorkflows);
|
|
6567
6600
|
reviewWorkflowsMiddlewares.contentTypeMiddleware(strapi2);
|
|
6568
6601
|
extendReviewWorkflowContentTypes({ strapi: strapi2 });
|
|
@@ -6607,6 +6640,12 @@ const workflow = {
|
|
|
6607
6640
|
relation: "oneToMany",
|
|
6608
6641
|
mappedBy: "workflow"
|
|
6609
6642
|
},
|
|
6643
|
+
stageRequiredToPublish: {
|
|
6644
|
+
type: "relation",
|
|
6645
|
+
target: "plugin::review-workflows.workflow-stage",
|
|
6646
|
+
relation: "oneToOne",
|
|
6647
|
+
required: false
|
|
6648
|
+
},
|
|
6610
6649
|
contentTypes: {
|
|
6611
6650
|
type: "json",
|
|
6612
6651
|
required: true,
|
|
@@ -6756,6 +6795,7 @@ const bootstrap = async (args) => {
|
|
|
6756
6795
|
const docsMiddlewares = getService("document-service-middlewares");
|
|
6757
6796
|
strapi.documents.use(docsMiddlewares.assignStageOnCreate);
|
|
6758
6797
|
strapi.documents.use(docsMiddlewares.handleStageOnUpdate);
|
|
6798
|
+
strapi.documents.use(docsMiddlewares.checkStageBeforePublish);
|
|
6759
6799
|
};
|
|
6760
6800
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
6761
6801
|
};
|
|
@@ -6837,23 +6877,6 @@ const reviewWorkflows = {
|
|
|
6837
6877
|
]
|
|
6838
6878
|
}
|
|
6839
6879
|
},
|
|
6840
|
-
{
|
|
6841
|
-
method: "GET",
|
|
6842
|
-
path: "/workflows/:id",
|
|
6843
|
-
handler: "workflows.findById",
|
|
6844
|
-
config: {
|
|
6845
|
-
middlewares: [enableFeatureMiddleware("review-workflows")],
|
|
6846
|
-
policies: [
|
|
6847
|
-
"admin::isAuthenticatedAdmin",
|
|
6848
|
-
{
|
|
6849
|
-
name: "admin::hasPermissions",
|
|
6850
|
-
config: {
|
|
6851
|
-
actions: ["admin::review-workflows.read"]
|
|
6852
|
-
}
|
|
6853
|
-
}
|
|
6854
|
-
]
|
|
6855
|
-
}
|
|
6856
|
-
},
|
|
6857
6880
|
{
|
|
6858
6881
|
method: "GET",
|
|
6859
6882
|
path: "/workflows/:workflow_id/stages",
|
|
@@ -6917,7 +6940,7 @@ const reviewWorkflows = {
|
|
|
6917
6940
|
{
|
|
6918
6941
|
name: "admin::hasPermissions",
|
|
6919
6942
|
config: {
|
|
6920
|
-
actions: ["admin::users.read"
|
|
6943
|
+
actions: ["admin::users.read"]
|
|
6921
6944
|
}
|
|
6922
6945
|
}
|
|
6923
6946
|
]
|
|
@@ -7005,9 +7028,9 @@ const processFilters = ({ strapi: strapi2 }, filters = {}) => {
|
|
|
7005
7028
|
};
|
|
7006
7029
|
const processPopulate = (populate) => {
|
|
7007
7030
|
if (!populate) {
|
|
7008
|
-
return
|
|
7031
|
+
return WORKFLOW_POPULATE;
|
|
7009
7032
|
}
|
|
7010
|
-
return
|
|
7033
|
+
return populate;
|
|
7011
7034
|
};
|
|
7012
7035
|
const workflows$1 = ({ strapi: strapi2 }) => {
|
|
7013
7036
|
const workflowsContentTypes = workflowsContentTypesFactory({ strapi: strapi2 });
|
|
@@ -7058,14 +7081,27 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7058
7081
|
const stages2 = await getService("stages", { strapi: strapi2 }).createMany(opts.data.stages);
|
|
7059
7082
|
const mapIds = fp.map(fp.get("id"));
|
|
7060
7083
|
createOpts = fp.set("data.stages", mapIds(stages2), createOpts);
|
|
7084
|
+
if (opts.data.stageRequiredToPublishName) {
|
|
7085
|
+
const stageRequiredToPublish = stages2.find(
|
|
7086
|
+
(stage) => stage.name === opts.data.stageRequiredToPublishName
|
|
7087
|
+
);
|
|
7088
|
+
if (!stageRequiredToPublish) {
|
|
7089
|
+
throw new errors.ApplicationError("Stage required to publish does not exist");
|
|
7090
|
+
}
|
|
7091
|
+
createOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, createOpts);
|
|
7092
|
+
}
|
|
7061
7093
|
if (opts.data.contentTypes) {
|
|
7062
7094
|
await workflowsContentTypes.migrate({
|
|
7063
7095
|
destContentTypes: opts.data.contentTypes,
|
|
7064
7096
|
stageId: stages2[0].id
|
|
7065
7097
|
});
|
|
7066
7098
|
}
|
|
7067
|
-
|
|
7068
|
-
|
|
7099
|
+
const createdWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).create(strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, createOpts));
|
|
7100
|
+
metrics.sendDidCreateWorkflow(createdWorkflow.id, !!opts.data.stageRequiredToPublishName);
|
|
7101
|
+
if (opts.data.stageRequiredToPublishName) {
|
|
7102
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(opts.data.contentTypes);
|
|
7103
|
+
}
|
|
7104
|
+
return createdWorkflow;
|
|
7069
7105
|
});
|
|
7070
7106
|
},
|
|
7071
7107
|
/**
|
|
@@ -7078,6 +7114,7 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7078
7114
|
async update(workflow2, opts) {
|
|
7079
7115
|
const stageService = getService("stages", { strapi: strapi2 });
|
|
7080
7116
|
let updateOpts = { ...opts, populate: { ...WORKFLOW_POPULATE } };
|
|
7117
|
+
let updatedStages = [];
|
|
7081
7118
|
let updatedStageIds;
|
|
7082
7119
|
await workflowValidator.validateWorkflowCount();
|
|
7083
7120
|
return strapi2.db.transaction(async () => {
|
|
@@ -7086,9 +7123,28 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7086
7123
|
opts.data.stages.forEach(
|
|
7087
7124
|
(stage) => this.assertStageBelongsToWorkflow(stage.id, workflow2)
|
|
7088
7125
|
);
|
|
7089
|
-
|
|
7126
|
+
updatedStages = await stageService.replaceStages(
|
|
7127
|
+
workflow2.stages,
|
|
7128
|
+
opts.data.stages,
|
|
7129
|
+
workflow2.contentTypes
|
|
7130
|
+
);
|
|
7131
|
+
updatedStageIds = updatedStages.map((stage) => stage.id);
|
|
7090
7132
|
updateOpts = fp.set("data.stages", updatedStageIds, updateOpts);
|
|
7091
7133
|
}
|
|
7134
|
+
if (opts.data.stageRequiredToPublishName !== void 0) {
|
|
7135
|
+
const stages2 = updatedStages ?? workflow2.stages;
|
|
7136
|
+
if (opts.data.stageRequiredToPublishName === null) {
|
|
7137
|
+
updateOpts = fp.set("data.stageRequiredToPublish", null, updateOpts);
|
|
7138
|
+
} else {
|
|
7139
|
+
const stageRequiredToPublish = stages2.find(
|
|
7140
|
+
(stage) => stage.name === opts.data.stageRequiredToPublishName
|
|
7141
|
+
);
|
|
7142
|
+
if (!stageRequiredToPublish) {
|
|
7143
|
+
throw new errors.ApplicationError("Stage required to publish does not exist");
|
|
7144
|
+
}
|
|
7145
|
+
updateOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, updateOpts);
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
7092
7148
|
if (opts.data.contentTypes) {
|
|
7093
7149
|
await workflowsContentTypes.migrate({
|
|
7094
7150
|
srcContentTypes: workflow2.contentTypes,
|
|
@@ -7096,12 +7152,17 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7096
7152
|
stageId: updatedStageIds ? updatedStageIds[0] : workflow2.stages[0].id
|
|
7097
7153
|
});
|
|
7098
7154
|
}
|
|
7099
|
-
metrics.sendDidEditWorkflow();
|
|
7155
|
+
metrics.sendDidEditWorkflow(workflow2.id, !!opts.data.stageRequiredToPublishName);
|
|
7100
7156
|
const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, updateOpts);
|
|
7101
|
-
|
|
7157
|
+
const updatedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).update({
|
|
7102
7158
|
...query,
|
|
7103
7159
|
where: { id: workflow2.id }
|
|
7104
7160
|
});
|
|
7161
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes([
|
|
7162
|
+
...workflow2.contentTypes,
|
|
7163
|
+
...opts.data.contentTypes || []
|
|
7164
|
+
]);
|
|
7165
|
+
return updatedWorkflow;
|
|
7105
7166
|
});
|
|
7106
7167
|
},
|
|
7107
7168
|
/**
|
|
@@ -7124,10 +7185,12 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7124
7185
|
destContentTypes: []
|
|
7125
7186
|
});
|
|
7126
7187
|
const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, opts);
|
|
7127
|
-
|
|
7188
|
+
const deletedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).delete({
|
|
7128
7189
|
...query,
|
|
7129
7190
|
where: { id: workflow2.id }
|
|
7130
7191
|
});
|
|
7192
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(workflow2.contentTypes);
|
|
7193
|
+
return deletedWorkflow;
|
|
7131
7194
|
});
|
|
7132
7195
|
},
|
|
7133
7196
|
/**
|
|
@@ -7338,25 +7401,26 @@ const stages$1 = ({ strapi: strapi2 }) => {
|
|
|
7338
7401
|
},
|
|
7339
7402
|
/**
|
|
7340
7403
|
* Update the stage of an entity
|
|
7341
|
-
*
|
|
7342
|
-
* @param {object} entityInfo
|
|
7343
|
-
* @param {number} entityInfo.id - Entity id
|
|
7344
|
-
* @param {string} entityInfo.modelUID - the content-type of the entity
|
|
7345
|
-
* @param {number} stageId - The id of the stage to assign to the entity
|
|
7346
7404
|
*/
|
|
7347
|
-
async updateEntity(
|
|
7405
|
+
async updateEntity(entityToUpdate, model, stageId) {
|
|
7348
7406
|
const stage = await this.findById(stageId);
|
|
7407
|
+
const { documentId, locale } = entityToUpdate;
|
|
7349
7408
|
await workflowValidator.validateWorkflowCount();
|
|
7350
7409
|
if (!stage) {
|
|
7351
7410
|
throw new ApplicationError$2(`Selected stage does not exist`);
|
|
7352
7411
|
}
|
|
7353
|
-
const entity = await strapi2.
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7412
|
+
const entity = await strapi2.documents(model).update({
|
|
7413
|
+
documentId,
|
|
7414
|
+
locale,
|
|
7415
|
+
// Stage doesn't have DP or i18n enabled, connecting it through the `id`
|
|
7416
|
+
// will be safer than relying on the `documentId` + `locale` + `status` transformation
|
|
7417
|
+
data: { [ENTITY_STAGE_ATTRIBUTE]: fp.pick(["id"], stage) },
|
|
7358
7418
|
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
7359
7419
|
});
|
|
7420
|
+
const { tableName } = strapi2.db.metadata.get(model);
|
|
7421
|
+
await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
|
|
7422
|
+
updated_at: new Date(entityToUpdate.updatedAt)
|
|
7423
|
+
});
|
|
7360
7424
|
metrics.sendDidChangeEntryStage();
|
|
7361
7425
|
return entity;
|
|
7362
7426
|
},
|
|
@@ -7503,32 +7567,28 @@ const assignees$1 = ({ strapi: strapi2 }) => {
|
|
|
7503
7567
|
/**
|
|
7504
7568
|
* Update the assignee of an entity
|
|
7505
7569
|
*/
|
|
7506
|
-
async updateEntityAssignee(
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7570
|
+
async updateEntityAssignee(entityToUpdate, model, assigneeId) {
|
|
7571
|
+
const { documentId, locale } = entityToUpdate;
|
|
7572
|
+
if (!fp.isNil(assigneeId)) {
|
|
7573
|
+
const userExists = await getAdminService("user", { strapi: strapi2 }).exists({ id: assigneeId });
|
|
7574
|
+
if (!userExists) {
|
|
7575
|
+
throw new ApplicationError(`Selected user does not exist`);
|
|
7576
|
+
}
|
|
7513
7577
|
}
|
|
7514
|
-
|
|
7515
|
-
|
|
7578
|
+
const oldAssigneeId = await this.findEntityAssigneeId(entityToUpdate.id, model);
|
|
7579
|
+
metrics.sendDidEditAssignee(oldAssigneeId, assigneeId || null);
|
|
7580
|
+
const entity = await strapi2.documents(model).update({
|
|
7516
7581
|
documentId,
|
|
7517
7582
|
locale,
|
|
7518
|
-
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId },
|
|
7583
|
+
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId || null },
|
|
7519
7584
|
populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
|
|
7520
7585
|
fields: []
|
|
7521
7586
|
});
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
return strapi2.documents(model).update({
|
|
7526
|
-
documentId,
|
|
7527
|
-
locale,
|
|
7528
|
-
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: null },
|
|
7529
|
-
populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
|
|
7530
|
-
fields: []
|
|
7587
|
+
const { tableName } = strapi2.db.metadata.get(model);
|
|
7588
|
+
await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
|
|
7589
|
+
updated_at: new Date(entityToUpdate.updatedAt)
|
|
7531
7590
|
});
|
|
7591
|
+
return entity;
|
|
7532
7592
|
}
|
|
7533
7593
|
};
|
|
7534
7594
|
};
|
|
@@ -7601,11 +7661,11 @@ const sendDidDeleteStage = async () => {
|
|
|
7601
7661
|
const sendDidChangeEntryStage = async () => {
|
|
7602
7662
|
strapi.telemetry.send("didChangeEntryStage", {});
|
|
7603
7663
|
};
|
|
7604
|
-
const sendDidCreateWorkflow = async () => {
|
|
7605
|
-
strapi.telemetry.send("didCreateWorkflow", {});
|
|
7664
|
+
const sendDidCreateWorkflow = async (workflowId, hasRequiredStageToPublish) => {
|
|
7665
|
+
strapi.telemetry.send("didCreateWorkflow", { workflowId, hasRequiredStageToPublish });
|
|
7606
7666
|
};
|
|
7607
|
-
const sendDidEditWorkflow = async () => {
|
|
7608
|
-
strapi.telemetry.send("didEditWorkflow", {});
|
|
7667
|
+
const sendDidEditWorkflow = async (workflowId, hasRequiredStageToPublish) => {
|
|
7668
|
+
strapi.telemetry.send("didEditWorkflow", { workflowId, hasRequiredStageToPublish });
|
|
7609
7669
|
};
|
|
7610
7670
|
const sendDidEditAssignee = async (fromId, toId) => {
|
|
7611
7671
|
strapi.telemetry.send("didEditAssignee", { from: fromId, to: toId });
|
|
@@ -7630,13 +7690,13 @@ const reviewWorkflowsMetrics = {
|
|
|
7630
7690
|
sendDidSendReviewWorkflowPropertiesOnceAWeek,
|
|
7631
7691
|
sendDidEditAssignee
|
|
7632
7692
|
};
|
|
7633
|
-
function _typeof(
|
|
7693
|
+
function _typeof(o) {
|
|
7634
7694
|
"@babel/helpers - typeof";
|
|
7635
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(
|
|
7636
|
-
return typeof
|
|
7637
|
-
} : function(
|
|
7638
|
-
return
|
|
7639
|
-
}, _typeof(
|
|
7695
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
|
|
7696
|
+
return typeof o2;
|
|
7697
|
+
} : function(o2) {
|
|
7698
|
+
return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
7699
|
+
}, _typeof(o);
|
|
7640
7700
|
}
|
|
7641
7701
|
function toInteger(dirtyNumber) {
|
|
7642
7702
|
if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
|
|
@@ -7771,7 +7831,12 @@ const reviewWorkflowsWeeklyMetrics = ({ strapi: strapi2 }) => {
|
|
|
7771
7831
|
},
|
|
7772
7832
|
async registerCron() {
|
|
7773
7833
|
const weeklySchedule = await this.ensureWeeklyStoredCronSchedule();
|
|
7774
|
-
strapi2.cron.add({
|
|
7834
|
+
strapi2.cron.add({
|
|
7835
|
+
reviewWorkflowsWeekly: {
|
|
7836
|
+
task: this.sendMetrics.bind(this),
|
|
7837
|
+
options: weeklySchedule
|
|
7838
|
+
}
|
|
7839
|
+
});
|
|
7775
7840
|
}
|
|
7776
7841
|
};
|
|
7777
7842
|
};
|
|
@@ -7827,6 +7892,7 @@ const handleStageOnUpdate = async (ctx, next) => {
|
|
|
7827
7892
|
strapi.eventHub.emit(WORKFLOW_UPDATE_STAGE, {
|
|
7828
7893
|
model: model.modelName,
|
|
7829
7894
|
uid: model.uid,
|
|
7895
|
+
// TODO v6: Rename to "entry", which is what is used for regular CRUD updates
|
|
7830
7896
|
entity: {
|
|
7831
7897
|
// @ts-expect-error
|
|
7832
7898
|
id: result?.id,
|
|
@@ -7852,9 +7918,27 @@ const handleStageOnUpdate = async (ctx, next) => {
|
|
|
7852
7918
|
}
|
|
7853
7919
|
return next();
|
|
7854
7920
|
};
|
|
7921
|
+
const checkStageBeforePublish = async (ctx, next) => {
|
|
7922
|
+
if (ctx.action !== "publish") {
|
|
7923
|
+
return next();
|
|
7924
|
+
}
|
|
7925
|
+
const workflow2 = await getService("workflows").getAssignedWorkflow(ctx.contentType.uid, {
|
|
7926
|
+
populate: "stageRequiredToPublish"
|
|
7927
|
+
});
|
|
7928
|
+
if (!workflow2 || !workflow2.stageRequiredToPublish) {
|
|
7929
|
+
return next();
|
|
7930
|
+
}
|
|
7931
|
+
const { documentId } = ctx.params;
|
|
7932
|
+
const entryStage = await getEntityStage(ctx.contentType.uid, documentId, ctx.params);
|
|
7933
|
+
if (entryStage.id !== workflow2.stageRequiredToPublish.id) {
|
|
7934
|
+
throw new errors.ValidationError("Entry is not at the required stage to publish");
|
|
7935
|
+
}
|
|
7936
|
+
return next();
|
|
7937
|
+
};
|
|
7855
7938
|
const documentServiceMiddleware = () => ({
|
|
7856
7939
|
assignStageOnCreate,
|
|
7857
|
-
handleStageOnUpdate
|
|
7940
|
+
handleStageOnUpdate,
|
|
7941
|
+
checkStageBeforePublish
|
|
7858
7942
|
});
|
|
7859
7943
|
const services = {
|
|
7860
7944
|
workflows: workflows$1,
|
|
@@ -7904,12 +7988,14 @@ const validateContentTypes = yup.array().of(
|
|
|
7904
7988
|
const validateWorkflowCreateSchema = yup.object().shape({
|
|
7905
7989
|
name: yup.string().max(255).min(1, "Workflow name can not be empty").required(),
|
|
7906
7990
|
stages: yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not create a workflow without stages").max(200, "Can not have more than 200 stages").required("Can not create a workflow without stages"),
|
|
7907
|
-
contentTypes: validateContentTypes
|
|
7991
|
+
contentTypes: validateContentTypes,
|
|
7992
|
+
stageRequiredToPublishName: yup.string().min(1).nullable()
|
|
7908
7993
|
});
|
|
7909
7994
|
const validateWorkflowUpdateSchema = yup.object().shape({
|
|
7910
7995
|
name: yup.string().max(255).min(1, "Workflow name can not be empty"),
|
|
7911
7996
|
stages: yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not update a workflow without stages").max(200, "Can not have more than 200 stages"),
|
|
7912
|
-
contentTypes: validateContentTypes
|
|
7997
|
+
contentTypes: validateContentTypes,
|
|
7998
|
+
stageRequiredToPublishName: yup.string().min(1).nullable()
|
|
7913
7999
|
});
|
|
7914
8000
|
const validateUpdateAssigneeOnEntitySchema = yup.object().shape({
|
|
7915
8001
|
id: yup.number().integer().min(1).nullable()
|
|
@@ -8028,30 +8114,6 @@ const workflows = {
|
|
|
8028
8114
|
workflowCount
|
|
8029
8115
|
}
|
|
8030
8116
|
};
|
|
8031
|
-
},
|
|
8032
|
-
/**
|
|
8033
|
-
* Get one workflow based on its id contained in request parameters
|
|
8034
|
-
* Returns count of workflows in meta, used to prevent workflow edition when
|
|
8035
|
-
* max workflow count is reached for the current plan
|
|
8036
|
-
* @param {import('koa').BaseContext} ctx - koa context
|
|
8037
|
-
*/
|
|
8038
|
-
async findById(ctx) {
|
|
8039
|
-
const { id } = ctx.params;
|
|
8040
|
-
const { query } = ctx.request;
|
|
8041
|
-
const { sanitizeOutput, sanitizedQuery } = getWorkflowsPermissionChecker(
|
|
8042
|
-
{ strapi },
|
|
8043
|
-
ctx.state.userAbility
|
|
8044
|
-
);
|
|
8045
|
-
const { populate } = await sanitizedQuery.read(query);
|
|
8046
|
-
const workflowService = getService("workflows");
|
|
8047
|
-
const [workflow2, workflowCount] = await Promise.all([
|
|
8048
|
-
workflowService.findById(id, { populate }).then(formatWorkflowToAdmin),
|
|
8049
|
-
workflowService.count()
|
|
8050
|
-
]);
|
|
8051
|
-
ctx.body = {
|
|
8052
|
-
data: await sanitizeOutput(workflow2),
|
|
8053
|
-
meta: { workflowCount }
|
|
8054
|
-
};
|
|
8055
8117
|
}
|
|
8056
8118
|
};
|
|
8057
8119
|
function sanitizeStage({ strapi: strapi2 }, userAbility) {
|
|
@@ -8136,7 +8198,7 @@ const stages = {
|
|
|
8136
8198
|
);
|
|
8137
8199
|
const workflow2 = await workflowService.assertContentTypeBelongsToWorkflow(modelUID);
|
|
8138
8200
|
workflowService.assertStageBelongsToWorkflow(stageId, workflow2);
|
|
8139
|
-
const updatedEntity = await stagesService.updateEntity(
|
|
8201
|
+
const updatedEntity = await stagesService.updateEntity(entity, modelUID, stageId);
|
|
8140
8202
|
ctx.body = { data: await sanitizeOutput(updatedEntity) };
|
|
8141
8203
|
},
|
|
8142
8204
|
/**
|
|
@@ -8156,10 +8218,9 @@ const stages = {
|
|
|
8156
8218
|
if (strapi.plugin("content-manager").service("permission-checker").create({ userAbility: ctx.state.userAbility, model: modelUID }).cannot.read()) {
|
|
8157
8219
|
return ctx.forbidden();
|
|
8158
8220
|
}
|
|
8159
|
-
const locale = await validateLocale(query?.locale);
|
|
8221
|
+
const locale = await validateLocale(query?.locale) ?? void 0;
|
|
8160
8222
|
const entity = await strapi.documents(modelUID).findOne({
|
|
8161
8223
|
documentId,
|
|
8162
|
-
// @ts-expect-error - locale should be also null in the doc service types
|
|
8163
8224
|
locale,
|
|
8164
8225
|
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
8165
8226
|
});
|
|
@@ -8168,12 +8229,13 @@ const stages = {
|
|
|
8168
8229
|
}
|
|
8169
8230
|
const entityStageId = entity[ENTITY_STAGE_ATTRIBUTE]?.id;
|
|
8170
8231
|
const canTransition = stagePermissions2.can(STAGE_TRANSITION_UID, entityStageId);
|
|
8171
|
-
const [workflowCount,
|
|
8232
|
+
const [workflowCount, workflowResult] = await Promise.all([
|
|
8172
8233
|
workflowService.count(),
|
|
8173
8234
|
workflowService.getAssignedWorkflow(modelUID, {
|
|
8174
8235
|
populate: "stages"
|
|
8175
8236
|
})
|
|
8176
8237
|
]);
|
|
8238
|
+
const workflowStages = workflowResult ? workflowResult.stages : [];
|
|
8177
8239
|
const meta = {
|
|
8178
8240
|
stageCount: workflowStages.length,
|
|
8179
8241
|
workflowCount
|
|
@@ -8209,22 +8271,32 @@ const assignees = {
|
|
|
8209
8271
|
async updateEntity(ctx) {
|
|
8210
8272
|
const assigneeService = getService("assignees");
|
|
8211
8273
|
const workflowService = getService("workflows");
|
|
8274
|
+
const stagePermissions2 = getService("stage-permissions");
|
|
8212
8275
|
const { model_uid: model, id: documentId } = ctx.params;
|
|
8213
|
-
const
|
|
8276
|
+
const locale = await validateLocale(ctx.request.query?.locale) ?? void 0;
|
|
8214
8277
|
const { sanitizeOutput } = strapi.plugin("content-manager").service("permission-checker").create({ userAbility: ctx.state.userAbility, model });
|
|
8278
|
+
const entity = await strapi.documents(model).findOne({
|
|
8279
|
+
documentId,
|
|
8280
|
+
locale,
|
|
8281
|
+
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
8282
|
+
});
|
|
8283
|
+
if (!entity) {
|
|
8284
|
+
ctx.throw(404, "Entity not found");
|
|
8285
|
+
}
|
|
8286
|
+
const canTransitionStage = stagePermissions2.can(
|
|
8287
|
+
STAGE_TRANSITION_UID,
|
|
8288
|
+
entity[ENTITY_STAGE_ATTRIBUTE]?.id
|
|
8289
|
+
);
|
|
8290
|
+
if (!canTransitionStage) {
|
|
8291
|
+
ctx.throw(403, "Stage transition permission is required");
|
|
8292
|
+
}
|
|
8215
8293
|
const { id: assigneeId } = await validateUpdateAssigneeOnEntity(
|
|
8216
8294
|
ctx.request?.body?.data,
|
|
8217
8295
|
"You should pass a valid id to the body of the put request."
|
|
8218
8296
|
);
|
|
8219
|
-
await validateLocale(locale);
|
|
8220
8297
|
await workflowService.assertContentTypeBelongsToWorkflow(model);
|
|
8221
|
-
const
|
|
8222
|
-
|
|
8223
|
-
locale || null,
|
|
8224
|
-
model,
|
|
8225
|
-
assigneeId
|
|
8226
|
-
);
|
|
8227
|
-
ctx.body = { data: await sanitizeOutput(entity) };
|
|
8298
|
+
const updatedEntity = await assigneeService.updateEntityAssignee(entity, model, assigneeId);
|
|
8299
|
+
ctx.body = { data: await sanitizeOutput(updatedEntity) };
|
|
8228
8300
|
}
|
|
8229
8301
|
};
|
|
8230
8302
|
const controllers = {
|