@strapi/content-releases 0.0.0-experimental.d4cb32ce579e12a4436d68036f2327132fba1309 → 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb
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-xAkiD42p.mjs → App-B2R2exNT.mjs} +656 -625
- package/dist/_chunks/App-B2R2exNT.mjs.map +1 -0
- package/dist/_chunks/{App-OK4Xac-O.js → App-CEwOQkKT.js} +671 -641
- package/dist/_chunks/App-CEwOQkKT.js.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/{en-veqvqeEr.mjs → en-B9Ur3VsE.mjs} +14 -5
- package/dist/_chunks/en-B9Ur3VsE.mjs.map +1 -0
- package/dist/_chunks/{en-r0otWaln.js → en-DtFJ5ViE.js} +14 -5
- package/dist/_chunks/en-DtFJ5ViE.js.map +1 -0
- package/dist/_chunks/{index-JvA2_26n.js → index-BrWv-zV4.js} +258 -244
- package/dist/_chunks/index-BrWv-zV4.js.map +1 -0
- package/dist/_chunks/{index-exoiSU3V.mjs → index-DbmynICx.mjs} +264 -248
- package/dist/_chunks/index-DbmynICx.mjs.map +1 -0
- package/dist/admin/index.js +1 -15
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +2 -16
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/CMReleasesContainer.d.ts +22 -0
- package/dist/admin/src/components/RelativeTime.d.ts +28 -0
- package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
- package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
- package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
- package/dist/admin/src/components/ReleaseModal.d.ts +17 -0
- package/dist/admin/src/constants.d.ts +58 -0
- package/dist/admin/src/index.d.ts +3 -0
- package/dist/admin/src/pages/App.d.ts +1 -0
- package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
- package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
- package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
- package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
- package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
- package/dist/admin/src/pluginId.d.ts +1 -0
- package/dist/admin/src/services/release.d.ts +105 -0
- package/dist/admin/src/store/hooks.d.ts +7 -0
- package/dist/admin/src/utils/api.d.ts +6 -0
- package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
- package/dist/admin/src/utils/time.d.ts +1 -0
- package/dist/server/index.js +675 -232
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +675 -232
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts +5 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -0
- package/dist/server/src/constants.d.ts +12 -0
- package/dist/server/src/constants.d.ts.map +1 -0
- package/dist/server/src/content-types/index.d.ts +99 -0
- package/dist/server/src/content-types/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release/index.d.ts +48 -0
- package/dist/server/src/content-types/release/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release/schema.d.ts +47 -0
- package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
- package/dist/server/src/content-types/release-action/index.d.ts +50 -0
- package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
- package/dist/server/src/content-types/release-action/schema.d.ts +49 -0
- package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
- package/dist/server/src/controllers/index.d.ts +20 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -0
- package/dist/server/src/controllers/release-action.d.ts +10 -0
- package/dist/server/src/controllers/release-action.d.ts.map +1 -0
- package/dist/server/src/controllers/release.d.ts +12 -0
- package/dist/server/src/controllers/release.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/release-action.d.ts +8 -0
- package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/release.d.ts +2 -0
- package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
- package/dist/server/src/destroy.d.ts +5 -0
- package/dist/server/src/destroy.d.ts.map +1 -0
- package/dist/server/src/index.d.ts +2096 -0
- package/dist/server/src/index.d.ts.map +1 -0
- package/dist/server/src/migrations/index.d.ts +13 -0
- package/dist/server/src/migrations/index.d.ts.map +1 -0
- package/dist/server/src/register.d.ts +5 -0
- package/dist/server/src/register.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts +35 -0
- package/dist/server/src/routes/index.d.ts.map +1 -0
- package/dist/server/src/routes/release-action.d.ts +18 -0
- package/dist/server/src/routes/release-action.d.ts.map +1 -0
- package/dist/server/src/routes/release.d.ts +18 -0
- package/dist/server/src/routes/release.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +1826 -0
- package/dist/server/src/services/index.d.ts.map +1 -0
- package/dist/server/src/services/release.d.ts +66 -0
- package/dist/server/src/services/release.d.ts.map +1 -0
- package/dist/server/src/services/scheduling.d.ts +18 -0
- package/dist/server/src/services/scheduling.d.ts.map +1 -0
- package/dist/server/src/services/validation.d.ts +18 -0
- package/dist/server/src/services/validation.d.ts.map +1 -0
- package/dist/server/src/utils/index.d.ts +14 -0
- package/dist/server/src/utils/index.d.ts.map +1 -0
- package/dist/shared/contracts/release-actions.d.ts +131 -0
- package/dist/shared/contracts/release-actions.d.ts.map +1 -0
- package/dist/shared/contracts/releases.d.ts +182 -0
- package/dist/shared/contracts/releases.d.ts.map +1 -0
- package/dist/shared/types.d.ts +24 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/validation-schemas.d.ts +2 -0
- package/dist/shared/validation-schemas.d.ts.map +1 -0
- package/package.json +29 -36
- package/dist/_chunks/App-OK4Xac-O.js.map +0 -1
- package/dist/_chunks/App-xAkiD42p.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-r0otWaln.js.map +0 -1
- package/dist/_chunks/en-veqvqeEr.mjs.map +0 -1
- package/dist/_chunks/index-JvA2_26n.js.map +0 -1
- package/dist/_chunks/index-exoiSU3V.mjs.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const utils = require("@strapi/utils");
|
|
3
|
+
const isEqual = require("lodash/isEqual");
|
|
3
4
|
const lodash = require("lodash");
|
|
4
5
|
const _ = require("lodash/fp");
|
|
5
|
-
const EE = require("@strapi/strapi/dist/utils/ee");
|
|
6
6
|
const nodeSchedule = require("node-schedule");
|
|
7
7
|
const yup = require("yup");
|
|
8
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -24,8 +24,8 @@ function _interopNamespace(e) {
|
|
|
24
24
|
n.default = e;
|
|
25
25
|
return Object.freeze(n);
|
|
26
26
|
}
|
|
27
|
+
const isEqual__default = /* @__PURE__ */ _interopDefault(isEqual);
|
|
27
28
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
|
28
|
-
const EE__default = /* @__PURE__ */ _interopDefault(EE);
|
|
29
29
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
30
30
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
31
31
|
const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
|
|
@@ -76,6 +76,32 @@ const ACTIONS = [
|
|
|
76
76
|
const ALLOWED_WEBHOOK_EVENTS = {
|
|
77
77
|
RELEASES_PUBLISH: "releases.publish"
|
|
78
78
|
};
|
|
79
|
+
const getService = (name, { strapi: strapi2 }) => {
|
|
80
|
+
return strapi2.plugin("content-releases").service(name);
|
|
81
|
+
};
|
|
82
|
+
const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 }) => {
|
|
83
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
84
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
85
|
+
const entry = await strapi2.db.query(contentTypeUid).findOne({
|
|
86
|
+
where: { id: entryId },
|
|
87
|
+
populate
|
|
88
|
+
});
|
|
89
|
+
return entry;
|
|
90
|
+
};
|
|
91
|
+
const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 }) => {
|
|
92
|
+
try {
|
|
93
|
+
await strapi2.entityValidator.validateEntityCreation(
|
|
94
|
+
strapi2.getModel(contentTypeUid),
|
|
95
|
+
entry,
|
|
96
|
+
void 0,
|
|
97
|
+
// @ts-expect-error - FIXME: entity here is unnecessary
|
|
98
|
+
entry
|
|
99
|
+
);
|
|
100
|
+
return true;
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
79
105
|
async function deleteActionsOnDisableDraftAndPublish({
|
|
80
106
|
oldContentTypes,
|
|
81
107
|
contentTypes: contentTypes2
|
|
@@ -97,36 +123,205 @@ async function deleteActionsOnDisableDraftAndPublish({
|
|
|
97
123
|
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
98
124
|
const deletedContentTypes = lodash.difference(lodash.keys(oldContentTypes), lodash.keys(contentTypes2)) ?? [];
|
|
99
125
|
if (deletedContentTypes.length) {
|
|
100
|
-
await utils.
|
|
126
|
+
await utils.async.map(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
101
127
|
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
102
128
|
});
|
|
103
129
|
}
|
|
104
130
|
}
|
|
105
|
-
|
|
131
|
+
async function migrateIsValidAndStatusReleases() {
|
|
132
|
+
const releasesWithoutStatus = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
133
|
+
where: {
|
|
134
|
+
status: null,
|
|
135
|
+
releasedAt: null
|
|
136
|
+
},
|
|
137
|
+
populate: {
|
|
138
|
+
actions: {
|
|
139
|
+
populate: {
|
|
140
|
+
entry: true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
utils.async.map(releasesWithoutStatus, async (release2) => {
|
|
146
|
+
const actions = release2.actions;
|
|
147
|
+
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
148
|
+
for (const action of notValidatedActions) {
|
|
149
|
+
if (action.entry) {
|
|
150
|
+
const populatedEntry = await getPopulatedEntry(action.contentType, action.entry.id, {
|
|
151
|
+
strapi
|
|
152
|
+
});
|
|
153
|
+
if (populatedEntry) {
|
|
154
|
+
const isEntryValid = getEntryValidStatus(action.contentType, populatedEntry, { strapi });
|
|
155
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
156
|
+
where: {
|
|
157
|
+
id: action.id
|
|
158
|
+
},
|
|
159
|
+
data: {
|
|
160
|
+
isEntryValid
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
167
|
+
});
|
|
168
|
+
const publishedReleases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
169
|
+
where: {
|
|
170
|
+
status: null,
|
|
171
|
+
releasedAt: {
|
|
172
|
+
$notNull: true
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
utils.async.map(publishedReleases, async (release2) => {
|
|
177
|
+
return strapi.db.query(RELEASE_MODEL_UID).update({
|
|
178
|
+
where: {
|
|
179
|
+
id: release2.id
|
|
180
|
+
},
|
|
181
|
+
data: {
|
|
182
|
+
status: "done"
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
188
|
+
if (oldContentTypes !== void 0 && contentTypes2 !== void 0) {
|
|
189
|
+
const contentTypesWithDraftAndPublish = Object.keys(oldContentTypes).filter(
|
|
190
|
+
(uid) => oldContentTypes[uid]?.options?.draftAndPublish
|
|
191
|
+
);
|
|
192
|
+
const releasesAffected = /* @__PURE__ */ new Set();
|
|
193
|
+
utils.async.map(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
|
|
194
|
+
const oldContentType = oldContentTypes[contentTypeUID];
|
|
195
|
+
const contentType = contentTypes2[contentTypeUID];
|
|
196
|
+
if (!isEqual__default.default(oldContentType?.attributes, contentType?.attributes)) {
|
|
197
|
+
const actions = await strapi.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
198
|
+
where: {
|
|
199
|
+
contentType: contentTypeUID
|
|
200
|
+
},
|
|
201
|
+
populate: {
|
|
202
|
+
entry: true,
|
|
203
|
+
release: true
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
await utils.async.map(actions, async (action) => {
|
|
207
|
+
if (action.entry && action.release) {
|
|
208
|
+
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
209
|
+
strapi
|
|
210
|
+
});
|
|
211
|
+
if (populatedEntry) {
|
|
212
|
+
const isEntryValid = await getEntryValidStatus(contentTypeUID, populatedEntry, {
|
|
213
|
+
strapi
|
|
214
|
+
});
|
|
215
|
+
releasesAffected.add(action.release.id);
|
|
216
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
217
|
+
where: {
|
|
218
|
+
id: action.id
|
|
219
|
+
},
|
|
220
|
+
data: {
|
|
221
|
+
isEntryValid
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}).then(() => {
|
|
229
|
+
utils.async.map(releasesAffected, async (releaseId) => {
|
|
230
|
+
return getService("release", { strapi }).updateReleaseStatus(releaseId);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function disableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
236
|
+
if (!oldContentTypes) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
240
|
+
if (!i18nPlugin) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
for (const uid in contentTypes2) {
|
|
244
|
+
if (!oldContentTypes[uid]) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
const oldContentType = oldContentTypes[uid];
|
|
248
|
+
const contentType = contentTypes2[uid];
|
|
249
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
250
|
+
if (isLocalizedContentType(oldContentType) && !isLocalizedContentType(contentType)) {
|
|
251
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
252
|
+
locale: null
|
|
253
|
+
}).where({ contentType: uid }).execute();
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function enableContentTypeLocalized({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
258
|
+
if (!oldContentTypes) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const i18nPlugin = strapi.plugin("i18n");
|
|
262
|
+
if (!i18nPlugin) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
for (const uid in contentTypes2) {
|
|
266
|
+
if (!oldContentTypes[uid]) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const oldContentType = oldContentTypes[uid];
|
|
270
|
+
const contentType = contentTypes2[uid];
|
|
271
|
+
const { isLocalizedContentType } = i18nPlugin.service("content-types");
|
|
272
|
+
const { getDefaultLocale } = i18nPlugin.service("locales");
|
|
273
|
+
if (!isLocalizedContentType(oldContentType) && isLocalizedContentType(contentType)) {
|
|
274
|
+
const defaultLocale = await getDefaultLocale();
|
|
275
|
+
await strapi.db.queryBuilder(RELEASE_ACTION_MODEL_UID).update({
|
|
276
|
+
locale: defaultLocale
|
|
277
|
+
}).where({ contentType: uid }).execute();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
106
281
|
const register = async ({ strapi: strapi2 }) => {
|
|
107
|
-
if (features
|
|
108
|
-
await strapi2.admin
|
|
109
|
-
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
110
|
-
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType);
|
|
282
|
+
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
283
|
+
await strapi2.service("admin::permission").actionProvider.registerMany(ACTIONS);
|
|
284
|
+
strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized).register(deleteActionsOnDisableDraftAndPublish);
|
|
285
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
286
|
+
}
|
|
287
|
+
if (strapi2.plugin("graphql")) {
|
|
288
|
+
const graphqlExtensionService = strapi2.plugin("graphql").service("extension");
|
|
289
|
+
graphqlExtensionService.shadowCRUD(RELEASE_MODEL_UID).disable();
|
|
290
|
+
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
111
291
|
}
|
|
112
292
|
};
|
|
113
|
-
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
114
|
-
return strapi2.plugin("content-releases").service(name);
|
|
115
|
-
};
|
|
116
|
-
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
117
293
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
118
|
-
if (features
|
|
294
|
+
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
295
|
+
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
|
|
296
|
+
(uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
|
|
297
|
+
);
|
|
119
298
|
strapi2.db.lifecycles.subscribe({
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
299
|
+
models: contentTypesWithDraftAndPublish,
|
|
300
|
+
async afterDelete(event) {
|
|
301
|
+
try {
|
|
302
|
+
const { model, result } = event;
|
|
303
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
304
|
+
const { id } = result;
|
|
305
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
306
|
+
where: {
|
|
307
|
+
actions: {
|
|
308
|
+
target_type: model.uid,
|
|
309
|
+
target_id: id
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
314
|
+
where: {
|
|
315
|
+
target_type: model.uid,
|
|
316
|
+
target_id: id
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
for (const release2 of releases) {
|
|
320
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
128
321
|
}
|
|
129
|
-
}
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
strapi2.log.error("Error while deleting release actions after entry delete", { error });
|
|
130
325
|
}
|
|
131
326
|
},
|
|
132
327
|
/**
|
|
@@ -146,41 +341,88 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
146
341
|
* We make this only after deleteMany is succesfully executed to avoid errors
|
|
147
342
|
*/
|
|
148
343
|
async afterDeleteMany(event) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
344
|
+
try {
|
|
345
|
+
const { model, state } = event;
|
|
346
|
+
const entriesToDelete = state.entriesToDelete;
|
|
347
|
+
if (entriesToDelete) {
|
|
348
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
349
|
+
where: {
|
|
350
|
+
actions: {
|
|
351
|
+
target_type: model.uid,
|
|
352
|
+
target_id: {
|
|
353
|
+
$in: entriesToDelete.map((entry) => entry.id)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
157
356
|
}
|
|
357
|
+
});
|
|
358
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
359
|
+
where: {
|
|
360
|
+
target_type: model.uid,
|
|
361
|
+
target_id: {
|
|
362
|
+
$in: entriesToDelete.map((entry) => entry.id)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
for (const release2 of releases) {
|
|
367
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
158
368
|
}
|
|
369
|
+
}
|
|
370
|
+
} catch (error) {
|
|
371
|
+
strapi2.log.error("Error while deleting release actions after entry deleteMany", {
|
|
372
|
+
error
|
|
159
373
|
});
|
|
160
374
|
}
|
|
375
|
+
},
|
|
376
|
+
async afterUpdate(event) {
|
|
377
|
+
try {
|
|
378
|
+
const { model, result } = event;
|
|
379
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
380
|
+
const isEntryValid = await getEntryValidStatus(model.uid, result, {
|
|
381
|
+
strapi: strapi2
|
|
382
|
+
});
|
|
383
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
384
|
+
where: {
|
|
385
|
+
target_type: model.uid,
|
|
386
|
+
target_id: result.id
|
|
387
|
+
},
|
|
388
|
+
data: {
|
|
389
|
+
isEntryValid
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
393
|
+
where: {
|
|
394
|
+
actions: {
|
|
395
|
+
target_type: model.uid,
|
|
396
|
+
target_id: result.id
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
for (const release2 of releases) {
|
|
401
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} catch (error) {
|
|
405
|
+
strapi2.log.error("Error while updating release actions after entry update", { error });
|
|
406
|
+
}
|
|
161
407
|
}
|
|
162
408
|
});
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
});
|
|
173
|
-
}
|
|
409
|
+
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
410
|
+
strapi2.log.error(
|
|
411
|
+
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
412
|
+
);
|
|
413
|
+
throw err;
|
|
414
|
+
});
|
|
415
|
+
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
416
|
+
strapi2.get("webhookStore").addAllowedEvent(key, value);
|
|
417
|
+
});
|
|
174
418
|
}
|
|
175
419
|
};
|
|
176
420
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
job.cancel();
|
|
183
|
-
}
|
|
421
|
+
const scheduledJobs = getService("scheduling", {
|
|
422
|
+
strapi: strapi2
|
|
423
|
+
}).getAll();
|
|
424
|
+
for (const [, job] of scheduledJobs) {
|
|
425
|
+
job.cancel();
|
|
184
426
|
}
|
|
185
427
|
};
|
|
186
428
|
const schema$1 = {
|
|
@@ -215,6 +457,11 @@ const schema$1 = {
|
|
|
215
457
|
timezone: {
|
|
216
458
|
type: "string"
|
|
217
459
|
},
|
|
460
|
+
status: {
|
|
461
|
+
type: "enumeration",
|
|
462
|
+
enum: ["ready", "blocked", "failed", "done", "empty"],
|
|
463
|
+
required: true
|
|
464
|
+
},
|
|
218
465
|
actions: {
|
|
219
466
|
type: "relation",
|
|
220
467
|
relation: "oneToMany",
|
|
@@ -267,6 +514,9 @@ const schema = {
|
|
|
267
514
|
relation: "manyToOne",
|
|
268
515
|
target: RELEASE_MODEL_UID,
|
|
269
516
|
inversedBy: "actions"
|
|
517
|
+
},
|
|
518
|
+
isEntryValid: {
|
|
519
|
+
type: "boolean"
|
|
270
520
|
}
|
|
271
521
|
}
|
|
272
522
|
};
|
|
@@ -297,6 +547,94 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
297
547
|
release: release2
|
|
298
548
|
});
|
|
299
549
|
};
|
|
550
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
551
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
552
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
553
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
554
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
555
|
+
try {
|
|
556
|
+
if (actionType === "publish") {
|
|
557
|
+
await entityManagerService.publish(entry, uid);
|
|
558
|
+
} else {
|
|
559
|
+
await entityManagerService.unpublish(entry, uid);
|
|
560
|
+
}
|
|
561
|
+
} catch (error) {
|
|
562
|
+
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
563
|
+
;
|
|
564
|
+
else {
|
|
565
|
+
throw error;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
570
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
571
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
572
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
573
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
574
|
+
filters: {
|
|
575
|
+
id: {
|
|
576
|
+
$in: entriesToPublishIds
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
populate
|
|
580
|
+
});
|
|
581
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
582
|
+
filters: {
|
|
583
|
+
id: {
|
|
584
|
+
$in: entriestoUnpublishIds
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
populate
|
|
588
|
+
});
|
|
589
|
+
if (entriesToPublish.length > 0) {
|
|
590
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
591
|
+
}
|
|
592
|
+
if (entriesToUnpublish.length > 0) {
|
|
593
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
const getFormattedActions = async (releaseId) => {
|
|
597
|
+
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
598
|
+
where: {
|
|
599
|
+
release: {
|
|
600
|
+
id: releaseId
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
populate: {
|
|
604
|
+
entry: {
|
|
605
|
+
fields: ["id"]
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
if (actions.length === 0) {
|
|
610
|
+
throw new utils.errors.ValidationError("No entries to publish");
|
|
611
|
+
}
|
|
612
|
+
const collectionTypeActions = {};
|
|
613
|
+
const singleTypeActions = [];
|
|
614
|
+
for (const action of actions) {
|
|
615
|
+
const contentTypeUid = action.contentType;
|
|
616
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
617
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
618
|
+
collectionTypeActions[contentTypeUid] = {
|
|
619
|
+
entriesToPublishIds: [],
|
|
620
|
+
entriesToUnpublishIds: []
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
if (action.type === "publish") {
|
|
624
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
625
|
+
} else {
|
|
626
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
singleTypeActions.push({
|
|
630
|
+
uid: contentTypeUid,
|
|
631
|
+
action: action.type,
|
|
632
|
+
id: action.entry.id
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return { collectionTypeActions, singleTypeActions };
|
|
637
|
+
};
|
|
300
638
|
return {
|
|
301
639
|
async create(releaseData, { user }) {
|
|
302
640
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
@@ -310,10 +648,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
310
648
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
311
649
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
312
650
|
]);
|
|
313
|
-
const release2 = await strapi2.
|
|
314
|
-
data:
|
|
651
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).create({
|
|
652
|
+
data: {
|
|
653
|
+
...releaseWithCreatorFields,
|
|
654
|
+
status: "empty"
|
|
655
|
+
}
|
|
315
656
|
});
|
|
316
|
-
if (
|
|
657
|
+
if (releaseWithCreatorFields.scheduledAt) {
|
|
317
658
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
318
659
|
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
319
660
|
}
|
|
@@ -321,28 +662,36 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
321
662
|
return release2;
|
|
322
663
|
},
|
|
323
664
|
async findOne(id, query = {}) {
|
|
324
|
-
const
|
|
325
|
-
|
|
665
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_MODEL_UID, query);
|
|
666
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
667
|
+
...dbQuery,
|
|
668
|
+
where: { id }
|
|
326
669
|
});
|
|
327
670
|
return release2;
|
|
328
671
|
},
|
|
329
672
|
findPage(query) {
|
|
330
|
-
|
|
331
|
-
|
|
673
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_MODEL_UID, query ?? {});
|
|
674
|
+
return strapi2.db.query(RELEASE_MODEL_UID).findPage({
|
|
675
|
+
...dbQuery,
|
|
332
676
|
populate: {
|
|
333
677
|
actions: {
|
|
334
|
-
// @ts-expect-error Ignore missing properties
|
|
335
678
|
count: true
|
|
336
679
|
}
|
|
337
680
|
}
|
|
338
681
|
});
|
|
339
682
|
},
|
|
340
|
-
async findManyWithContentTypeEntryAttached(contentTypeUid,
|
|
683
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
684
|
+
let entries = entriesIds;
|
|
685
|
+
if (!Array.isArray(entriesIds)) {
|
|
686
|
+
entries = [entriesIds];
|
|
687
|
+
}
|
|
341
688
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
342
689
|
where: {
|
|
343
690
|
actions: {
|
|
344
691
|
target_type: contentTypeUid,
|
|
345
|
-
target_id:
|
|
692
|
+
target_id: {
|
|
693
|
+
$in: entries
|
|
694
|
+
}
|
|
346
695
|
},
|
|
347
696
|
releasedAt: {
|
|
348
697
|
$null: true
|
|
@@ -353,18 +702,25 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
353
702
|
actions: {
|
|
354
703
|
where: {
|
|
355
704
|
target_type: contentTypeUid,
|
|
356
|
-
target_id:
|
|
705
|
+
target_id: {
|
|
706
|
+
$in: entries
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
populate: {
|
|
710
|
+
entry: {
|
|
711
|
+
select: ["id"]
|
|
712
|
+
}
|
|
357
713
|
}
|
|
358
714
|
}
|
|
359
715
|
}
|
|
360
716
|
});
|
|
361
717
|
return releases.map((release2) => {
|
|
362
718
|
if (release2.actions?.length) {
|
|
363
|
-
const
|
|
719
|
+
const actionsForEntry = release2.actions;
|
|
364
720
|
delete release2.actions;
|
|
365
721
|
return {
|
|
366
722
|
...release2,
|
|
367
|
-
|
|
723
|
+
actions: actionsForEntry
|
|
368
724
|
};
|
|
369
725
|
}
|
|
370
726
|
return release2;
|
|
@@ -423,29 +779,24 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
423
779
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name, id),
|
|
424
780
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
425
781
|
]);
|
|
426
|
-
const release2 = await strapi2.
|
|
782
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id } });
|
|
427
783
|
if (!release2) {
|
|
428
784
|
throw new utils.errors.NotFoundError(`No release found for id ${id}`);
|
|
429
785
|
}
|
|
430
786
|
if (release2.releasedAt) {
|
|
431
787
|
throw new utils.errors.ValidationError("Release already published");
|
|
432
788
|
}
|
|
433
|
-
const updatedRelease = await strapi2.
|
|
434
|
-
|
|
435
|
-
* The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
|
|
436
|
-
* is not compatible with the type we are passing here: UpdateRelease.Request['body']
|
|
437
|
-
*/
|
|
438
|
-
// @ts-expect-error see above
|
|
789
|
+
const updatedRelease = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
790
|
+
where: { id },
|
|
439
791
|
data: releaseWithCreatorFields
|
|
440
792
|
});
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
schedulingService.cancel(id);
|
|
447
|
-
}
|
|
793
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
794
|
+
if (releaseData.scheduledAt) {
|
|
795
|
+
await schedulingService.set(id, releaseData.scheduledAt);
|
|
796
|
+
} else if (release2.scheduledAt) {
|
|
797
|
+
schedulingService.cancel(id);
|
|
448
798
|
}
|
|
799
|
+
this.updateReleaseStatus(id);
|
|
449
800
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
450
801
|
return updatedRelease;
|
|
451
802
|
},
|
|
@@ -457,7 +808,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
457
808
|
validateEntryContentType(action.entry.contentType),
|
|
458
809
|
validateUniqueEntry(releaseId, action)
|
|
459
810
|
]);
|
|
460
|
-
const release2 = await strapi2.
|
|
811
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
461
812
|
if (!release2) {
|
|
462
813
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
463
814
|
}
|
|
@@ -465,11 +816,14 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
465
816
|
throw new utils.errors.ValidationError("Release already published");
|
|
466
817
|
}
|
|
467
818
|
const { entry, type } = action;
|
|
468
|
-
|
|
819
|
+
const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
|
|
820
|
+
const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
|
|
821
|
+
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
469
822
|
data: {
|
|
470
823
|
type,
|
|
471
824
|
contentType: entry.contentType,
|
|
472
825
|
locale: entry.locale,
|
|
826
|
+
isEntryValid,
|
|
473
827
|
entry: {
|
|
474
828
|
id: entry.id,
|
|
475
829
|
__type: entry.contentType,
|
|
@@ -477,30 +831,35 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
477
831
|
},
|
|
478
832
|
release: releaseId
|
|
479
833
|
},
|
|
480
|
-
populate: { release: {
|
|
834
|
+
populate: { release: { select: ["id"] }, entry: { select: ["id"] } }
|
|
481
835
|
});
|
|
836
|
+
this.updateReleaseStatus(releaseId);
|
|
837
|
+
return releaseAction2;
|
|
482
838
|
},
|
|
483
839
|
async findActions(releaseId, query) {
|
|
484
|
-
const release2 = await strapi2.
|
|
485
|
-
|
|
840
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
841
|
+
where: { id: releaseId },
|
|
842
|
+
select: ["id"]
|
|
486
843
|
});
|
|
487
844
|
if (!release2) {
|
|
488
845
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
489
846
|
}
|
|
490
|
-
|
|
491
|
-
|
|
847
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
848
|
+
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
849
|
+
...dbQuery,
|
|
492
850
|
populate: {
|
|
493
851
|
entry: {
|
|
494
852
|
populate: "*"
|
|
495
853
|
}
|
|
496
854
|
},
|
|
497
|
-
|
|
855
|
+
where: {
|
|
498
856
|
release: releaseId
|
|
499
857
|
}
|
|
500
858
|
});
|
|
501
859
|
},
|
|
502
860
|
async countActions(query) {
|
|
503
|
-
|
|
861
|
+
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
862
|
+
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
504
863
|
},
|
|
505
864
|
async groupActions(actions, groupBy) {
|
|
506
865
|
const contentTypeUids = actions.reduce((acc, action) => {
|
|
@@ -509,9 +868,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
509
868
|
}
|
|
510
869
|
return acc;
|
|
511
870
|
}, []);
|
|
512
|
-
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
|
|
513
|
-
contentTypeUids
|
|
514
|
-
);
|
|
871
|
+
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(contentTypeUids);
|
|
515
872
|
const allLocalesDictionary = await this.getLocalesDataForActions();
|
|
516
873
|
const formattedData = actions.map((action) => {
|
|
517
874
|
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
@@ -581,10 +938,11 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
581
938
|
return componentsMap;
|
|
582
939
|
},
|
|
583
940
|
async delete(releaseId) {
|
|
584
|
-
const release2 = await strapi2.
|
|
941
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
942
|
+
where: { id: releaseId },
|
|
585
943
|
populate: {
|
|
586
944
|
actions: {
|
|
587
|
-
|
|
945
|
+
select: ["id"]
|
|
588
946
|
}
|
|
589
947
|
}
|
|
590
948
|
});
|
|
@@ -602,9 +960,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
602
960
|
}
|
|
603
961
|
}
|
|
604
962
|
});
|
|
605
|
-
await strapi2.
|
|
963
|
+
await strapi2.db.query(RELEASE_MODEL_UID).delete({
|
|
964
|
+
where: {
|
|
965
|
+
id: releaseId
|
|
966
|
+
}
|
|
967
|
+
});
|
|
606
968
|
});
|
|
607
|
-
if (
|
|
969
|
+
if (release2.scheduledAt) {
|
|
608
970
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
609
971
|
await schedulingService.cancel(release2.id);
|
|
610
972
|
}
|
|
@@ -612,139 +974,69 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
612
974
|
return release2;
|
|
613
975
|
},
|
|
614
976
|
async publish(releaseId) {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
actions: {
|
|
622
|
-
populate: {
|
|
623
|
-
entry: {
|
|
624
|
-
fields: ["id"]
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
);
|
|
631
|
-
if (!releaseWithPopulatedActionEntries) {
|
|
977
|
+
const {
|
|
978
|
+
release: release2,
|
|
979
|
+
error
|
|
980
|
+
} = await strapi2.db.transaction(async ({ trx }) => {
|
|
981
|
+
const lockedRelease = await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).select(["id", "name", "releasedAt", "status"]).first().transacting(trx).forUpdate().execute();
|
|
982
|
+
if (!lockedRelease) {
|
|
632
983
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
633
984
|
}
|
|
634
|
-
if (
|
|
985
|
+
if (lockedRelease.releasedAt) {
|
|
635
986
|
throw new utils.errors.ValidationError("Release already published");
|
|
636
987
|
}
|
|
637
|
-
if (
|
|
638
|
-
throw new utils.errors.ValidationError("
|
|
988
|
+
if (lockedRelease.status === "failed") {
|
|
989
|
+
throw new utils.errors.ValidationError("Release failed to publish");
|
|
639
990
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
collectionTypeActions[contentTypeUid] = {
|
|
647
|
-
entriestoPublishIds: [],
|
|
648
|
-
entriesToUnpublishIds: []
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
if (action.type === "publish") {
|
|
652
|
-
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
653
|
-
} else {
|
|
654
|
-
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
655
|
-
}
|
|
656
|
-
} else {
|
|
657
|
-
singleTypeActions.push({
|
|
658
|
-
uid: contentTypeUid,
|
|
659
|
-
action: action.type,
|
|
660
|
-
id: action.entry.id
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
665
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
666
|
-
await strapi2.db.transaction(async () => {
|
|
667
|
-
for (const { uid, action, id } of singleTypeActions) {
|
|
668
|
-
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
669
|
-
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
670
|
-
try {
|
|
671
|
-
if (action === "publish") {
|
|
672
|
-
await entityManagerService.publish(entry, uid);
|
|
673
|
-
} else {
|
|
674
|
-
await entityManagerService.unpublish(entry, uid);
|
|
675
|
-
}
|
|
676
|
-
} catch (error) {
|
|
677
|
-
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft")) {
|
|
678
|
-
} else {
|
|
679
|
-
throw error;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
684
|
-
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
685
|
-
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
686
|
-
const entriesToPublish = await strapi2.entityService.findMany(
|
|
687
|
-
contentTypeUid,
|
|
688
|
-
{
|
|
689
|
-
filters: {
|
|
690
|
-
id: {
|
|
691
|
-
$in: entriestoPublishIds
|
|
692
|
-
}
|
|
693
|
-
},
|
|
694
|
-
populate
|
|
695
|
-
}
|
|
696
|
-
);
|
|
697
|
-
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
698
|
-
contentTypeUid,
|
|
699
|
-
{
|
|
700
|
-
filters: {
|
|
701
|
-
id: {
|
|
702
|
-
$in: entriesToUnpublishIds
|
|
703
|
-
}
|
|
704
|
-
},
|
|
705
|
-
populate
|
|
706
|
-
}
|
|
707
|
-
);
|
|
708
|
-
if (entriesToPublish.length > 0) {
|
|
709
|
-
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
991
|
+
try {
|
|
992
|
+
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
993
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(releaseId);
|
|
994
|
+
await strapi2.db.transaction(async () => {
|
|
995
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
996
|
+
await publishSingleTypeAction(uid, action, id);
|
|
710
997
|
}
|
|
711
|
-
|
|
712
|
-
|
|
998
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
999
|
+
const uid = contentTypeUid;
|
|
1000
|
+
await publishCollectionTypeAction(
|
|
1001
|
+
uid,
|
|
1002
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
1003
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
1004
|
+
);
|
|
713
1005
|
}
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
releasedAt: /* @__PURE__ */ new Date()
|
|
723
|
-
},
|
|
724
|
-
populate: {
|
|
725
|
-
actions: {
|
|
726
|
-
// @ts-expect-error is not expecting count but it is working
|
|
727
|
-
count: true
|
|
1006
|
+
});
|
|
1007
|
+
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1008
|
+
where: {
|
|
1009
|
+
id: releaseId
|
|
1010
|
+
},
|
|
1011
|
+
data: {
|
|
1012
|
+
status: "done",
|
|
1013
|
+
releasedAt: /* @__PURE__ */ new Date()
|
|
728
1014
|
}
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1015
|
+
});
|
|
732
1016
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
733
1017
|
isPublished: true,
|
|
734
|
-
release:
|
|
1018
|
+
release: release22
|
|
735
1019
|
});
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
} catch (error) {
|
|
740
|
-
if (strapi2.features.future.isEnabled("contentReleasesScheduling")) {
|
|
1020
|
+
strapi2.telemetry.send("didPublishContentRelease");
|
|
1021
|
+
return { release: release22, error: null };
|
|
1022
|
+
} catch (error2) {
|
|
741
1023
|
dispatchWebhook(ALLOWED_WEBHOOK_EVENTS.RELEASES_PUBLISH, {
|
|
742
1024
|
isPublished: false,
|
|
743
|
-
error
|
|
1025
|
+
error: error2
|
|
744
1026
|
});
|
|
1027
|
+
await strapi2.db?.queryBuilder(RELEASE_MODEL_UID).where({ id: releaseId }).update({
|
|
1028
|
+
status: "failed"
|
|
1029
|
+
}).transacting(trx).execute();
|
|
1030
|
+
return {
|
|
1031
|
+
release: null,
|
|
1032
|
+
error: error2
|
|
1033
|
+
};
|
|
745
1034
|
}
|
|
1035
|
+
});
|
|
1036
|
+
if (error instanceof Error) {
|
|
746
1037
|
throw error;
|
|
747
1038
|
}
|
|
1039
|
+
return release2;
|
|
748
1040
|
},
|
|
749
1041
|
async updateAction(actionId, releaseId, update) {
|
|
750
1042
|
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
@@ -783,14 +1075,67 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
783
1075
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
784
1076
|
);
|
|
785
1077
|
}
|
|
1078
|
+
this.updateReleaseStatus(releaseId);
|
|
786
1079
|
return deletedAction;
|
|
1080
|
+
},
|
|
1081
|
+
async updateReleaseStatus(releaseId) {
|
|
1082
|
+
const [totalActions, invalidActions] = await Promise.all([
|
|
1083
|
+
this.countActions({
|
|
1084
|
+
filters: {
|
|
1085
|
+
release: releaseId
|
|
1086
|
+
}
|
|
1087
|
+
}),
|
|
1088
|
+
this.countActions({
|
|
1089
|
+
filters: {
|
|
1090
|
+
release: releaseId,
|
|
1091
|
+
isEntryValid: false
|
|
1092
|
+
}
|
|
1093
|
+
})
|
|
1094
|
+
]);
|
|
1095
|
+
if (totalActions > 0) {
|
|
1096
|
+
if (invalidActions > 0) {
|
|
1097
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1098
|
+
where: {
|
|
1099
|
+
id: releaseId
|
|
1100
|
+
},
|
|
1101
|
+
data: {
|
|
1102
|
+
status: "blocked"
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1107
|
+
where: {
|
|
1108
|
+
id: releaseId
|
|
1109
|
+
},
|
|
1110
|
+
data: {
|
|
1111
|
+
status: "ready"
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1116
|
+
where: {
|
|
1117
|
+
id: releaseId
|
|
1118
|
+
},
|
|
1119
|
+
data: {
|
|
1120
|
+
status: "empty"
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
787
1123
|
}
|
|
788
1124
|
};
|
|
789
1125
|
};
|
|
1126
|
+
class AlreadyOnReleaseError extends utils.errors.ApplicationError {
|
|
1127
|
+
constructor(message) {
|
|
1128
|
+
super(message);
|
|
1129
|
+
this.name = "AlreadyOnReleaseError";
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
790
1132
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
791
1133
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
792
|
-
const release2 = await strapi2.
|
|
793
|
-
|
|
1134
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
1135
|
+
where: {
|
|
1136
|
+
id: releaseId
|
|
1137
|
+
},
|
|
1138
|
+
populate: { actions: { populate: { entry: { select: ["id"] } } } }
|
|
794
1139
|
});
|
|
795
1140
|
if (!release2) {
|
|
796
1141
|
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
@@ -799,7 +1144,7 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
799
1144
|
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
800
1145
|
);
|
|
801
1146
|
if (isEntryInRelease) {
|
|
802
|
-
throw new
|
|
1147
|
+
throw new AlreadyOnReleaseError(
|
|
803
1148
|
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
804
1149
|
);
|
|
805
1150
|
}
|
|
@@ -816,10 +1161,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
816
1161
|
}
|
|
817
1162
|
},
|
|
818
1163
|
async validatePendingReleasesLimit() {
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
EE__default.default.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
822
|
-
);
|
|
1164
|
+
const featureCfg = strapi2.ee.features.get("cms-content-releases");
|
|
1165
|
+
const maximumPendingReleases = typeof featureCfg === "object" && featureCfg?.options?.maximumReleases || 3;
|
|
823
1166
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
824
1167
|
filters: {
|
|
825
1168
|
releasedAt: {
|
|
@@ -832,8 +1175,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
832
1175
|
}
|
|
833
1176
|
},
|
|
834
1177
|
async validateUniqueNameForPendingRelease(name, id) {
|
|
835
|
-
const pendingReleases = await strapi2.
|
|
836
|
-
|
|
1178
|
+
const pendingReleases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
1179
|
+
where: {
|
|
837
1180
|
releasedAt: {
|
|
838
1181
|
$null: true
|
|
839
1182
|
},
|
|
@@ -862,7 +1205,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
862
1205
|
}
|
|
863
1206
|
const job = nodeSchedule.scheduleJob(scheduleDate, async () => {
|
|
864
1207
|
try {
|
|
865
|
-
await getService("release").publish(releaseId);
|
|
1208
|
+
await getService("release", { strapi: strapi2 }).publish(releaseId);
|
|
866
1209
|
} catch (error) {
|
|
867
1210
|
}
|
|
868
1211
|
this.cancel(releaseId);
|
|
@@ -907,7 +1250,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
907
1250
|
const services = {
|
|
908
1251
|
release: createReleaseService,
|
|
909
1252
|
"release-validation": createReleaseValidationService,
|
|
910
|
-
|
|
1253
|
+
scheduling: createSchedulingService
|
|
911
1254
|
};
|
|
912
1255
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
913
1256
|
name: yup__namespace.string().trim().required(),
|
|
@@ -932,7 +1275,7 @@ const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
|
932
1275
|
const validateRelease = utils.validateYupSchema(RELEASE_SCHEMA);
|
|
933
1276
|
const releaseController = {
|
|
934
1277
|
async findMany(ctx) {
|
|
935
|
-
const permissionsManager = strapi.admin
|
|
1278
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
936
1279
|
ability: ctx.state.userAbility,
|
|
937
1280
|
model: RELEASE_MODEL_UID
|
|
938
1281
|
});
|
|
@@ -960,7 +1303,12 @@ const releaseController = {
|
|
|
960
1303
|
}
|
|
961
1304
|
};
|
|
962
1305
|
});
|
|
963
|
-
|
|
1306
|
+
const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
|
|
1307
|
+
where: {
|
|
1308
|
+
releasedAt: null
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
964
1312
|
}
|
|
965
1313
|
},
|
|
966
1314
|
async findOne(ctx) {
|
|
@@ -977,7 +1325,7 @@ const releaseController = {
|
|
|
977
1325
|
});
|
|
978
1326
|
const sanitizedRelease = {
|
|
979
1327
|
...release2,
|
|
980
|
-
createdBy: release2.createdBy ? strapi.admin
|
|
1328
|
+
createdBy: release2.createdBy ? strapi.service("admin::user").sanitizeUser(release2.createdBy) : null
|
|
981
1329
|
};
|
|
982
1330
|
const data = {
|
|
983
1331
|
...sanitizedRelease,
|
|
@@ -989,19 +1337,48 @@ const releaseController = {
|
|
|
989
1337
|
};
|
|
990
1338
|
ctx.body = { data };
|
|
991
1339
|
},
|
|
1340
|
+
async mapEntriesToReleases(ctx) {
|
|
1341
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1342
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1343
|
+
throw new utils.errors.ValidationError("Missing required query parameters");
|
|
1344
|
+
}
|
|
1345
|
+
const releaseService = getService("release", { strapi });
|
|
1346
|
+
const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
|
|
1347
|
+
contentTypeUid,
|
|
1348
|
+
entriesIds
|
|
1349
|
+
);
|
|
1350
|
+
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1351
|
+
// TODO: Fix for v5 removed mappedEntriedToRelease
|
|
1352
|
+
(acc, release2) => {
|
|
1353
|
+
release2.actions.forEach((action) => {
|
|
1354
|
+
if (!acc[action.entry.id]) {
|
|
1355
|
+
acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
|
|
1356
|
+
} else {
|
|
1357
|
+
acc[action.entry.id].push({ id: release2.id, name: release2.name });
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
return acc;
|
|
1361
|
+
},
|
|
1362
|
+
// TODO: Fix for v5 removed mappedEntriedToRelease
|
|
1363
|
+
{}
|
|
1364
|
+
);
|
|
1365
|
+
ctx.body = {
|
|
1366
|
+
data: mappedEntriesInReleases
|
|
1367
|
+
};
|
|
1368
|
+
},
|
|
992
1369
|
async create(ctx) {
|
|
993
1370
|
const user = ctx.state.user;
|
|
994
1371
|
const releaseArgs = ctx.request.body;
|
|
995
1372
|
await validateRelease(releaseArgs);
|
|
996
1373
|
const releaseService = getService("release", { strapi });
|
|
997
1374
|
const release2 = await releaseService.create(releaseArgs, { user });
|
|
998
|
-
const permissionsManager = strapi.admin
|
|
1375
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
999
1376
|
ability: ctx.state.userAbility,
|
|
1000
1377
|
model: RELEASE_MODEL_UID
|
|
1001
1378
|
});
|
|
1002
|
-
ctx.
|
|
1379
|
+
ctx.created({
|
|
1003
1380
|
data: await permissionsManager.sanitizeOutput(release2)
|
|
1004
|
-
};
|
|
1381
|
+
});
|
|
1005
1382
|
},
|
|
1006
1383
|
async update(ctx) {
|
|
1007
1384
|
const user = ctx.state.user;
|
|
@@ -1010,7 +1387,7 @@ const releaseController = {
|
|
|
1010
1387
|
await validateRelease(releaseArgs);
|
|
1011
1388
|
const releaseService = getService("release", { strapi });
|
|
1012
1389
|
const release2 = await releaseService.update(id, releaseArgs, { user });
|
|
1013
|
-
const permissionsManager = strapi.admin
|
|
1390
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1014
1391
|
ability: ctx.state.userAbility,
|
|
1015
1392
|
model: RELEASE_MODEL_UID
|
|
1016
1393
|
});
|
|
@@ -1074,13 +1451,45 @@ const releaseActionController = {
|
|
|
1074
1451
|
await validateReleaseAction(releaseActionArgs);
|
|
1075
1452
|
const releaseService = getService("release", { strapi });
|
|
1076
1453
|
const releaseAction2 = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1077
|
-
ctx.
|
|
1454
|
+
ctx.created({
|
|
1078
1455
|
data: releaseAction2
|
|
1079
|
-
};
|
|
1456
|
+
});
|
|
1457
|
+
},
|
|
1458
|
+
async createMany(ctx) {
|
|
1459
|
+
const releaseId = ctx.params.releaseId;
|
|
1460
|
+
const releaseActionsArgs = ctx.request.body;
|
|
1461
|
+
await Promise.all(
|
|
1462
|
+
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1463
|
+
);
|
|
1464
|
+
const releaseService = getService("release", { strapi });
|
|
1465
|
+
const releaseActions = await strapi.db.transaction(async () => {
|
|
1466
|
+
const releaseActions2 = await Promise.all(
|
|
1467
|
+
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1468
|
+
try {
|
|
1469
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1470
|
+
return action;
|
|
1471
|
+
} catch (error) {
|
|
1472
|
+
if (error instanceof AlreadyOnReleaseError) {
|
|
1473
|
+
return null;
|
|
1474
|
+
}
|
|
1475
|
+
throw error;
|
|
1476
|
+
}
|
|
1477
|
+
})
|
|
1478
|
+
);
|
|
1479
|
+
return releaseActions2;
|
|
1480
|
+
});
|
|
1481
|
+
const newReleaseActions = releaseActions.filter((action) => action !== null);
|
|
1482
|
+
ctx.created({
|
|
1483
|
+
data: newReleaseActions,
|
|
1484
|
+
meta: {
|
|
1485
|
+
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1486
|
+
totalEntries: releaseActions.length
|
|
1487
|
+
}
|
|
1488
|
+
});
|
|
1080
1489
|
},
|
|
1081
1490
|
async findMany(ctx) {
|
|
1082
1491
|
const releaseId = ctx.params.releaseId;
|
|
1083
|
-
const permissionsManager = strapi.admin
|
|
1492
|
+
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1084
1493
|
ability: ctx.state.userAbility,
|
|
1085
1494
|
model: RELEASE_ACTION_MODEL_UID
|
|
1086
1495
|
});
|
|
@@ -1094,14 +1503,14 @@ const releaseActionController = {
|
|
|
1094
1503
|
if (acc[action.contentType]) {
|
|
1095
1504
|
return acc;
|
|
1096
1505
|
}
|
|
1097
|
-
const contentTypePermissionsManager = strapi.admin
|
|
1506
|
+
const contentTypePermissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1098
1507
|
ability: ctx.state.userAbility,
|
|
1099
1508
|
model: action.contentType
|
|
1100
1509
|
});
|
|
1101
1510
|
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
1102
1511
|
return acc;
|
|
1103
1512
|
}, {});
|
|
1104
|
-
const sanitizedResults = await utils.
|
|
1513
|
+
const sanitizedResults = await utils.async.map(results, async (action) => ({
|
|
1105
1514
|
...action,
|
|
1106
1515
|
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1107
1516
|
}));
|
|
@@ -1146,6 +1555,22 @@ const controllers = { release: releaseController, "release-action": releaseActio
|
|
|
1146
1555
|
const release = {
|
|
1147
1556
|
type: "admin",
|
|
1148
1557
|
routes: [
|
|
1558
|
+
{
|
|
1559
|
+
method: "GET",
|
|
1560
|
+
path: "/mapEntriesToReleases",
|
|
1561
|
+
handler: "release.mapEntriesToReleases",
|
|
1562
|
+
config: {
|
|
1563
|
+
policies: [
|
|
1564
|
+
"admin::isAuthenticatedAdmin",
|
|
1565
|
+
{
|
|
1566
|
+
name: "admin::hasPermissions",
|
|
1567
|
+
config: {
|
|
1568
|
+
actions: ["plugin::content-releases.read"]
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
]
|
|
1572
|
+
}
|
|
1573
|
+
},
|
|
1149
1574
|
{
|
|
1150
1575
|
method: "POST",
|
|
1151
1576
|
path: "/",
|
|
@@ -1263,6 +1688,22 @@ const releaseAction = {
|
|
|
1263
1688
|
]
|
|
1264
1689
|
}
|
|
1265
1690
|
},
|
|
1691
|
+
{
|
|
1692
|
+
method: "POST",
|
|
1693
|
+
path: "/:releaseId/actions/bulk",
|
|
1694
|
+
handler: "release-action.createMany",
|
|
1695
|
+
config: {
|
|
1696
|
+
policies: [
|
|
1697
|
+
"admin::isAuthenticatedAdmin",
|
|
1698
|
+
{
|
|
1699
|
+
name: "admin::hasPermissions",
|
|
1700
|
+
config: {
|
|
1701
|
+
actions: ["plugin::content-releases.create-action"]
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
]
|
|
1705
|
+
}
|
|
1706
|
+
},
|
|
1266
1707
|
{
|
|
1267
1708
|
method: "GET",
|
|
1268
1709
|
path: "/:releaseId/actions",
|
|
@@ -1317,9 +1758,8 @@ const routes = {
|
|
|
1317
1758
|
release,
|
|
1318
1759
|
"release-action": releaseAction
|
|
1319
1760
|
};
|
|
1320
|
-
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1321
1761
|
const getPlugin = () => {
|
|
1322
|
-
if (features.isEnabled("cms-content-releases")) {
|
|
1762
|
+
if (strapi.ee.features.isEnabled("cms-content-releases")) {
|
|
1323
1763
|
return {
|
|
1324
1764
|
register,
|
|
1325
1765
|
bootstrap,
|
|
@@ -1331,6 +1771,9 @@ const getPlugin = () => {
|
|
|
1331
1771
|
};
|
|
1332
1772
|
}
|
|
1333
1773
|
return {
|
|
1774
|
+
// Always return register, it handles its own feature check
|
|
1775
|
+
register,
|
|
1776
|
+
// Always return contentTypes to avoid losing data when the feature is disabled
|
|
1334
1777
|
contentTypes
|
|
1335
1778
|
};
|
|
1336
1779
|
};
|