@strapi/content-releases 0.0.0-experimental.f0d4afee92a0d386f80385590c87955656f995ce → 0.0.0-experimental.f28dba7c374eae9c02b95b4b77aba4c3ad41a841
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-dLXY5ei3.js +1353 -0
- package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
- package/dist/_chunks/{App-Cne--1Z8.mjs → App-jrh58sXY.mjs} +558 -602
- package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-_MxP6-Dt.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +7 -8
- package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-Be3acS2L.js → PurchaseContentReleases-bpIYXOfu.js} +6 -7
- package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
- package/dist/_chunks/{en-CmYoEnA7.js → en-HrREghh3.js} +2 -9
- package/dist/_chunks/en-HrREghh3.js.map +1 -0
- package/dist/_chunks/{en-D0yVZFqf.mjs → en-ltT1TlKQ.mjs} +2 -9
- package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
- package/dist/_chunks/index-CVO0Rqdm.js +1336 -0
- package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
- package/dist/_chunks/index-PiOGBETy.mjs +1315 -0
- package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
- package/dist/admin/index.js +15 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +16 -2
- package/dist/admin/index.mjs.map +1 -1
- package/dist/server/index.js +638 -834
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +638 -835
- package/dist/server/index.mjs.map +1 -1
- package/package.json +39 -33
- package/strapi-server.js +3 -0
- package/dist/_chunks/App-BKB1esYS.js +0 -1395
- package/dist/_chunks/App-BKB1esYS.js.map +0 -1
- package/dist/_chunks/App-Cne--1Z8.mjs.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +0 -1
- package/dist/_chunks/ReleasesSettingsPage-C1WwGWIH.mjs +0 -178
- package/dist/_chunks/ReleasesSettingsPage-C1WwGWIH.mjs.map +0 -1
- package/dist/_chunks/ReleasesSettingsPage-kuXIwpWp.js +0 -178
- package/dist/_chunks/ReleasesSettingsPage-kuXIwpWp.js.map +0 -1
- package/dist/_chunks/en-CmYoEnA7.js.map +0 -1
- package/dist/_chunks/en-D0yVZFqf.mjs.map +0 -1
- package/dist/_chunks/index-5Odi61vw.js +0 -1381
- package/dist/_chunks/index-5Odi61vw.js.map +0 -1
- package/dist/_chunks/index-Cy7qwpaU.mjs +0 -1362
- package/dist/_chunks/index-Cy7qwpaU.mjs.map +0 -1
- package/dist/_chunks/schemas-BE1LxE9J.js +0 -62
- package/dist/_chunks/schemas-BE1LxE9J.js.map +0 -1
- package/dist/_chunks/schemas-DdA2ic2U.mjs +0 -44
- package/dist/_chunks/schemas-DdA2ic2U.mjs.map +0 -1
- package/dist/admin/src/components/RelativeTime.d.ts +0 -28
- package/dist/admin/src/components/ReleaseAction.d.ts +0 -3
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -26
- package/dist/admin/src/components/ReleaseActionModal.d.ts +0 -24
- package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -9
- package/dist/admin/src/components/ReleaseListCell.d.ts +0 -28
- package/dist/admin/src/components/ReleaseModal.d.ts +0 -17
- package/dist/admin/src/components/ReleasesPanel.d.ts +0 -3
- package/dist/admin/src/constants.d.ts +0 -76
- package/dist/admin/src/index.d.ts +0 -3
- package/dist/admin/src/modules/hooks.d.ts +0 -7
- package/dist/admin/src/pages/App.d.ts +0 -1
- package/dist/admin/src/pages/PurchaseContentReleases.d.ts +0 -2
- package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -2
- package/dist/admin/src/pages/ReleasesPage.d.ts +0 -8
- package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +0 -1
- package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -181
- package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -39
- package/dist/admin/src/pluginId.d.ts +0 -1
- package/dist/admin/src/services/release.d.ts +0 -112
- package/dist/admin/src/store/hooks.d.ts +0 -7
- package/dist/admin/src/utils/api.d.ts +0 -6
- package/dist/admin/src/utils/prefixPluginTranslations.d.ts +0 -3
- package/dist/admin/src/utils/time.d.ts +0 -10
- package/dist/admin/src/validation/schemas.d.ts +0 -6
- package/dist/server/src/bootstrap.d.ts +0 -5
- package/dist/server/src/bootstrap.d.ts.map +0 -1
- package/dist/server/src/constants.d.ts +0 -21
- package/dist/server/src/constants.d.ts.map +0 -1
- package/dist/server/src/content-types/index.d.ts +0 -97
- package/dist/server/src/content-types/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/index.d.ts +0 -48
- package/dist/server/src/content-types/release/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/schema.d.ts +0 -47
- package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/index.d.ts +0 -48
- package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/schema.d.ts +0 -47
- package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
- package/dist/server/src/controllers/index.d.ts +0 -25
- package/dist/server/src/controllers/index.d.ts.map +0 -1
- package/dist/server/src/controllers/release-action.d.ts +0 -10
- package/dist/server/src/controllers/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/release.d.ts +0 -18
- package/dist/server/src/controllers/release.d.ts.map +0 -1
- package/dist/server/src/controllers/settings.d.ts +0 -11
- package/dist/server/src/controllers/settings.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release-action.d.ts +0 -14
- package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release.d.ts +0 -4
- package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/settings.d.ts +0 -3
- package/dist/server/src/controllers/validation/settings.d.ts.map +0 -1
- package/dist/server/src/destroy.d.ts +0 -5
- package/dist/server/src/destroy.d.ts.map +0 -1
- package/dist/server/src/index.d.ts +0 -2115
- package/dist/server/src/index.d.ts.map +0 -1
- package/dist/server/src/middlewares/documents.d.ts +0 -6
- package/dist/server/src/middlewares/documents.d.ts.map +0 -1
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +0 -9
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +0 -1
- package/dist/server/src/migrations/index.d.ts +0 -13
- package/dist/server/src/migrations/index.d.ts.map +0 -1
- package/dist/server/src/register.d.ts +0 -5
- package/dist/server/src/register.d.ts.map +0 -1
- package/dist/server/src/routes/index.d.ts +0 -51
- package/dist/server/src/routes/index.d.ts.map +0 -1
- package/dist/server/src/routes/release-action.d.ts +0 -18
- package/dist/server/src/routes/release-action.d.ts.map +0 -1
- package/dist/server/src/routes/release.d.ts +0 -18
- package/dist/server/src/routes/release.d.ts.map +0 -1
- package/dist/server/src/routes/settings.d.ts +0 -18
- package/dist/server/src/routes/settings.d.ts.map +0 -1
- package/dist/server/src/services/index.d.ts +0 -1828
- package/dist/server/src/services/index.d.ts.map +0 -1
- package/dist/server/src/services/release-action.d.ts +0 -38
- package/dist/server/src/services/release-action.d.ts.map +0 -1
- package/dist/server/src/services/release.d.ts +0 -31
- package/dist/server/src/services/release.d.ts.map +0 -1
- package/dist/server/src/services/scheduling.d.ts +0 -18
- package/dist/server/src/services/scheduling.d.ts.map +0 -1
- package/dist/server/src/services/settings.d.ts +0 -13
- package/dist/server/src/services/settings.d.ts.map +0 -1
- package/dist/server/src/services/validation.d.ts +0 -18
- package/dist/server/src/services/validation.d.ts.map +0 -1
- package/dist/server/src/utils/index.d.ts +0 -35
- package/dist/server/src/utils/index.d.ts.map +0 -1
- package/dist/shared/contracts/release-actions.d.ts +0 -130
- package/dist/shared/contracts/release-actions.d.ts.map +0 -1
- package/dist/shared/contracts/releases.d.ts +0 -184
- package/dist/shared/contracts/releases.d.ts.map +0 -1
- package/dist/shared/contracts/settings.d.ts +0 -39
- package/dist/shared/contracts/settings.d.ts.map +0 -1
- package/dist/shared/types.d.ts +0 -24
- package/dist/shared/types.d.ts.map +0 -1
package/dist/server/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { contentTypes as contentTypes$1,
|
|
1
|
+
import { contentTypes as contentTypes$1, mapAsync, setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
|
|
2
2
|
import isEqual from "lodash/isEqual";
|
|
3
3
|
import { difference, keys } from "lodash";
|
|
4
4
|
import _ from "lodash/fp";
|
|
5
|
+
import EE from "@strapi/strapi/dist/utils/ee";
|
|
5
6
|
import { scheduleJob } from "node-schedule";
|
|
6
7
|
import * as yup from "yup";
|
|
7
8
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
@@ -48,38 +49,21 @@ const ACTIONS = [
|
|
|
48
49
|
displayName: "Add an entry to a release",
|
|
49
50
|
uid: "create-action",
|
|
50
51
|
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"
|
|
68
52
|
}
|
|
69
53
|
];
|
|
70
54
|
const ALLOWED_WEBHOOK_EVENTS = {
|
|
71
55
|
RELEASES_PUBLISH: "releases.publish"
|
|
72
56
|
};
|
|
73
|
-
const getService = (name, { strapi: strapi2 }) => {
|
|
57
|
+
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
74
58
|
return strapi2.plugin("content-releases").service(name);
|
|
75
59
|
};
|
|
76
|
-
const
|
|
60
|
+
const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
77
61
|
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
78
|
-
const populate = await populateBuilderService(
|
|
79
|
-
const entry = await
|
|
80
|
-
return
|
|
62
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
63
|
+
const entry = await strapi2.entityService.findOne(contentTypeUid, entryId, { populate });
|
|
64
|
+
return entry;
|
|
81
65
|
};
|
|
82
|
-
const
|
|
66
|
+
const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
83
67
|
try {
|
|
84
68
|
await strapi2.entityValidator.validateEntityCreation(
|
|
85
69
|
strapi2.getModel(contentTypeUid),
|
|
@@ -93,38 +77,6 @@ const isEntryValid = async (contentTypeUid, entry, { strapi: strapi2 }) => {
|
|
|
93
77
|
return false;
|
|
94
78
|
}
|
|
95
79
|
};
|
|
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
|
-
};
|
|
128
80
|
async function deleteActionsOnDisableDraftAndPublish({
|
|
129
81
|
oldContentTypes,
|
|
130
82
|
contentTypes: contentTypes2
|
|
@@ -146,7 +98,7 @@ async function deleteActionsOnDisableDraftAndPublish({
|
|
|
146
98
|
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
147
99
|
const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes2)) ?? [];
|
|
148
100
|
if (deletedContentTypes.length) {
|
|
149
|
-
await
|
|
101
|
+
await mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
150
102
|
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
151
103
|
});
|
|
152
104
|
}
|
|
@@ -165,27 +117,25 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
165
117
|
}
|
|
166
118
|
}
|
|
167
119
|
});
|
|
168
|
-
|
|
120
|
+
mapAsync(releasesWithoutStatus, async (release2) => {
|
|
169
121
|
const actions = release2.actions;
|
|
170
122
|
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
171
123
|
for (const action of notValidatedActions) {
|
|
172
124
|
if (action.entry) {
|
|
173
|
-
const
|
|
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
|
-
}
|
|
125
|
+
const populatedEntry = await getPopulatedEntry(action.contentType, action.entry.id, {
|
|
126
|
+
strapi
|
|
188
127
|
});
|
|
128
|
+
if (populatedEntry) {
|
|
129
|
+
const isEntryValid = getEntryValidStatus(action.contentType, populatedEntry, { strapi });
|
|
130
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
131
|
+
where: {
|
|
132
|
+
id: action.id
|
|
133
|
+
},
|
|
134
|
+
data: {
|
|
135
|
+
isEntryValid
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
189
139
|
}
|
|
190
140
|
}
|
|
191
141
|
return getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
@@ -198,7 +148,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
198
148
|
}
|
|
199
149
|
}
|
|
200
150
|
});
|
|
201
|
-
|
|
151
|
+
mapAsync(publishedReleases, async (release2) => {
|
|
202
152
|
return strapi.db.query(RELEASE_MODEL_UID).update({
|
|
203
153
|
where: {
|
|
204
154
|
id: release2.id
|
|
@@ -215,7 +165,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
215
165
|
(uid) => oldContentTypes[uid]?.options?.draftAndPublish
|
|
216
166
|
);
|
|
217
167
|
const releasesAffected = /* @__PURE__ */ new Set();
|
|
218
|
-
|
|
168
|
+
mapAsync(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
|
|
219
169
|
const oldContentType = oldContentTypes[contentTypeUID];
|
|
220
170
|
const contentType = contentTypes2[contentTypeUID];
|
|
221
171
|
if (!isEqual(oldContentType?.attributes, contentType?.attributes)) {
|
|
@@ -228,30 +178,30 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
228
178
|
release: true
|
|
229
179
|
}
|
|
230
180
|
});
|
|
231
|
-
await
|
|
232
|
-
if (action.entry && action.release
|
|
233
|
-
const
|
|
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
|
-
}
|
|
181
|
+
await mapAsync(actions, async (action) => {
|
|
182
|
+
if (action.entry && action.release) {
|
|
183
|
+
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
184
|
+
strapi
|
|
249
185
|
});
|
|
186
|
+
if (populatedEntry) {
|
|
187
|
+
const isEntryValid = await getEntryValidStatus(contentTypeUID, populatedEntry, {
|
|
188
|
+
strapi
|
|
189
|
+
});
|
|
190
|
+
releasesAffected.add(action.release.id);
|
|
191
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
192
|
+
where: {
|
|
193
|
+
id: action.id
|
|
194
|
+
},
|
|
195
|
+
data: {
|
|
196
|
+
isEntryValid
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
250
200
|
}
|
|
251
201
|
});
|
|
252
202
|
}
|
|
253
203
|
}).then(() => {
|
|
254
|
-
|
|
204
|
+
mapAsync(releasesAffected, async (releaseId) => {
|
|
255
205
|
return getService("release", { strapi }).updateReleaseStatus(releaseId);
|
|
256
206
|
});
|
|
257
207
|
});
|
|
@@ -303,43 +253,11 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
|
|
|
303
253
|
}
|
|
304
254
|
}
|
|
305
255
|
}
|
|
306
|
-
const
|
|
307
|
-
name: "content-releases::5.0.0-add-entry-document-id-to-release-actions",
|
|
308
|
-
async up(trx, db) {
|
|
309
|
-
const hasTable = await trx.schema.hasTable("strapi_release_actions");
|
|
310
|
-
if (!hasTable) {
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const hasPolymorphicColumn = await trx.schema.hasColumn("strapi_release_actions", "target_id");
|
|
314
|
-
if (hasPolymorphicColumn) {
|
|
315
|
-
const hasEntryDocumentIdColumn = await trx.schema.hasColumn(
|
|
316
|
-
"strapi_release_actions",
|
|
317
|
-
"entry_document_id"
|
|
318
|
-
);
|
|
319
|
-
if (!hasEntryDocumentIdColumn) {
|
|
320
|
-
await trx.schema.alterTable("strapi_release_actions", (table) => {
|
|
321
|
-
table.string("entry_document_id");
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
const releaseActions = await trx.select("*").from("strapi_release_actions");
|
|
325
|
-
async.map(releaseActions, async (action) => {
|
|
326
|
-
const { target_type, target_id } = action;
|
|
327
|
-
const entry = await db.query(target_type).findOne({ where: { id: target_id } });
|
|
328
|
-
if (entry) {
|
|
329
|
-
await trx("strapi_release_actions").update({ entry_document_id: entry.documentId }).where("id", action.id);
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
},
|
|
334
|
-
async down() {
|
|
335
|
-
throw new Error("not implemented");
|
|
336
|
-
}
|
|
337
|
-
};
|
|
256
|
+
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
338
257
|
const register = async ({ strapi: strapi2 }) => {
|
|
339
|
-
if (
|
|
340
|
-
await strapi2.
|
|
341
|
-
strapi2.
|
|
342
|
-
strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized).register(deleteActionsOnDisableDraftAndPublish);
|
|
258
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
259
|
+
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
260
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
|
|
343
261
|
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
344
262
|
}
|
|
345
263
|
if (strapi2.plugin("graphql")) {
|
|
@@ -348,134 +266,129 @@ const register = async ({ strapi: strapi2 }) => {
|
|
|
348
266
|
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
349
267
|
}
|
|
350
268
|
};
|
|
351
|
-
const
|
|
352
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
353
|
-
where: {
|
|
354
|
-
actions: {
|
|
355
|
-
contentType,
|
|
356
|
-
entryDocumentId: entry.documentId,
|
|
357
|
-
locale: entry.locale
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
const entryStatus = await isEntryValid(contentType, entry, { strapi });
|
|
362
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
363
|
-
where: {
|
|
364
|
-
contentType,
|
|
365
|
-
entryDocumentId: entry.documentId,
|
|
366
|
-
locale: entry.locale
|
|
367
|
-
},
|
|
368
|
-
data: {
|
|
369
|
-
isEntryValid: entryStatus
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
for (const release2 of releases) {
|
|
373
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
const deleteActionsAndUpdateReleaseStatus = async (params) => {
|
|
377
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
378
|
-
where: {
|
|
379
|
-
actions: params
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
383
|
-
where: params
|
|
384
|
-
});
|
|
385
|
-
for (const release2 of releases) {
|
|
386
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
const deleteActionsOnDelete = async (ctx, next) => {
|
|
390
|
-
if (ctx.action !== "delete") {
|
|
391
|
-
return next();
|
|
392
|
-
}
|
|
393
|
-
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
394
|
-
return next();
|
|
395
|
-
}
|
|
396
|
-
const contentType = ctx.contentType.uid;
|
|
397
|
-
const { documentId, locale } = ctx.params;
|
|
398
|
-
const result = await next();
|
|
399
|
-
if (!result) {
|
|
400
|
-
return result;
|
|
401
|
-
}
|
|
402
|
-
try {
|
|
403
|
-
deleteActionsAndUpdateReleaseStatus({
|
|
404
|
-
contentType,
|
|
405
|
-
entryDocumentId: documentId,
|
|
406
|
-
...locale !== "*" && { locale }
|
|
407
|
-
});
|
|
408
|
-
} catch (error) {
|
|
409
|
-
strapi.log.error("Error while deleting release actions after delete", {
|
|
410
|
-
error
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
return result;
|
|
414
|
-
};
|
|
415
|
-
const updateActionsOnUpdate = async (ctx, next) => {
|
|
416
|
-
if (ctx.action !== "update") {
|
|
417
|
-
return next();
|
|
418
|
-
}
|
|
419
|
-
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
420
|
-
return next();
|
|
421
|
-
}
|
|
422
|
-
const contentType = ctx.contentType.uid;
|
|
423
|
-
const result = await next();
|
|
424
|
-
if (!result) {
|
|
425
|
-
return result;
|
|
426
|
-
}
|
|
427
|
-
try {
|
|
428
|
-
updateActionsStatusAndUpdateReleaseStatus(contentType, result);
|
|
429
|
-
} catch (error) {
|
|
430
|
-
strapi.log.error("Error while updating release actions after update", {
|
|
431
|
-
error
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
return result;
|
|
435
|
-
};
|
|
436
|
-
const deleteReleasesActionsAndUpdateReleaseStatus = async (params) => {
|
|
437
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
438
|
-
where: {
|
|
439
|
-
actions: params
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
443
|
-
where: params
|
|
444
|
-
});
|
|
445
|
-
for (const release2 of releases) {
|
|
446
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
447
|
-
}
|
|
448
|
-
};
|
|
269
|
+
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
449
270
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
450
|
-
if (
|
|
271
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
451
272
|
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
|
|
452
273
|
(uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
|
|
453
274
|
);
|
|
454
275
|
strapi2.db.lifecycles.subscribe({
|
|
455
276
|
models: contentTypesWithDraftAndPublish,
|
|
277
|
+
async afterDelete(event) {
|
|
278
|
+
try {
|
|
279
|
+
const { model, result } = event;
|
|
280
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
281
|
+
const { id } = result;
|
|
282
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
283
|
+
where: {
|
|
284
|
+
actions: {
|
|
285
|
+
target_type: model.uid,
|
|
286
|
+
target_id: id
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
291
|
+
where: {
|
|
292
|
+
target_type: model.uid,
|
|
293
|
+
target_id: id
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
for (const release2 of releases) {
|
|
297
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
} catch (error) {
|
|
301
|
+
strapi2.log.error("Error while deleting release actions after entry delete", { error });
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
/**
|
|
305
|
+
* deleteMany hook doesn't return the deleted entries ids
|
|
306
|
+
* so we need to fetch them before deleting the entries to save the ids on our state
|
|
307
|
+
*/
|
|
308
|
+
async beforeDeleteMany(event) {
|
|
309
|
+
const { model, params } = event;
|
|
310
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
311
|
+
const { where } = params;
|
|
312
|
+
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
313
|
+
event.state.entriesToDelete = entriesToDelete;
|
|
314
|
+
}
|
|
315
|
+
},
|
|
456
316
|
/**
|
|
457
|
-
*
|
|
317
|
+
* We delete the release actions related to deleted entries
|
|
318
|
+
* We make this only after deleteMany is succesfully executed to avoid errors
|
|
458
319
|
*/
|
|
459
320
|
async afterDeleteMany(event) {
|
|
460
321
|
try {
|
|
461
|
-
const model =
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
322
|
+
const { model, state } = event;
|
|
323
|
+
const entriesToDelete = state.entriesToDelete;
|
|
324
|
+
if (entriesToDelete) {
|
|
325
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
326
|
+
where: {
|
|
327
|
+
actions: {
|
|
328
|
+
target_type: model.uid,
|
|
329
|
+
target_id: {
|
|
330
|
+
$in: entriesToDelete.map(
|
|
331
|
+
(entry) => entry.id
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
338
|
+
where: {
|
|
339
|
+
target_type: model.uid,
|
|
340
|
+
target_id: {
|
|
341
|
+
$in: entriesToDelete.map((entry) => entry.id)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
468
344
|
});
|
|
345
|
+
for (const release2 of releases) {
|
|
346
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
347
|
+
}
|
|
469
348
|
}
|
|
470
349
|
} catch (error) {
|
|
471
350
|
strapi2.log.error("Error while deleting release actions after entry deleteMany", {
|
|
472
351
|
error
|
|
473
352
|
});
|
|
474
353
|
}
|
|
354
|
+
},
|
|
355
|
+
async afterUpdate(event) {
|
|
356
|
+
try {
|
|
357
|
+
const { model, result } = event;
|
|
358
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
359
|
+
const isEntryValid = await getEntryValidStatus(
|
|
360
|
+
model.uid,
|
|
361
|
+
result,
|
|
362
|
+
{
|
|
363
|
+
strapi: strapi2
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
367
|
+
where: {
|
|
368
|
+
target_type: model.uid,
|
|
369
|
+
target_id: result.id
|
|
370
|
+
},
|
|
371
|
+
data: {
|
|
372
|
+
isEntryValid
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
376
|
+
where: {
|
|
377
|
+
actions: {
|
|
378
|
+
target_type: model.uid,
|
|
379
|
+
target_id: result.id
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
for (const release2 of releases) {
|
|
384
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
} catch (error) {
|
|
388
|
+
strapi2.log.error("Error while updating release actions after entry update", { error });
|
|
389
|
+
}
|
|
475
390
|
}
|
|
476
391
|
});
|
|
477
|
-
strapi2.documents.use(deleteActionsOnDelete);
|
|
478
|
-
strapi2.documents.use(updateActionsOnUpdate);
|
|
479
392
|
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
480
393
|
strapi2.log.error(
|
|
481
394
|
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
@@ -483,7 +396,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
483
396
|
throw err;
|
|
484
397
|
});
|
|
485
398
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
486
|
-
strapi2.
|
|
399
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
487
400
|
});
|
|
488
401
|
}
|
|
489
402
|
};
|
|
@@ -567,13 +480,15 @@ const schema = {
|
|
|
567
480
|
enum: ["publish", "unpublish"],
|
|
568
481
|
required: true
|
|
569
482
|
},
|
|
483
|
+
entry: {
|
|
484
|
+
type: "relation",
|
|
485
|
+
relation: "morphToOne",
|
|
486
|
+
configurable: false
|
|
487
|
+
},
|
|
570
488
|
contentType: {
|
|
571
489
|
type: "string",
|
|
572
490
|
required: true
|
|
573
491
|
},
|
|
574
|
-
entryDocumentId: {
|
|
575
|
-
type: "string"
|
|
576
|
-
},
|
|
577
492
|
locale: {
|
|
578
493
|
type: "string"
|
|
579
494
|
},
|
|
@@ -595,6 +510,18 @@ const contentTypes = {
|
|
|
595
510
|
release: release$1,
|
|
596
511
|
"release-action": releaseAction$1
|
|
597
512
|
};
|
|
513
|
+
const getGroupName = (queryValue) => {
|
|
514
|
+
switch (queryValue) {
|
|
515
|
+
case "contentType":
|
|
516
|
+
return "contentType.displayName";
|
|
517
|
+
case "action":
|
|
518
|
+
return "type";
|
|
519
|
+
case "locale":
|
|
520
|
+
return _.getOr("No locale", "locale.name");
|
|
521
|
+
default:
|
|
522
|
+
return "contentType.displayName";
|
|
523
|
+
}
|
|
524
|
+
};
|
|
598
525
|
const createReleaseService = ({ strapi: strapi2 }) => {
|
|
599
526
|
const dispatchWebhook = (event, { isPublished, release: release2, error }) => {
|
|
600
527
|
strapi2.eventHub.emit(event, {
|
|
@@ -603,32 +530,93 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
603
530
|
release: release2
|
|
604
531
|
});
|
|
605
532
|
};
|
|
533
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
534
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
535
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
536
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
537
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
538
|
+
try {
|
|
539
|
+
if (actionType === "publish") {
|
|
540
|
+
await entityManagerService.publish(entry, uid);
|
|
541
|
+
} else {
|
|
542
|
+
await entityManagerService.unpublish(entry, uid);
|
|
543
|
+
}
|
|
544
|
+
} catch (error) {
|
|
545
|
+
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
546
|
+
;
|
|
547
|
+
else {
|
|
548
|
+
throw error;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
553
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
554
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
555
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
556
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
557
|
+
filters: {
|
|
558
|
+
id: {
|
|
559
|
+
$in: entriesToPublishIds
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
populate
|
|
563
|
+
});
|
|
564
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
565
|
+
filters: {
|
|
566
|
+
id: {
|
|
567
|
+
$in: entriestoUnpublishIds
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
populate
|
|
571
|
+
});
|
|
572
|
+
if (entriesToPublish.length > 0) {
|
|
573
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
574
|
+
}
|
|
575
|
+
if (entriesToUnpublish.length > 0) {
|
|
576
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
606
579
|
const getFormattedActions = async (releaseId) => {
|
|
607
580
|
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
608
581
|
where: {
|
|
609
582
|
release: {
|
|
610
583
|
id: releaseId
|
|
611
584
|
}
|
|
585
|
+
},
|
|
586
|
+
populate: {
|
|
587
|
+
entry: {
|
|
588
|
+
fields: ["id"]
|
|
589
|
+
}
|
|
612
590
|
}
|
|
613
591
|
});
|
|
614
592
|
if (actions.length === 0) {
|
|
615
593
|
throw new errors.ValidationError("No entries to publish");
|
|
616
594
|
}
|
|
617
|
-
const
|
|
595
|
+
const collectionTypeActions = {};
|
|
596
|
+
const singleTypeActions = [];
|
|
618
597
|
for (const action of actions) {
|
|
619
598
|
const contentTypeUid = action.contentType;
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
599
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
600
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
601
|
+
collectionTypeActions[contentTypeUid] = {
|
|
602
|
+
entriesToPublishIds: [],
|
|
603
|
+
entriesToUnpublishIds: []
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
if (action.type === "publish") {
|
|
607
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
608
|
+
} else {
|
|
609
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
singleTypeActions.push({
|
|
613
|
+
uid: contentTypeUid,
|
|
614
|
+
action: action.type,
|
|
615
|
+
id: action.entry.id
|
|
616
|
+
});
|
|
625
617
|
}
|
|
626
|
-
formattedActions[contentTypeUid][action.type].push({
|
|
627
|
-
documentId: action.entryDocumentId,
|
|
628
|
-
locale: action.locale
|
|
629
|
-
});
|
|
630
618
|
}
|
|
631
|
-
return
|
|
619
|
+
return { collectionTypeActions, singleTypeActions };
|
|
632
620
|
};
|
|
633
621
|
return {
|
|
634
622
|
async create(releaseData, { user }) {
|
|
@@ -643,7 +631,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
643
631
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
644
632
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
645
633
|
]);
|
|
646
|
-
const release2 = await strapi2.
|
|
634
|
+
const release2 = await strapi2.entityService.create(RELEASE_MODEL_UID, {
|
|
647
635
|
data: {
|
|
648
636
|
...releaseWithCreatorFields,
|
|
649
637
|
status: "empty"
|
|
@@ -657,28 +645,107 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
657
645
|
return release2;
|
|
658
646
|
},
|
|
659
647
|
async findOne(id, query = {}) {
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
...dbQuery,
|
|
663
|
-
where: { id }
|
|
648
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id, {
|
|
649
|
+
...query
|
|
664
650
|
});
|
|
665
651
|
return release2;
|
|
666
652
|
},
|
|
667
653
|
findPage(query) {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
...dbQuery,
|
|
654
|
+
return strapi2.entityService.findPage(RELEASE_MODEL_UID, {
|
|
655
|
+
...query,
|
|
671
656
|
populate: {
|
|
672
657
|
actions: {
|
|
658
|
+
// @ts-expect-error Ignore missing properties
|
|
673
659
|
count: true
|
|
674
660
|
}
|
|
675
661
|
}
|
|
676
662
|
});
|
|
677
663
|
},
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
664
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
665
|
+
let entries = entriesIds;
|
|
666
|
+
if (!Array.isArray(entriesIds)) {
|
|
667
|
+
entries = [entriesIds];
|
|
668
|
+
}
|
|
669
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
670
|
+
where: {
|
|
671
|
+
actions: {
|
|
672
|
+
target_type: contentTypeUid,
|
|
673
|
+
target_id: {
|
|
674
|
+
$in: entries
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
releasedAt: {
|
|
678
|
+
$null: true
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
populate: {
|
|
682
|
+
// Filter the action to get only the content type entry
|
|
683
|
+
actions: {
|
|
684
|
+
where: {
|
|
685
|
+
target_type: contentTypeUid,
|
|
686
|
+
target_id: {
|
|
687
|
+
$in: entries
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
populate: {
|
|
691
|
+
entry: {
|
|
692
|
+
select: ["id"]
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
return releases.map((release2) => {
|
|
699
|
+
if (release2.actions?.length) {
|
|
700
|
+
const actionsForEntry = release2.actions;
|
|
701
|
+
delete release2.actions;
|
|
702
|
+
return {
|
|
703
|
+
...release2,
|
|
704
|
+
actions: actionsForEntry
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
return release2;
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
711
|
+
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
712
|
+
where: {
|
|
713
|
+
releasedAt: {
|
|
714
|
+
$null: true
|
|
715
|
+
},
|
|
716
|
+
actions: {
|
|
717
|
+
target_type: contentTypeUid,
|
|
718
|
+
target_id: entryId
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
723
|
+
where: {
|
|
724
|
+
$or: [
|
|
725
|
+
{
|
|
726
|
+
id: {
|
|
727
|
+
$notIn: releasesRelated.map((release2) => release2.id)
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
actions: null
|
|
732
|
+
}
|
|
733
|
+
],
|
|
734
|
+
releasedAt: {
|
|
735
|
+
$null: true
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
return releases.map((release2) => {
|
|
740
|
+
if (release2.actions?.length) {
|
|
741
|
+
const [actionForEntry] = release2.actions;
|
|
742
|
+
delete release2.actions;
|
|
743
|
+
return {
|
|
744
|
+
...release2,
|
|
745
|
+
action: actionForEntry
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
return release2;
|
|
682
749
|
});
|
|
683
750
|
},
|
|
684
751
|
async update(id, releaseData, { user }) {
|
|
@@ -693,15 +760,19 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
693
760
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name, id),
|
|
694
761
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
695
762
|
]);
|
|
696
|
-
const release2 = await strapi2.
|
|
763
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id);
|
|
697
764
|
if (!release2) {
|
|
698
765
|
throw new errors.NotFoundError(`No release found for id ${id}`);
|
|
699
766
|
}
|
|
700
767
|
if (release2.releasedAt) {
|
|
701
768
|
throw new errors.ValidationError("Release already published");
|
|
702
769
|
}
|
|
703
|
-
const updatedRelease = await strapi2.
|
|
704
|
-
|
|
770
|
+
const updatedRelease = await strapi2.entityService.update(RELEASE_MODEL_UID, id, {
|
|
771
|
+
/*
|
|
772
|
+
* The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
|
|
773
|
+
* is not compatible with the type we are passing here: UpdateRelease.Request['body']
|
|
774
|
+
*/
|
|
775
|
+
// @ts-expect-error see above
|
|
705
776
|
data: releaseWithCreatorFields
|
|
706
777
|
});
|
|
707
778
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
@@ -714,6 +785,132 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
714
785
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
715
786
|
return updatedRelease;
|
|
716
787
|
},
|
|
788
|
+
async createAction(releaseId, action, { disableUpdateReleaseStatus = false } = {}) {
|
|
789
|
+
const { validateEntryContentType, validateUniqueEntry } = getService("release-validation", {
|
|
790
|
+
strapi: strapi2
|
|
791
|
+
});
|
|
792
|
+
await Promise.all([
|
|
793
|
+
validateEntryContentType(action.entry.contentType),
|
|
794
|
+
validateUniqueEntry(releaseId, action)
|
|
795
|
+
]);
|
|
796
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId);
|
|
797
|
+
if (!release2) {
|
|
798
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
799
|
+
}
|
|
800
|
+
if (release2.releasedAt) {
|
|
801
|
+
throw new errors.ValidationError("Release already published");
|
|
802
|
+
}
|
|
803
|
+
const { entry, type } = action;
|
|
804
|
+
const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
|
|
805
|
+
const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
|
|
806
|
+
const releaseAction2 = await strapi2.entityService.create(RELEASE_ACTION_MODEL_UID, {
|
|
807
|
+
data: {
|
|
808
|
+
type,
|
|
809
|
+
contentType: entry.contentType,
|
|
810
|
+
locale: entry.locale,
|
|
811
|
+
isEntryValid,
|
|
812
|
+
entry: {
|
|
813
|
+
id: entry.id,
|
|
814
|
+
__type: entry.contentType,
|
|
815
|
+
__pivot: { field: "entry" }
|
|
816
|
+
},
|
|
817
|
+
release: releaseId
|
|
818
|
+
},
|
|
819
|
+
populate: { release: { fields: ["id"] }, entry: { fields: ["id"] } }
|
|
820
|
+
});
|
|
821
|
+
if (!disableUpdateReleaseStatus) {
|
|
822
|
+
this.updateReleaseStatus(releaseId);
|
|
823
|
+
}
|
|
824
|
+
return releaseAction2;
|
|
825
|
+
},
|
|
826
|
+
async findActions(releaseId, query) {
|
|
827
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
828
|
+
fields: ["id"]
|
|
829
|
+
});
|
|
830
|
+
if (!release2) {
|
|
831
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
832
|
+
}
|
|
833
|
+
return strapi2.entityService.findPage(RELEASE_ACTION_MODEL_UID, {
|
|
834
|
+
...query,
|
|
835
|
+
populate: {
|
|
836
|
+
entry: {
|
|
837
|
+
populate: "*"
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
filters: {
|
|
841
|
+
release: releaseId
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
},
|
|
845
|
+
async countActions(query) {
|
|
846
|
+
return strapi2.entityService.count(RELEASE_ACTION_MODEL_UID, query);
|
|
847
|
+
},
|
|
848
|
+
async groupActions(actions, groupBy) {
|
|
849
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
850
|
+
if (!acc.includes(action.contentType)) {
|
|
851
|
+
acc.push(action.contentType);
|
|
852
|
+
}
|
|
853
|
+
return acc;
|
|
854
|
+
}, []);
|
|
855
|
+
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
|
|
856
|
+
contentTypeUids
|
|
857
|
+
);
|
|
858
|
+
const allLocalesDictionary = await this.getLocalesDataForActions();
|
|
859
|
+
const formattedData = actions.map((action) => {
|
|
860
|
+
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
861
|
+
return {
|
|
862
|
+
...action,
|
|
863
|
+
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
864
|
+
contentType: {
|
|
865
|
+
displayName,
|
|
866
|
+
mainFieldValue: action.entry[mainField],
|
|
867
|
+
uid: action.contentType
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
});
|
|
871
|
+
const groupName = getGroupName(groupBy);
|
|
872
|
+
return _.groupBy(groupName)(formattedData);
|
|
873
|
+
},
|
|
874
|
+
async getLocalesDataForActions() {
|
|
875
|
+
if (!strapi2.plugin("i18n")) {
|
|
876
|
+
return {};
|
|
877
|
+
}
|
|
878
|
+
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
879
|
+
return allLocales.reduce((acc, locale) => {
|
|
880
|
+
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
881
|
+
return acc;
|
|
882
|
+
}, {});
|
|
883
|
+
},
|
|
884
|
+
async getContentTypesDataForActions(contentTypesUids) {
|
|
885
|
+
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
886
|
+
const contentTypesData = {};
|
|
887
|
+
for (const contentTypeUid of contentTypesUids) {
|
|
888
|
+
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
889
|
+
uid: contentTypeUid
|
|
890
|
+
});
|
|
891
|
+
contentTypesData[contentTypeUid] = {
|
|
892
|
+
mainField: contentTypeConfig.settings.mainField,
|
|
893
|
+
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
return contentTypesData;
|
|
897
|
+
},
|
|
898
|
+
getContentTypeModelsFromActions(actions) {
|
|
899
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
900
|
+
if (!acc.includes(action.contentType)) {
|
|
901
|
+
acc.push(action.contentType);
|
|
902
|
+
}
|
|
903
|
+
return acc;
|
|
904
|
+
}, []);
|
|
905
|
+
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
906
|
+
(acc, contentTypeUid) => {
|
|
907
|
+
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
908
|
+
return acc;
|
|
909
|
+
},
|
|
910
|
+
{}
|
|
911
|
+
);
|
|
912
|
+
return contentTypeModelsMap;
|
|
913
|
+
},
|
|
717
914
|
async getAllComponents() {
|
|
718
915
|
const contentManagerComponentsService = strapi2.plugin("content-manager").service("components");
|
|
719
916
|
const components = await contentManagerComponentsService.findAllComponents();
|
|
@@ -727,11 +924,10 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
727
924
|
return componentsMap;
|
|
728
925
|
},
|
|
729
926
|
async delete(releaseId) {
|
|
730
|
-
const release2 = await strapi2.
|
|
731
|
-
where: { id: releaseId },
|
|
927
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
732
928
|
populate: {
|
|
733
929
|
actions: {
|
|
734
|
-
|
|
930
|
+
fields: ["id"]
|
|
735
931
|
}
|
|
736
932
|
}
|
|
737
933
|
});
|
|
@@ -749,11 +945,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
749
945
|
}
|
|
750
946
|
}
|
|
751
947
|
});
|
|
752
|
-
await strapi2.
|
|
753
|
-
where: {
|
|
754
|
-
id: releaseId
|
|
755
|
-
}
|
|
756
|
-
});
|
|
948
|
+
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
757
949
|
});
|
|
758
950
|
if (release2.scheduledAt) {
|
|
759
951
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
@@ -779,19 +971,22 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
779
971
|
}
|
|
780
972
|
try {
|
|
781
973
|
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
async () => Promise.all(
|
|
785
|
-
Object.keys(formattedActions).map(async (contentTypeUid) => {
|
|
786
|
-
const contentType = contentTypeUid;
|
|
787
|
-
const { publish, unpublish } = formattedActions[contentType];
|
|
788
|
-
return Promise.all([
|
|
789
|
-
...publish.map((params) => strapi2.documents(contentType).publish(params)),
|
|
790
|
-
...unpublish.map((params) => strapi2.documents(contentType).unpublish(params))
|
|
791
|
-
]);
|
|
792
|
-
})
|
|
793
|
-
)
|
|
974
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
975
|
+
releaseId
|
|
794
976
|
);
|
|
977
|
+
await strapi2.db.transaction(async () => {
|
|
978
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
979
|
+
await publishSingleTypeAction(uid, action, id);
|
|
980
|
+
}
|
|
981
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
982
|
+
const uid = contentTypeUid;
|
|
983
|
+
await publishCollectionTypeAction(
|
|
984
|
+
uid,
|
|
985
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
986
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
795
990
|
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
796
991
|
where: {
|
|
797
992
|
id: releaseId
|
|
@@ -821,226 +1016,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
821
1016
|
};
|
|
822
1017
|
}
|
|
823
1018
|
});
|
|
824
|
-
if (error
|
|
825
|
-
throw error;
|
|
826
|
-
}
|
|
827
|
-
return release2;
|
|
828
|
-
},
|
|
829
|
-
async updateReleaseStatus(releaseId) {
|
|
830
|
-
const releaseActionService = getService("release-action", { strapi: strapi2 });
|
|
831
|
-
const [totalActions, invalidActions] = await Promise.all([
|
|
832
|
-
releaseActionService.countActions({
|
|
833
|
-
filters: {
|
|
834
|
-
release: releaseId
|
|
835
|
-
}
|
|
836
|
-
}),
|
|
837
|
-
releaseActionService.countActions({
|
|
838
|
-
filters: {
|
|
839
|
-
release: releaseId,
|
|
840
|
-
isEntryValid: false
|
|
841
|
-
}
|
|
842
|
-
})
|
|
843
|
-
]);
|
|
844
|
-
if (totalActions > 0) {
|
|
845
|
-
if (invalidActions > 0) {
|
|
846
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
847
|
-
where: {
|
|
848
|
-
id: releaseId
|
|
849
|
-
},
|
|
850
|
-
data: {
|
|
851
|
-
status: "blocked"
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
856
|
-
where: {
|
|
857
|
-
id: releaseId
|
|
858
|
-
},
|
|
859
|
-
data: {
|
|
860
|
-
status: "ready"
|
|
861
|
-
}
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
865
|
-
where: {
|
|
866
|
-
id: releaseId
|
|
867
|
-
},
|
|
868
|
-
data: {
|
|
869
|
-
status: "empty"
|
|
870
|
-
}
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
};
|
|
875
|
-
const getGroupName = (queryValue) => {
|
|
876
|
-
switch (queryValue) {
|
|
877
|
-
case "contentType":
|
|
878
|
-
return "contentType.displayName";
|
|
879
|
-
case "type":
|
|
880
|
-
return "type";
|
|
881
|
-
case "locale":
|
|
882
|
-
return _.getOr("No locale", "locale.name");
|
|
883
|
-
default:
|
|
884
|
-
return "contentType.displayName";
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
888
|
-
const getLocalesDataForActions = async () => {
|
|
889
|
-
if (!strapi2.plugin("i18n")) {
|
|
890
|
-
return {};
|
|
891
|
-
}
|
|
892
|
-
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
893
|
-
return allLocales.reduce((acc, locale) => {
|
|
894
|
-
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
895
|
-
return acc;
|
|
896
|
-
}, {});
|
|
897
|
-
};
|
|
898
|
-
const getContentTypesDataForActions = async (contentTypesUids) => {
|
|
899
|
-
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
900
|
-
const contentTypesData = {};
|
|
901
|
-
for (const contentTypeUid of contentTypesUids) {
|
|
902
|
-
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
903
|
-
uid: contentTypeUid
|
|
904
|
-
});
|
|
905
|
-
contentTypesData[contentTypeUid] = {
|
|
906
|
-
mainField: contentTypeConfig.settings.mainField,
|
|
907
|
-
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
return contentTypesData;
|
|
911
|
-
};
|
|
912
|
-
return {
|
|
913
|
-
async create(releaseId, action, { disableUpdateReleaseStatus = false } = {}) {
|
|
914
|
-
const { validateEntryData, validateUniqueEntry } = getService("release-validation", {
|
|
915
|
-
strapi: strapi2
|
|
916
|
-
});
|
|
917
|
-
await Promise.all([
|
|
918
|
-
validateEntryData(action.contentType, action.entryDocumentId),
|
|
919
|
-
validateUniqueEntry(releaseId, action)
|
|
920
|
-
]);
|
|
921
|
-
const model = strapi2.contentType(action.contentType);
|
|
922
|
-
if (model.kind === "singleType") {
|
|
923
|
-
const document = await strapi2.db.query(model.uid).findOne({ select: ["documentId"] });
|
|
924
|
-
if (!document) {
|
|
925
|
-
throw new errors.NotFoundError(`No entry found for contentType ${action.contentType}`);
|
|
926
|
-
}
|
|
927
|
-
action.entryDocumentId = document.documentId;
|
|
928
|
-
}
|
|
929
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
930
|
-
if (!release2) {
|
|
931
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
932
|
-
}
|
|
933
|
-
if (release2.releasedAt) {
|
|
934
|
-
throw new errors.ValidationError("Release already published");
|
|
935
|
-
}
|
|
936
|
-
const actionStatus = action.type === "publish" ? await getDraftEntryValidStatus(
|
|
937
|
-
{
|
|
938
|
-
contentType: action.contentType,
|
|
939
|
-
documentId: action.entryDocumentId,
|
|
940
|
-
locale: action.locale
|
|
941
|
-
},
|
|
942
|
-
{
|
|
943
|
-
strapi: strapi2
|
|
944
|
-
}
|
|
945
|
-
) : true;
|
|
946
|
-
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
947
|
-
data: {
|
|
948
|
-
...action,
|
|
949
|
-
release: release2.id,
|
|
950
|
-
isEntryValid: actionStatus
|
|
951
|
-
},
|
|
952
|
-
populate: { release: { select: ["id"] } }
|
|
953
|
-
});
|
|
954
|
-
if (!disableUpdateReleaseStatus) {
|
|
955
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
956
|
-
}
|
|
957
|
-
return releaseAction2;
|
|
958
|
-
},
|
|
959
|
-
async findPage(releaseId, query) {
|
|
960
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
961
|
-
where: { id: releaseId },
|
|
962
|
-
select: ["id"]
|
|
963
|
-
});
|
|
964
|
-
if (!release2) {
|
|
965
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
1019
|
+
if (error) {
|
|
1020
|
+
throw error;
|
|
966
1021
|
}
|
|
967
|
-
|
|
968
|
-
const { results: actions, pagination } = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
969
|
-
...dbQuery,
|
|
970
|
-
where: {
|
|
971
|
-
release: releaseId
|
|
972
|
-
}
|
|
973
|
-
});
|
|
974
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
975
|
-
const actionsWithEntry = await async.map(actions, async (action) => {
|
|
976
|
-
const populate = await populateBuilderService(action.contentType).populateDeep(Infinity).build();
|
|
977
|
-
const entry = await getEntry(
|
|
978
|
-
{
|
|
979
|
-
contentType: action.contentType,
|
|
980
|
-
documentId: action.entryDocumentId,
|
|
981
|
-
locale: action.locale,
|
|
982
|
-
populate,
|
|
983
|
-
status: action.type === "publish" ? "draft" : "published"
|
|
984
|
-
},
|
|
985
|
-
{ strapi: strapi2 }
|
|
986
|
-
);
|
|
987
|
-
return {
|
|
988
|
-
...action,
|
|
989
|
-
entry,
|
|
990
|
-
status: entry ? await getEntryStatus(action.contentType, entry) : null
|
|
991
|
-
};
|
|
992
|
-
});
|
|
993
|
-
return {
|
|
994
|
-
results: actionsWithEntry,
|
|
995
|
-
pagination
|
|
996
|
-
};
|
|
997
|
-
},
|
|
998
|
-
async groupActions(actions, groupBy) {
|
|
999
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
1000
|
-
if (!acc.includes(action.contentType)) {
|
|
1001
|
-
acc.push(action.contentType);
|
|
1002
|
-
}
|
|
1003
|
-
return acc;
|
|
1004
|
-
}, []);
|
|
1005
|
-
const allReleaseContentTypesDictionary = await getContentTypesDataForActions(contentTypeUids);
|
|
1006
|
-
const allLocalesDictionary = await getLocalesDataForActions();
|
|
1007
|
-
const formattedData = actions.map((action) => {
|
|
1008
|
-
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
1009
|
-
return {
|
|
1010
|
-
...action,
|
|
1011
|
-
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
1012
|
-
contentType: {
|
|
1013
|
-
displayName,
|
|
1014
|
-
mainFieldValue: action.entry[mainField],
|
|
1015
|
-
uid: action.contentType
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
|
-
});
|
|
1019
|
-
const groupName = getGroupName(groupBy);
|
|
1020
|
-
return _.groupBy(groupName)(formattedData);
|
|
1021
|
-
},
|
|
1022
|
-
getContentTypeModelsFromActions(actions) {
|
|
1023
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
1024
|
-
if (!acc.includes(action.contentType)) {
|
|
1025
|
-
acc.push(action.contentType);
|
|
1026
|
-
}
|
|
1027
|
-
return acc;
|
|
1028
|
-
}, []);
|
|
1029
|
-
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
1030
|
-
(acc, contentTypeUid) => {
|
|
1031
|
-
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
1032
|
-
return acc;
|
|
1033
|
-
},
|
|
1034
|
-
{}
|
|
1035
|
-
);
|
|
1036
|
-
return contentTypeModelsMap;
|
|
1037
|
-
},
|
|
1038
|
-
async countActions(query) {
|
|
1039
|
-
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
1040
|
-
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
1022
|
+
return release2;
|
|
1041
1023
|
},
|
|
1042
|
-
async
|
|
1043
|
-
const
|
|
1024
|
+
async updateAction(actionId, releaseId, update) {
|
|
1025
|
+
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
1044
1026
|
where: {
|
|
1045
1027
|
id: actionId,
|
|
1046
1028
|
release: {
|
|
@@ -1049,42 +1031,17 @@ const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
|
1049
1031
|
$null: true
|
|
1050
1032
|
}
|
|
1051
1033
|
}
|
|
1052
|
-
}
|
|
1034
|
+
},
|
|
1035
|
+
data: update
|
|
1053
1036
|
});
|
|
1054
|
-
if (!
|
|
1037
|
+
if (!updatedAction) {
|
|
1055
1038
|
throw new errors.NotFoundError(
|
|
1056
1039
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1057
1040
|
);
|
|
1058
1041
|
}
|
|
1059
|
-
const actionStatus = update.type === "publish" ? await getDraftEntryValidStatus(
|
|
1060
|
-
{
|
|
1061
|
-
contentType: action.contentType,
|
|
1062
|
-
documentId: action.entryDocumentId,
|
|
1063
|
-
locale: action.locale
|
|
1064
|
-
},
|
|
1065
|
-
{
|
|
1066
|
-
strapi: strapi2
|
|
1067
|
-
}
|
|
1068
|
-
) : true;
|
|
1069
|
-
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
1070
|
-
where: {
|
|
1071
|
-
id: actionId,
|
|
1072
|
-
release: {
|
|
1073
|
-
id: releaseId,
|
|
1074
|
-
releasedAt: {
|
|
1075
|
-
$null: true
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
},
|
|
1079
|
-
data: {
|
|
1080
|
-
...update,
|
|
1081
|
-
isEntryValid: actionStatus
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(releaseId);
|
|
1085
1042
|
return updatedAction;
|
|
1086
1043
|
},
|
|
1087
|
-
async
|
|
1044
|
+
async deleteAction(actionId, releaseId) {
|
|
1088
1045
|
const deletedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).delete({
|
|
1089
1046
|
where: {
|
|
1090
1047
|
id: actionId,
|
|
@@ -1101,8 +1058,51 @@ const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
|
1101
1058
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1102
1059
|
);
|
|
1103
1060
|
}
|
|
1104
|
-
|
|
1061
|
+
this.updateReleaseStatus(releaseId);
|
|
1105
1062
|
return deletedAction;
|
|
1063
|
+
},
|
|
1064
|
+
async updateReleaseStatus(releaseId) {
|
|
1065
|
+
const [totalActions, invalidActions] = await Promise.all([
|
|
1066
|
+
this.countActions({
|
|
1067
|
+
filters: {
|
|
1068
|
+
release: releaseId
|
|
1069
|
+
}
|
|
1070
|
+
}),
|
|
1071
|
+
this.countActions({
|
|
1072
|
+
filters: {
|
|
1073
|
+
release: releaseId,
|
|
1074
|
+
isEntryValid: false
|
|
1075
|
+
}
|
|
1076
|
+
})
|
|
1077
|
+
]);
|
|
1078
|
+
if (totalActions > 0) {
|
|
1079
|
+
if (invalidActions > 0) {
|
|
1080
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1081
|
+
where: {
|
|
1082
|
+
id: releaseId
|
|
1083
|
+
},
|
|
1084
|
+
data: {
|
|
1085
|
+
status: "blocked"
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1090
|
+
where: {
|
|
1091
|
+
id: releaseId
|
|
1092
|
+
},
|
|
1093
|
+
data: {
|
|
1094
|
+
status: "ready"
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1099
|
+
where: {
|
|
1100
|
+
id: releaseId
|
|
1101
|
+
},
|
|
1102
|
+
data: {
|
|
1103
|
+
status: "empty"
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
1106
|
}
|
|
1107
1107
|
};
|
|
1108
1108
|
};
|
|
@@ -1114,43 +1114,37 @@ class AlreadyOnReleaseError extends errors.ApplicationError {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1116
1116
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1117
|
-
const release2 = await strapi2.
|
|
1118
|
-
|
|
1119
|
-
id: releaseId
|
|
1120
|
-
},
|
|
1121
|
-
populate: {
|
|
1122
|
-
actions: true
|
|
1123
|
-
}
|
|
1117
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
1118
|
+
populate: { actions: { populate: { entry: { fields: ["id"] } } } }
|
|
1124
1119
|
});
|
|
1125
1120
|
if (!release2) {
|
|
1126
1121
|
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
1127
1122
|
}
|
|
1128
1123
|
const isEntryInRelease = release2.actions.some(
|
|
1129
|
-
(action) => action.
|
|
1124
|
+
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1130
1125
|
);
|
|
1131
1126
|
if (isEntryInRelease) {
|
|
1132
1127
|
throw new AlreadyOnReleaseError(
|
|
1133
|
-
`Entry with
|
|
1128
|
+
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1134
1129
|
);
|
|
1135
1130
|
}
|
|
1136
1131
|
},
|
|
1137
|
-
|
|
1132
|
+
validateEntryContentType(contentTypeUid) {
|
|
1138
1133
|
const contentType = strapi2.contentType(contentTypeUid);
|
|
1139
1134
|
if (!contentType) {
|
|
1140
1135
|
throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
|
1141
1136
|
}
|
|
1142
|
-
if (!
|
|
1137
|
+
if (!contentType.options?.draftAndPublish) {
|
|
1143
1138
|
throw new errors.ValidationError(
|
|
1144
1139
|
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
1145
1140
|
);
|
|
1146
1141
|
}
|
|
1147
|
-
if (contentType.kind === "collectionType" && !entryDocumentId) {
|
|
1148
|
-
throw new errors.ValidationError("Document id is required for collection type");
|
|
1149
|
-
}
|
|
1150
1142
|
},
|
|
1151
1143
|
async validatePendingReleasesLimit() {
|
|
1152
|
-
const
|
|
1153
|
-
|
|
1144
|
+
const maximumPendingReleases = (
|
|
1145
|
+
// @ts-expect-error - options is not typed into features
|
|
1146
|
+
EE.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
1147
|
+
);
|
|
1154
1148
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
1155
1149
|
filters: {
|
|
1156
1150
|
releasedAt: {
|
|
@@ -1163,8 +1157,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1163
1157
|
}
|
|
1164
1158
|
},
|
|
1165
1159
|
async validateUniqueNameForPendingRelease(name, id) {
|
|
1166
|
-
const pendingReleases = await strapi2.
|
|
1167
|
-
|
|
1160
|
+
const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
|
|
1161
|
+
filters: {
|
|
1168
1162
|
releasedAt: {
|
|
1169
1163
|
$null: true
|
|
1170
1164
|
},
|
|
@@ -1193,7 +1187,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1193
1187
|
}
|
|
1194
1188
|
const job = scheduleJob(scheduleDate, async () => {
|
|
1195
1189
|
try {
|
|
1196
|
-
await getService("release"
|
|
1190
|
+
await getService("release").publish(releaseId);
|
|
1197
1191
|
} catch (error) {
|
|
1198
1192
|
}
|
|
1199
1193
|
this.cancel(releaseId);
|
|
@@ -1235,172 +1229,85 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1235
1229
|
}
|
|
1236
1230
|
};
|
|
1237
1231
|
};
|
|
1238
|
-
const DEFAULT_SETTINGS = {
|
|
1239
|
-
defaultTimezone: null
|
|
1240
|
-
};
|
|
1241
|
-
const createSettingsService = ({ strapi: strapi2 }) => {
|
|
1242
|
-
const getStore = async () => strapi2.store({ type: "core", name: "content-releases" });
|
|
1243
|
-
return {
|
|
1244
|
-
async update({ settings: settings2 }) {
|
|
1245
|
-
const store = await getStore();
|
|
1246
|
-
store.set({ key: "settings", value: settings2 });
|
|
1247
|
-
return settings2;
|
|
1248
|
-
},
|
|
1249
|
-
async find() {
|
|
1250
|
-
const store = await getStore();
|
|
1251
|
-
const settings2 = await store.get({ key: "settings" });
|
|
1252
|
-
return {
|
|
1253
|
-
...DEFAULT_SETTINGS,
|
|
1254
|
-
...settings2 || {}
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
|
-
};
|
|
1258
|
-
};
|
|
1259
1232
|
const services = {
|
|
1260
1233
|
release: createReleaseService,
|
|
1261
|
-
"release-action": createReleaseActionService,
|
|
1262
1234
|
"release-validation": createReleaseValidationService,
|
|
1263
|
-
scheduling: createSchedulingService
|
|
1264
|
-
settings: createSettingsService
|
|
1235
|
+
scheduling: createSchedulingService
|
|
1265
1236
|
};
|
|
1266
|
-
const RELEASE_SCHEMA = yup
|
|
1267
|
-
name: yup
|
|
1268
|
-
scheduledAt: yup
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1237
|
+
const RELEASE_SCHEMA = yup.object().shape({
|
|
1238
|
+
name: yup.string().trim().required(),
|
|
1239
|
+
scheduledAt: yup.string().nullable(),
|
|
1240
|
+
isScheduled: yup.boolean().optional(),
|
|
1241
|
+
time: yup.string().when("isScheduled", {
|
|
1242
|
+
is: true,
|
|
1243
|
+
then: yup.string().trim().required(),
|
|
1244
|
+
otherwise: yup.string().nullable()
|
|
1245
|
+
}),
|
|
1246
|
+
timezone: yup.string().when("isScheduled", {
|
|
1247
|
+
is: true,
|
|
1248
|
+
then: yup.string().required().nullable(),
|
|
1249
|
+
otherwise: yup.string().nullable()
|
|
1250
|
+
}),
|
|
1251
|
+
date: yup.string().when("isScheduled", {
|
|
1252
|
+
is: true,
|
|
1253
|
+
then: yup.string().required().nullable(),
|
|
1254
|
+
otherwise: yup.string().nullable()
|
|
1273
1255
|
})
|
|
1274
1256
|
}).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();
|
|
1281
1257
|
const validateRelease = validateYupSchema(RELEASE_SCHEMA);
|
|
1282
|
-
const validatefindByDocumentAttachedParams = validateYupSchema(
|
|
1283
|
-
FIND_BY_DOCUMENT_ATTACHED_PARAMS_SCHEMA
|
|
1284
|
-
);
|
|
1285
1258
|
const releaseController = {
|
|
1286
|
-
|
|
1287
|
-
|
|
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({
|
|
1259
|
+
async findMany(ctx) {
|
|
1260
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1293
1261
|
ability: ctx.state.userAbility,
|
|
1294
1262
|
model: RELEASE_MODEL_UID
|
|
1295
1263
|
});
|
|
1296
1264
|
await permissionsManager.validateQuery(ctx.query);
|
|
1297
1265
|
const releaseService = getService("release", { strapi });
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
const
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
}
|
|
1306
|
-
query.entryDocumentId = document.documentId;
|
|
1307
|
-
}
|
|
1308
|
-
const { contentType, hasEntryAttached, entryDocumentId, locale } = query;
|
|
1309
|
-
const isEntryAttached = typeof hasEntryAttached === "string" ? Boolean(JSON.parse(hasEntryAttached)) : false;
|
|
1310
|
-
if (isEntryAttached) {
|
|
1311
|
-
const releases = await releaseService.findMany({
|
|
1312
|
-
where: {
|
|
1313
|
-
releasedAt: null,
|
|
1314
|
-
actions: {
|
|
1315
|
-
contentType,
|
|
1316
|
-
entryDocumentId: entryDocumentId ?? null,
|
|
1317
|
-
locale: locale ?? null
|
|
1318
|
-
}
|
|
1319
|
-
},
|
|
1320
|
-
populate: {
|
|
1321
|
-
actions: {
|
|
1322
|
-
fields: ["type"],
|
|
1323
|
-
filters: {
|
|
1324
|
-
contentType,
|
|
1325
|
-
entryDocumentId: entryDocumentId ?? null,
|
|
1326
|
-
locale: locale ?? null
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
});
|
|
1331
|
-
ctx.body = { data: releases };
|
|
1266
|
+
const isFindManyForContentTypeEntry = Boolean(ctx.query?.contentTypeUid && ctx.query?.entryId);
|
|
1267
|
+
if (isFindManyForContentTypeEntry) {
|
|
1268
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1269
|
+
const contentTypeUid = query.contentTypeUid;
|
|
1270
|
+
const entryId = query.entryId;
|
|
1271
|
+
const hasEntryAttached = typeof query.hasEntryAttached === "string" ? JSON.parse(query.hasEntryAttached) : false;
|
|
1272
|
+
const data = hasEntryAttached ? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId) : await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
|
|
1273
|
+
ctx.body = { data };
|
|
1332
1274
|
} else {
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1275
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1276
|
+
const { results, pagination } = await releaseService.findPage(query);
|
|
1277
|
+
const data = results.map((release2) => {
|
|
1278
|
+
const { actions, ...releaseData } = release2;
|
|
1279
|
+
return {
|
|
1280
|
+
...releaseData,
|
|
1336
1281
|
actions: {
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1282
|
+
meta: {
|
|
1283
|
+
count: actions.count
|
|
1284
|
+
}
|
|
1340
1285
|
}
|
|
1341
|
-
}
|
|
1286
|
+
};
|
|
1342
1287
|
});
|
|
1343
|
-
const
|
|
1288
|
+
const pendingReleasesCount = await strapi.query(RELEASE_MODEL_UID).count({
|
|
1344
1289
|
where: {
|
|
1345
|
-
$or: [
|
|
1346
|
-
{
|
|
1347
|
-
id: {
|
|
1348
|
-
$notIn: relatedReleases.map((release2) => release2.id)
|
|
1349
|
-
}
|
|
1350
|
-
},
|
|
1351
|
-
{
|
|
1352
|
-
actions: null
|
|
1353
|
-
}
|
|
1354
|
-
],
|
|
1355
1290
|
releasedAt: null
|
|
1356
1291
|
}
|
|
1357
1292
|
});
|
|
1358
|
-
ctx.body = { data:
|
|
1293
|
+
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
1359
1294
|
}
|
|
1360
1295
|
},
|
|
1361
|
-
async findPage(ctx) {
|
|
1362
|
-
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1363
|
-
ability: ctx.state.userAbility,
|
|
1364
|
-
model: RELEASE_MODEL_UID
|
|
1365
|
-
});
|
|
1366
|
-
await permissionsManager.validateQuery(ctx.query);
|
|
1367
|
-
const releaseService = getService("release", { strapi });
|
|
1368
|
-
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1369
|
-
const { results, pagination } = await releaseService.findPage(query);
|
|
1370
|
-
const data = results.map((release2) => {
|
|
1371
|
-
const { actions, ...releaseData } = release2;
|
|
1372
|
-
return {
|
|
1373
|
-
...releaseData,
|
|
1374
|
-
actions: {
|
|
1375
|
-
meta: {
|
|
1376
|
-
count: actions.count
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
};
|
|
1380
|
-
});
|
|
1381
|
-
const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
|
|
1382
|
-
where: {
|
|
1383
|
-
releasedAt: null
|
|
1384
|
-
}
|
|
1385
|
-
});
|
|
1386
|
-
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
1387
|
-
},
|
|
1388
1296
|
async findOne(ctx) {
|
|
1389
1297
|
const id = ctx.params.id;
|
|
1390
1298
|
const releaseService = getService("release", { strapi });
|
|
1391
|
-
const releaseActionService = getService("release-action", { strapi });
|
|
1392
1299
|
const release2 = await releaseService.findOne(id, { populate: ["createdBy"] });
|
|
1393
1300
|
if (!release2) {
|
|
1394
1301
|
throw new errors.NotFoundError(`Release not found for id: ${id}`);
|
|
1395
1302
|
}
|
|
1396
|
-
const count = await
|
|
1303
|
+
const count = await releaseService.countActions({
|
|
1397
1304
|
filters: {
|
|
1398
1305
|
release: id
|
|
1399
1306
|
}
|
|
1400
1307
|
});
|
|
1401
1308
|
const sanitizedRelease = {
|
|
1402
1309
|
...release2,
|
|
1403
|
-
createdBy: release2.createdBy ? strapi.
|
|
1310
|
+
createdBy: release2.createdBy ? strapi.admin.services.user.sanitizeUser(release2.createdBy) : null
|
|
1404
1311
|
};
|
|
1405
1312
|
const data = {
|
|
1406
1313
|
...sanitizedRelease,
|
|
@@ -1413,39 +1320,22 @@ const releaseController = {
|
|
|
1413
1320
|
ctx.body = { data };
|
|
1414
1321
|
},
|
|
1415
1322
|
async mapEntriesToReleases(ctx) {
|
|
1416
|
-
const { contentTypeUid,
|
|
1417
|
-
if (!contentTypeUid || !
|
|
1323
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1324
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1418
1325
|
throw new errors.ValidationError("Missing required query parameters");
|
|
1419
1326
|
}
|
|
1420
1327
|
const releaseService = getService("release", { strapi });
|
|
1421
|
-
const releasesWithActions = await releaseService.
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
contentType: contentTypeUid,
|
|
1426
|
-
entryDocumentId: {
|
|
1427
|
-
$in: documentIds
|
|
1428
|
-
},
|
|
1429
|
-
locale
|
|
1430
|
-
}
|
|
1431
|
-
},
|
|
1432
|
-
populate: {
|
|
1433
|
-
actions: true
|
|
1434
|
-
}
|
|
1435
|
-
});
|
|
1328
|
+
const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
|
|
1329
|
+
contentTypeUid,
|
|
1330
|
+
entriesIds
|
|
1331
|
+
);
|
|
1436
1332
|
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1437
1333
|
(acc, release2) => {
|
|
1438
1334
|
release2.actions.forEach((action) => {
|
|
1439
|
-
if (action.
|
|
1440
|
-
|
|
1441
|
-
}
|
|
1442
|
-
if (locale && action.locale !== locale) {
|
|
1443
|
-
return;
|
|
1444
|
-
}
|
|
1445
|
-
if (!acc[action.entryDocumentId]) {
|
|
1446
|
-
acc[action.entryDocumentId] = [{ id: release2.id, name: release2.name }];
|
|
1335
|
+
if (!acc[action.entry.id]) {
|
|
1336
|
+
acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
|
|
1447
1337
|
} else {
|
|
1448
|
-
acc[action.
|
|
1338
|
+
acc[action.entry.id].push({ id: release2.id, name: release2.name });
|
|
1449
1339
|
}
|
|
1450
1340
|
});
|
|
1451
1341
|
return acc;
|
|
@@ -1462,13 +1352,13 @@ const releaseController = {
|
|
|
1462
1352
|
await validateRelease(releaseArgs);
|
|
1463
1353
|
const releaseService = getService("release", { strapi });
|
|
1464
1354
|
const release2 = await releaseService.create(releaseArgs, { user });
|
|
1465
|
-
const permissionsManager = strapi.
|
|
1355
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1466
1356
|
ability: ctx.state.userAbility,
|
|
1467
1357
|
model: RELEASE_MODEL_UID
|
|
1468
1358
|
});
|
|
1469
|
-
ctx.
|
|
1359
|
+
ctx.body = {
|
|
1470
1360
|
data: await permissionsManager.sanitizeOutput(release2)
|
|
1471
|
-
}
|
|
1361
|
+
};
|
|
1472
1362
|
},
|
|
1473
1363
|
async update(ctx) {
|
|
1474
1364
|
const user = ctx.state.user;
|
|
@@ -1477,7 +1367,7 @@ const releaseController = {
|
|
|
1477
1367
|
await validateRelease(releaseArgs);
|
|
1478
1368
|
const releaseService = getService("release", { strapi });
|
|
1479
1369
|
const release2 = await releaseService.update(id, releaseArgs, { user });
|
|
1480
|
-
const permissionsManager = strapi.
|
|
1370
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1481
1371
|
ability: ctx.state.userAbility,
|
|
1482
1372
|
model: RELEASE_MODEL_UID
|
|
1483
1373
|
});
|
|
@@ -1494,18 +1384,18 @@ const releaseController = {
|
|
|
1494
1384
|
};
|
|
1495
1385
|
},
|
|
1496
1386
|
async publish(ctx) {
|
|
1387
|
+
const user = ctx.state.user;
|
|
1497
1388
|
const id = ctx.params.id;
|
|
1498
1389
|
const releaseService = getService("release", { strapi });
|
|
1499
|
-
const
|
|
1500
|
-
const release2 = await releaseService.publish(id);
|
|
1390
|
+
const release2 = await releaseService.publish(id, { user });
|
|
1501
1391
|
const [countPublishActions, countUnpublishActions] = await Promise.all([
|
|
1502
|
-
|
|
1392
|
+
releaseService.countActions({
|
|
1503
1393
|
filters: {
|
|
1504
1394
|
release: id,
|
|
1505
1395
|
type: "publish"
|
|
1506
1396
|
}
|
|
1507
1397
|
}),
|
|
1508
|
-
|
|
1398
|
+
releaseService.countActions({
|
|
1509
1399
|
filters: {
|
|
1510
1400
|
release: id,
|
|
1511
1401
|
type: "unpublish"
|
|
@@ -1523,30 +1413,27 @@ const releaseController = {
|
|
|
1523
1413
|
}
|
|
1524
1414
|
};
|
|
1525
1415
|
const RELEASE_ACTION_SCHEMA = yup$1.object().shape({
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1416
|
+
entry: yup$1.object().shape({
|
|
1417
|
+
id: yup$1.strapiID().required(),
|
|
1418
|
+
contentType: yup$1.string().required()
|
|
1419
|
+
}).required(),
|
|
1529
1420
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1530
1421
|
});
|
|
1531
1422
|
const RELEASE_ACTION_UPDATE_SCHEMA = yup$1.object().shape({
|
|
1532
1423
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1533
1424
|
});
|
|
1534
|
-
const FIND_MANY_ACTIONS_PARAMS = yup$1.object().shape({
|
|
1535
|
-
groupBy: yup$1.string().oneOf(["action", "contentType", "locale"])
|
|
1536
|
-
});
|
|
1537
1425
|
const validateReleaseAction = validateYupSchema(RELEASE_ACTION_SCHEMA);
|
|
1538
1426
|
const validateReleaseActionUpdateSchema = validateYupSchema(RELEASE_ACTION_UPDATE_SCHEMA);
|
|
1539
|
-
const validateFindManyActionsParams = validateYupSchema(FIND_MANY_ACTIONS_PARAMS);
|
|
1540
1427
|
const releaseActionController = {
|
|
1541
1428
|
async create(ctx) {
|
|
1542
1429
|
const releaseId = ctx.params.releaseId;
|
|
1543
1430
|
const releaseActionArgs = ctx.request.body;
|
|
1544
1431
|
await validateReleaseAction(releaseActionArgs);
|
|
1545
|
-
const
|
|
1546
|
-
const releaseAction2 = await
|
|
1547
|
-
ctx.
|
|
1432
|
+
const releaseService = getService("release", { strapi });
|
|
1433
|
+
const releaseAction2 = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1434
|
+
ctx.body = {
|
|
1548
1435
|
data: releaseAction2
|
|
1549
|
-
}
|
|
1436
|
+
};
|
|
1550
1437
|
},
|
|
1551
1438
|
async createMany(ctx) {
|
|
1552
1439
|
const releaseId = ctx.params.releaseId;
|
|
@@ -1554,13 +1441,12 @@ const releaseActionController = {
|
|
|
1554
1441
|
await Promise.all(
|
|
1555
1442
|
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1556
1443
|
);
|
|
1557
|
-
const releaseActionService = getService("release-action", { strapi });
|
|
1558
1444
|
const releaseService = getService("release", { strapi });
|
|
1559
1445
|
const releaseActions = await strapi.db.transaction(async () => {
|
|
1560
1446
|
const releaseActions2 = await Promise.all(
|
|
1561
1447
|
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1562
1448
|
try {
|
|
1563
|
-
const action = await
|
|
1449
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs, {
|
|
1564
1450
|
disableUpdateReleaseStatus: true
|
|
1565
1451
|
});
|
|
1566
1452
|
return action;
|
|
@@ -1578,51 +1464,43 @@ const releaseActionController = {
|
|
|
1578
1464
|
if (newReleaseActions.length > 0) {
|
|
1579
1465
|
releaseService.updateReleaseStatus(releaseId);
|
|
1580
1466
|
}
|
|
1581
|
-
ctx.
|
|
1467
|
+
ctx.body = {
|
|
1582
1468
|
data: newReleaseActions,
|
|
1583
1469
|
meta: {
|
|
1584
1470
|
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1585
1471
|
totalEntries: releaseActions.length
|
|
1586
1472
|
}
|
|
1587
|
-
}
|
|
1473
|
+
};
|
|
1588
1474
|
},
|
|
1589
1475
|
async findMany(ctx) {
|
|
1590
1476
|
const releaseId = ctx.params.releaseId;
|
|
1591
|
-
const permissionsManager = strapi.
|
|
1477
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1592
1478
|
ability: ctx.state.userAbility,
|
|
1593
1479
|
model: RELEASE_ACTION_MODEL_UID
|
|
1594
1480
|
});
|
|
1595
|
-
await validateFindManyActionsParams(ctx.query);
|
|
1596
|
-
if (ctx.query.groupBy) {
|
|
1597
|
-
if (!["action", "contentType", "locale"].includes(ctx.query.groupBy)) {
|
|
1598
|
-
ctx.badRequest("Invalid groupBy parameter");
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
ctx.query.sort = ctx.query.groupBy === "action" ? "type" : ctx.query.groupBy;
|
|
1602
|
-
delete ctx.query.groupBy;
|
|
1603
1481
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1604
|
-
const
|
|
1605
|
-
const { results, pagination } = await
|
|
1482
|
+
const releaseService = getService("release", { strapi });
|
|
1483
|
+
const { results, pagination } = await releaseService.findActions(releaseId, {
|
|
1484
|
+
sort: query.groupBy === "action" ? "type" : query.groupBy,
|
|
1606
1485
|
...query
|
|
1607
1486
|
});
|
|
1608
1487
|
const contentTypeOutputSanitizers = results.reduce((acc, action) => {
|
|
1609
1488
|
if (acc[action.contentType]) {
|
|
1610
1489
|
return acc;
|
|
1611
1490
|
}
|
|
1612
|
-
const contentTypePermissionsManager = strapi.
|
|
1491
|
+
const contentTypePermissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1613
1492
|
ability: ctx.state.userAbility,
|
|
1614
1493
|
model: action.contentType
|
|
1615
1494
|
});
|
|
1616
1495
|
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
1617
1496
|
return acc;
|
|
1618
1497
|
}, {});
|
|
1619
|
-
const sanitizedResults = await
|
|
1498
|
+
const sanitizedResults = await mapAsync(results, async (action) => ({
|
|
1620
1499
|
...action,
|
|
1621
|
-
entry:
|
|
1500
|
+
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1622
1501
|
}));
|
|
1623
|
-
const groupedData = await
|
|
1624
|
-
const contentTypes2 =
|
|
1625
|
-
const releaseService = getService("release", { strapi });
|
|
1502
|
+
const groupedData = await releaseService.groupActions(sanitizedResults, query.groupBy);
|
|
1503
|
+
const contentTypes2 = releaseService.getContentTypeModelsFromActions(results);
|
|
1626
1504
|
const components = await releaseService.getAllComponents();
|
|
1627
1505
|
ctx.body = {
|
|
1628
1506
|
data: groupedData,
|
|
@@ -1638,8 +1516,8 @@ const releaseActionController = {
|
|
|
1638
1516
|
const releaseId = ctx.params.releaseId;
|
|
1639
1517
|
const releaseActionUpdateArgs = ctx.request.body;
|
|
1640
1518
|
await validateReleaseActionUpdateSchema(releaseActionUpdateArgs);
|
|
1641
|
-
const
|
|
1642
|
-
const updatedAction = await
|
|
1519
|
+
const releaseService = getService("release", { strapi });
|
|
1520
|
+
const updatedAction = await releaseService.updateAction(
|
|
1643
1521
|
actionId,
|
|
1644
1522
|
releaseId,
|
|
1645
1523
|
releaseActionUpdateArgs
|
|
@@ -1651,36 +1529,14 @@ const releaseActionController = {
|
|
|
1651
1529
|
async delete(ctx) {
|
|
1652
1530
|
const actionId = ctx.params.actionId;
|
|
1653
1531
|
const releaseId = ctx.params.releaseId;
|
|
1654
|
-
const
|
|
1655
|
-
const deletedReleaseAction = await
|
|
1532
|
+
const releaseService = getService("release", { strapi });
|
|
1533
|
+
const deletedReleaseAction = await releaseService.deleteAction(actionId, releaseId);
|
|
1656
1534
|
ctx.body = {
|
|
1657
1535
|
data: deletedReleaseAction
|
|
1658
1536
|
};
|
|
1659
1537
|
}
|
|
1660
1538
|
};
|
|
1661
|
-
const
|
|
1662
|
-
defaultTimezone: yup.string().nullable().default(null)
|
|
1663
|
-
}).required().noUnknown();
|
|
1664
|
-
const validateSettings = validateYupSchema(SETTINGS_SCHEMA);
|
|
1665
|
-
const settingsController = {
|
|
1666
|
-
async find(ctx) {
|
|
1667
|
-
const settingsService = getService("settings", { strapi });
|
|
1668
|
-
const settings2 = await settingsService.find();
|
|
1669
|
-
ctx.body = { data: settings2 };
|
|
1670
|
-
},
|
|
1671
|
-
async update(ctx) {
|
|
1672
|
-
const settingsBody = ctx.request.body;
|
|
1673
|
-
const settings2 = await validateSettings(settingsBody);
|
|
1674
|
-
const settingsService = getService("settings", { strapi });
|
|
1675
|
-
const updatedSettings = await settingsService.update({ settings: settings2 });
|
|
1676
|
-
ctx.body = { data: updatedSettings };
|
|
1677
|
-
}
|
|
1678
|
-
};
|
|
1679
|
-
const controllers = {
|
|
1680
|
-
release: releaseController,
|
|
1681
|
-
"release-action": releaseActionController,
|
|
1682
|
-
settings: settingsController
|
|
1683
|
-
};
|
|
1539
|
+
const controllers = { release: releaseController, "release-action": releaseActionController };
|
|
1684
1540
|
const release = {
|
|
1685
1541
|
type: "admin",
|
|
1686
1542
|
routes: [
|
|
@@ -1700,22 +1556,6 @@ const release = {
|
|
|
1700
1556
|
]
|
|
1701
1557
|
}
|
|
1702
1558
|
},
|
|
1703
|
-
{
|
|
1704
|
-
method: "GET",
|
|
1705
|
-
path: "/getByDocumentAttached",
|
|
1706
|
-
handler: "release.findByDocumentAttached",
|
|
1707
|
-
config: {
|
|
1708
|
-
policies: [
|
|
1709
|
-
"admin::isAuthenticatedAdmin",
|
|
1710
|
-
{
|
|
1711
|
-
name: "admin::hasPermissions",
|
|
1712
|
-
config: {
|
|
1713
|
-
actions: ["plugin::content-releases.read"]
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
]
|
|
1717
|
-
}
|
|
1718
|
-
},
|
|
1719
1559
|
{
|
|
1720
1560
|
method: "POST",
|
|
1721
1561
|
path: "/",
|
|
@@ -1735,7 +1575,7 @@ const release = {
|
|
|
1735
1575
|
{
|
|
1736
1576
|
method: "GET",
|
|
1737
1577
|
path: "/",
|
|
1738
|
-
handler: "release.
|
|
1578
|
+
handler: "release.findMany",
|
|
1739
1579
|
config: {
|
|
1740
1580
|
policies: [
|
|
1741
1581
|
"admin::isAuthenticatedAdmin",
|
|
@@ -1899,50 +1739,13 @@ const releaseAction = {
|
|
|
1899
1739
|
}
|
|
1900
1740
|
]
|
|
1901
1741
|
};
|
|
1902
|
-
const settings = {
|
|
1903
|
-
type: "admin",
|
|
1904
|
-
routes: [
|
|
1905
|
-
{
|
|
1906
|
-
method: "GET",
|
|
1907
|
-
path: "/settings",
|
|
1908
|
-
handler: "settings.find",
|
|
1909
|
-
config: {
|
|
1910
|
-
policies: [
|
|
1911
|
-
"admin::isAuthenticatedAdmin",
|
|
1912
|
-
{
|
|
1913
|
-
name: "admin::hasPermissions",
|
|
1914
|
-
config: {
|
|
1915
|
-
actions: ["plugin::content-releases.settings.read"]
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
]
|
|
1919
|
-
}
|
|
1920
|
-
},
|
|
1921
|
-
{
|
|
1922
|
-
method: "PUT",
|
|
1923
|
-
path: "/settings",
|
|
1924
|
-
handler: "settings.update",
|
|
1925
|
-
config: {
|
|
1926
|
-
policies: [
|
|
1927
|
-
"admin::isAuthenticatedAdmin",
|
|
1928
|
-
{
|
|
1929
|
-
name: "admin::hasPermissions",
|
|
1930
|
-
config: {
|
|
1931
|
-
actions: ["plugin::content-releases.settings.update"]
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
]
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
]
|
|
1938
|
-
};
|
|
1939
1742
|
const routes = {
|
|
1940
|
-
settings,
|
|
1941
1743
|
release,
|
|
1942
1744
|
"release-action": releaseAction
|
|
1943
1745
|
};
|
|
1746
|
+
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1944
1747
|
const getPlugin = () => {
|
|
1945
|
-
if (
|
|
1748
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
1946
1749
|
return {
|
|
1947
1750
|
register,
|
|
1948
1751
|
bootstrap,
|