@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.bd712ad3930045f4a5d2144c119e0b7856e97fc4
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/LICENSE +18 -3
- package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-BWQv6yRj.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-BWQv6yRj.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs → ComponentConfigurationPage-C7ImeKGM.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-C7ImeKGM.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
- package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
- package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-CEGwxV-L.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-CEGwxV-L.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-MItFGzT9.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-MItFGzT9.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-CmMi2Xsn.js} +46 -48
- package/dist/_chunks/EditViewPage-CmMi2Xsn.js.map +1 -0
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-DhmAg0NK.mjs} +47 -47
- package/dist/_chunks/EditViewPage-DhmAg0NK.mjs.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-1DLtcLAI.js} +948 -777
- package/dist/_chunks/Field-1DLtcLAI.js.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-Cs62u5pl.mjs} +896 -724
- package/dist/_chunks/Field-Cs62u5pl.mjs.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-CqFA7F_V.js} +42 -41
- package/dist/_chunks/Form-CqFA7F_V.js.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-zYHtzGUX.mjs} +43 -41
- package/dist/_chunks/Form-zYHtzGUX.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-BblwXv7-.js} +149 -66
- package/dist/_chunks/History-BblwXv7-.js.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-DalgFQ3D.mjs} +149 -65
- package/dist/_chunks/History-DalgFQ3D.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-Cpy4QqNd.js} +61 -62
- package/dist/_chunks/ListConfigurationPage-Cpy4QqNd.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-DWy-vRzs.mjs} +58 -58
- package/dist/_chunks/ListConfigurationPage-DWy-vRzs.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-BkAwIW9s.mjs} +90 -106
- package/dist/_chunks/ListViewPage-BkAwIW9s.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-DFjn1DNW.js} +95 -111
- package/dist/_chunks/ListViewPage-DFjn1DNW.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-B9BCNNdL.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-B9BCNNdL.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-C-3ykoxs.js} +5 -5
- package/dist/_chunks/NoContentTypePage-C-3ykoxs.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-Bt_HWGat.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-Bt_HWGat.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-DKLmDZnZ.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-DKLmDZnZ.js.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-CJmTbZ8T.mjs} +66 -56
- package/dist/_chunks/Relations-CJmTbZ8T.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-CrxfoH2n.js} +70 -61
- package/dist/_chunks/Relations-CrxfoH2n.js.map +1 -0
- package/dist/_chunks/{en-MBPul9Su.mjs → en-Ux26r5pl.mjs} +7 -1
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Ux26r5pl.mjs.map} +1 -1
- package/dist/_chunks/{en-C-V1_90f.js → en-fbKQxLGn.js} +7 -1
- package/dist/_chunks/{en-C-V1_90f.js.map → en-fbKQxLGn.js.map} +1 -1
- package/dist/_chunks/{index-X_2tafck.js → index-Buwn78Rt.js} +1507 -868
- package/dist/_chunks/index-Buwn78Rt.js.map +1 -0
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-D1344xdw.mjs} +1476 -836
- package/dist/_chunks/index-D1344xdw.mjs.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-ChVuUpa1.mjs} +32 -27
- package/dist/_chunks/layout-ChVuUpa1.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-DRuJUpas.js} +32 -29
- package/dist/_chunks/layout-DRuJUpas.js.map +1 -0
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-B-deMCy4.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-B-deMCy4.mjs.map} +1 -1
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-DuoUwyJr.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-DuoUwyJr.js.map} +1 -1
- package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
- package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +3 -3
- package/dist/admin/src/exports.d.ts +1 -0
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +5 -8
- package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
- package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
- package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +10 -4
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- package/dist/admin/src/services/api.d.ts +2 -3
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +5 -5
- package/dist/admin/src/services/documents.d.ts +29 -17
- package/dist/admin/src/services/init.d.ts +2 -2
- package/dist/admin/src/services/relations.d.ts +3 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/api.d.ts +4 -18
- package/dist/admin/src/utils/validation.d.ts +1 -6
- package/dist/server/index.js +547 -416
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +555 -424
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/index.d.ts +1 -1
- package/dist/server/src/history/services/history.d.ts +2 -4
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/index.d.ts +6 -2
- package/dist/server/src/history/services/index.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts +9 -0
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
- package/dist/server/src/history/services/utils.d.ts +41 -9
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/history/utils.d.ts +6 -2
- package/dist/server/src/history/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +18 -39
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts +13 -12
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -29
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +18 -39
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +8 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +14 -6
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/relations.d.ts +2 -2
- package/dist/shared/contracts/relations.d.ts.map +1 -1
- package/package.json +13 -14
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
- package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
- package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
- package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
- package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
- package/dist/_chunks/History-C17LiyRg.js.map +0 -1
- package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
- package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
- package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
- package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
- package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
- package/dist/_chunks/index-X_2tafck.js.map +0 -1
- package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
- package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
- package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
package/dist/server/index.js
CHANGED
@@ -138,40 +138,65 @@ const FIELDS_TO_IGNORE = [
|
|
138
138
|
"strapi_stage",
|
139
139
|
"strapi_assignee"
|
140
140
|
];
|
141
|
-
const getSchemaAttributesDiff = (versionSchemaAttributes, contentTypeSchemaAttributes) => {
|
142
|
-
const sanitizedContentTypeSchemaAttributes = fp.omit(FIELDS_TO_IGNORE, contentTypeSchemaAttributes);
|
143
|
-
const reduceDifferenceToAttributesObject = (diffKeys, source) => {
|
144
|
-
return diffKeys.reduce((previousAttributesObject, diffKey) => {
|
145
|
-
previousAttributesObject[diffKey] = source[diffKey];
|
146
|
-
return previousAttributesObject;
|
147
|
-
}, {});
|
148
|
-
};
|
149
|
-
const versionSchemaKeys = Object.keys(versionSchemaAttributes);
|
150
|
-
const contentTypeSchemaAttributesKeys = Object.keys(sanitizedContentTypeSchemaAttributes);
|
151
|
-
const uniqueToContentType = fp.difference(contentTypeSchemaAttributesKeys, versionSchemaKeys);
|
152
|
-
const added = reduceDifferenceToAttributesObject(
|
153
|
-
uniqueToContentType,
|
154
|
-
sanitizedContentTypeSchemaAttributes
|
155
|
-
);
|
156
|
-
const uniqueToVersion = fp.difference(versionSchemaKeys, contentTypeSchemaAttributesKeys);
|
157
|
-
const removed = reduceDifferenceToAttributesObject(uniqueToVersion, versionSchemaAttributes);
|
158
|
-
return { added, removed };
|
159
|
-
};
|
160
141
|
const DEFAULT_RETENTION_DAYS = 90;
|
161
|
-
const
|
162
|
-
const
|
163
|
-
|
164
|
-
|
142
|
+
const createServiceUtils = ({ strapi: strapi2 }) => {
|
143
|
+
const getSchemaAttributesDiff = (versionSchemaAttributes, contentTypeSchemaAttributes) => {
|
144
|
+
const sanitizedContentTypeSchemaAttributes = fp.omit(
|
145
|
+
FIELDS_TO_IGNORE,
|
146
|
+
contentTypeSchemaAttributes
|
147
|
+
);
|
148
|
+
const reduceDifferenceToAttributesObject = (diffKeys, source) => {
|
149
|
+
return diffKeys.reduce(
|
150
|
+
(previousAttributesObject, diffKey) => {
|
151
|
+
previousAttributesObject[diffKey] = source[diffKey];
|
152
|
+
return previousAttributesObject;
|
153
|
+
},
|
154
|
+
{}
|
155
|
+
);
|
156
|
+
};
|
157
|
+
const versionSchemaKeys = Object.keys(versionSchemaAttributes);
|
158
|
+
const contentTypeSchemaAttributesKeys = Object.keys(sanitizedContentTypeSchemaAttributes);
|
159
|
+
const uniqueToContentType = fp.difference(contentTypeSchemaAttributesKeys, versionSchemaKeys);
|
160
|
+
const added = reduceDifferenceToAttributesObject(
|
161
|
+
uniqueToContentType,
|
162
|
+
sanitizedContentTypeSchemaAttributes
|
163
|
+
);
|
164
|
+
const uniqueToVersion = fp.difference(versionSchemaKeys, contentTypeSchemaAttributesKeys);
|
165
|
+
const removed = reduceDifferenceToAttributesObject(uniqueToVersion, versionSchemaAttributes);
|
166
|
+
return { added, removed };
|
165
167
|
};
|
166
|
-
const
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
168
|
+
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
169
|
+
if (Array.isArray(versionRelationData)) {
|
170
|
+
if (versionRelationData.length === 0)
|
171
|
+
return versionRelationData;
|
172
|
+
const existingAndMissingRelations = await Promise.all(
|
173
|
+
versionRelationData.map((relation) => {
|
174
|
+
return strapi2.documents(attribute.target).findOne({
|
175
|
+
documentId: relation.documentId,
|
176
|
+
locale: relation.locale || void 0
|
177
|
+
});
|
178
|
+
})
|
179
|
+
);
|
180
|
+
return existingAndMissingRelations.filter(
|
181
|
+
(relation) => relation !== null
|
182
|
+
);
|
173
183
|
}
|
174
|
-
return
|
184
|
+
return strapi2.documents(attribute.target).findOne({
|
185
|
+
documentId: versionRelationData.documentId,
|
186
|
+
locale: versionRelationData.locale || void 0
|
187
|
+
});
|
188
|
+
};
|
189
|
+
const getMediaRestoreValue = async (versionRelationData, attribute) => {
|
190
|
+
if (attribute.multiple) {
|
191
|
+
const existingAndMissingMedias = await Promise.all(
|
192
|
+
// @ts-expect-error Fix the type definitions so this isn't any
|
193
|
+
versionRelationData.map((media) => {
|
194
|
+
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
195
|
+
})
|
196
|
+
);
|
197
|
+
return existingAndMissingMedias.filter((media) => media != null);
|
198
|
+
}
|
199
|
+
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
175
200
|
};
|
176
201
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
177
202
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
@@ -187,6 +212,15 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
187
212
|
{}
|
188
213
|
);
|
189
214
|
};
|
215
|
+
const getRetentionDays = () => {
|
216
|
+
const featureConfig = strapi2.ee.features.get("cms-content-history");
|
217
|
+
const licenseRetentionDays = typeof featureConfig === "object" && featureConfig?.options.retentionDays;
|
218
|
+
const userRetentionDays = strapi2.config.get("admin.history.retentionDays");
|
219
|
+
if (userRetentionDays && userRetentionDays < licenseRetentionDays) {
|
220
|
+
return userRetentionDays;
|
221
|
+
}
|
222
|
+
return Math.min(licenseRetentionDays, DEFAULT_RETENTION_DAYS);
|
223
|
+
};
|
190
224
|
const getVersionStatus = async (contentTypeUid, document) => {
|
191
225
|
const documentMetadataService = strapi2.plugin("content-manager").service("document-metadata");
|
192
226
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
@@ -198,6 +232,10 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
198
232
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
199
233
|
switch (attribute.type) {
|
200
234
|
case "relation": {
|
235
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
236
|
+
if (isMorphRelation) {
|
237
|
+
break;
|
238
|
+
}
|
201
239
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
202
240
|
if (isVisible2) {
|
203
241
|
acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
|
@@ -228,80 +266,68 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
228
266
|
return acc;
|
229
267
|
}, {});
|
230
268
|
};
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
238
|
-
return next();
|
269
|
+
const buildMediaResponse = async (values) => {
|
270
|
+
return values.slice(0, 25).reduce(
|
271
|
+
async (currentRelationDataPromise, entry) => {
|
272
|
+
const currentRelationData = await currentRelationDataPromise;
|
273
|
+
if (!entry) {
|
274
|
+
return currentRelationData;
|
239
275
|
}
|
240
|
-
|
241
|
-
|
276
|
+
const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
|
277
|
+
if (relatedEntry) {
|
278
|
+
currentRelationData.results.push(relatedEntry);
|
279
|
+
} else {
|
280
|
+
currentRelationData.meta.missingCount += 1;
|
242
281
|
}
|
243
|
-
|
244
|
-
|
245
|
-
|
282
|
+
return currentRelationData;
|
283
|
+
},
|
284
|
+
Promise.resolve({
|
285
|
+
results: [],
|
286
|
+
meta: { missingCount: 0 }
|
287
|
+
})
|
288
|
+
);
|
289
|
+
};
|
290
|
+
const buildRelationReponse = async (values, attributeSchema) => {
|
291
|
+
return values.slice(0, 25).reduce(
|
292
|
+
async (currentRelationDataPromise, entry) => {
|
293
|
+
const currentRelationData = await currentRelationDataPromise;
|
294
|
+
if (!entry) {
|
295
|
+
return currentRelationData;
|
246
296
|
}
|
247
|
-
const
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
documentId: documentContext.documentId,
|
253
|
-
locale,
|
254
|
-
populate: getDeepPopulate2(contentTypeUid)
|
255
|
-
});
|
256
|
-
const status = await getVersionStatus(contentTypeUid, document);
|
257
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
258
|
-
const componentsSchemas = Object.keys(
|
259
|
-
attributesSchema
|
260
|
-
).reduce((currentComponentSchemas, key) => {
|
261
|
-
const fieldSchema = attributesSchema[key];
|
262
|
-
if (fieldSchema.type === "component") {
|
263
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
264
|
-
return {
|
265
|
-
...currentComponentSchemas,
|
266
|
-
[fieldSchema.component]: componentSchema
|
267
|
-
};
|
268
|
-
}
|
269
|
-
return currentComponentSchemas;
|
270
|
-
}, {});
|
271
|
-
await strapi2.db.transaction(async ({ onCommit }) => {
|
272
|
-
onCommit(() => {
|
273
|
-
this.createVersion({
|
274
|
-
contentType: contentTypeUid,
|
275
|
-
data: fp.omit(FIELDS_TO_IGNORE, document),
|
276
|
-
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
277
|
-
componentsSchemas,
|
278
|
-
relatedDocumentId: documentContext.documentId,
|
279
|
-
locale,
|
280
|
-
status
|
281
|
-
});
|
297
|
+
const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
|
298
|
+
if (relatedEntry) {
|
299
|
+
currentRelationData.results.push({
|
300
|
+
...relatedEntry,
|
301
|
+
status: await getVersionStatus(attributeSchema.target, relatedEntry)
|
282
302
|
});
|
283
|
-
}
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
303
|
+
} else {
|
304
|
+
currentRelationData.meta.missingCount += 1;
|
305
|
+
}
|
306
|
+
return currentRelationData;
|
307
|
+
},
|
308
|
+
Promise.resolve({
|
309
|
+
results: [],
|
310
|
+
meta: { missingCount: 0 }
|
311
|
+
})
|
312
|
+
);
|
313
|
+
};
|
314
|
+
return {
|
315
|
+
getSchemaAttributesDiff,
|
316
|
+
getRelationRestoreValue,
|
317
|
+
getMediaRestoreValue,
|
318
|
+
getDefaultLocale,
|
319
|
+
getLocaleDictionary,
|
320
|
+
getRetentionDays,
|
321
|
+
getVersionStatus,
|
322
|
+
getDeepPopulate: getDeepPopulate2,
|
323
|
+
buildMediaResponse,
|
324
|
+
buildRelationReponse
|
325
|
+
};
|
326
|
+
};
|
327
|
+
const createHistoryService = ({ strapi: strapi2 }) => {
|
328
|
+
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
329
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
330
|
+
return {
|
305
331
|
async createVersion(historyVersionData) {
|
306
332
|
await query.create({
|
307
333
|
data: {
|
@@ -312,7 +338,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
312
338
|
});
|
313
339
|
},
|
314
340
|
async findVersionsPage(params) {
|
315
|
-
const locale = params.query.locale || await getDefaultLocale();
|
341
|
+
const locale = params.query.locale || await serviceUtils.getDefaultLocale();
|
316
342
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
317
343
|
query.findPage({
|
318
344
|
...params.query,
|
@@ -326,78 +352,34 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
326
352
|
populate: ["createdBy"],
|
327
353
|
orderBy: [{ createdAt: "desc" }]
|
328
354
|
}),
|
329
|
-
getLocaleDictionary()
|
355
|
+
serviceUtils.getLocaleDictionary()
|
330
356
|
]);
|
331
|
-
const buildRelationReponse = async (values, attributeSchema) => {
|
332
|
-
return values.slice(0, 25).reduce(
|
333
|
-
async (currentRelationDataPromise, entry) => {
|
334
|
-
const currentRelationData = await currentRelationDataPromise;
|
335
|
-
if (!entry) {
|
336
|
-
return currentRelationData;
|
337
|
-
}
|
338
|
-
const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
|
339
|
-
const permissionChecker2 = getService$1("permission-checker").create({
|
340
|
-
userAbility: params.state.userAbility,
|
341
|
-
model: attributeSchema.target
|
342
|
-
});
|
343
|
-
const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
|
344
|
-
if (sanitizedEntry) {
|
345
|
-
currentRelationData.results.push({
|
346
|
-
...sanitizedEntry,
|
347
|
-
status: await getVersionStatus(attributeSchema.target, sanitizedEntry)
|
348
|
-
});
|
349
|
-
} else {
|
350
|
-
currentRelationData.meta.missingCount += 1;
|
351
|
-
}
|
352
|
-
return currentRelationData;
|
353
|
-
},
|
354
|
-
Promise.resolve({
|
355
|
-
results: [],
|
356
|
-
meta: { missingCount: 0 }
|
357
|
-
})
|
358
|
-
);
|
359
|
-
};
|
360
|
-
const buildMediaResponse = async (values) => {
|
361
|
-
return values.slice(0, 25).reduce(
|
362
|
-
async (currentRelationDataPromise, entry) => {
|
363
|
-
const currentRelationData = await currentRelationDataPromise;
|
364
|
-
if (!entry) {
|
365
|
-
return currentRelationData;
|
366
|
-
}
|
367
|
-
const permissionChecker2 = getService$1("permission-checker").create({
|
368
|
-
userAbility: params.state.userAbility,
|
369
|
-
model: "plugin::upload.file"
|
370
|
-
});
|
371
|
-
const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
|
372
|
-
const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
|
373
|
-
if (sanitizedEntry) {
|
374
|
-
currentRelationData.results.push(sanitizedEntry);
|
375
|
-
} else {
|
376
|
-
currentRelationData.meta.missingCount += 1;
|
377
|
-
}
|
378
|
-
return currentRelationData;
|
379
|
-
},
|
380
|
-
Promise.resolve({
|
381
|
-
results: [],
|
382
|
-
meta: { missingCount: 0 }
|
383
|
-
})
|
384
|
-
);
|
385
|
-
};
|
386
357
|
const populateEntryRelations = async (entry) => {
|
387
358
|
const entryWithRelations = await Object.entries(entry.schema).reduce(
|
388
359
|
async (currentDataWithRelations, [attributeKey, attributeSchema]) => {
|
389
360
|
const attributeValue = entry.data[attributeKey];
|
390
361
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
391
362
|
if (attributeSchema.type === "media") {
|
363
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
364
|
+
userAbility: params.state.userAbility,
|
365
|
+
model: "plugin::upload.file"
|
366
|
+
});
|
367
|
+
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
368
|
+
const sanitizedResults = await Promise.all(
|
369
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
370
|
+
);
|
392
371
|
return {
|
393
372
|
...await currentDataWithRelations,
|
394
|
-
[attributeKey]:
|
373
|
+
[attributeKey]: {
|
374
|
+
results: sanitizedResults,
|
375
|
+
meta: response.meta
|
376
|
+
}
|
395
377
|
};
|
396
378
|
}
|
397
379
|
if (attributeSchema.type === "relation" && attributeSchema.relation !== "morphToOne" && attributeSchema.relation !== "morphToMany") {
|
398
380
|
if (attributeSchema.target === "admin::user") {
|
399
381
|
const adminUsers = await Promise.all(
|
400
|
-
attributeValues.map(
|
382
|
+
attributeValues.map((userToPopulate) => {
|
401
383
|
if (userToPopulate == null) {
|
402
384
|
return null;
|
403
385
|
}
|
@@ -414,9 +396,23 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
414
396
|
[attributeKey]: adminUsers
|
415
397
|
};
|
416
398
|
}
|
399
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
400
|
+
userAbility: params.state.userAbility,
|
401
|
+
model: attributeSchema.target
|
402
|
+
});
|
403
|
+
const response = await serviceUtils.buildRelationReponse(
|
404
|
+
attributeValues,
|
405
|
+
attributeSchema
|
406
|
+
);
|
407
|
+
const sanitizedResults = await Promise.all(
|
408
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
409
|
+
);
|
417
410
|
return {
|
418
411
|
...await currentDataWithRelations,
|
419
|
-
[attributeKey]:
|
412
|
+
[attributeKey]: {
|
413
|
+
results: sanitizedResults,
|
414
|
+
meta: response.meta
|
415
|
+
}
|
420
416
|
};
|
421
417
|
}
|
422
418
|
return currentDataWithRelations;
|
@@ -431,7 +427,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
431
427
|
...result,
|
432
428
|
data: await populateEntryRelations(result),
|
433
429
|
meta: {
|
434
|
-
unknownAttributes: getSchemaAttributesDiff(
|
430
|
+
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
435
431
|
result.schema,
|
436
432
|
strapi2.getModel(params.query.contentType).attributes
|
437
433
|
)
|
@@ -448,7 +444,10 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
448
444
|
async restoreVersion(versionId) {
|
449
445
|
const version = await query.findOne({ where: { id: versionId } });
|
450
446
|
const contentTypeSchemaAttributes = strapi2.getModel(version.contentType).attributes;
|
451
|
-
const schemaDiff = getSchemaAttributesDiff(
|
447
|
+
const schemaDiff = serviceUtils.getSchemaAttributesDiff(
|
448
|
+
version.schema,
|
449
|
+
contentTypeSchemaAttributes
|
450
|
+
);
|
452
451
|
const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(
|
453
452
|
(currentData, addedKey) => {
|
454
453
|
currentData[addedKey] = null;
|
@@ -461,61 +460,26 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
461
460
|
FIELDS_TO_IGNORE,
|
462
461
|
contentTypeSchemaAttributes
|
463
462
|
);
|
464
|
-
const
|
465
|
-
|
466
|
-
|
467
|
-
const
|
468
|
-
if (
|
463
|
+
const reducer = strapiUtils.async.reduce(Object.entries(sanitizedSchemaAttributes));
|
464
|
+
const dataWithoutMissingRelations = await reducer(
|
465
|
+
async (previousRelationAttributes, [name, attribute]) => {
|
466
|
+
const versionRelationData = version.data[name];
|
467
|
+
if (!versionRelationData) {
|
469
468
|
return previousRelationAttributes;
|
470
469
|
}
|
471
470
|
if (attribute.type === "relation" && // TODO: handle polymorphic relations
|
472
471
|
attribute.relation !== "morphToOne" && attribute.relation !== "morphToMany") {
|
473
|
-
|
474
|
-
|
475
|
-
return previousRelationAttributes;
|
476
|
-
const existingAndMissingRelations = await Promise.all(
|
477
|
-
relationData.map((relation) => {
|
478
|
-
return strapi2.documents(attribute.target).findOne({
|
479
|
-
documentId: relation.documentId,
|
480
|
-
locale: relation.locale || void 0
|
481
|
-
});
|
482
|
-
})
|
483
|
-
);
|
484
|
-
const existingRelations = existingAndMissingRelations.filter(
|
485
|
-
(relation) => relation !== null
|
486
|
-
);
|
487
|
-
previousRelationAttributes[name] = existingRelations;
|
488
|
-
} else {
|
489
|
-
const existingRelation = await strapi2.documents(attribute.target).findOne({
|
490
|
-
documentId: relationData.documentId,
|
491
|
-
locale: relationData.locale || void 0
|
492
|
-
});
|
493
|
-
if (!existingRelation) {
|
494
|
-
previousRelationAttributes[name] = null;
|
495
|
-
}
|
496
|
-
}
|
472
|
+
const data2 = await serviceUtils.getRelationRestoreValue(versionRelationData, attribute);
|
473
|
+
previousRelationAttributes[name] = data2;
|
497
474
|
}
|
498
475
|
if (attribute.type === "media") {
|
499
|
-
|
500
|
-
|
501
|
-
// @ts-expect-error Fix the type definitions so this isn't any
|
502
|
-
relationData.map((media) => {
|
503
|
-
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
504
|
-
})
|
505
|
-
);
|
506
|
-
const existingMedias = existingAndMissingMedias.filter((media) => media != null);
|
507
|
-
previousRelationAttributes[name] = existingMedias;
|
508
|
-
} else {
|
509
|
-
const existingMedia = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: version.data[name].id } });
|
510
|
-
if (!existingMedia) {
|
511
|
-
previousRelationAttributes[name] = null;
|
512
|
-
}
|
513
|
-
}
|
476
|
+
const data2 = await serviceUtils.getMediaRestoreValue(versionRelationData, attribute);
|
477
|
+
previousRelationAttributes[name] = data2;
|
514
478
|
}
|
515
479
|
return previousRelationAttributes;
|
516
480
|
},
|
517
481
|
// Clone to avoid mutating the original version data
|
518
|
-
|
482
|
+
structuredClone(dataWithoutAddedAttributes)
|
519
483
|
);
|
520
484
|
const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
521
485
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -530,8 +494,102 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
530
494
|
}
|
531
495
|
};
|
532
496
|
};
|
497
|
+
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
498
|
+
const state = {
|
499
|
+
deleteExpiredJob: null,
|
500
|
+
isInitialized: false
|
501
|
+
};
|
502
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
503
|
+
return {
|
504
|
+
async bootstrap() {
|
505
|
+
if (state.isInitialized) {
|
506
|
+
return;
|
507
|
+
}
|
508
|
+
strapi2.documents.use(async (context, next) => {
|
509
|
+
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
510
|
+
return next();
|
511
|
+
}
|
512
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
513
|
+
return next();
|
514
|
+
}
|
515
|
+
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
516
|
+
return next();
|
517
|
+
}
|
518
|
+
const contentTypeUid = context.contentType.uid;
|
519
|
+
if (!contentTypeUid.startsWith("api::")) {
|
520
|
+
return next();
|
521
|
+
}
|
522
|
+
const result = await next();
|
523
|
+
const documentContext = {
|
524
|
+
documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
|
525
|
+
locale: context.params?.locale
|
526
|
+
};
|
527
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
528
|
+
const locale = documentContext.locale || defaultLocale;
|
529
|
+
if (Array.isArray(locale)) {
|
530
|
+
strapi2.log.warn(
|
531
|
+
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
532
|
+
);
|
533
|
+
return next();
|
534
|
+
}
|
535
|
+
const document = await strapi2.documents(contentTypeUid).findOne({
|
536
|
+
documentId: documentContext.documentId,
|
537
|
+
locale,
|
538
|
+
populate: serviceUtils.getDeepPopulate(contentTypeUid)
|
539
|
+
});
|
540
|
+
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
541
|
+
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
542
|
+
const componentsSchemas = Object.keys(
|
543
|
+
attributesSchema
|
544
|
+
).reduce((currentComponentSchemas, key) => {
|
545
|
+
const fieldSchema = attributesSchema[key];
|
546
|
+
if (fieldSchema.type === "component") {
|
547
|
+
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
548
|
+
return {
|
549
|
+
...currentComponentSchemas,
|
550
|
+
[fieldSchema.component]: componentSchema
|
551
|
+
};
|
552
|
+
}
|
553
|
+
return currentComponentSchemas;
|
554
|
+
}, {});
|
555
|
+
await strapi2.db.transaction(async ({ onCommit }) => {
|
556
|
+
onCommit(() => {
|
557
|
+
getService(strapi2, "history").createVersion({
|
558
|
+
contentType: contentTypeUid,
|
559
|
+
data: fp.omit(FIELDS_TO_IGNORE, document),
|
560
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
561
|
+
componentsSchemas,
|
562
|
+
relatedDocumentId: documentContext.documentId,
|
563
|
+
locale,
|
564
|
+
status
|
565
|
+
});
|
566
|
+
});
|
567
|
+
});
|
568
|
+
return result;
|
569
|
+
});
|
570
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
571
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
572
|
+
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
573
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
574
|
+
where: {
|
575
|
+
created_at: {
|
576
|
+
$lt: expirationDate.toISOString()
|
577
|
+
}
|
578
|
+
}
|
579
|
+
});
|
580
|
+
});
|
581
|
+
state.isInitialized = true;
|
582
|
+
},
|
583
|
+
async destroy() {
|
584
|
+
if (state.deleteExpiredJob) {
|
585
|
+
state.deleteExpiredJob.cancel();
|
586
|
+
}
|
587
|
+
}
|
588
|
+
};
|
589
|
+
};
|
533
590
|
const services$1 = {
|
534
|
-
history: createHistoryService
|
591
|
+
history: createHistoryService,
|
592
|
+
lifecycles: createLifecyclesService
|
535
593
|
};
|
536
594
|
const info = { pluginName: "content-manager", type: "admin" };
|
537
595
|
const historyVersionRouter = {
|
@@ -611,10 +669,10 @@ const getFeature = () => {
|
|
611
669
|
strapi2.get("models").add(historyVersion);
|
612
670
|
},
|
613
671
|
bootstrap({ strapi: strapi2 }) {
|
614
|
-
getService(strapi2, "
|
672
|
+
getService(strapi2, "lifecycles").bootstrap();
|
615
673
|
},
|
616
674
|
destroy({ strapi: strapi2 }) {
|
617
|
-
getService(strapi2, "
|
675
|
+
getService(strapi2, "lifecycles").destroy();
|
618
676
|
},
|
619
677
|
controllers: controllers$1,
|
620
678
|
services: services$1,
|
@@ -1433,7 +1491,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
|
|
1433
1491
|
const TYPES = ["singleType", "collectionType"];
|
1434
1492
|
const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
|
1435
1493
|
const bulkActionInputSchema = strapiUtils.yup.object({
|
1436
|
-
|
1494
|
+
documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
|
1437
1495
|
}).required();
|
1438
1496
|
const generateUIDInputSchema = strapiUtils.yup.object({
|
1439
1497
|
contentTypeUID: strapiUtils.yup.string().required(),
|
@@ -1532,15 +1590,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1532
1590
|
}
|
1533
1591
|
}, body);
|
1534
1592
|
};
|
1535
|
-
const
|
1593
|
+
const singleLocaleSchema = strapiUtils.yup.string().nullable();
|
1594
|
+
const multipleLocaleSchema = strapiUtils.yup.lazy(
|
1595
|
+
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1596
|
+
);
|
1597
|
+
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1598
|
+
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1599
|
+
const { allowMultipleLocales } = opts;
|
1536
1600
|
const { locale, status, ...rest } = request || {};
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1601
|
+
const schema = strapiUtils.yup.object().shape({
|
1602
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1603
|
+
status: statusSchema
|
1604
|
+
});
|
1605
|
+
try {
|
1606
|
+
await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1607
|
+
return { locale, status, ...rest };
|
1608
|
+
} catch (error) {
|
1609
|
+
throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
|
1542
1610
|
}
|
1543
|
-
|
1611
|
+
};
|
1612
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1613
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1614
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1615
|
+
let {
|
1616
|
+
meta: { availableLocales, availableStatus }
|
1617
|
+
} = serviceOutput;
|
1618
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1619
|
+
availableLocales = await strapiUtils.async.map(
|
1620
|
+
availableLocales,
|
1621
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1622
|
+
);
|
1623
|
+
availableStatus = await strapiUtils.async.map(
|
1624
|
+
availableStatus,
|
1625
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1626
|
+
);
|
1627
|
+
return {
|
1628
|
+
...serviceOutput,
|
1629
|
+
meta: {
|
1630
|
+
availableLocales,
|
1631
|
+
availableStatus
|
1632
|
+
}
|
1633
|
+
};
|
1544
1634
|
};
|
1545
1635
|
const createDocument = async (ctx, opts) => {
|
1546
1636
|
const { userAbility, user } = ctx.state;
|
@@ -1555,7 +1645,7 @@ const createDocument = async (ctx, opts) => {
|
|
1555
1645
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1556
1646
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1557
1647
|
const sanitizedBody = await sanitizeFn(body);
|
1558
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
|
1648
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
|
1559
1649
|
return documentManager2.create(model, {
|
1560
1650
|
data: sanitizedBody,
|
1561
1651
|
locale,
|
@@ -1574,7 +1664,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1574
1664
|
}
|
1575
1665
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1576
1666
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1577
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1667
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1578
1668
|
const [documentVersion, documentExists] = await Promise.all([
|
1579
1669
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1580
1670
|
documentManager2.exists(model, id)
|
@@ -1612,7 +1702,7 @@ const collectionTypes = {
|
|
1612
1702
|
}
|
1613
1703
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1614
1704
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1615
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1705
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1616
1706
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1617
1707
|
{ ...permissionQuery, populate, locale, status },
|
1618
1708
|
model
|
@@ -1641,14 +1731,13 @@ const collectionTypes = {
|
|
1641
1731
|
const { userAbility } = ctx.state;
|
1642
1732
|
const { model, id } = ctx.params;
|
1643
1733
|
const documentManager2 = getService$1("document-manager");
|
1644
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1645
1734
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1646
1735
|
if (permissionChecker2.cannot.read()) {
|
1647
1736
|
return ctx.forbidden();
|
1648
1737
|
}
|
1649
1738
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1650
1739
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1651
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
1740
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1652
1741
|
const version = await documentManager2.findOne(id, model, {
|
1653
1742
|
populate,
|
1654
1743
|
locale,
|
@@ -1659,8 +1748,10 @@ const collectionTypes = {
|
|
1659
1748
|
if (!exists) {
|
1660
1749
|
return ctx.notFound();
|
1661
1750
|
}
|
1662
|
-
const { meta } = await
|
1751
|
+
const { meta } = await formatDocumentWithMetadata(
|
1752
|
+
permissionChecker2,
|
1663
1753
|
model,
|
1754
|
+
// @ts-expect-error TODO: fix
|
1664
1755
|
{ id, locale, publishedAt: null },
|
1665
1756
|
{ availableLocales: true, availableStatus: false }
|
1666
1757
|
);
|
@@ -1671,12 +1762,11 @@ const collectionTypes = {
|
|
1671
1762
|
return ctx.forbidden();
|
1672
1763
|
}
|
1673
1764
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1674
|
-
ctx.body = await
|
1765
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1675
1766
|
},
|
1676
1767
|
async create(ctx) {
|
1677
1768
|
const { userAbility } = ctx.state;
|
1678
1769
|
const { model } = ctx.params;
|
1679
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1680
1770
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1681
1771
|
const [totalEntries, document] = await Promise.all([
|
1682
1772
|
strapi.db.query(model).count(),
|
@@ -1684,7 +1774,7 @@ const collectionTypes = {
|
|
1684
1774
|
]);
|
1685
1775
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1686
1776
|
ctx.status = 201;
|
1687
|
-
ctx.body = await
|
1777
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1688
1778
|
// Empty metadata as it's not relevant for a new document
|
1689
1779
|
availableLocales: false,
|
1690
1780
|
availableStatus: false
|
@@ -1698,25 +1788,23 @@ const collectionTypes = {
|
|
1698
1788
|
async update(ctx) {
|
1699
1789
|
const { userAbility } = ctx.state;
|
1700
1790
|
const { model } = ctx.params;
|
1701
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1702
1791
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1703
1792
|
const updatedVersion = await updateDocument(ctx);
|
1704
1793
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1705
|
-
ctx.body = await
|
1794
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1706
1795
|
},
|
1707
1796
|
async clone(ctx) {
|
1708
1797
|
const { userAbility, user } = ctx.state;
|
1709
1798
|
const { model, sourceId: id } = ctx.params;
|
1710
1799
|
const { body } = ctx.request;
|
1711
1800
|
const documentManager2 = getService$1("document-manager");
|
1712
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1713
1801
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1714
1802
|
if (permissionChecker2.cannot.create()) {
|
1715
1803
|
return ctx.forbidden();
|
1716
1804
|
}
|
1717
1805
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1718
1806
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1719
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1807
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1720
1808
|
const document = await documentManager2.findOne(id, model, {
|
1721
1809
|
populate,
|
1722
1810
|
locale,
|
@@ -1732,7 +1820,7 @@ const collectionTypes = {
|
|
1732
1820
|
const sanitizedBody = await sanitizeFn(body);
|
1733
1821
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1734
1822
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1735
|
-
ctx.body = await
|
1823
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1736
1824
|
// Empty metadata as it's not relevant for a new document
|
1737
1825
|
availableLocales: false,
|
1738
1826
|
availableStatus: false
|
@@ -1761,7 +1849,7 @@ const collectionTypes = {
|
|
1761
1849
|
}
|
1762
1850
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1763
1851
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1764
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1852
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1765
1853
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1766
1854
|
if (documentLocales.length === 0) {
|
1767
1855
|
return ctx.notFound();
|
@@ -1783,7 +1871,6 @@ const collectionTypes = {
|
|
1783
1871
|
const { id, model } = ctx.params;
|
1784
1872
|
const { body } = ctx.request;
|
1785
1873
|
const documentManager2 = getService$1("document-manager");
|
1786
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1787
1874
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1788
1875
|
if (permissionChecker2.cannot.publish()) {
|
1789
1876
|
return ctx.forbidden();
|
@@ -1795,21 +1882,25 @@ const collectionTypes = {
|
|
1795
1882
|
if (permissionChecker2.cannot.publish(document)) {
|
1796
1883
|
throw new strapiUtils.errors.ForbiddenError();
|
1797
1884
|
}
|
1798
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1799
|
-
|
1885
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1886
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1800
1887
|
locale
|
1801
1888
|
// TODO: Allow setting creator fields on publish
|
1802
1889
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1803
1890
|
});
|
1891
|
+
if (!publishResult || publishResult.length === 0) {
|
1892
|
+
throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
|
1893
|
+
}
|
1894
|
+
return publishResult[0];
|
1804
1895
|
});
|
1805
1896
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1806
|
-
ctx.body = await
|
1897
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1807
1898
|
},
|
1808
1899
|
async bulkPublish(ctx) {
|
1809
1900
|
const { userAbility } = ctx.state;
|
1810
1901
|
const { model } = ctx.params;
|
1811
1902
|
const { body } = ctx.request;
|
1812
|
-
const {
|
1903
|
+
const { documentIds } = body;
|
1813
1904
|
await validateBulkActionInput(body);
|
1814
1905
|
const documentManager2 = getService$1("document-manager");
|
1815
1906
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1818,8 +1909,11 @@ const collectionTypes = {
|
|
1818
1909
|
}
|
1819
1910
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1820
1911
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1821
|
-
const
|
1822
|
-
const
|
1912
|
+
const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
|
1913
|
+
const entityPromises = documentIds.map(
|
1914
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1915
|
+
);
|
1916
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1823
1917
|
for (const entity of entities) {
|
1824
1918
|
if (!entity) {
|
1825
1919
|
return ctx.notFound();
|
@@ -1828,24 +1922,25 @@ const collectionTypes = {
|
|
1828
1922
|
return ctx.forbidden();
|
1829
1923
|
}
|
1830
1924
|
}
|
1831
|
-
const
|
1925
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1832
1926
|
ctx.body = { count };
|
1833
1927
|
},
|
1834
1928
|
async bulkUnpublish(ctx) {
|
1835
1929
|
const { userAbility } = ctx.state;
|
1836
1930
|
const { model } = ctx.params;
|
1837
1931
|
const { body } = ctx.request;
|
1838
|
-
const {
|
1932
|
+
const { documentIds } = body;
|
1839
1933
|
await validateBulkActionInput(body);
|
1840
1934
|
const documentManager2 = getService$1("document-manager");
|
1841
1935
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1842
1936
|
if (permissionChecker2.cannot.unpublish()) {
|
1843
1937
|
return ctx.forbidden();
|
1844
1938
|
}
|
1845
|
-
const
|
1846
|
-
const
|
1847
|
-
|
1848
|
-
|
1939
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1940
|
+
const entityPromises = documentIds.map(
|
1941
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1942
|
+
);
|
1943
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1849
1944
|
for (const entity of entities) {
|
1850
1945
|
if (!entity) {
|
1851
1946
|
return ctx.notFound();
|
@@ -1854,7 +1949,8 @@ const collectionTypes = {
|
|
1854
1949
|
return ctx.forbidden();
|
1855
1950
|
}
|
1856
1951
|
}
|
1857
|
-
const
|
1952
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1953
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1858
1954
|
ctx.body = { count };
|
1859
1955
|
},
|
1860
1956
|
async unpublish(ctx) {
|
@@ -1864,7 +1960,6 @@ const collectionTypes = {
|
|
1864
1960
|
body: { discardDraft, ...body }
|
1865
1961
|
} = ctx.request;
|
1866
1962
|
const documentManager2 = getService$1("document-manager");
|
1867
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1868
1963
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1869
1964
|
if (permissionChecker2.cannot.unpublish()) {
|
1870
1965
|
return ctx.forbidden();
|
@@ -1874,7 +1969,7 @@ const collectionTypes = {
|
|
1874
1969
|
}
|
1875
1970
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1876
1971
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1877
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1972
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1878
1973
|
const document = await documentManager2.findOne(id, model, {
|
1879
1974
|
populate,
|
1880
1975
|
locale,
|
@@ -1896,7 +1991,7 @@ const collectionTypes = {
|
|
1896
1991
|
ctx.body = await strapiUtils.async.pipe(
|
1897
1992
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1898
1993
|
permissionChecker2.sanitizeOutput,
|
1899
|
-
(document2) =>
|
1994
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1900
1995
|
)(document);
|
1901
1996
|
});
|
1902
1997
|
},
|
@@ -1905,14 +2000,13 @@ const collectionTypes = {
|
|
1905
2000
|
const { id, model } = ctx.params;
|
1906
2001
|
const { body } = ctx.request;
|
1907
2002
|
const documentManager2 = getService$1("document-manager");
|
1908
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1909
2003
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1910
2004
|
if (permissionChecker2.cannot.discard()) {
|
1911
2005
|
return ctx.forbidden();
|
1912
2006
|
}
|
1913
2007
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1914
2008
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1915
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2009
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1916
2010
|
const document = await documentManager2.findOne(id, model, {
|
1917
2011
|
populate,
|
1918
2012
|
locale,
|
@@ -1927,14 +2021,14 @@ const collectionTypes = {
|
|
1927
2021
|
ctx.body = await strapiUtils.async.pipe(
|
1928
2022
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1929
2023
|
permissionChecker2.sanitizeOutput,
|
1930
|
-
(document2) =>
|
2024
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1931
2025
|
)(document);
|
1932
2026
|
},
|
1933
2027
|
async bulkDelete(ctx) {
|
1934
2028
|
const { userAbility } = ctx.state;
|
1935
2029
|
const { model } = ctx.params;
|
1936
2030
|
const { query, body } = ctx.request;
|
1937
|
-
const {
|
2031
|
+
const { documentIds } = body;
|
1938
2032
|
await validateBulkActionInput(body);
|
1939
2033
|
const documentManager2 = getService$1("document-manager");
|
1940
2034
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1942,14 +2036,22 @@ const collectionTypes = {
|
|
1942
2036
|
return ctx.forbidden();
|
1943
2037
|
}
|
1944
2038
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1945
|
-
const
|
1946
|
-
const
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
2039
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2040
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2041
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2042
|
+
populate,
|
2043
|
+
locale
|
2044
|
+
});
|
2045
|
+
if (documentLocales.length === 0) {
|
2046
|
+
return ctx.notFound();
|
2047
|
+
}
|
2048
|
+
for (const document of documentLocales) {
|
2049
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2050
|
+
return ctx.forbidden();
|
1950
2051
|
}
|
1951
|
-
}
|
1952
|
-
const
|
2052
|
+
}
|
2053
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2054
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1953
2055
|
ctx.body = { count };
|
1954
2056
|
},
|
1955
2057
|
async countDraftRelations(ctx) {
|
@@ -1962,7 +2064,7 @@ const collectionTypes = {
|
|
1962
2064
|
}
|
1963
2065
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1964
2066
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1965
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
2067
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1966
2068
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1967
2069
|
if (!entity) {
|
1968
2070
|
return ctx.notFound();
|
@@ -1977,7 +2079,7 @@ const collectionTypes = {
|
|
1977
2079
|
},
|
1978
2080
|
async countManyEntriesDraftRelations(ctx) {
|
1979
2081
|
const { userAbility } = ctx.state;
|
1980
|
-
const ids = ctx.request.query.
|
2082
|
+
const ids = ctx.request.query.documentIds;
|
1981
2083
|
const locale = ctx.request.query.locale;
|
1982
2084
|
const { model } = ctx.params;
|
1983
2085
|
const documentManager2 = getService$1("document-manager");
|
@@ -1985,16 +2087,16 @@ const collectionTypes = {
|
|
1985
2087
|
if (permissionChecker2.cannot.read()) {
|
1986
2088
|
return ctx.forbidden();
|
1987
2089
|
}
|
1988
|
-
const
|
2090
|
+
const documents = await documentManager2.findMany(
|
1989
2091
|
{
|
1990
2092
|
filters: {
|
1991
|
-
|
2093
|
+
documentId: ids
|
1992
2094
|
},
|
1993
2095
|
locale
|
1994
2096
|
},
|
1995
2097
|
model
|
1996
2098
|
);
|
1997
|
-
if (!
|
2099
|
+
if (!documents) {
|
1998
2100
|
return ctx.notFound();
|
1999
2101
|
}
|
2000
2102
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2490,7 +2592,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2490
2592
|
throw new strapiUtils.errors.ForbiddenError();
|
2491
2593
|
}
|
2492
2594
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2493
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2595
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2494
2596
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2495
2597
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2496
2598
|
// Find the first document to check if it exists
|
@@ -2527,12 +2629,11 @@ const singleTypes = {
|
|
2527
2629
|
const { model } = ctx.params;
|
2528
2630
|
const { query = {} } = ctx.request;
|
2529
2631
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2530
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2531
2632
|
if (permissionChecker2.cannot.read()) {
|
2532
2633
|
return ctx.forbidden();
|
2533
2634
|
}
|
2534
2635
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2535
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2636
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2536
2637
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2537
2638
|
if (!version) {
|
2538
2639
|
if (permissionChecker2.cannot.create()) {
|
@@ -2542,8 +2643,10 @@ const singleTypes = {
|
|
2542
2643
|
if (!document) {
|
2543
2644
|
return ctx.notFound();
|
2544
2645
|
}
|
2545
|
-
const { meta } = await
|
2646
|
+
const { meta } = await formatDocumentWithMetadata(
|
2647
|
+
permissionChecker2,
|
2546
2648
|
model,
|
2649
|
+
// @ts-expect-error - fix types
|
2547
2650
|
{ id: document.documentId, locale, publishedAt: null },
|
2548
2651
|
{ availableLocales: true, availableStatus: false }
|
2549
2652
|
);
|
@@ -2554,16 +2657,15 @@ const singleTypes = {
|
|
2554
2657
|
return ctx.forbidden();
|
2555
2658
|
}
|
2556
2659
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2557
|
-
ctx.body = await
|
2660
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2558
2661
|
},
|
2559
2662
|
async createOrUpdate(ctx) {
|
2560
2663
|
const { userAbility } = ctx.state;
|
2561
2664
|
const { model } = ctx.params;
|
2562
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2563
2665
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2564
2666
|
const document = await createOrUpdateDocument(ctx);
|
2565
2667
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2566
|
-
ctx.body = await
|
2668
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2567
2669
|
},
|
2568
2670
|
async delete(ctx) {
|
2569
2671
|
const { userAbility } = ctx.state;
|
@@ -2576,7 +2678,7 @@ const singleTypes = {
|
|
2576
2678
|
}
|
2577
2679
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2578
2680
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2579
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2681
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2580
2682
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2581
2683
|
populate,
|
2582
2684
|
locale
|
@@ -2599,7 +2701,6 @@ const singleTypes = {
|
|
2599
2701
|
const { model } = ctx.params;
|
2600
2702
|
const { query = {} } = ctx.request;
|
2601
2703
|
const documentManager2 = getService$1("document-manager");
|
2602
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2603
2704
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2604
2705
|
if (permissionChecker2.cannot.publish()) {
|
2605
2706
|
return ctx.forbidden();
|
@@ -2614,11 +2715,12 @@ const singleTypes = {
|
|
2614
2715
|
if (permissionChecker2.cannot.publish(document)) {
|
2615
2716
|
throw new strapiUtils.errors.ForbiddenError();
|
2616
2717
|
}
|
2617
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2618
|
-
|
2718
|
+
const { locale } = await getDocumentLocaleAndStatus(document);
|
2719
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2720
|
+
return publishResult.at(0);
|
2619
2721
|
});
|
2620
2722
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2621
|
-
ctx.body = await
|
2723
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2622
2724
|
},
|
2623
2725
|
async unpublish(ctx) {
|
2624
2726
|
const { userAbility } = ctx.state;
|
@@ -2628,7 +2730,6 @@ const singleTypes = {
|
|
2628
2730
|
query = {}
|
2629
2731
|
} = ctx.request;
|
2630
2732
|
const documentManager2 = getService$1("document-manager");
|
2631
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2632
2733
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2633
2734
|
if (permissionChecker2.cannot.unpublish()) {
|
2634
2735
|
return ctx.forbidden();
|
@@ -2637,7 +2738,7 @@ const singleTypes = {
|
|
2637
2738
|
return ctx.forbidden();
|
2638
2739
|
}
|
2639
2740
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2640
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2741
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2641
2742
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2642
2743
|
if (!document) {
|
2643
2744
|
return ctx.notFound();
|
@@ -2655,7 +2756,7 @@ const singleTypes = {
|
|
2655
2756
|
ctx.body = await strapiUtils.async.pipe(
|
2656
2757
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2657
2758
|
permissionChecker2.sanitizeOutput,
|
2658
|
-
(document2) =>
|
2759
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2659
2760
|
)(document);
|
2660
2761
|
});
|
2661
2762
|
},
|
@@ -2664,13 +2765,12 @@ const singleTypes = {
|
|
2664
2765
|
const { model } = ctx.params;
|
2665
2766
|
const { body, query = {} } = ctx.request;
|
2666
2767
|
const documentManager2 = getService$1("document-manager");
|
2667
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2668
2768
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2669
2769
|
if (permissionChecker2.cannot.discard()) {
|
2670
2770
|
return ctx.forbidden();
|
2671
2771
|
}
|
2672
2772
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2673
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2773
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2674
2774
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2675
2775
|
if (!document) {
|
2676
2776
|
return ctx.notFound();
|
@@ -2681,7 +2781,7 @@ const singleTypes = {
|
|
2681
2781
|
ctx.body = await strapiUtils.async.pipe(
|
2682
2782
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2683
2783
|
permissionChecker2.sanitizeOutput,
|
2684
|
-
(document2) =>
|
2784
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2685
2785
|
)(document);
|
2686
2786
|
},
|
2687
2787
|
async countDraftRelations(ctx) {
|
@@ -2690,7 +2790,7 @@ const singleTypes = {
|
|
2690
2790
|
const { query } = ctx.request;
|
2691
2791
|
const documentManager2 = getService$1("document-manager");
|
2692
2792
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2693
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2793
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2694
2794
|
if (permissionChecker2.cannot.read()) {
|
2695
2795
|
return ctx.forbidden();
|
2696
2796
|
}
|
@@ -2711,7 +2811,7 @@ const uid$1 = {
|
|
2711
2811
|
async generateUID(ctx) {
|
2712
2812
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2713
2813
|
const { query = {} } = ctx.request;
|
2714
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2814
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2715
2815
|
await validateUIDField(contentTypeUID, field);
|
2716
2816
|
const uidService = getService$1("uid");
|
2717
2817
|
ctx.body = {
|
@@ -2723,7 +2823,7 @@ const uid$1 = {
|
|
2723
2823
|
ctx.request.body
|
2724
2824
|
);
|
2725
2825
|
const { query = {} } = ctx.request;
|
2726
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2826
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2727
2827
|
await validateUIDField(contentTypeUID, field);
|
2728
2828
|
const uidService = getService$1("uid");
|
2729
2829
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3514,7 +3614,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3514
3614
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3515
3615
|
}
|
3516
3616
|
});
|
3517
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
|
3617
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
|
3518
3618
|
const { isAnyToMany } = strapiUtils__default.default.relations;
|
3519
3619
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
|
3520
3620
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3605,6 +3705,42 @@ const getDeepPopulate = (uid2, {
|
|
3605
3705
|
{}
|
3606
3706
|
);
|
3607
3707
|
};
|
3708
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3709
|
+
initialPopulate = {},
|
3710
|
+
countMany = false,
|
3711
|
+
countOne = false,
|
3712
|
+
maxLevel = Infinity
|
3713
|
+
} = {}, level = 1) => {
|
3714
|
+
if (level > maxLevel) {
|
3715
|
+
return {};
|
3716
|
+
}
|
3717
|
+
const model = strapi.getModel(uid2);
|
3718
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3719
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3720
|
+
return populateAcc;
|
3721
|
+
}
|
3722
|
+
if (isScalarAttribute(attribute)) {
|
3723
|
+
return fp.merge(populateAcc, {
|
3724
|
+
[attributeName]: true
|
3725
|
+
});
|
3726
|
+
}
|
3727
|
+
return fp.merge(
|
3728
|
+
populateAcc,
|
3729
|
+
getPopulateFor(
|
3730
|
+
attributeName,
|
3731
|
+
model,
|
3732
|
+
{
|
3733
|
+
// @ts-expect-error - improve types
|
3734
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3735
|
+
countMany,
|
3736
|
+
countOne,
|
3737
|
+
maxLevel
|
3738
|
+
},
|
3739
|
+
level
|
3740
|
+
)
|
3741
|
+
);
|
3742
|
+
}, {});
|
3743
|
+
};
|
3608
3744
|
const getDeepPopulateDraftCount = (uid2) => {
|
3609
3745
|
const model = strapi.getModel(uid2);
|
3610
3746
|
let hasRelations = false;
|
@@ -3626,22 +3762,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3626
3762
|
attribute.component
|
3627
3763
|
);
|
3628
3764
|
if (childHasRelations) {
|
3629
|
-
populateAcc[attributeName] = {
|
3765
|
+
populateAcc[attributeName] = {
|
3766
|
+
populate: populate2
|
3767
|
+
};
|
3630
3768
|
hasRelations = true;
|
3631
3769
|
}
|
3632
3770
|
break;
|
3633
3771
|
}
|
3634
3772
|
case "dynamiczone": {
|
3635
|
-
const
|
3636
|
-
const { populate:
|
3637
|
-
if (
|
3773
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3774
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3775
|
+
if (componentHasRelations) {
|
3638
3776
|
hasRelations = true;
|
3639
|
-
return
|
3777
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3640
3778
|
}
|
3641
3779
|
return acc;
|
3642
3780
|
}, {});
|
3643
|
-
if (!fp.isEmpty(
|
3644
|
-
populateAcc[attributeName] = {
|
3781
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
3782
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3645
3783
|
}
|
3646
3784
|
break;
|
3647
3785
|
}
|
@@ -3833,41 +3971,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3833
3971
|
"updatedBy",
|
3834
3972
|
"status"
|
3835
3973
|
];
|
3836
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
3974
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
3975
|
+
"id",
|
3976
|
+
"locale",
|
3977
|
+
"updatedAt",
|
3978
|
+
"createdAt",
|
3979
|
+
"status",
|
3980
|
+
"publishedAt",
|
3981
|
+
"documentId"
|
3982
|
+
];
|
3837
3983
|
const CONTENT_MANAGER_STATUS = {
|
3838
3984
|
PUBLISHED: "published",
|
3839
3985
|
DRAFT: "draft",
|
3840
3986
|
MODIFIED: "modified"
|
3841
3987
|
};
|
3842
|
-
const
|
3843
|
-
if (!
|
3988
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
3989
|
+
if (!version || !version.updatedAt) {
|
3844
3990
|
return false;
|
3845
3991
|
}
|
3846
|
-
const
|
3847
|
-
const
|
3848
|
-
|
3849
|
-
return difference <= threshold;
|
3992
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
3993
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
3994
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3850
3995
|
};
|
3851
3996
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3852
3997
|
/**
|
3853
3998
|
* Returns available locales of a document for the current status
|
3854
3999
|
*/
|
3855
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4000
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3856
4001
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3857
4002
|
delete versionsByLocale[version.locale];
|
3858
|
-
|
3859
|
-
|
3860
|
-
|
4003
|
+
const model = strapi2.getModel(uid2);
|
4004
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4005
|
+
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4006
|
+
({ key }, { remove }) => {
|
4007
|
+
if (keysToKeep.includes(key)) {
|
4008
|
+
return;
|
4009
|
+
}
|
4010
|
+
remove(key);
|
4011
|
+
},
|
4012
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4013
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4014
|
+
localeVersion
|
4015
|
+
);
|
4016
|
+
const mappingResult = await strapiUtils.async.map(
|
4017
|
+
Object.values(versionsByLocale),
|
4018
|
+
async (localeVersions) => {
|
4019
|
+
const mappedLocaleVersions = await strapiUtils.async.map(
|
4020
|
+
localeVersions,
|
4021
|
+
traversalFunction
|
4022
|
+
);
|
4023
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4024
|
+
return mappedLocaleVersions[0];
|
4025
|
+
}
|
4026
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
4027
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
4028
|
+
if (!draftVersion) {
|
4029
|
+
return;
|
4030
|
+
}
|
4031
|
+
return {
|
4032
|
+
...draftVersion,
|
4033
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4034
|
+
};
|
3861
4035
|
}
|
3862
|
-
|
3863
|
-
|
3864
|
-
if (!draftVersion)
|
3865
|
-
return;
|
3866
|
-
return {
|
3867
|
-
...fp.pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
|
3868
|
-
status: this.getStatus(draftVersion, otherVersions)
|
3869
|
-
};
|
3870
|
-
}).filter(Boolean);
|
4036
|
+
);
|
4037
|
+
return mappingResult.filter(Boolean);
|
3871
4038
|
},
|
3872
4039
|
/**
|
3873
4040
|
* Returns available status of a document for the current locale
|
@@ -3905,26 +4072,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3905
4072
|
});
|
3906
4073
|
},
|
3907
4074
|
getStatus(version, otherDocumentStatuses) {
|
3908
|
-
|
3909
|
-
|
3910
|
-
|
4075
|
+
let draftVersion;
|
4076
|
+
let publishedVersion;
|
4077
|
+
if (version.publishedAt) {
|
4078
|
+
publishedVersion = version;
|
4079
|
+
} else {
|
4080
|
+
draftVersion = version;
|
3911
4081
|
}
|
3912
|
-
|
3913
|
-
|
3914
|
-
|
3915
|
-
|
3916
|
-
|
4082
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4083
|
+
if (otherVersion?.publishedAt) {
|
4084
|
+
publishedVersion = otherVersion;
|
4085
|
+
} else if (otherVersion) {
|
4086
|
+
draftVersion = otherVersion;
|
3917
4087
|
}
|
3918
|
-
if (
|
4088
|
+
if (!draftVersion)
|
3919
4089
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3920
|
-
|
3921
|
-
|
4090
|
+
if (!publishedVersion)
|
4091
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4092
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4093
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3922
4094
|
},
|
4095
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4096
|
+
// We could refactor this so the locales are only loaded when they're
|
4097
|
+
// needed. e.g. in the bulk locale action modal.
|
3923
4098
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4099
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3924
4100
|
const versions = await strapi2.db.query(uid2).findMany({
|
3925
4101
|
where: { documentId: version.documentId },
|
3926
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3927
4102
|
populate: {
|
4103
|
+
// Populate only fields that require validation for bulk locale actions
|
4104
|
+
...populate,
|
4105
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3928
4106
|
createdBy: {
|
3929
4107
|
select: ["id", "firstname", "lastname", "email"]
|
3930
4108
|
},
|
@@ -3933,7 +4111,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3933
4111
|
}
|
3934
4112
|
}
|
3935
4113
|
});
|
3936
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4114
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3937
4115
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3938
4116
|
return {
|
3939
4117
|
availableLocales: availableLocalesResult,
|
@@ -3946,8 +4124,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3946
4124
|
* - Available status of the document for the current locale
|
3947
4125
|
*/
|
3948
4126
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3949
|
-
if (!document)
|
4127
|
+
if (!document) {
|
3950
4128
|
return document;
|
4129
|
+
}
|
3951
4130
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
3952
4131
|
if (!hasDraftAndPublish) {
|
3953
4132
|
opts.availableStatus = false;
|
@@ -3997,26 +4176,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
3997
4176
|
}, 0);
|
3998
4177
|
};
|
3999
4178
|
const { ApplicationError } = strapiUtils.errors;
|
4000
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4001
4179
|
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
4002
4180
|
const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
|
4003
4181
|
const omitIdField = fp.omit("id");
|
4004
|
-
const emitEvent = async (uid2, event, document) => {
|
4005
|
-
const modelDef = strapi.getModel(uid2);
|
4006
|
-
const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
|
4007
|
-
{
|
4008
|
-
schema: modelDef,
|
4009
|
-
getModel(uid22) {
|
4010
|
-
return strapi.getModel(uid22);
|
4011
|
-
}
|
4012
|
-
},
|
4013
|
-
document
|
4014
|
-
);
|
4015
|
-
strapi.eventHub.emit(event, {
|
4016
|
-
model: modelDef.modelName,
|
4017
|
-
entry: sanitizedDocument
|
4018
|
-
});
|
4019
|
-
};
|
4020
4182
|
const documentManager = ({ strapi: strapi2 }) => {
|
4021
4183
|
return {
|
4022
4184
|
async findOne(id, uid2, opts = {}) {
|
@@ -4035,6 +4197,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4035
4197
|
} else if (opts.locale && opts.locale !== "*") {
|
4036
4198
|
where.locale = opts.locale;
|
4037
4199
|
}
|
4200
|
+
if (typeof opts.isPublished === "boolean") {
|
4201
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4202
|
+
}
|
4038
4203
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4039
4204
|
},
|
4040
4205
|
async findMany(opts, uid2) {
|
@@ -4042,20 +4207,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4042
4207
|
return strapi2.documents(uid2).findMany(params);
|
4043
4208
|
},
|
4044
4209
|
async findPage(opts, uid2) {
|
4045
|
-
const
|
4046
|
-
|
4210
|
+
const params = strapiUtils.pagination.withDefaultPagination(opts || {}, {
|
4211
|
+
maxLimit: 1e3
|
4212
|
+
});
|
4047
4213
|
const [documents, total = 0] = await Promise.all([
|
4048
|
-
strapi2.documents(uid2).findMany(
|
4049
|
-
strapi2.documents(uid2).count(
|
4214
|
+
strapi2.documents(uid2).findMany(params),
|
4215
|
+
strapi2.documents(uid2).count(params)
|
4050
4216
|
]);
|
4051
4217
|
return {
|
4052
4218
|
results: documents,
|
4053
|
-
pagination:
|
4054
|
-
page,
|
4055
|
-
pageSize,
|
4056
|
-
pageCount: Math.ceil(total / pageSize),
|
4057
|
-
total
|
4058
|
-
}
|
4219
|
+
pagination: strapiUtils.pagination.transformPagedPaginationInfo(params, total)
|
4059
4220
|
};
|
4060
4221
|
},
|
4061
4222
|
async create(uid2, opts = {}) {
|
@@ -4101,70 +4262,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4101
4262
|
return {};
|
4102
4263
|
},
|
4103
4264
|
// FIXME: handle relations
|
4104
|
-
async deleteMany(
|
4105
|
-
const
|
4106
|
-
|
4107
|
-
|
4108
|
-
}
|
4109
|
-
return { count: docs.length };
|
4265
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4266
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4267
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4268
|
+
});
|
4269
|
+
return { count: deletedEntries.length };
|
4110
4270
|
},
|
4111
4271
|
async publish(id, uid2, opts = {}) {
|
4112
4272
|
const populate = await buildDeepPopulate(uid2);
|
4113
4273
|
const params = { ...opts, populate };
|
4114
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4274
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4115
4275
|
},
|
4116
|
-
async publishMany(
|
4117
|
-
|
4118
|
-
|
4119
|
-
|
4120
|
-
|
4121
|
-
|
4122
|
-
|
4123
|
-
strapi2.getModel(uid2),
|
4124
|
-
document,
|
4125
|
-
void 0,
|
4126
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4127
|
-
document
|
4128
|
-
);
|
4129
|
-
})
|
4130
|
-
);
|
4131
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4132
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4133
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4134
|
-
const populate = await buildDeepPopulate(uid2);
|
4135
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4136
|
-
where: filters,
|
4137
|
-
data
|
4138
|
-
});
|
4139
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4140
|
-
where: filters,
|
4141
|
-
populate
|
4276
|
+
async publishMany(uid2, documentIds, locale) {
|
4277
|
+
return strapi2.db.transaction(async () => {
|
4278
|
+
const results = await Promise.all(
|
4279
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4280
|
+
);
|
4281
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4282
|
+
return publishedEntitiesCount;
|
4142
4283
|
});
|
4143
|
-
await Promise.all(
|
4144
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4145
|
-
);
|
4146
|
-
return publishedEntitiesCount;
|
4147
4284
|
},
|
4148
|
-
async unpublishMany(
|
4149
|
-
|
4150
|
-
return
|
4151
|
-
|
4152
|
-
|
4153
|
-
|
4154
|
-
|
4155
|
-
const populate = await buildDeepPopulate(uid2);
|
4156
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4157
|
-
where: filters,
|
4158
|
-
data
|
4159
|
-
});
|
4160
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4161
|
-
where: filters,
|
4162
|
-
populate
|
4285
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4286
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4287
|
+
return Promise.all(
|
4288
|
+
documentIds.map(
|
4289
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4290
|
+
)
|
4291
|
+
);
|
4163
4292
|
});
|
4164
|
-
|
4165
|
-
|
4166
|
-
);
|
4167
|
-
return unpublishedEntitiesCount;
|
4293
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4294
|
+
return { count: unpublishedEntitiesCount };
|
4168
4295
|
},
|
4169
4296
|
async unpublish(id, uid2, opts = {}) {
|
4170
4297
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4189,16 +4316,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4189
4316
|
}
|
4190
4317
|
return sumDraftCounts(document, uid2);
|
4191
4318
|
},
|
4192
|
-
async countManyEntriesDraftRelations(
|
4319
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4193
4320
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4194
4321
|
if (!hasRelations) {
|
4195
4322
|
return 0;
|
4196
4323
|
}
|
4324
|
+
let localeFilter = {};
|
4325
|
+
if (locale) {
|
4326
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4327
|
+
}
|
4197
4328
|
const entities = await strapi2.db.query(uid2).findMany({
|
4198
4329
|
populate,
|
4199
4330
|
where: {
|
4200
|
-
|
4201
|
-
...
|
4331
|
+
documentId: { $in: documentIds },
|
4332
|
+
...localeFilter
|
4202
4333
|
}
|
4203
4334
|
});
|
4204
4335
|
const totalNumberDraftRelations = entities.reduce(
|