@strapi/content-releases 5.0.0-beta.1 → 5.0.0-beta.11
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/{App-1LckaIGY.js → App-B5UOQWbt.js} +375 -368
- package/dist/_chunks/App-B5UOQWbt.js.map +1 -0
- package/dist/_chunks/{App-X01LBg5V.mjs → App-DcXlnXrr.mjs} +371 -363
- package/dist/_chunks/App-DcXlnXrr.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-Be3acS2L.js} +8 -7
- package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +9 -8
- package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +1 -0
- package/dist/_chunks/SettingsPage-ped5WZ6Q.js +40 -0
- package/dist/_chunks/SettingsPage-ped5WZ6Q.js.map +1 -0
- package/dist/_chunks/SettingsPage-w5dOMAtL.mjs +40 -0
- package/dist/_chunks/SettingsPage-w5dOMAtL.mjs.map +1 -0
- package/dist/_chunks/{en-faJDuv3q.js → en-aH5E5UNw.js} +12 -2
- package/dist/_chunks/en-aH5E5UNw.js.map +1 -0
- package/dist/_chunks/{en-RdapH-9X.mjs → en-ahPQUZv2.mjs} +12 -2
- package/dist/_chunks/en-ahPQUZv2.mjs.map +1 -0
- package/dist/_chunks/{index-cYWov2wa.js → index-BgID5UQ7.js} +549 -525
- package/dist/_chunks/index-BgID5UQ7.js.map +1 -0
- package/dist/_chunks/{index-OD9AlD-6.mjs → index-LUuvped4.mjs} +551 -525
- package/dist/_chunks/index-LUuvped4.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +3 -3
- package/dist/admin/src/components/ReleaseActionModal.d.ts +24 -0
- package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
- package/dist/admin/src/components/ReleaseModal.d.ts +3 -2
- package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
- package/dist/admin/src/pages/SettingsPage.d.ts +1 -0
- package/dist/admin/src/services/release.d.ts +51 -313
- package/dist/admin/src/utils/api.d.ts +6 -0
- package/dist/server/index.js +824 -579
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +825 -580
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/constants.d.ts +11 -2
- package/dist/server/src/constants.d.ts.map +1 -1
- package/dist/server/src/content-types/index.d.ts +3 -5
- package/dist/server/src/content-types/index.d.ts.map +1 -1
- package/dist/server/src/content-types/release-action/index.d.ts +3 -5
- package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
- package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
- package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +6 -2
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/release-action.d.ts +0 -1
- package/dist/server/src/controllers/release-action.d.ts.map +1 -1
- package/dist/server/src/controllers/release.d.ts +7 -1
- package/dist/server/src/controllers/release.d.ts.map +1 -1
- package/dist/server/src/controllers/settings.d.ts +11 -0
- package/dist/server/src/controllers/settings.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/release-action.d.ts +7 -1
- package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/release.d.ts +1 -0
- package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/settings.d.ts +2 -0
- package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
- package/dist/server/src/destroy.d.ts +1 -1
- package/dist/server/src/destroy.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +73 -57
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/middlewares/documents.d.ts +6 -0
- package/dist/server/src/middlewares/documents.d.ts.map +1 -0
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
- package/dist/server/src/migrations/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts +16 -0
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/routes/release-action.d.ts.map +1 -1
- package/dist/server/src/routes/release.d.ts.map +1 -1
- package/dist/server/src/routes/settings.d.ts +18 -0
- package/dist/server/src/routes/settings.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +41 -41
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/release-action.d.ts +36 -0
- package/dist/server/src/services/release-action.d.ts.map +1 -0
- package/dist/server/src/services/release.d.ts +7 -42
- package/dist/server/src/services/release.d.ts.map +1 -1
- package/dist/server/src/services/scheduling.d.ts +1 -1
- package/dist/server/src/services/scheduling.d.ts.map +1 -1
- package/dist/server/src/services/settings.d.ts +13 -0
- package/dist/server/src/services/settings.d.ts.map +1 -0
- package/dist/server/src/services/validation.d.ts +2 -2
- package/dist/server/src/services/validation.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +33 -12
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/release-actions.d.ts +6 -5
- package/dist/shared/contracts/release-actions.d.ts.map +1 -1
- package/dist/shared/contracts/releases.d.ts +23 -6
- package/dist/shared/contracts/releases.d.ts.map +1 -1
- package/dist/shared/contracts/settings.d.ts +39 -0
- package/dist/shared/contracts/settings.d.ts.map +1 -0
- package/dist/shared/validation-schemas.d.ts +1 -0
- package/dist/shared/validation-schemas.d.ts.map +1 -1
- package/package.json +19 -18
- package/dist/_chunks/App-1LckaIGY.js.map +0 -1
- package/dist/_chunks/App-X01LBg5V.mjs.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
- package/dist/_chunks/en-RdapH-9X.mjs.map +0 -1
- package/dist/_chunks/en-faJDuv3q.js.map +0 -1
- package/dist/_chunks/index-OD9AlD-6.mjs.map +0 -1
- package/dist/_chunks/index-cYWov2wa.js.map +0 -1
- package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
- package/dist/admin/src/services/axios.d.ts +0 -29
package/dist/server/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { contentTypes as contentTypes$1, async, setCreatorFields, errors,
|
|
1
|
+
import { contentTypes as contentTypes$1, async, setCreatorFields, errors, yup as yup$1, validateYupSchema } from "@strapi/utils";
|
|
2
2
|
import isEqual from "lodash/isEqual";
|
|
3
3
|
import { difference, keys } from "lodash";
|
|
4
4
|
import _ from "lodash/fp";
|
|
@@ -48,24 +48,38 @@ const ACTIONS = [
|
|
|
48
48
|
displayName: "Add an entry to a release",
|
|
49
49
|
uid: "create-action",
|
|
50
50
|
pluginName: "content-releases"
|
|
51
|
+
},
|
|
52
|
+
// Settings
|
|
53
|
+
{
|
|
54
|
+
uid: "settings.read",
|
|
55
|
+
section: "settings",
|
|
56
|
+
displayName: "Read",
|
|
57
|
+
category: "content releases",
|
|
58
|
+
subCategory: "options",
|
|
59
|
+
pluginName: "content-releases"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
uid: "settings.update",
|
|
63
|
+
section: "settings",
|
|
64
|
+
displayName: "Edit",
|
|
65
|
+
category: "content releases",
|
|
66
|
+
subCategory: "options",
|
|
67
|
+
pluginName: "content-releases"
|
|
51
68
|
}
|
|
52
69
|
];
|
|
53
70
|
const ALLOWED_WEBHOOK_EVENTS = {
|
|
54
71
|
RELEASES_PUBLISH: "releases.publish"
|
|
55
72
|
};
|
|
56
|
-
const getService = (name, { strapi: strapi2 }
|
|
73
|
+
const getService = (name, { strapi: strapi2 }) => {
|
|
57
74
|
return strapi2.plugin("content-releases").service(name);
|
|
58
75
|
};
|
|
59
|
-
const
|
|
76
|
+
const getDraftEntryValidStatus = async ({ contentType, documentId, locale }, { strapi: strapi2 }) => {
|
|
60
77
|
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
61
|
-
const populate = await populateBuilderService(
|
|
62
|
-
const entry = await strapi2
|
|
63
|
-
|
|
64
|
-
populate
|
|
65
|
-
});
|
|
66
|
-
return entry;
|
|
78
|
+
const populate = await populateBuilderService(contentType).populateDeep(Infinity).build();
|
|
79
|
+
const entry = await getEntry({ contentType, documentId, locale, populate }, { strapi: strapi2 });
|
|
80
|
+
return isEntryValid(contentType, entry, { strapi: strapi2 });
|
|
67
81
|
};
|
|
68
|
-
const
|
|
82
|
+
const isEntryValid = async (contentTypeUid, entry, { strapi: strapi2 }) => {
|
|
69
83
|
try {
|
|
70
84
|
await strapi2.entityValidator.validateEntityCreation(
|
|
71
85
|
strapi2.getModel(contentTypeUid),
|
|
@@ -79,6 +93,38 @@ const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } =
|
|
|
79
93
|
return false;
|
|
80
94
|
}
|
|
81
95
|
};
|
|
96
|
+
const getEntry = async ({
|
|
97
|
+
contentType,
|
|
98
|
+
documentId,
|
|
99
|
+
locale,
|
|
100
|
+
populate,
|
|
101
|
+
status = "draft"
|
|
102
|
+
}, { strapi: strapi2 }) => {
|
|
103
|
+
if (documentId) {
|
|
104
|
+
return strapi2.documents(contentType).findOne({ documentId, locale, populate, status });
|
|
105
|
+
}
|
|
106
|
+
return strapi2.documents(contentType).findFirst({ locale, populate, status });
|
|
107
|
+
};
|
|
108
|
+
const getEntryStatus = async (contentType, entry) => {
|
|
109
|
+
if (entry.publishedAt) {
|
|
110
|
+
return "published";
|
|
111
|
+
}
|
|
112
|
+
const publishedEntry = await strapi.documents(contentType).findOne({
|
|
113
|
+
documentId: entry.documentId,
|
|
114
|
+
locale: entry.locale,
|
|
115
|
+
status: "published",
|
|
116
|
+
fields: ["updatedAt"]
|
|
117
|
+
});
|
|
118
|
+
if (!publishedEntry) {
|
|
119
|
+
return "draft";
|
|
120
|
+
}
|
|
121
|
+
const entryUpdatedAt = new Date(entry.updatedAt).getTime();
|
|
122
|
+
const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();
|
|
123
|
+
if (entryUpdatedAt > publishedEntryUpdatedAt) {
|
|
124
|
+
return "modified";
|
|
125
|
+
}
|
|
126
|
+
return "published";
|
|
127
|
+
};
|
|
82
128
|
async function deleteActionsOnDisableDraftAndPublish({
|
|
83
129
|
oldContentTypes,
|
|
84
130
|
contentTypes: contentTypes2
|
|
@@ -124,20 +170,22 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
124
170
|
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
125
171
|
for (const action of notValidatedActions) {
|
|
126
172
|
if (action.entry) {
|
|
127
|
-
const
|
|
128
|
-
|
|
173
|
+
const isEntryValid2 = getDraftEntryValidStatus(
|
|
174
|
+
{
|
|
175
|
+
contentType: action.contentType,
|
|
176
|
+
documentId: action.entryDocumentId,
|
|
177
|
+
locale: action.locale
|
|
178
|
+
},
|
|
179
|
+
{ strapi }
|
|
180
|
+
);
|
|
181
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
182
|
+
where: {
|
|
183
|
+
id: action.id
|
|
184
|
+
},
|
|
185
|
+
data: {
|
|
186
|
+
isEntryValid: isEntryValid2
|
|
187
|
+
}
|
|
129
188
|
});
|
|
130
|
-
if (populatedEntry) {
|
|
131
|
-
const isEntryValid = getEntryValidStatus(action.contentType, populatedEntry, { strapi });
|
|
132
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
133
|
-
where: {
|
|
134
|
-
id: action.id
|
|
135
|
-
},
|
|
136
|
-
data: {
|
|
137
|
-
isEntryValid
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
189
|
}
|
|
142
190
|
}
|
|
143
191
|
return getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
@@ -181,24 +229,24 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
181
229
|
}
|
|
182
230
|
});
|
|
183
231
|
await async.map(actions, async (action) => {
|
|
184
|
-
if (action.entry && action.release) {
|
|
185
|
-
const
|
|
186
|
-
|
|
232
|
+
if (action.entry && action.release && action.type === "publish") {
|
|
233
|
+
const isEntryValid2 = await getDraftEntryValidStatus(
|
|
234
|
+
{
|
|
235
|
+
contentType: contentTypeUID,
|
|
236
|
+
documentId: action.entryDocumentId,
|
|
237
|
+
locale: action.locale
|
|
238
|
+
},
|
|
239
|
+
{ strapi }
|
|
240
|
+
);
|
|
241
|
+
releasesAffected.add(action.release.id);
|
|
242
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
243
|
+
where: {
|
|
244
|
+
id: action.id
|
|
245
|
+
},
|
|
246
|
+
data: {
|
|
247
|
+
isEntryValid: isEntryValid2
|
|
248
|
+
}
|
|
187
249
|
});
|
|
188
|
-
if (populatedEntry) {
|
|
189
|
-
const isEntryValid = await getEntryValidStatus(contentTypeUID, populatedEntry, {
|
|
190
|
-
strapi
|
|
191
|
-
});
|
|
192
|
-
releasesAffected.add(action.release.id);
|
|
193
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
194
|
-
where: {
|
|
195
|
-
id: action.id
|
|
196
|
-
},
|
|
197
|
-
data: {
|
|
198
|
-
isEntryValid
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
250
|
}
|
|
203
251
|
});
|
|
204
252
|
}
|
|
@@ -213,13 +261,16 @@ async function disableContentTypeLocalized({ oldContentTypes, contentTypes: cont
|
|
|
213
261
|
if (!oldContentTypes) {
|
|
214
262
|
return;
|
|
215
263
|
}
|
|
264
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
265
|
+
if (!i18nPlugin) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
216
268
|
for (const uid in contentTypes2) {
|
|
217
269
|
if (!oldContentTypes[uid]) {
|
|
218
270
|
continue;
|
|
219
271
|
}
|
|
220
272
|
const oldContentType = oldContentTypes[uid];
|
|
221
273
|
const contentType = contentTypes2[uid];
|
|
222
|
-
const i18nPlugin = strapi.plugin("i18n");
|
|
223
274
|
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
224
275
|
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
225
276
|
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -232,13 +283,16 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
|
|
|
232
283
|
if (!oldContentTypes) {
|
|
233
284
|
return;
|
|
234
285
|
}
|
|
286
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
287
|
+
if (!i18nPlugin) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
235
290
|
for (const uid in contentTypes2) {
|
|
236
291
|
if (!oldContentTypes[uid]) {
|
|
237
292
|
continue;
|
|
238
293
|
}
|
|
239
294
|
const oldContentType = oldContentTypes[uid];
|
|
240
295
|
const contentType = contentTypes2[uid];
|
|
241
|
-
const i18nPlugin = strapi.plugin("i18n");
|
|
242
296
|
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
243
297
|
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
244
298
|
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
@@ -249,9 +303,38 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
|
|
|
249
303
|
}
|
|
250
304
|
}
|
|
251
305
|
}
|
|
306
|
+
const addEntryDocumentToReleaseActions = {
|
|
307
|
+
name: "content-releases::5.0.0-add-entry-document-id-to-release-actions",
|
|
308
|
+
async up(trx, db) {
|
|
309
|
+
const hasPolymorphicColumn = await trx.schema.hasColumn("strapi_release_actions", "target_id");
|
|
310
|
+
if (hasPolymorphicColumn) {
|
|
311
|
+
const hasEntryDocumentIdColumn = await trx.schema.hasColumn(
|
|
312
|
+
"strapi_release_actions",
|
|
313
|
+
"entry_document_id"
|
|
314
|
+
);
|
|
315
|
+
if (!hasEntryDocumentIdColumn) {
|
|
316
|
+
await trx.schema.alterTable("strapi_release_actions", (table) => {
|
|
317
|
+
table.string("entry_document_id");
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
const releaseActions = await trx.select("*").from("strapi_release_actions");
|
|
321
|
+
async.map(releaseActions, async (action) => {
|
|
322
|
+
const { target_type, target_id } = action;
|
|
323
|
+
const entry = await db.query(target_type).findOne({ where: { id: target_id } });
|
|
324
|
+
if (entry) {
|
|
325
|
+
await trx("strapi_release_actions").update({ entry_document_id: entry.documentId }).where("id", action.id);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
async down() {
|
|
331
|
+
throw new Error("not implemented");
|
|
332
|
+
}
|
|
333
|
+
};
|
|
252
334
|
const register = async ({ strapi: strapi2 }) => {
|
|
253
335
|
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
254
|
-
await strapi2.admin
|
|
336
|
+
await strapi2.service("admin::permission").actionProvider.registerMany(ACTIONS);
|
|
337
|
+
strapi2.db.migrations.providers.internal.register(addEntryDocumentToReleaseActions);
|
|
255
338
|
strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized).register(deleteActionsOnDisableDraftAndPublish);
|
|
256
339
|
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
257
340
|
}
|
|
@@ -261,6 +344,104 @@ const register = async ({ strapi: strapi2 }) => {
|
|
|
261
344
|
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
262
345
|
}
|
|
263
346
|
};
|
|
347
|
+
const updateActionsStatusAndUpdateReleaseStatus = async (contentType, entry) => {
|
|
348
|
+
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
349
|
+
where: {
|
|
350
|
+
actions: {
|
|
351
|
+
contentType,
|
|
352
|
+
entryDocumentId: entry.documentId,
|
|
353
|
+
locale: entry.locale
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
const entryStatus = await isEntryValid(contentType, entry, { strapi });
|
|
358
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
359
|
+
where: {
|
|
360
|
+
contentType,
|
|
361
|
+
entryDocumentId: entry.documentId,
|
|
362
|
+
locale: entry.locale
|
|
363
|
+
},
|
|
364
|
+
data: {
|
|
365
|
+
isEntryValid: entryStatus
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
for (const release2 of releases) {
|
|
369
|
+
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const deleteActionsAndUpdateReleaseStatus = async (params) => {
|
|
373
|
+
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
374
|
+
where: {
|
|
375
|
+
actions: params
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
379
|
+
where: params
|
|
380
|
+
});
|
|
381
|
+
for (const release2 of releases) {
|
|
382
|
+
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
const deleteActionsOnDelete = async (ctx, next) => {
|
|
386
|
+
if (ctx.action !== "delete") {
|
|
387
|
+
return next();
|
|
388
|
+
}
|
|
389
|
+
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
390
|
+
return next();
|
|
391
|
+
}
|
|
392
|
+
const contentType = ctx.contentType.uid;
|
|
393
|
+
const { documentId, locale } = ctx.params;
|
|
394
|
+
const result = await next();
|
|
395
|
+
if (!result) {
|
|
396
|
+
return result;
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
deleteActionsAndUpdateReleaseStatus({
|
|
400
|
+
contentType,
|
|
401
|
+
entryDocumentId: documentId,
|
|
402
|
+
...locale !== "*" && { locale }
|
|
403
|
+
});
|
|
404
|
+
} catch (error) {
|
|
405
|
+
strapi.log.error("Error while deleting release actions after delete", {
|
|
406
|
+
error
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return result;
|
|
410
|
+
};
|
|
411
|
+
const updateActionsOnUpdate = async (ctx, next) => {
|
|
412
|
+
if (ctx.action !== "update") {
|
|
413
|
+
return next();
|
|
414
|
+
}
|
|
415
|
+
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
416
|
+
return next();
|
|
417
|
+
}
|
|
418
|
+
const contentType = ctx.contentType.uid;
|
|
419
|
+
const result = await next();
|
|
420
|
+
if (!result) {
|
|
421
|
+
return result;
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
updateActionsStatusAndUpdateReleaseStatus(contentType, result);
|
|
425
|
+
} catch (error) {
|
|
426
|
+
strapi.log.error("Error while updating release actions after update", {
|
|
427
|
+
error
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
return result;
|
|
431
|
+
};
|
|
432
|
+
const deleteReleasesActionsAndUpdateReleaseStatus = async (params) => {
|
|
433
|
+
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
434
|
+
where: {
|
|
435
|
+
actions: params
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
439
|
+
where: params
|
|
440
|
+
});
|
|
441
|
+
for (const release2 of releases) {
|
|
442
|
+
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
264
445
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
265
446
|
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
266
447
|
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
|
|
@@ -268,115 +449,29 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
268
449
|
);
|
|
269
450
|
strapi2.db.lifecycles.subscribe({
|
|
270
451
|
models: contentTypesWithDraftAndPublish,
|
|
271
|
-
async afterDelete(event) {
|
|
272
|
-
try {
|
|
273
|
-
const { model, result } = event;
|
|
274
|
-
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
275
|
-
const { id } = result;
|
|
276
|
-
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
277
|
-
where: {
|
|
278
|
-
actions: {
|
|
279
|
-
target_type: model.uid,
|
|
280
|
-
target_id: id
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
285
|
-
where: {
|
|
286
|
-
target_type: model.uid,
|
|
287
|
-
target_id: id
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
for (const release2 of releases) {
|
|
291
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
} catch (error) {
|
|
295
|
-
strapi2.log.error("Error while deleting release actions after entry delete", { error });
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
|
-
/**
|
|
299
|
-
* deleteMany hook doesn't return the deleted entries ids
|
|
300
|
-
* so we need to fetch them before deleting the entries to save the ids on our state
|
|
301
|
-
*/
|
|
302
|
-
async beforeDeleteMany(event) {
|
|
303
|
-
const { model, params } = event;
|
|
304
|
-
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
305
|
-
const { where } = params;
|
|
306
|
-
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
307
|
-
event.state.entriesToDelete = entriesToDelete;
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
452
|
/**
|
|
311
|
-
*
|
|
312
|
-
* We make this only after deleteMany is succesfully executed to avoid errors
|
|
453
|
+
* deleteMany is still used outside documents service, for example when deleting a locale
|
|
313
454
|
*/
|
|
314
455
|
async afterDeleteMany(event) {
|
|
315
456
|
try {
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
target_id: {
|
|
324
|
-
$in: entriesToDelete.map((entry) => entry.id)
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
330
|
-
where: {
|
|
331
|
-
target_type: model.uid,
|
|
332
|
-
target_id: {
|
|
333
|
-
$in: entriesToDelete.map((entry) => entry.id)
|
|
334
|
-
}
|
|
335
|
-
}
|
|
457
|
+
const model = strapi2.getModel(event.model.uid);
|
|
458
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
459
|
+
const { where } = event.params;
|
|
460
|
+
deleteReleasesActionsAndUpdateReleaseStatus({
|
|
461
|
+
contentType: model.uid,
|
|
462
|
+
locale: where.locale ?? null,
|
|
463
|
+
...where.documentId && { entryDocumentId: where.documentId }
|
|
336
464
|
});
|
|
337
|
-
for (const release2 of releases) {
|
|
338
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
339
|
-
}
|
|
340
465
|
}
|
|
341
466
|
} catch (error) {
|
|
342
467
|
strapi2.log.error("Error while deleting release actions after entry deleteMany", {
|
|
343
468
|
error
|
|
344
469
|
});
|
|
345
470
|
}
|
|
346
|
-
},
|
|
347
|
-
async afterUpdate(event) {
|
|
348
|
-
try {
|
|
349
|
-
const { model, result } = event;
|
|
350
|
-
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
351
|
-
const isEntryValid = await getEntryValidStatus(model.uid, result, {
|
|
352
|
-
strapi: strapi2
|
|
353
|
-
});
|
|
354
|
-
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
355
|
-
where: {
|
|
356
|
-
target_type: model.uid,
|
|
357
|
-
target_id: result.id
|
|
358
|
-
},
|
|
359
|
-
data: {
|
|
360
|
-
isEntryValid
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
364
|
-
where: {
|
|
365
|
-
actions: {
|
|
366
|
-
target_type: model.uid,
|
|
367
|
-
target_id: result.id
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
for (const release2 of releases) {
|
|
372
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
} catch (error) {
|
|
376
|
-
strapi2.log.error("Error while updating release actions after entry update", { error });
|
|
377
|
-
}
|
|
378
471
|
}
|
|
379
472
|
});
|
|
473
|
+
strapi2.documents.use(deleteActionsOnDelete);
|
|
474
|
+
strapi2.documents.use(updateActionsOnUpdate);
|
|
380
475
|
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
381
476
|
strapi2.log.error(
|
|
382
477
|
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
@@ -384,7 +479,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
384
479
|
throw err;
|
|
385
480
|
});
|
|
386
481
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
387
|
-
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
482
|
+
strapi2.get("webhookStore").addAllowedEvent(key, value);
|
|
388
483
|
});
|
|
389
484
|
}
|
|
390
485
|
};
|
|
@@ -468,15 +563,13 @@ const schema = {
|
|
|
468
563
|
enum: ["publish", "unpublish"],
|
|
469
564
|
required: true
|
|
470
565
|
},
|
|
471
|
-
entry: {
|
|
472
|
-
type: "relation",
|
|
473
|
-
relation: "morphToOne",
|
|
474
|
-
configurable: false
|
|
475
|
-
},
|
|
476
566
|
contentType: {
|
|
477
567
|
type: "string",
|
|
478
568
|
required: true
|
|
479
569
|
},
|
|
570
|
+
entryDocumentId: {
|
|
571
|
+
type: "string"
|
|
572
|
+
},
|
|
480
573
|
locale: {
|
|
481
574
|
type: "string"
|
|
482
575
|
},
|
|
@@ -498,18 +591,6 @@ const contentTypes = {
|
|
|
498
591
|
release: release$1,
|
|
499
592
|
"release-action": releaseAction$1
|
|
500
593
|
};
|
|
501
|
-
const getGroupName = (queryValue) => {
|
|
502
|
-
switch (queryValue) {
|
|
503
|
-
case "contentType":
|
|
504
|
-
return "contentType.displayName";
|
|
505
|
-
case "action":
|
|
506
|
-
return "type";
|
|
507
|
-
case "locale":
|
|
508
|
-
return _.getOr("No locale", "locale.name");
|
|
509
|
-
default:
|
|
510
|
-
return "contentType.displayName";
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
594
|
const createReleaseService = ({ strapi: strapi2 }) => {
|
|
514
595
|
const dispatchWebhook = (event, { isPublished, release: release2, error }) => {
|
|
515
596
|
strapi2.eventHub.emit(event, {
|
|
@@ -518,93 +599,32 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
518
599
|
release: release2
|
|
519
600
|
});
|
|
520
601
|
};
|
|
521
|
-
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
522
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
523
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
524
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
525
|
-
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
526
|
-
try {
|
|
527
|
-
if (actionType === "publish") {
|
|
528
|
-
await entityManagerService.publish(entry, uid);
|
|
529
|
-
} else {
|
|
530
|
-
await entityManagerService.unpublish(entry, uid);
|
|
531
|
-
}
|
|
532
|
-
} catch (error) {
|
|
533
|
-
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
534
|
-
;
|
|
535
|
-
else {
|
|
536
|
-
throw error;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
541
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
542
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
543
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
544
|
-
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
545
|
-
filters: {
|
|
546
|
-
id: {
|
|
547
|
-
$in: entriesToPublishIds
|
|
548
|
-
}
|
|
549
|
-
},
|
|
550
|
-
populate
|
|
551
|
-
});
|
|
552
|
-
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
553
|
-
filters: {
|
|
554
|
-
id: {
|
|
555
|
-
$in: entriestoUnpublishIds
|
|
556
|
-
}
|
|
557
|
-
},
|
|
558
|
-
populate
|
|
559
|
-
});
|
|
560
|
-
if (entriesToPublish.length > 0) {
|
|
561
|
-
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
562
|
-
}
|
|
563
|
-
if (entriesToUnpublish.length > 0) {
|
|
564
|
-
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
602
|
const getFormattedActions = async (releaseId) => {
|
|
568
603
|
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
569
604
|
where: {
|
|
570
605
|
release: {
|
|
571
606
|
id: releaseId
|
|
572
607
|
}
|
|
573
|
-
},
|
|
574
|
-
populate: {
|
|
575
|
-
entry: {
|
|
576
|
-
fields: ["id"]
|
|
577
|
-
}
|
|
578
608
|
}
|
|
579
609
|
});
|
|
580
610
|
if (actions.length === 0) {
|
|
581
611
|
throw new errors.ValidationError("No entries to publish");
|
|
582
612
|
}
|
|
583
|
-
const
|
|
584
|
-
const singleTypeActions = [];
|
|
613
|
+
const formattedActions = {};
|
|
585
614
|
for (const action of actions) {
|
|
586
615
|
const contentTypeUid = action.contentType;
|
|
587
|
-
if (
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
if (action.type === "publish") {
|
|
595
|
-
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
596
|
-
} else {
|
|
597
|
-
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
598
|
-
}
|
|
599
|
-
} else {
|
|
600
|
-
singleTypeActions.push({
|
|
601
|
-
uid: contentTypeUid,
|
|
602
|
-
action: action.type,
|
|
603
|
-
id: action.entry.id
|
|
604
|
-
});
|
|
616
|
+
if (!formattedActions[contentTypeUid]) {
|
|
617
|
+
formattedActions[contentTypeUid] = {
|
|
618
|
+
publish: [],
|
|
619
|
+
unpublish: []
|
|
620
|
+
};
|
|
605
621
|
}
|
|
622
|
+
formattedActions[contentTypeUid][action.type].push({
|
|
623
|
+
documentId: action.entryDocumentId,
|
|
624
|
+
locale: action.locale
|
|
625
|
+
});
|
|
606
626
|
}
|
|
607
|
-
return
|
|
627
|
+
return formattedActions;
|
|
608
628
|
};
|
|
609
629
|
return {
|
|
610
630
|
async create(releaseData, { user }) {
|
|
@@ -651,78 +671,10 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
651
671
|
}
|
|
652
672
|
});
|
|
653
673
|
},
|
|
654
|
-
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
target_type: contentTypeUid,
|
|
659
|
-
target_id: entryId
|
|
660
|
-
},
|
|
661
|
-
releasedAt: {
|
|
662
|
-
$null: true
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
populate: {
|
|
666
|
-
// Filter the action to get only the content type entry
|
|
667
|
-
actions: {
|
|
668
|
-
where: {
|
|
669
|
-
target_type: contentTypeUid,
|
|
670
|
-
target_id: entryId
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
return releases.map((release2) => {
|
|
676
|
-
if (release2.actions?.length) {
|
|
677
|
-
const [actionForEntry] = release2.actions;
|
|
678
|
-
delete release2.actions;
|
|
679
|
-
return {
|
|
680
|
-
...release2,
|
|
681
|
-
action: actionForEntry
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
return release2;
|
|
685
|
-
});
|
|
686
|
-
},
|
|
687
|
-
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
688
|
-
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
689
|
-
where: {
|
|
690
|
-
releasedAt: {
|
|
691
|
-
$null: true
|
|
692
|
-
},
|
|
693
|
-
actions: {
|
|
694
|
-
target_type: contentTypeUid,
|
|
695
|
-
target_id: entryId
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
});
|
|
699
|
-
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
700
|
-
where: {
|
|
701
|
-
$or: [
|
|
702
|
-
{
|
|
703
|
-
id: {
|
|
704
|
-
$notIn: releasesRelated.map((release2) => release2.id)
|
|
705
|
-
}
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
actions: null
|
|
709
|
-
}
|
|
710
|
-
],
|
|
711
|
-
releasedAt: {
|
|
712
|
-
$null: true
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
});
|
|
716
|
-
return releases.map((release2) => {
|
|
717
|
-
if (release2.actions?.length) {
|
|
718
|
-
const [actionForEntry] = release2.actions;
|
|
719
|
-
delete release2.actions;
|
|
720
|
-
return {
|
|
721
|
-
...release2,
|
|
722
|
-
action: actionForEntry
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
return release2;
|
|
674
|
+
findMany(query) {
|
|
675
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_MODEL_UID, query ?? {});
|
|
676
|
+
return strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
677
|
+
...dbQuery
|
|
726
678
|
});
|
|
727
679
|
},
|
|
728
680
|
async update(id, releaseData, { user }) {
|
|
@@ -758,133 +710,6 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
758
710
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
759
711
|
return updatedRelease;
|
|
760
712
|
},
|
|
761
|
-
async createAction(releaseId, action) {
|
|
762
|
-
const { validateEntryContentType, validateUniqueEntry } = getService("release-validation", {
|
|
763
|
-
strapi: strapi2
|
|
764
|
-
});
|
|
765
|
-
await Promise.all([
|
|
766
|
-
validateEntryContentType(action.entry.contentType),
|
|
767
|
-
validateUniqueEntry(releaseId, action)
|
|
768
|
-
]);
|
|
769
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
770
|
-
if (!release2) {
|
|
771
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
772
|
-
}
|
|
773
|
-
if (release2.releasedAt) {
|
|
774
|
-
throw new errors.ValidationError("Release already published");
|
|
775
|
-
}
|
|
776
|
-
const { entry, type } = action;
|
|
777
|
-
const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
|
|
778
|
-
const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
|
|
779
|
-
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
780
|
-
data: {
|
|
781
|
-
type,
|
|
782
|
-
contentType: entry.contentType,
|
|
783
|
-
locale: entry.locale,
|
|
784
|
-
isEntryValid,
|
|
785
|
-
entry: {
|
|
786
|
-
id: entry.id,
|
|
787
|
-
__type: entry.contentType,
|
|
788
|
-
__pivot: { field: "entry" }
|
|
789
|
-
},
|
|
790
|
-
release: releaseId
|
|
791
|
-
},
|
|
792
|
-
populate: { release: { select: ["id"] }, entry: { select: ["id"] } }
|
|
793
|
-
});
|
|
794
|
-
this.updateReleaseStatus(releaseId);
|
|
795
|
-
return releaseAction2;
|
|
796
|
-
},
|
|
797
|
-
async findActions(releaseId, query) {
|
|
798
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
799
|
-
where: { id: releaseId },
|
|
800
|
-
select: ["id"]
|
|
801
|
-
});
|
|
802
|
-
if (!release2) {
|
|
803
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
804
|
-
}
|
|
805
|
-
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
806
|
-
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
807
|
-
...dbQuery,
|
|
808
|
-
populate: {
|
|
809
|
-
entry: {
|
|
810
|
-
populate: "*"
|
|
811
|
-
}
|
|
812
|
-
},
|
|
813
|
-
where: {
|
|
814
|
-
release: releaseId
|
|
815
|
-
}
|
|
816
|
-
});
|
|
817
|
-
},
|
|
818
|
-
async countActions(query) {
|
|
819
|
-
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
820
|
-
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
821
|
-
},
|
|
822
|
-
async groupActions(actions, groupBy) {
|
|
823
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
824
|
-
if (!acc.includes(action.contentType)) {
|
|
825
|
-
acc.push(action.contentType);
|
|
826
|
-
}
|
|
827
|
-
return acc;
|
|
828
|
-
}, []);
|
|
829
|
-
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
|
|
830
|
-
contentTypeUids
|
|
831
|
-
);
|
|
832
|
-
const allLocalesDictionary = await this.getLocalesDataForActions();
|
|
833
|
-
const formattedData = actions.map((action) => {
|
|
834
|
-
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
835
|
-
return {
|
|
836
|
-
...action,
|
|
837
|
-
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
838
|
-
contentType: {
|
|
839
|
-
displayName,
|
|
840
|
-
mainFieldValue: action.entry[mainField],
|
|
841
|
-
uid: action.contentType
|
|
842
|
-
}
|
|
843
|
-
};
|
|
844
|
-
});
|
|
845
|
-
const groupName = getGroupName(groupBy);
|
|
846
|
-
return _.groupBy(groupName)(formattedData);
|
|
847
|
-
},
|
|
848
|
-
async getLocalesDataForActions() {
|
|
849
|
-
if (!strapi2.plugin("i18n")) {
|
|
850
|
-
return {};
|
|
851
|
-
}
|
|
852
|
-
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
853
|
-
return allLocales.reduce((acc, locale) => {
|
|
854
|
-
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
855
|
-
return acc;
|
|
856
|
-
}, {});
|
|
857
|
-
},
|
|
858
|
-
async getContentTypesDataForActions(contentTypesUids) {
|
|
859
|
-
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
860
|
-
const contentTypesData = {};
|
|
861
|
-
for (const contentTypeUid of contentTypesUids) {
|
|
862
|
-
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
863
|
-
uid: contentTypeUid
|
|
864
|
-
});
|
|
865
|
-
contentTypesData[contentTypeUid] = {
|
|
866
|
-
mainField: contentTypeConfig.settings.mainField,
|
|
867
|
-
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
return contentTypesData;
|
|
871
|
-
},
|
|
872
|
-
getContentTypeModelsFromActions(actions) {
|
|
873
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
874
|
-
if (!acc.includes(action.contentType)) {
|
|
875
|
-
acc.push(action.contentType);
|
|
876
|
-
}
|
|
877
|
-
return acc;
|
|
878
|
-
}, []);
|
|
879
|
-
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
880
|
-
(acc, contentTypeUid) => {
|
|
881
|
-
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
882
|
-
return acc;
|
|
883
|
-
},
|
|
884
|
-
{}
|
|
885
|
-
);
|
|
886
|
-
return contentTypeModelsMap;
|
|
887
|
-
},
|
|
888
713
|
async getAllComponents() {
|
|
889
714
|
const contentManagerComponentsService = strapi2.plugin("content-manager").service("components");
|
|
890
715
|
const components = await contentManagerComponentsService.findAllComponents();
|
|
@@ -950,22 +775,19 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
950
775
|
}
|
|
951
776
|
try {
|
|
952
777
|
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
953
|
-
const
|
|
954
|
-
|
|
778
|
+
const formattedActions = await getFormattedActions(releaseId);
|
|
779
|
+
await strapi2.db.transaction(
|
|
780
|
+
async () => Promise.all(
|
|
781
|
+
Object.keys(formattedActions).map(async (contentTypeUid) => {
|
|
782
|
+
const contentType = contentTypeUid;
|
|
783
|
+
const { publish, unpublish } = formattedActions[contentType];
|
|
784
|
+
return Promise.all([
|
|
785
|
+
...publish.map((params) => strapi2.documents(contentType).publish(params)),
|
|
786
|
+
...unpublish.map((params) => strapi2.documents(contentType).unpublish(params))
|
|
787
|
+
]);
|
|
788
|
+
})
|
|
789
|
+
)
|
|
955
790
|
);
|
|
956
|
-
await strapi2.db.transaction(async () => {
|
|
957
|
-
for (const { uid, action, id } of singleTypeActions) {
|
|
958
|
-
await publishSingleTypeAction(uid, action, id);
|
|
959
|
-
}
|
|
960
|
-
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
961
|
-
const uid = contentTypeUid;
|
|
962
|
-
await publishCollectionTypeAction(
|
|
963
|
-
uid,
|
|
964
|
-
collectionTypeActions[uid].entriesToPublishIds,
|
|
965
|
-
collectionTypeActions[uid].entriesToUnpublishIds
|
|
966
|
-
);
|
|
967
|
-
}
|
|
968
|
-
});
|
|
969
791
|
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
970
792
|
where: {
|
|
971
793
|
id: releaseId
|
|
@@ -995,13 +817,216 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
995
817
|
};
|
|
996
818
|
}
|
|
997
819
|
});
|
|
998
|
-
if (error instanceof Error) {
|
|
999
|
-
throw error;
|
|
1000
|
-
}
|
|
1001
|
-
return release2;
|
|
820
|
+
if (error instanceof Error) {
|
|
821
|
+
throw error;
|
|
822
|
+
}
|
|
823
|
+
return release2;
|
|
824
|
+
},
|
|
825
|
+
async updateReleaseStatus(releaseId) {
|
|
826
|
+
const releaseActionService = getService("release-action", { strapi: strapi2 });
|
|
827
|
+
const [totalActions, invalidActions] = await Promise.all([
|
|
828
|
+
releaseActionService.countActions({
|
|
829
|
+
filters: {
|
|
830
|
+
release: releaseId
|
|
831
|
+
}
|
|
832
|
+
}),
|
|
833
|
+
releaseActionService.countActions({
|
|
834
|
+
filters: {
|
|
835
|
+
release: releaseId,
|
|
836
|
+
isEntryValid: false
|
|
837
|
+
}
|
|
838
|
+
})
|
|
839
|
+
]);
|
|
840
|
+
if (totalActions > 0) {
|
|
841
|
+
if (invalidActions > 0) {
|
|
842
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
843
|
+
where: {
|
|
844
|
+
id: releaseId
|
|
845
|
+
},
|
|
846
|
+
data: {
|
|
847
|
+
status: "blocked"
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
852
|
+
where: {
|
|
853
|
+
id: releaseId
|
|
854
|
+
},
|
|
855
|
+
data: {
|
|
856
|
+
status: "ready"
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
861
|
+
where: {
|
|
862
|
+
id: releaseId
|
|
863
|
+
},
|
|
864
|
+
data: {
|
|
865
|
+
status: "empty"
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
};
|
|
871
|
+
const getGroupName = (queryValue) => {
|
|
872
|
+
switch (queryValue) {
|
|
873
|
+
case "contentType":
|
|
874
|
+
return "contentType.displayName";
|
|
875
|
+
case "type":
|
|
876
|
+
return "type";
|
|
877
|
+
case "locale":
|
|
878
|
+
return _.getOr("No locale", "locale.name");
|
|
879
|
+
default:
|
|
880
|
+
return "contentType.displayName";
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
884
|
+
const getLocalesDataForActions = async () => {
|
|
885
|
+
if (!strapi2.plugin("i18n")) {
|
|
886
|
+
return {};
|
|
887
|
+
}
|
|
888
|
+
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
889
|
+
return allLocales.reduce((acc, locale) => {
|
|
890
|
+
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
891
|
+
return acc;
|
|
892
|
+
}, {});
|
|
893
|
+
};
|
|
894
|
+
const getContentTypesDataForActions = async (contentTypesUids) => {
|
|
895
|
+
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
896
|
+
const contentTypesData = {};
|
|
897
|
+
for (const contentTypeUid of contentTypesUids) {
|
|
898
|
+
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
899
|
+
uid: contentTypeUid
|
|
900
|
+
});
|
|
901
|
+
contentTypesData[contentTypeUid] = {
|
|
902
|
+
mainField: contentTypeConfig.settings.mainField,
|
|
903
|
+
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
return contentTypesData;
|
|
907
|
+
};
|
|
908
|
+
return {
|
|
909
|
+
async create(releaseId, action) {
|
|
910
|
+
const { validateEntryData, validateUniqueEntry } = getService("release-validation", {
|
|
911
|
+
strapi: strapi2
|
|
912
|
+
});
|
|
913
|
+
await Promise.all([
|
|
914
|
+
validateEntryData(action.contentType, action.entryDocumentId),
|
|
915
|
+
validateUniqueEntry(releaseId, action)
|
|
916
|
+
]);
|
|
917
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
918
|
+
if (!release2) {
|
|
919
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
920
|
+
}
|
|
921
|
+
if (release2.releasedAt) {
|
|
922
|
+
throw new errors.ValidationError("Release already published");
|
|
923
|
+
}
|
|
924
|
+
const actionStatus = action.type === "publish" ? await getDraftEntryValidStatus(
|
|
925
|
+
{
|
|
926
|
+
contentType: action.contentType,
|
|
927
|
+
documentId: action.entryDocumentId,
|
|
928
|
+
locale: action.locale
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
strapi: strapi2
|
|
932
|
+
}
|
|
933
|
+
) : true;
|
|
934
|
+
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
935
|
+
data: {
|
|
936
|
+
...action,
|
|
937
|
+
release: release2.id,
|
|
938
|
+
isEntryValid: actionStatus
|
|
939
|
+
},
|
|
940
|
+
populate: { release: { select: ["id"] } }
|
|
941
|
+
});
|
|
942
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
943
|
+
return releaseAction2;
|
|
944
|
+
},
|
|
945
|
+
async findPage(releaseId, query) {
|
|
946
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
947
|
+
where: { id: releaseId },
|
|
948
|
+
select: ["id"]
|
|
949
|
+
});
|
|
950
|
+
if (!release2) {
|
|
951
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
952
|
+
}
|
|
953
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
954
|
+
const { results: actions, pagination } = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
955
|
+
...dbQuery,
|
|
956
|
+
where: {
|
|
957
|
+
release: releaseId
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
961
|
+
const actionsWithEntry = await async.map(actions, async (action) => {
|
|
962
|
+
const populate = await populateBuilderService(action.contentType).populateDeep(Infinity).build();
|
|
963
|
+
const entry = await getEntry(
|
|
964
|
+
{
|
|
965
|
+
contentType: action.contentType,
|
|
966
|
+
documentId: action.entryDocumentId,
|
|
967
|
+
locale: action.locale,
|
|
968
|
+
populate,
|
|
969
|
+
status: action.type === "publish" ? "draft" : "published"
|
|
970
|
+
},
|
|
971
|
+
{ strapi: strapi2 }
|
|
972
|
+
);
|
|
973
|
+
return {
|
|
974
|
+
...action,
|
|
975
|
+
entry,
|
|
976
|
+
status: entry ? await getEntryStatus(action.contentType, entry) : null
|
|
977
|
+
};
|
|
978
|
+
});
|
|
979
|
+
return {
|
|
980
|
+
results: actionsWithEntry,
|
|
981
|
+
pagination
|
|
982
|
+
};
|
|
983
|
+
},
|
|
984
|
+
async groupActions(actions, groupBy) {
|
|
985
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
986
|
+
if (!acc.includes(action.contentType)) {
|
|
987
|
+
acc.push(action.contentType);
|
|
988
|
+
}
|
|
989
|
+
return acc;
|
|
990
|
+
}, []);
|
|
991
|
+
const allReleaseContentTypesDictionary = await getContentTypesDataForActions(contentTypeUids);
|
|
992
|
+
const allLocalesDictionary = await getLocalesDataForActions();
|
|
993
|
+
const formattedData = actions.map((action) => {
|
|
994
|
+
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
995
|
+
return {
|
|
996
|
+
...action,
|
|
997
|
+
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
998
|
+
contentType: {
|
|
999
|
+
displayName,
|
|
1000
|
+
mainFieldValue: action.entry[mainField],
|
|
1001
|
+
uid: action.contentType
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
});
|
|
1005
|
+
const groupName = getGroupName(groupBy);
|
|
1006
|
+
return _.groupBy(groupName)(formattedData);
|
|
1002
1007
|
},
|
|
1003
|
-
|
|
1004
|
-
const
|
|
1008
|
+
getContentTypeModelsFromActions(actions) {
|
|
1009
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
1010
|
+
if (!acc.includes(action.contentType)) {
|
|
1011
|
+
acc.push(action.contentType);
|
|
1012
|
+
}
|
|
1013
|
+
return acc;
|
|
1014
|
+
}, []);
|
|
1015
|
+
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
1016
|
+
(acc, contentTypeUid) => {
|
|
1017
|
+
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
1018
|
+
return acc;
|
|
1019
|
+
},
|
|
1020
|
+
{}
|
|
1021
|
+
);
|
|
1022
|
+
return contentTypeModelsMap;
|
|
1023
|
+
},
|
|
1024
|
+
async countActions(query) {
|
|
1025
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
1026
|
+
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
1027
|
+
},
|
|
1028
|
+
async update(actionId, releaseId, update) {
|
|
1029
|
+
const action = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findOne({
|
|
1005
1030
|
where: {
|
|
1006
1031
|
id: actionId,
|
|
1007
1032
|
release: {
|
|
@@ -1010,17 +1035,42 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1010
1035
|
$null: true
|
|
1011
1036
|
}
|
|
1012
1037
|
}
|
|
1013
|
-
}
|
|
1014
|
-
data: update
|
|
1038
|
+
}
|
|
1015
1039
|
});
|
|
1016
|
-
if (!
|
|
1040
|
+
if (!action) {
|
|
1017
1041
|
throw new errors.NotFoundError(
|
|
1018
1042
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1019
1043
|
);
|
|
1020
1044
|
}
|
|
1045
|
+
const actionStatus = update.type === "publish" ? getDraftEntryValidStatus(
|
|
1046
|
+
{
|
|
1047
|
+
contentType: action.contentType,
|
|
1048
|
+
documentId: action.entryDocumentId,
|
|
1049
|
+
locale: action.locale
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
strapi: strapi2
|
|
1053
|
+
}
|
|
1054
|
+
) : true;
|
|
1055
|
+
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
1056
|
+
where: {
|
|
1057
|
+
id: actionId,
|
|
1058
|
+
release: {
|
|
1059
|
+
id: releaseId,
|
|
1060
|
+
releasedAt: {
|
|
1061
|
+
$null: true
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
},
|
|
1065
|
+
data: {
|
|
1066
|
+
...update,
|
|
1067
|
+
isEntryValid: actionStatus
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(releaseId);
|
|
1021
1071
|
return updatedAction;
|
|
1022
1072
|
},
|
|
1023
|
-
async
|
|
1073
|
+
async delete(actionId, releaseId) {
|
|
1024
1074
|
const deletedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).delete({
|
|
1025
1075
|
where: {
|
|
1026
1076
|
id: actionId,
|
|
@@ -1037,51 +1087,8 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
1037
1087
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1038
1088
|
);
|
|
1039
1089
|
}
|
|
1040
|
-
|
|
1090
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(releaseId);
|
|
1041
1091
|
return deletedAction;
|
|
1042
|
-
},
|
|
1043
|
-
async updateReleaseStatus(releaseId) {
|
|
1044
|
-
const [totalActions, invalidActions] = await Promise.all([
|
|
1045
|
-
this.countActions({
|
|
1046
|
-
filters: {
|
|
1047
|
-
release: releaseId
|
|
1048
|
-
}
|
|
1049
|
-
}),
|
|
1050
|
-
this.countActions({
|
|
1051
|
-
filters: {
|
|
1052
|
-
release: releaseId,
|
|
1053
|
-
isEntryValid: false
|
|
1054
|
-
}
|
|
1055
|
-
})
|
|
1056
|
-
]);
|
|
1057
|
-
if (totalActions > 0) {
|
|
1058
|
-
if (invalidActions > 0) {
|
|
1059
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1060
|
-
where: {
|
|
1061
|
-
id: releaseId
|
|
1062
|
-
},
|
|
1063
|
-
data: {
|
|
1064
|
-
status: "blocked"
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1069
|
-
where: {
|
|
1070
|
-
id: releaseId
|
|
1071
|
-
},
|
|
1072
|
-
data: {
|
|
1073
|
-
status: "ready"
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
}
|
|
1077
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1078
|
-
where: {
|
|
1079
|
-
id: releaseId
|
|
1080
|
-
},
|
|
1081
|
-
data: {
|
|
1082
|
-
status: "empty"
|
|
1083
|
-
}
|
|
1084
|
-
});
|
|
1085
1092
|
}
|
|
1086
1093
|
};
|
|
1087
1094
|
};
|
|
@@ -1097,33 +1104,39 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1097
1104
|
where: {
|
|
1098
1105
|
id: releaseId
|
|
1099
1106
|
},
|
|
1100
|
-
populate: {
|
|
1107
|
+
populate: {
|
|
1108
|
+
actions: true
|
|
1109
|
+
}
|
|
1101
1110
|
});
|
|
1102
1111
|
if (!release2) {
|
|
1103
1112
|
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
1104
1113
|
}
|
|
1105
1114
|
const isEntryInRelease = release2.actions.some(
|
|
1106
|
-
(action) => Number(action.
|
|
1115
|
+
(action) => Number(action.entryDocumentId) === Number(releaseActionArgs.entryDocumentId) && action.contentType === releaseActionArgs.contentType && action.locale === releaseActionArgs.locale
|
|
1107
1116
|
);
|
|
1108
1117
|
if (isEntryInRelease) {
|
|
1109
1118
|
throw new AlreadyOnReleaseError(
|
|
1110
|
-
`Entry with
|
|
1119
|
+
`Entry with documentId ${releaseActionArgs.entryDocumentId} ${releaseActionArgs.locale ? `(${releaseActionArgs.locale})` : ""} and contentType ${releaseActionArgs.contentType} already exists in release with id ${releaseId}`
|
|
1111
1120
|
);
|
|
1112
1121
|
}
|
|
1113
1122
|
},
|
|
1114
|
-
|
|
1123
|
+
validateEntryData(contentTypeUid, entryDocumentId) {
|
|
1115
1124
|
const contentType = strapi2.contentType(contentTypeUid);
|
|
1116
1125
|
if (!contentType) {
|
|
1117
1126
|
throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
|
1118
1127
|
}
|
|
1119
|
-
if (!contentType
|
|
1128
|
+
if (!contentTypes$1.hasDraftAndPublish(contentType)) {
|
|
1120
1129
|
throw new errors.ValidationError(
|
|
1121
1130
|
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
1122
1131
|
);
|
|
1123
1132
|
}
|
|
1133
|
+
if (contentType.kind === "collectionType" && !entryDocumentId) {
|
|
1134
|
+
throw new errors.ValidationError("Document id is required for collection type");
|
|
1135
|
+
}
|
|
1124
1136
|
},
|
|
1125
1137
|
async validatePendingReleasesLimit() {
|
|
1126
|
-
const
|
|
1138
|
+
const featureCfg = strapi2.ee.features.get("cms-content-releases");
|
|
1139
|
+
const maximumPendingReleases = typeof featureCfg === "object" && featureCfg?.options?.maximumReleases || 3;
|
|
1127
1140
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
1128
1141
|
filters: {
|
|
1129
1142
|
releasedAt: {
|
|
@@ -1166,7 +1179,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1166
1179
|
}
|
|
1167
1180
|
const job = scheduleJob(scheduleDate, async () => {
|
|
1168
1181
|
try {
|
|
1169
|
-
await getService("release").publish(releaseId);
|
|
1182
|
+
await getService("release", { strapi: strapi2 }).publish(releaseId);
|
|
1170
1183
|
} catch (error) {
|
|
1171
1184
|
}
|
|
1172
1185
|
this.cancel(releaseId);
|
|
@@ -1208,10 +1221,33 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1208
1221
|
}
|
|
1209
1222
|
};
|
|
1210
1223
|
};
|
|
1224
|
+
const DEFAULT_SETTINGS = {
|
|
1225
|
+
defaultTimezone: null
|
|
1226
|
+
};
|
|
1227
|
+
const createSettingsService = ({ strapi: strapi2 }) => {
|
|
1228
|
+
const getStore = async () => strapi2.store({ type: "core", name: "content-releases" });
|
|
1229
|
+
return {
|
|
1230
|
+
async update({ settings: settings2 }) {
|
|
1231
|
+
const store = await getStore();
|
|
1232
|
+
store.set({ key: "settings", value: settings2 });
|
|
1233
|
+
return settings2;
|
|
1234
|
+
},
|
|
1235
|
+
async find() {
|
|
1236
|
+
const store = await getStore();
|
|
1237
|
+
const settings2 = await store.get({ key: "settings" });
|
|
1238
|
+
return {
|
|
1239
|
+
...DEFAULT_SETTINGS,
|
|
1240
|
+
...settings2 || {}
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
};
|
|
1211
1245
|
const services = {
|
|
1212
1246
|
release: createReleaseService,
|
|
1247
|
+
"release-action": createReleaseActionService,
|
|
1213
1248
|
"release-validation": createReleaseValidationService,
|
|
1214
|
-
scheduling: createSchedulingService
|
|
1249
|
+
scheduling: createSchedulingService,
|
|
1250
|
+
settings: createSettingsService
|
|
1215
1251
|
};
|
|
1216
1252
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
1217
1253
|
name: yup.string().trim().required(),
|
|
@@ -1233,60 +1269,125 @@ const RELEASE_SCHEMA = yup.object().shape({
|
|
|
1233
1269
|
otherwise: yup.string().nullable()
|
|
1234
1270
|
})
|
|
1235
1271
|
}).required().noUnknown();
|
|
1272
|
+
const SETTINGS_SCHEMA = yup.object().shape({
|
|
1273
|
+
defaultTimezone: yup.string().nullable().default(null)
|
|
1274
|
+
}).required().noUnknown();
|
|
1275
|
+
const FIND_BY_DOCUMENT_ATTACHED_PARAMS_SCHEMA = yup$1.object().shape({
|
|
1276
|
+
contentType: yup$1.string().required(),
|
|
1277
|
+
entryDocumentId: yup$1.string().nullable(),
|
|
1278
|
+
hasEntryAttached: yup$1.string().nullable(),
|
|
1279
|
+
locale: yup$1.string().nullable()
|
|
1280
|
+
}).required().noUnknown();
|
|
1236
1281
|
const validateRelease = validateYupSchema(RELEASE_SCHEMA);
|
|
1282
|
+
const validatefindByDocumentAttachedParams = validateYupSchema(
|
|
1283
|
+
FIND_BY_DOCUMENT_ATTACHED_PARAMS_SCHEMA
|
|
1284
|
+
);
|
|
1237
1285
|
const releaseController = {
|
|
1238
|
-
|
|
1239
|
-
|
|
1286
|
+
/**
|
|
1287
|
+
* Find releases based on documents attached or not to the release.
|
|
1288
|
+
* If `hasEntryAttached` is true, it will return all releases that have the entry attached.
|
|
1289
|
+
* If `hasEntryAttached` is false, it will return all releases that don't have the entry attached.
|
|
1290
|
+
*/
|
|
1291
|
+
async findByDocumentAttached(ctx) {
|
|
1292
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1240
1293
|
ability: ctx.state.userAbility,
|
|
1241
1294
|
model: RELEASE_MODEL_UID
|
|
1242
1295
|
});
|
|
1243
1296
|
await permissionsManager.validateQuery(ctx.query);
|
|
1244
1297
|
const releaseService = getService("release", { strapi });
|
|
1245
|
-
const
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1298
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1299
|
+
await validatefindByDocumentAttachedParams(query);
|
|
1300
|
+
const { contentType, entryDocumentId, hasEntryAttached, locale } = query;
|
|
1301
|
+
const isEntryAttached = typeof hasEntryAttached === "string" ? Boolean(JSON.parse(hasEntryAttached)) : false;
|
|
1302
|
+
if (isEntryAttached) {
|
|
1303
|
+
const releases = await releaseService.findMany({
|
|
1304
|
+
where: {
|
|
1305
|
+
releasedAt: null,
|
|
1306
|
+
actions: {
|
|
1307
|
+
contentType,
|
|
1308
|
+
entryDocumentId: entryDocumentId ?? null,
|
|
1309
|
+
locale: locale ?? null
|
|
1310
|
+
}
|
|
1311
|
+
},
|
|
1312
|
+
populate: {
|
|
1313
|
+
actions: {
|
|
1314
|
+
fields: ["type"]
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1318
|
+
ctx.body = { data: releases };
|
|
1253
1319
|
} else {
|
|
1254
|
-
const
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
const { actions, ...releaseData } = release2;
|
|
1258
|
-
return {
|
|
1259
|
-
...releaseData,
|
|
1320
|
+
const relatedReleases = await releaseService.findMany({
|
|
1321
|
+
where: {
|
|
1322
|
+
releasedAt: null,
|
|
1260
1323
|
actions: {
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1324
|
+
contentType,
|
|
1325
|
+
entryDocumentId: entryDocumentId ?? null,
|
|
1326
|
+
locale: locale ?? null
|
|
1264
1327
|
}
|
|
1265
|
-
}
|
|
1328
|
+
}
|
|
1266
1329
|
});
|
|
1267
|
-
const
|
|
1330
|
+
const releases = await releaseService.findMany({
|
|
1268
1331
|
where: {
|
|
1332
|
+
$or: [
|
|
1333
|
+
{
|
|
1334
|
+
id: {
|
|
1335
|
+
$notIn: relatedReleases.map((release2) => release2.id)
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
actions: null
|
|
1340
|
+
}
|
|
1341
|
+
],
|
|
1269
1342
|
releasedAt: null
|
|
1270
1343
|
}
|
|
1271
1344
|
});
|
|
1272
|
-
ctx.body = { data
|
|
1345
|
+
ctx.body = { data: releases };
|
|
1273
1346
|
}
|
|
1274
1347
|
},
|
|
1348
|
+
async findPage(ctx) {
|
|
1349
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1350
|
+
ability: ctx.state.userAbility,
|
|
1351
|
+
model: RELEASE_MODEL_UID
|
|
1352
|
+
});
|
|
1353
|
+
await permissionsManager.validateQuery(ctx.query);
|
|
1354
|
+
const releaseService = getService("release", { strapi });
|
|
1355
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1356
|
+
const { results, pagination } = await releaseService.findPage(query);
|
|
1357
|
+
const data = results.map((release2) => {
|
|
1358
|
+
const { actions, ...releaseData } = release2;
|
|
1359
|
+
return {
|
|
1360
|
+
...releaseData,
|
|
1361
|
+
actions: {
|
|
1362
|
+
meta: {
|
|
1363
|
+
count: actions.count
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
});
|
|
1368
|
+
const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
|
|
1369
|
+
where: {
|
|
1370
|
+
releasedAt: null
|
|
1371
|
+
}
|
|
1372
|
+
});
|
|
1373
|
+
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
1374
|
+
},
|
|
1275
1375
|
async findOne(ctx) {
|
|
1276
1376
|
const id = ctx.params.id;
|
|
1277
1377
|
const releaseService = getService("release", { strapi });
|
|
1378
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1278
1379
|
const release2 = await releaseService.findOne(id, { populate: ["createdBy"] });
|
|
1279
1380
|
if (!release2) {
|
|
1280
1381
|
throw new errors.NotFoundError(`Release not found for id: ${id}`);
|
|
1281
1382
|
}
|
|
1282
|
-
const count = await
|
|
1383
|
+
const count = await releaseActionService.countActions({
|
|
1283
1384
|
filters: {
|
|
1284
1385
|
release: id
|
|
1285
1386
|
}
|
|
1286
1387
|
});
|
|
1287
1388
|
const sanitizedRelease = {
|
|
1288
1389
|
...release2,
|
|
1289
|
-
createdBy: release2.createdBy ? strapi.admin
|
|
1390
|
+
createdBy: release2.createdBy ? strapi.service("admin::user").sanitizeUser(release2.createdBy) : null
|
|
1290
1391
|
};
|
|
1291
1392
|
const data = {
|
|
1292
1393
|
...sanitizedRelease,
|
|
@@ -1298,19 +1399,56 @@ const releaseController = {
|
|
|
1298
1399
|
};
|
|
1299
1400
|
ctx.body = { data };
|
|
1300
1401
|
},
|
|
1402
|
+
/* @TODO: Migrate to new api
|
|
1403
|
+
async mapEntriesToReleases(ctx: Koa.Context) {
|
|
1404
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1405
|
+
|
|
1406
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1407
|
+
throw new errors.ValidationError('Missing required query parameters');
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
const releaseService = getService('release', { strapi });
|
|
1411
|
+
|
|
1412
|
+
const releasesWithActions = await releaseService.findMany(
|
|
1413
|
+
contentTypeUid,
|
|
1414
|
+
entriesIds
|
|
1415
|
+
);
|
|
1416
|
+
|
|
1417
|
+
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1418
|
+
// TODO: Fix for v5 removed mappedEntriedToRelease
|
|
1419
|
+
(acc: MapEntriesToReleases.Response['data'], release: Release) => {
|
|
1420
|
+
release.actions.forEach((action) => {
|
|
1421
|
+
if (!acc[action.entry.id]) {
|
|
1422
|
+
acc[action.entry.id] = [{ id: release.id, name: release.name }];
|
|
1423
|
+
} else {
|
|
1424
|
+
acc[action.entry.id].push({ id: release.id, name: release.name });
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
return acc;
|
|
1429
|
+
},
|
|
1430
|
+
// TODO: Fix for v5 removed mappedEntriedToRelease
|
|
1431
|
+
{} as MapEntriesToReleases.Response['data']
|
|
1432
|
+
);
|
|
1433
|
+
|
|
1434
|
+
ctx.body = {
|
|
1435
|
+
data: mappedEntriesInReleases,
|
|
1436
|
+
};
|
|
1437
|
+
},
|
|
1438
|
+
*/
|
|
1301
1439
|
async create(ctx) {
|
|
1302
1440
|
const user = ctx.state.user;
|
|
1303
1441
|
const releaseArgs = ctx.request.body;
|
|
1304
1442
|
await validateRelease(releaseArgs);
|
|
1305
1443
|
const releaseService = getService("release", { strapi });
|
|
1306
1444
|
const release2 = await releaseService.create(releaseArgs, { user });
|
|
1307
|
-
const permissionsManager = strapi.admin
|
|
1445
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1308
1446
|
ability: ctx.state.userAbility,
|
|
1309
1447
|
model: RELEASE_MODEL_UID
|
|
1310
1448
|
});
|
|
1311
|
-
ctx.
|
|
1449
|
+
ctx.created({
|
|
1312
1450
|
data: await permissionsManager.sanitizeOutput(release2)
|
|
1313
|
-
};
|
|
1451
|
+
});
|
|
1314
1452
|
},
|
|
1315
1453
|
async update(ctx) {
|
|
1316
1454
|
const user = ctx.state.user;
|
|
@@ -1319,7 +1457,7 @@ const releaseController = {
|
|
|
1319
1457
|
await validateRelease(releaseArgs);
|
|
1320
1458
|
const releaseService = getService("release", { strapi });
|
|
1321
1459
|
const release2 = await releaseService.update(id, releaseArgs, { user });
|
|
1322
|
-
const permissionsManager = strapi.admin
|
|
1460
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1323
1461
|
ability: ctx.state.userAbility,
|
|
1324
1462
|
model: RELEASE_MODEL_UID
|
|
1325
1463
|
});
|
|
@@ -1336,18 +1474,18 @@ const releaseController = {
|
|
|
1336
1474
|
};
|
|
1337
1475
|
},
|
|
1338
1476
|
async publish(ctx) {
|
|
1339
|
-
const user = ctx.state.user;
|
|
1340
1477
|
const id = ctx.params.id;
|
|
1341
1478
|
const releaseService = getService("release", { strapi });
|
|
1342
|
-
const
|
|
1479
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1480
|
+
const release2 = await releaseService.publish(id);
|
|
1343
1481
|
const [countPublishActions, countUnpublishActions] = await Promise.all([
|
|
1344
|
-
|
|
1482
|
+
releaseActionService.countActions({
|
|
1345
1483
|
filters: {
|
|
1346
1484
|
release: id,
|
|
1347
1485
|
type: "publish"
|
|
1348
1486
|
}
|
|
1349
1487
|
}),
|
|
1350
|
-
|
|
1488
|
+
releaseActionService.countActions({
|
|
1351
1489
|
filters: {
|
|
1352
1490
|
release: id,
|
|
1353
1491
|
type: "unpublish"
|
|
@@ -1365,42 +1503,47 @@ const releaseController = {
|
|
|
1365
1503
|
}
|
|
1366
1504
|
};
|
|
1367
1505
|
const RELEASE_ACTION_SCHEMA = yup$1.object().shape({
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
}).required(),
|
|
1506
|
+
contentType: yup$1.string().required(),
|
|
1507
|
+
entryDocumentId: yup$1.strapiID(),
|
|
1508
|
+
locale: yup$1.string(),
|
|
1372
1509
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1373
1510
|
});
|
|
1374
1511
|
const RELEASE_ACTION_UPDATE_SCHEMA = yup$1.object().shape({
|
|
1375
1512
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1376
1513
|
});
|
|
1514
|
+
const FIND_MANY_ACTIONS_PARAMS = yup$1.object().shape({
|
|
1515
|
+
groupBy: yup$1.string().oneOf(["action", "contentType", "locale"])
|
|
1516
|
+
});
|
|
1377
1517
|
const validateReleaseAction = validateYupSchema(RELEASE_ACTION_SCHEMA);
|
|
1378
1518
|
const validateReleaseActionUpdateSchema = validateYupSchema(RELEASE_ACTION_UPDATE_SCHEMA);
|
|
1519
|
+
const validateFindManyActionsParams = validateYupSchema(FIND_MANY_ACTIONS_PARAMS);
|
|
1379
1520
|
const releaseActionController = {
|
|
1380
1521
|
async create(ctx) {
|
|
1381
1522
|
const releaseId = ctx.params.releaseId;
|
|
1382
1523
|
const releaseActionArgs = ctx.request.body;
|
|
1383
1524
|
await validateReleaseAction(releaseActionArgs);
|
|
1384
|
-
const
|
|
1385
|
-
const releaseAction2 = await
|
|
1386
|
-
ctx.
|
|
1525
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1526
|
+
const releaseAction2 = await releaseActionService.create(releaseId, releaseActionArgs);
|
|
1527
|
+
ctx.created({
|
|
1387
1528
|
data: releaseAction2
|
|
1388
|
-
};
|
|
1529
|
+
});
|
|
1389
1530
|
},
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
const
|
|
1531
|
+
/*
|
|
1532
|
+
async createMany(ctx: Koa.Context) {
|
|
1533
|
+
const releaseId: CreateManyReleaseActions.Request['params']['releaseId'] = ctx.params.releaseId;
|
|
1534
|
+
const releaseActionsArgs = ctx.request.body as CreateManyReleaseActions.Request['body'];
|
|
1393
1535
|
await Promise.all(
|
|
1394
1536
|
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1395
1537
|
);
|
|
1396
|
-
const
|
|
1538
|
+
const releaseActionService = getService('release-action', { strapi });
|
|
1397
1539
|
const releaseActions = await strapi.db.transaction(async () => {
|
|
1398
|
-
const
|
|
1540
|
+
const releaseActions = await Promise.all(
|
|
1399
1541
|
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1400
1542
|
try {
|
|
1401
|
-
const action = await
|
|
1543
|
+
const action = await releaseActionService.create(releaseId, releaseActionArgs);
|
|
1402
1544
|
return action;
|
|
1403
1545
|
} catch (error) {
|
|
1546
|
+
// If the entry is already in the release, we don't want to throw an error, so we catch and ignore it
|
|
1404
1547
|
if (error instanceof AlreadyOnReleaseError) {
|
|
1405
1548
|
return null;
|
|
1406
1549
|
}
|
|
@@ -1408,34 +1551,42 @@ const releaseActionController = {
|
|
|
1408
1551
|
}
|
|
1409
1552
|
})
|
|
1410
1553
|
);
|
|
1411
|
-
return
|
|
1554
|
+
return releaseActions;
|
|
1412
1555
|
});
|
|
1413
1556
|
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1414
|
-
ctx.
|
|
1557
|
+
ctx.created({
|
|
1415
1558
|
data: newReleaseActions,
|
|
1416
1559
|
meta: {
|
|
1417
1560
|
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1418
|
-
totalEntries: releaseActions.length
|
|
1419
|
-
}
|
|
1420
|
-
};
|
|
1561
|
+
totalEntries: releaseActions.length,
|
|
1562
|
+
},
|
|
1563
|
+
});
|
|
1421
1564
|
},
|
|
1565
|
+
*/
|
|
1422
1566
|
async findMany(ctx) {
|
|
1423
1567
|
const releaseId = ctx.params.releaseId;
|
|
1424
|
-
const permissionsManager = strapi.admin
|
|
1568
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1425
1569
|
ability: ctx.state.userAbility,
|
|
1426
1570
|
model: RELEASE_ACTION_MODEL_UID
|
|
1427
1571
|
});
|
|
1572
|
+
await validateFindManyActionsParams(ctx.query);
|
|
1573
|
+
if (ctx.query.groupBy) {
|
|
1574
|
+
if (!["action", "contentType", "locale"].includes(ctx.query.groupBy)) {
|
|
1575
|
+
ctx.badRequest("Invalid groupBy parameter");
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
ctx.query.sort = ctx.query.groupBy === "action" ? "type" : ctx.query.groupBy;
|
|
1579
|
+
delete ctx.query.groupBy;
|
|
1428
1580
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1429
|
-
const
|
|
1430
|
-
const { results, pagination } = await
|
|
1431
|
-
sort: query.groupBy === "action" ? "type" : query.groupBy,
|
|
1581
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1582
|
+
const { results, pagination } = await releaseActionService.findPage(releaseId, {
|
|
1432
1583
|
...query
|
|
1433
1584
|
});
|
|
1434
1585
|
const contentTypeOutputSanitizers = results.reduce((acc, action) => {
|
|
1435
1586
|
if (acc[action.contentType]) {
|
|
1436
1587
|
return acc;
|
|
1437
1588
|
}
|
|
1438
|
-
const contentTypePermissionsManager = strapi.admin
|
|
1589
|
+
const contentTypePermissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1439
1590
|
ability: ctx.state.userAbility,
|
|
1440
1591
|
model: action.contentType
|
|
1441
1592
|
});
|
|
@@ -1444,10 +1595,11 @@ const releaseActionController = {
|
|
|
1444
1595
|
}, {});
|
|
1445
1596
|
const sanitizedResults = await async.map(results, async (action) => ({
|
|
1446
1597
|
...action,
|
|
1447
|
-
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1598
|
+
entry: action.entry ? await contentTypeOutputSanitizers[action.contentType](action.entry) : {}
|
|
1448
1599
|
}));
|
|
1449
|
-
const groupedData = await
|
|
1450
|
-
const contentTypes2 =
|
|
1600
|
+
const groupedData = await releaseActionService.groupActions(sanitizedResults, query.sort);
|
|
1601
|
+
const contentTypes2 = releaseActionService.getContentTypeModelsFromActions(results);
|
|
1602
|
+
const releaseService = getService("release", { strapi });
|
|
1451
1603
|
const components = await releaseService.getAllComponents();
|
|
1452
1604
|
ctx.body = {
|
|
1453
1605
|
data: groupedData,
|
|
@@ -1463,8 +1615,8 @@ const releaseActionController = {
|
|
|
1463
1615
|
const releaseId = ctx.params.releaseId;
|
|
1464
1616
|
const releaseActionUpdateArgs = ctx.request.body;
|
|
1465
1617
|
await validateReleaseActionUpdateSchema(releaseActionUpdateArgs);
|
|
1466
|
-
const
|
|
1467
|
-
const updatedAction = await
|
|
1618
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1619
|
+
const updatedAction = await releaseActionService.update(
|
|
1468
1620
|
actionId,
|
|
1469
1621
|
releaseId,
|
|
1470
1622
|
releaseActionUpdateArgs
|
|
@@ -1476,17 +1628,70 @@ const releaseActionController = {
|
|
|
1476
1628
|
async delete(ctx) {
|
|
1477
1629
|
const actionId = ctx.params.actionId;
|
|
1478
1630
|
const releaseId = ctx.params.releaseId;
|
|
1479
|
-
const
|
|
1480
|
-
const deletedReleaseAction = await
|
|
1631
|
+
const releaseActionService = getService("release-action", { strapi });
|
|
1632
|
+
const deletedReleaseAction = await releaseActionService.delete(actionId, releaseId);
|
|
1481
1633
|
ctx.body = {
|
|
1482
1634
|
data: deletedReleaseAction
|
|
1483
1635
|
};
|
|
1484
1636
|
}
|
|
1485
1637
|
};
|
|
1486
|
-
const
|
|
1638
|
+
const validateSettings = validateYupSchema(SETTINGS_SCHEMA);
|
|
1639
|
+
const settingsController = {
|
|
1640
|
+
async find(ctx) {
|
|
1641
|
+
const settingsService = getService("settings", { strapi });
|
|
1642
|
+
const settings2 = await settingsService.find();
|
|
1643
|
+
ctx.body = { data: settings2 };
|
|
1644
|
+
},
|
|
1645
|
+
async update(ctx) {
|
|
1646
|
+
const settingsBody = ctx.request.body;
|
|
1647
|
+
const settings2 = await validateSettings(settingsBody);
|
|
1648
|
+
const settingsService = getService("settings", { strapi });
|
|
1649
|
+
const updatedSettings = await settingsService.update({ settings: settings2 });
|
|
1650
|
+
ctx.body = { data: updatedSettings };
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
const controllers = {
|
|
1654
|
+
release: releaseController,
|
|
1655
|
+
"release-action": releaseActionController,
|
|
1656
|
+
settings: settingsController
|
|
1657
|
+
};
|
|
1487
1658
|
const release = {
|
|
1488
1659
|
type: "admin",
|
|
1489
1660
|
routes: [
|
|
1661
|
+
/*
|
|
1662
|
+
{
|
|
1663
|
+
method: 'GET',
|
|
1664
|
+
path: '/mapEntriesToReleases',
|
|
1665
|
+
handler: 'release.mapEntriesToReleases',
|
|
1666
|
+
config: {
|
|
1667
|
+
policies: [
|
|
1668
|
+
'admin::isAuthenticatedAdmin',
|
|
1669
|
+
{
|
|
1670
|
+
name: 'admin::hasPermissions',
|
|
1671
|
+
config: {
|
|
1672
|
+
actions: ['plugin::content-releases.read'],
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
],
|
|
1676
|
+
},
|
|
1677
|
+
},
|
|
1678
|
+
*/
|
|
1679
|
+
{
|
|
1680
|
+
method: "GET",
|
|
1681
|
+
path: "/getByDocumentAttached",
|
|
1682
|
+
handler: "release.findByDocumentAttached",
|
|
1683
|
+
config: {
|
|
1684
|
+
policies: [
|
|
1685
|
+
"admin::isAuthenticatedAdmin",
|
|
1686
|
+
{
|
|
1687
|
+
name: "admin::hasPermissions",
|
|
1688
|
+
config: {
|
|
1689
|
+
actions: ["plugin::content-releases.read"]
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
]
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1490
1695
|
{
|
|
1491
1696
|
method: "POST",
|
|
1492
1697
|
path: "/",
|
|
@@ -1506,7 +1711,7 @@ const release = {
|
|
|
1506
1711
|
{
|
|
1507
1712
|
method: "GET",
|
|
1508
1713
|
path: "/",
|
|
1509
|
-
handler: "release.
|
|
1714
|
+
handler: "release.findPage",
|
|
1510
1715
|
config: {
|
|
1511
1716
|
policies: [
|
|
1512
1717
|
"admin::isAuthenticatedAdmin",
|
|
@@ -1604,22 +1809,24 @@ const releaseAction = {
|
|
|
1604
1809
|
]
|
|
1605
1810
|
}
|
|
1606
1811
|
},
|
|
1812
|
+
/*
|
|
1607
1813
|
{
|
|
1608
|
-
method:
|
|
1609
|
-
path:
|
|
1610
|
-
handler:
|
|
1814
|
+
method: 'POST',
|
|
1815
|
+
path: '/:releaseId/actions/bulk',
|
|
1816
|
+
handler: 'release-action.createMany',
|
|
1611
1817
|
config: {
|
|
1612
1818
|
policies: [
|
|
1613
|
-
|
|
1819
|
+
'admin::isAuthenticatedAdmin',
|
|
1614
1820
|
{
|
|
1615
|
-
name:
|
|
1821
|
+
name: 'admin::hasPermissions',
|
|
1616
1822
|
config: {
|
|
1617
|
-
actions: [
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
]
|
|
1621
|
-
}
|
|
1823
|
+
actions: ['plugin::content-releases.create-action'],
|
|
1824
|
+
},
|
|
1825
|
+
},
|
|
1826
|
+
],
|
|
1827
|
+
},
|
|
1622
1828
|
},
|
|
1829
|
+
*/
|
|
1623
1830
|
{
|
|
1624
1831
|
method: "GET",
|
|
1625
1832
|
path: "/:releaseId/actions",
|
|
@@ -1670,7 +1877,45 @@ const releaseAction = {
|
|
|
1670
1877
|
}
|
|
1671
1878
|
]
|
|
1672
1879
|
};
|
|
1880
|
+
const settings = {
|
|
1881
|
+
type: "admin",
|
|
1882
|
+
routes: [
|
|
1883
|
+
{
|
|
1884
|
+
method: "GET",
|
|
1885
|
+
path: "/settings",
|
|
1886
|
+
handler: "settings.find",
|
|
1887
|
+
config: {
|
|
1888
|
+
policies: [
|
|
1889
|
+
"admin::isAuthenticatedAdmin",
|
|
1890
|
+
{
|
|
1891
|
+
name: "admin::hasPermissions",
|
|
1892
|
+
config: {
|
|
1893
|
+
actions: ["plugin::content-releases.settings.read"]
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
]
|
|
1897
|
+
}
|
|
1898
|
+
},
|
|
1899
|
+
{
|
|
1900
|
+
method: "PUT",
|
|
1901
|
+
path: "/settings",
|
|
1902
|
+
handler: "settings.update",
|
|
1903
|
+
config: {
|
|
1904
|
+
policies: [
|
|
1905
|
+
"admin::isAuthenticatedAdmin",
|
|
1906
|
+
{
|
|
1907
|
+
name: "admin::hasPermissions",
|
|
1908
|
+
config: {
|
|
1909
|
+
actions: ["plugin::content-releases.settings.update"]
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
]
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
]
|
|
1916
|
+
};
|
|
1673
1917
|
const routes = {
|
|
1918
|
+
settings,
|
|
1674
1919
|
release,
|
|
1675
1920
|
"release-action": releaseAction
|
|
1676
1921
|
};
|