@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.c3e9d4b26f9fd3d9eb530b5c11f9baa1d09b13ad
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/{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--2aLCv-G.mjs → ComponentConfigurationPage-BMajAl1u.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-BMajAl1u.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-y_7iLdmB.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-y_7iLdmB.js.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-CPVB8Uqc.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-CPVB8Uqc.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-CcOoD26O.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-CcOoD26O.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-CTTDHKkQ.js} +7 -9
- package/dist/_chunks/EditViewPage-CTTDHKkQ.js.map +1 -0
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-DWb0DE7R.mjs} +6 -6
- package/dist/_chunks/EditViewPage-DWb0DE7R.mjs.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-C5Z1Ivdv.js} +552 -661
- package/dist/_chunks/Field-C5Z1Ivdv.js.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-DnStdvQw.mjs} +500 -608
- package/dist/_chunks/Field-DnStdvQw.mjs.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-B81OtW-k.js} +21 -19
- package/dist/_chunks/Form-B81OtW-k.js.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-DqGgE55Q.mjs} +21 -18
- package/dist/_chunks/Form-DqGgE55Q.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-4NbOq2dX.js} +119 -49
- package/dist/_chunks/History-4NbOq2dX.js.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-DS6-HCYX.mjs} +119 -48
- package/dist/_chunks/History-DS6-HCYX.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-CpfstlYY.js} +17 -19
- package/dist/_chunks/ListConfigurationPage-CpfstlYY.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-DQJJltko.mjs} +14 -14
- package/dist/_chunks/ListConfigurationPage-DQJJltko.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-CA3I75m5.js} +43 -51
- package/dist/_chunks/ListViewPage-CA3I75m5.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-nQrOQuVo.mjs} +37 -45
- package/dist/_chunks/ListViewPage-nQrOQuVo.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-DbnHE22g.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-DbnHE22g.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-Dldu-_Mx.js} +5 -5
- package/dist/_chunks/NoContentTypePage-Dldu-_Mx.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-CO2MK200.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-CO2MK200.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-fOIkQM0v.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-fOIkQM0v.mjs.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-BDRl99Ux.mjs} +66 -56
- package/dist/_chunks/Relations-BDRl99Ux.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-DG2jnOcr.js} +70 -61
- package/dist/_chunks/Relations-DG2jnOcr.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-BZoNZMXL.js} +1556 -795
- package/dist/_chunks/index-BZoNZMXL.js.map +1 -0
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-Drt2DN7v.mjs} +1569 -807
- package/dist/_chunks/index-Drt2DN7v.mjs.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-BzAbmoO6.mjs} +27 -22
- package/dist/_chunks/layout-BzAbmoO6.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-DEYBqgF1.js} +28 -25
- package/dist/_chunks/layout-DEYBqgF1.js.map +1 -0
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-D0eZ4VWw.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-D0eZ4VWw.js.map} +1 -1
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-D26zVRdi.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-D26zVRdi.mjs.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 +8 -7
- 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 +3 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- 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 +67 -52
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- 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 +540 -414
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +548 -422
- 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);
|
@@ -228,80 +262,68 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
228
262
|
return acc;
|
229
263
|
}, {});
|
230
264
|
};
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
238
|
-
return next();
|
265
|
+
const buildMediaResponse = async (values) => {
|
266
|
+
return values.slice(0, 25).reduce(
|
267
|
+
async (currentRelationDataPromise, entry) => {
|
268
|
+
const currentRelationData = await currentRelationDataPromise;
|
269
|
+
if (!entry) {
|
270
|
+
return currentRelationData;
|
239
271
|
}
|
240
|
-
|
241
|
-
|
272
|
+
const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
|
273
|
+
if (relatedEntry) {
|
274
|
+
currentRelationData.results.push(relatedEntry);
|
275
|
+
} else {
|
276
|
+
currentRelationData.meta.missingCount += 1;
|
242
277
|
}
|
243
|
-
|
244
|
-
|
245
|
-
|
278
|
+
return currentRelationData;
|
279
|
+
},
|
280
|
+
Promise.resolve({
|
281
|
+
results: [],
|
282
|
+
meta: { missingCount: 0 }
|
283
|
+
})
|
284
|
+
);
|
285
|
+
};
|
286
|
+
const buildRelationReponse = async (values, attributeSchema) => {
|
287
|
+
return values.slice(0, 25).reduce(
|
288
|
+
async (currentRelationDataPromise, entry) => {
|
289
|
+
const currentRelationData = await currentRelationDataPromise;
|
290
|
+
if (!entry) {
|
291
|
+
return currentRelationData;
|
246
292
|
}
|
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
|
-
});
|
293
|
+
const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
|
294
|
+
if (relatedEntry) {
|
295
|
+
currentRelationData.results.push({
|
296
|
+
...relatedEntry,
|
297
|
+
status: await getVersionStatus(attributeSchema.target, relatedEntry)
|
282
298
|
});
|
283
|
-
}
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
299
|
+
} else {
|
300
|
+
currentRelationData.meta.missingCount += 1;
|
301
|
+
}
|
302
|
+
return currentRelationData;
|
303
|
+
},
|
304
|
+
Promise.resolve({
|
305
|
+
results: [],
|
306
|
+
meta: { missingCount: 0 }
|
307
|
+
})
|
308
|
+
);
|
309
|
+
};
|
310
|
+
return {
|
311
|
+
getSchemaAttributesDiff,
|
312
|
+
getRelationRestoreValue,
|
313
|
+
getMediaRestoreValue,
|
314
|
+
getDefaultLocale,
|
315
|
+
getLocaleDictionary,
|
316
|
+
getRetentionDays,
|
317
|
+
getVersionStatus,
|
318
|
+
getDeepPopulate: getDeepPopulate2,
|
319
|
+
buildMediaResponse,
|
320
|
+
buildRelationReponse
|
321
|
+
};
|
322
|
+
};
|
323
|
+
const createHistoryService = ({ strapi: strapi2 }) => {
|
324
|
+
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
325
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
326
|
+
return {
|
305
327
|
async createVersion(historyVersionData) {
|
306
328
|
await query.create({
|
307
329
|
data: {
|
@@ -312,7 +334,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
312
334
|
});
|
313
335
|
},
|
314
336
|
async findVersionsPage(params) {
|
315
|
-
const locale = params.query.locale || await getDefaultLocale();
|
337
|
+
const locale = params.query.locale || await serviceUtils.getDefaultLocale();
|
316
338
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
317
339
|
query.findPage({
|
318
340
|
...params.query,
|
@@ -326,78 +348,34 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
326
348
|
populate: ["createdBy"],
|
327
349
|
orderBy: [{ createdAt: "desc" }]
|
328
350
|
}),
|
329
|
-
getLocaleDictionary()
|
351
|
+
serviceUtils.getLocaleDictionary()
|
330
352
|
]);
|
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
353
|
const populateEntryRelations = async (entry) => {
|
387
354
|
const entryWithRelations = await Object.entries(entry.schema).reduce(
|
388
355
|
async (currentDataWithRelations, [attributeKey, attributeSchema]) => {
|
389
356
|
const attributeValue = entry.data[attributeKey];
|
390
357
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
391
358
|
if (attributeSchema.type === "media") {
|
359
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
360
|
+
userAbility: params.state.userAbility,
|
361
|
+
model: "plugin::upload.file"
|
362
|
+
});
|
363
|
+
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
364
|
+
const sanitizedResults = await Promise.all(
|
365
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
366
|
+
);
|
392
367
|
return {
|
393
368
|
...await currentDataWithRelations,
|
394
|
-
[attributeKey]:
|
369
|
+
[attributeKey]: {
|
370
|
+
results: sanitizedResults,
|
371
|
+
meta: response.meta
|
372
|
+
}
|
395
373
|
};
|
396
374
|
}
|
397
375
|
if (attributeSchema.type === "relation" && attributeSchema.relation !== "morphToOne" && attributeSchema.relation !== "morphToMany") {
|
398
376
|
if (attributeSchema.target === "admin::user") {
|
399
377
|
const adminUsers = await Promise.all(
|
400
|
-
attributeValues.map(
|
378
|
+
attributeValues.map((userToPopulate) => {
|
401
379
|
if (userToPopulate == null) {
|
402
380
|
return null;
|
403
381
|
}
|
@@ -414,9 +392,23 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
414
392
|
[attributeKey]: adminUsers
|
415
393
|
};
|
416
394
|
}
|
395
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
396
|
+
userAbility: params.state.userAbility,
|
397
|
+
model: attributeSchema.target
|
398
|
+
});
|
399
|
+
const response = await serviceUtils.buildRelationReponse(
|
400
|
+
attributeValues,
|
401
|
+
attributeSchema
|
402
|
+
);
|
403
|
+
const sanitizedResults = await Promise.all(
|
404
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
405
|
+
);
|
417
406
|
return {
|
418
407
|
...await currentDataWithRelations,
|
419
|
-
[attributeKey]:
|
408
|
+
[attributeKey]: {
|
409
|
+
results: sanitizedResults,
|
410
|
+
meta: response.meta
|
411
|
+
}
|
420
412
|
};
|
421
413
|
}
|
422
414
|
return currentDataWithRelations;
|
@@ -431,7 +423,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
431
423
|
...result,
|
432
424
|
data: await populateEntryRelations(result),
|
433
425
|
meta: {
|
434
|
-
unknownAttributes: getSchemaAttributesDiff(
|
426
|
+
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
435
427
|
result.schema,
|
436
428
|
strapi2.getModel(params.query.contentType).attributes
|
437
429
|
)
|
@@ -448,7 +440,10 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
448
440
|
async restoreVersion(versionId) {
|
449
441
|
const version = await query.findOne({ where: { id: versionId } });
|
450
442
|
const contentTypeSchemaAttributes = strapi2.getModel(version.contentType).attributes;
|
451
|
-
const schemaDiff = getSchemaAttributesDiff(
|
443
|
+
const schemaDiff = serviceUtils.getSchemaAttributesDiff(
|
444
|
+
version.schema,
|
445
|
+
contentTypeSchemaAttributes
|
446
|
+
);
|
452
447
|
const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(
|
453
448
|
(currentData, addedKey) => {
|
454
449
|
currentData[addedKey] = null;
|
@@ -461,61 +456,26 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
461
456
|
FIELDS_TO_IGNORE,
|
462
457
|
contentTypeSchemaAttributes
|
463
458
|
);
|
464
|
-
const
|
465
|
-
|
466
|
-
|
467
|
-
const
|
468
|
-
if (
|
459
|
+
const reducer = strapiUtils.async.reduce(Object.entries(sanitizedSchemaAttributes));
|
460
|
+
const dataWithoutMissingRelations = await reducer(
|
461
|
+
async (previousRelationAttributes, [name, attribute]) => {
|
462
|
+
const versionRelationData = version.data[name];
|
463
|
+
if (!versionRelationData) {
|
469
464
|
return previousRelationAttributes;
|
470
465
|
}
|
471
466
|
if (attribute.type === "relation" && // TODO: handle polymorphic relations
|
472
467
|
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
|
-
}
|
468
|
+
const data2 = await serviceUtils.getRelationRestoreValue(versionRelationData, attribute);
|
469
|
+
previousRelationAttributes[name] = data2;
|
497
470
|
}
|
498
471
|
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
|
-
}
|
472
|
+
const data2 = await serviceUtils.getMediaRestoreValue(versionRelationData, attribute);
|
473
|
+
previousRelationAttributes[name] = data2;
|
514
474
|
}
|
515
475
|
return previousRelationAttributes;
|
516
476
|
},
|
517
477
|
// Clone to avoid mutating the original version data
|
518
|
-
|
478
|
+
structuredClone(dataWithoutAddedAttributes)
|
519
479
|
);
|
520
480
|
const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
521
481
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -530,8 +490,101 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
530
490
|
}
|
531
491
|
};
|
532
492
|
};
|
493
|
+
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
|
+
const state = {
|
495
|
+
deleteExpiredJob: null,
|
496
|
+
isInitialized: false
|
497
|
+
};
|
498
|
+
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
+
const historyService = getService(strapi2, "history");
|
500
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
|
+
return {
|
502
|
+
async bootstrap() {
|
503
|
+
if (state.isInitialized) {
|
504
|
+
return;
|
505
|
+
}
|
506
|
+
strapi2.documents.use(async (context, next) => {
|
507
|
+
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
508
|
+
return next();
|
509
|
+
}
|
510
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
511
|
+
return next();
|
512
|
+
}
|
513
|
+
const contentTypeUid = context.contentType.uid;
|
514
|
+
if (!contentTypeUid.startsWith("api::")) {
|
515
|
+
return next();
|
516
|
+
}
|
517
|
+
const result = await next();
|
518
|
+
const documentContext = {
|
519
|
+
documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
|
520
|
+
locale: context.params?.locale
|
521
|
+
};
|
522
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
523
|
+
const locale = documentContext.locale || defaultLocale;
|
524
|
+
if (Array.isArray(locale)) {
|
525
|
+
strapi2.log.warn(
|
526
|
+
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
527
|
+
);
|
528
|
+
return next();
|
529
|
+
}
|
530
|
+
const document = await strapi2.documents(contentTypeUid).findOne({
|
531
|
+
documentId: documentContext.documentId,
|
532
|
+
locale,
|
533
|
+
populate: serviceUtils.getDeepPopulate(contentTypeUid)
|
534
|
+
});
|
535
|
+
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
536
|
+
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
537
|
+
const componentsSchemas = Object.keys(
|
538
|
+
attributesSchema
|
539
|
+
).reduce((currentComponentSchemas, key) => {
|
540
|
+
const fieldSchema = attributesSchema[key];
|
541
|
+
if (fieldSchema.type === "component") {
|
542
|
+
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
543
|
+
return {
|
544
|
+
...currentComponentSchemas,
|
545
|
+
[fieldSchema.component]: componentSchema
|
546
|
+
};
|
547
|
+
}
|
548
|
+
return currentComponentSchemas;
|
549
|
+
}, {});
|
550
|
+
await strapi2.db.transaction(async ({ onCommit }) => {
|
551
|
+
onCommit(() => {
|
552
|
+
historyService.createVersion({
|
553
|
+
contentType: contentTypeUid,
|
554
|
+
data: fp.omit(FIELDS_TO_IGNORE, document),
|
555
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
556
|
+
componentsSchemas,
|
557
|
+
relatedDocumentId: documentContext.documentId,
|
558
|
+
locale,
|
559
|
+
status
|
560
|
+
});
|
561
|
+
});
|
562
|
+
});
|
563
|
+
return result;
|
564
|
+
});
|
565
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
566
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
567
|
+
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
568
|
+
query.deleteMany({
|
569
|
+
where: {
|
570
|
+
created_at: {
|
571
|
+
$lt: expirationDate.toISOString()
|
572
|
+
}
|
573
|
+
}
|
574
|
+
});
|
575
|
+
});
|
576
|
+
state.isInitialized = true;
|
577
|
+
},
|
578
|
+
async destroy() {
|
579
|
+
if (state.deleteExpiredJob) {
|
580
|
+
state.deleteExpiredJob.cancel();
|
581
|
+
}
|
582
|
+
}
|
583
|
+
};
|
584
|
+
};
|
533
585
|
const services$1 = {
|
534
|
-
history: createHistoryService
|
586
|
+
history: createHistoryService,
|
587
|
+
lifecycles: createLifecyclesService
|
535
588
|
};
|
536
589
|
const info = { pluginName: "content-manager", type: "admin" };
|
537
590
|
const historyVersionRouter = {
|
@@ -611,10 +664,10 @@ const getFeature = () => {
|
|
611
664
|
strapi2.get("models").add(historyVersion);
|
612
665
|
},
|
613
666
|
bootstrap({ strapi: strapi2 }) {
|
614
|
-
getService(strapi2, "
|
667
|
+
getService(strapi2, "lifecycles").bootstrap();
|
615
668
|
},
|
616
669
|
destroy({ strapi: strapi2 }) {
|
617
|
-
getService(strapi2, "
|
670
|
+
getService(strapi2, "lifecycles").destroy();
|
618
671
|
},
|
619
672
|
controllers: controllers$1,
|
620
673
|
services: services$1,
|
@@ -1433,7 +1486,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
|
|
1433
1486
|
const TYPES = ["singleType", "collectionType"];
|
1434
1487
|
const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
|
1435
1488
|
const bulkActionInputSchema = strapiUtils.yup.object({
|
1436
|
-
|
1489
|
+
documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
|
1437
1490
|
}).required();
|
1438
1491
|
const generateUIDInputSchema = strapiUtils.yup.object({
|
1439
1492
|
contentTypeUID: strapiUtils.yup.string().required(),
|
@@ -1532,15 +1585,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1532
1585
|
}
|
1533
1586
|
}, body);
|
1534
1587
|
};
|
1535
|
-
const
|
1588
|
+
const singleLocaleSchema = strapiUtils.yup.string().nullable();
|
1589
|
+
const multipleLocaleSchema = strapiUtils.yup.lazy(
|
1590
|
+
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1591
|
+
);
|
1592
|
+
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1593
|
+
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1594
|
+
const { allowMultipleLocales } = opts;
|
1536
1595
|
const { locale, status, ...rest } = request || {};
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1596
|
+
const schema = strapiUtils.yup.object().shape({
|
1597
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1598
|
+
status: statusSchema
|
1599
|
+
});
|
1600
|
+
try {
|
1601
|
+
await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1602
|
+
return { locale, status, ...rest };
|
1603
|
+
} catch (error) {
|
1604
|
+
throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
|
1542
1605
|
}
|
1543
|
-
|
1606
|
+
};
|
1607
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1608
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1609
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1610
|
+
let {
|
1611
|
+
meta: { availableLocales, availableStatus }
|
1612
|
+
} = serviceOutput;
|
1613
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1614
|
+
availableLocales = await strapiUtils.async.map(
|
1615
|
+
availableLocales,
|
1616
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1617
|
+
);
|
1618
|
+
availableStatus = await strapiUtils.async.map(
|
1619
|
+
availableStatus,
|
1620
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1621
|
+
);
|
1622
|
+
return {
|
1623
|
+
...serviceOutput,
|
1624
|
+
meta: {
|
1625
|
+
availableLocales,
|
1626
|
+
availableStatus
|
1627
|
+
}
|
1628
|
+
};
|
1544
1629
|
};
|
1545
1630
|
const createDocument = async (ctx, opts) => {
|
1546
1631
|
const { userAbility, user } = ctx.state;
|
@@ -1555,7 +1640,7 @@ const createDocument = async (ctx, opts) => {
|
|
1555
1640
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1556
1641
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1557
1642
|
const sanitizedBody = await sanitizeFn(body);
|
1558
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
|
1643
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
|
1559
1644
|
return documentManager2.create(model, {
|
1560
1645
|
data: sanitizedBody,
|
1561
1646
|
locale,
|
@@ -1574,7 +1659,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1574
1659
|
}
|
1575
1660
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1576
1661
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1577
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1662
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1578
1663
|
const [documentVersion, documentExists] = await Promise.all([
|
1579
1664
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1580
1665
|
documentManager2.exists(model, id)
|
@@ -1612,7 +1697,7 @@ const collectionTypes = {
|
|
1612
1697
|
}
|
1613
1698
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1614
1699
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1615
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1700
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1616
1701
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1617
1702
|
{ ...permissionQuery, populate, locale, status },
|
1618
1703
|
model
|
@@ -1641,14 +1726,13 @@ const collectionTypes = {
|
|
1641
1726
|
const { userAbility } = ctx.state;
|
1642
1727
|
const { model, id } = ctx.params;
|
1643
1728
|
const documentManager2 = getService$1("document-manager");
|
1644
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1645
1729
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1646
1730
|
if (permissionChecker2.cannot.read()) {
|
1647
1731
|
return ctx.forbidden();
|
1648
1732
|
}
|
1649
1733
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1650
1734
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1651
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
1735
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1652
1736
|
const version = await documentManager2.findOne(id, model, {
|
1653
1737
|
populate,
|
1654
1738
|
locale,
|
@@ -1659,8 +1743,10 @@ const collectionTypes = {
|
|
1659
1743
|
if (!exists) {
|
1660
1744
|
return ctx.notFound();
|
1661
1745
|
}
|
1662
|
-
const { meta } = await
|
1746
|
+
const { meta } = await formatDocumentWithMetadata(
|
1747
|
+
permissionChecker2,
|
1663
1748
|
model,
|
1749
|
+
// @ts-expect-error TODO: fix
|
1664
1750
|
{ id, locale, publishedAt: null },
|
1665
1751
|
{ availableLocales: true, availableStatus: false }
|
1666
1752
|
);
|
@@ -1671,12 +1757,11 @@ const collectionTypes = {
|
|
1671
1757
|
return ctx.forbidden();
|
1672
1758
|
}
|
1673
1759
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1674
|
-
ctx.body = await
|
1760
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1675
1761
|
},
|
1676
1762
|
async create(ctx) {
|
1677
1763
|
const { userAbility } = ctx.state;
|
1678
1764
|
const { model } = ctx.params;
|
1679
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1680
1765
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1681
1766
|
const [totalEntries, document] = await Promise.all([
|
1682
1767
|
strapi.db.query(model).count(),
|
@@ -1684,7 +1769,7 @@ const collectionTypes = {
|
|
1684
1769
|
]);
|
1685
1770
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1686
1771
|
ctx.status = 201;
|
1687
|
-
ctx.body = await
|
1772
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1688
1773
|
// Empty metadata as it's not relevant for a new document
|
1689
1774
|
availableLocales: false,
|
1690
1775
|
availableStatus: false
|
@@ -1698,25 +1783,23 @@ const collectionTypes = {
|
|
1698
1783
|
async update(ctx) {
|
1699
1784
|
const { userAbility } = ctx.state;
|
1700
1785
|
const { model } = ctx.params;
|
1701
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1702
1786
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1703
1787
|
const updatedVersion = await updateDocument(ctx);
|
1704
1788
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1705
|
-
ctx.body = await
|
1789
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1706
1790
|
},
|
1707
1791
|
async clone(ctx) {
|
1708
1792
|
const { userAbility, user } = ctx.state;
|
1709
1793
|
const { model, sourceId: id } = ctx.params;
|
1710
1794
|
const { body } = ctx.request;
|
1711
1795
|
const documentManager2 = getService$1("document-manager");
|
1712
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1713
1796
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1714
1797
|
if (permissionChecker2.cannot.create()) {
|
1715
1798
|
return ctx.forbidden();
|
1716
1799
|
}
|
1717
1800
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1718
1801
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1719
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1802
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1720
1803
|
const document = await documentManager2.findOne(id, model, {
|
1721
1804
|
populate,
|
1722
1805
|
locale,
|
@@ -1732,7 +1815,7 @@ const collectionTypes = {
|
|
1732
1815
|
const sanitizedBody = await sanitizeFn(body);
|
1733
1816
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1734
1817
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1735
|
-
ctx.body = await
|
1818
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1736
1819
|
// Empty metadata as it's not relevant for a new document
|
1737
1820
|
availableLocales: false,
|
1738
1821
|
availableStatus: false
|
@@ -1761,7 +1844,7 @@ const collectionTypes = {
|
|
1761
1844
|
}
|
1762
1845
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1763
1846
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1764
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1847
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1765
1848
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1766
1849
|
if (documentLocales.length === 0) {
|
1767
1850
|
return ctx.notFound();
|
@@ -1783,7 +1866,6 @@ const collectionTypes = {
|
|
1783
1866
|
const { id, model } = ctx.params;
|
1784
1867
|
const { body } = ctx.request;
|
1785
1868
|
const documentManager2 = getService$1("document-manager");
|
1786
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1787
1869
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1788
1870
|
if (permissionChecker2.cannot.publish()) {
|
1789
1871
|
return ctx.forbidden();
|
@@ -1795,21 +1877,25 @@ const collectionTypes = {
|
|
1795
1877
|
if (permissionChecker2.cannot.publish(document)) {
|
1796
1878
|
throw new strapiUtils.errors.ForbiddenError();
|
1797
1879
|
}
|
1798
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1799
|
-
|
1880
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1881
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1800
1882
|
locale
|
1801
1883
|
// TODO: Allow setting creator fields on publish
|
1802
1884
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1803
1885
|
});
|
1886
|
+
if (!publishResult || publishResult.length === 0) {
|
1887
|
+
throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
|
1888
|
+
}
|
1889
|
+
return publishResult[0];
|
1804
1890
|
});
|
1805
1891
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1806
|
-
ctx.body = await
|
1892
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1807
1893
|
},
|
1808
1894
|
async bulkPublish(ctx) {
|
1809
1895
|
const { userAbility } = ctx.state;
|
1810
1896
|
const { model } = ctx.params;
|
1811
1897
|
const { body } = ctx.request;
|
1812
|
-
const {
|
1898
|
+
const { documentIds } = body;
|
1813
1899
|
await validateBulkActionInput(body);
|
1814
1900
|
const documentManager2 = getService$1("document-manager");
|
1815
1901
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1818,8 +1904,11 @@ const collectionTypes = {
|
|
1818
1904
|
}
|
1819
1905
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1820
1906
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1821
|
-
const
|
1822
|
-
const
|
1907
|
+
const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
|
1908
|
+
const entityPromises = documentIds.map(
|
1909
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1910
|
+
);
|
1911
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1823
1912
|
for (const entity of entities) {
|
1824
1913
|
if (!entity) {
|
1825
1914
|
return ctx.notFound();
|
@@ -1828,24 +1917,25 @@ const collectionTypes = {
|
|
1828
1917
|
return ctx.forbidden();
|
1829
1918
|
}
|
1830
1919
|
}
|
1831
|
-
const
|
1920
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1832
1921
|
ctx.body = { count };
|
1833
1922
|
},
|
1834
1923
|
async bulkUnpublish(ctx) {
|
1835
1924
|
const { userAbility } = ctx.state;
|
1836
1925
|
const { model } = ctx.params;
|
1837
1926
|
const { body } = ctx.request;
|
1838
|
-
const {
|
1927
|
+
const { documentIds } = body;
|
1839
1928
|
await validateBulkActionInput(body);
|
1840
1929
|
const documentManager2 = getService$1("document-manager");
|
1841
1930
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1842
1931
|
if (permissionChecker2.cannot.unpublish()) {
|
1843
1932
|
return ctx.forbidden();
|
1844
1933
|
}
|
1845
|
-
const
|
1846
|
-
const
|
1847
|
-
|
1848
|
-
|
1934
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1935
|
+
const entityPromises = documentIds.map(
|
1936
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1937
|
+
);
|
1938
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1849
1939
|
for (const entity of entities) {
|
1850
1940
|
if (!entity) {
|
1851
1941
|
return ctx.notFound();
|
@@ -1854,7 +1944,8 @@ const collectionTypes = {
|
|
1854
1944
|
return ctx.forbidden();
|
1855
1945
|
}
|
1856
1946
|
}
|
1857
|
-
const
|
1947
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1948
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1858
1949
|
ctx.body = { count };
|
1859
1950
|
},
|
1860
1951
|
async unpublish(ctx) {
|
@@ -1864,7 +1955,6 @@ const collectionTypes = {
|
|
1864
1955
|
body: { discardDraft, ...body }
|
1865
1956
|
} = ctx.request;
|
1866
1957
|
const documentManager2 = getService$1("document-manager");
|
1867
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1868
1958
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1869
1959
|
if (permissionChecker2.cannot.unpublish()) {
|
1870
1960
|
return ctx.forbidden();
|
@@ -1874,7 +1964,7 @@ const collectionTypes = {
|
|
1874
1964
|
}
|
1875
1965
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1876
1966
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1877
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1967
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1878
1968
|
const document = await documentManager2.findOne(id, model, {
|
1879
1969
|
populate,
|
1880
1970
|
locale,
|
@@ -1896,7 +1986,7 @@ const collectionTypes = {
|
|
1896
1986
|
ctx.body = await strapiUtils.async.pipe(
|
1897
1987
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1898
1988
|
permissionChecker2.sanitizeOutput,
|
1899
|
-
(document2) =>
|
1989
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1900
1990
|
)(document);
|
1901
1991
|
});
|
1902
1992
|
},
|
@@ -1905,14 +1995,13 @@ const collectionTypes = {
|
|
1905
1995
|
const { id, model } = ctx.params;
|
1906
1996
|
const { body } = ctx.request;
|
1907
1997
|
const documentManager2 = getService$1("document-manager");
|
1908
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1909
1998
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1910
1999
|
if (permissionChecker2.cannot.discard()) {
|
1911
2000
|
return ctx.forbidden();
|
1912
2001
|
}
|
1913
2002
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1914
2003
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1915
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2004
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1916
2005
|
const document = await documentManager2.findOne(id, model, {
|
1917
2006
|
populate,
|
1918
2007
|
locale,
|
@@ -1927,14 +2016,14 @@ const collectionTypes = {
|
|
1927
2016
|
ctx.body = await strapiUtils.async.pipe(
|
1928
2017
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1929
2018
|
permissionChecker2.sanitizeOutput,
|
1930
|
-
(document2) =>
|
2019
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1931
2020
|
)(document);
|
1932
2021
|
},
|
1933
2022
|
async bulkDelete(ctx) {
|
1934
2023
|
const { userAbility } = ctx.state;
|
1935
2024
|
const { model } = ctx.params;
|
1936
2025
|
const { query, body } = ctx.request;
|
1937
|
-
const {
|
2026
|
+
const { documentIds } = body;
|
1938
2027
|
await validateBulkActionInput(body);
|
1939
2028
|
const documentManager2 = getService$1("document-manager");
|
1940
2029
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1942,14 +2031,22 @@ const collectionTypes = {
|
|
1942
2031
|
return ctx.forbidden();
|
1943
2032
|
}
|
1944
2033
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1945
|
-
const
|
1946
|
-
const
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
2034
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2035
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2036
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2037
|
+
populate,
|
2038
|
+
locale
|
2039
|
+
});
|
2040
|
+
if (documentLocales.length === 0) {
|
2041
|
+
return ctx.notFound();
|
2042
|
+
}
|
2043
|
+
for (const document of documentLocales) {
|
2044
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2045
|
+
return ctx.forbidden();
|
1950
2046
|
}
|
1951
|
-
}
|
1952
|
-
const
|
2047
|
+
}
|
2048
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2049
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1953
2050
|
ctx.body = { count };
|
1954
2051
|
},
|
1955
2052
|
async countDraftRelations(ctx) {
|
@@ -1962,7 +2059,7 @@ const collectionTypes = {
|
|
1962
2059
|
}
|
1963
2060
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1964
2061
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1965
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
2062
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1966
2063
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1967
2064
|
if (!entity) {
|
1968
2065
|
return ctx.notFound();
|
@@ -1977,7 +2074,7 @@ const collectionTypes = {
|
|
1977
2074
|
},
|
1978
2075
|
async countManyEntriesDraftRelations(ctx) {
|
1979
2076
|
const { userAbility } = ctx.state;
|
1980
|
-
const ids = ctx.request.query.
|
2077
|
+
const ids = ctx.request.query.documentIds;
|
1981
2078
|
const locale = ctx.request.query.locale;
|
1982
2079
|
const { model } = ctx.params;
|
1983
2080
|
const documentManager2 = getService$1("document-manager");
|
@@ -1988,7 +2085,7 @@ const collectionTypes = {
|
|
1988
2085
|
const entities = await documentManager2.findMany(
|
1989
2086
|
{
|
1990
2087
|
filters: {
|
1991
|
-
|
2088
|
+
documentId: ids
|
1992
2089
|
},
|
1993
2090
|
locale
|
1994
2091
|
},
|
@@ -2490,7 +2587,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2490
2587
|
throw new strapiUtils.errors.ForbiddenError();
|
2491
2588
|
}
|
2492
2589
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2493
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2590
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2494
2591
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2495
2592
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2496
2593
|
// Find the first document to check if it exists
|
@@ -2527,12 +2624,11 @@ const singleTypes = {
|
|
2527
2624
|
const { model } = ctx.params;
|
2528
2625
|
const { query = {} } = ctx.request;
|
2529
2626
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2530
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2531
2627
|
if (permissionChecker2.cannot.read()) {
|
2532
2628
|
return ctx.forbidden();
|
2533
2629
|
}
|
2534
2630
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2535
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2631
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2536
2632
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2537
2633
|
if (!version) {
|
2538
2634
|
if (permissionChecker2.cannot.create()) {
|
@@ -2542,8 +2638,10 @@ const singleTypes = {
|
|
2542
2638
|
if (!document) {
|
2543
2639
|
return ctx.notFound();
|
2544
2640
|
}
|
2545
|
-
const { meta } = await
|
2641
|
+
const { meta } = await formatDocumentWithMetadata(
|
2642
|
+
permissionChecker2,
|
2546
2643
|
model,
|
2644
|
+
// @ts-expect-error - fix types
|
2547
2645
|
{ id: document.documentId, locale, publishedAt: null },
|
2548
2646
|
{ availableLocales: true, availableStatus: false }
|
2549
2647
|
);
|
@@ -2554,16 +2652,15 @@ const singleTypes = {
|
|
2554
2652
|
return ctx.forbidden();
|
2555
2653
|
}
|
2556
2654
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2557
|
-
ctx.body = await
|
2655
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2558
2656
|
},
|
2559
2657
|
async createOrUpdate(ctx) {
|
2560
2658
|
const { userAbility } = ctx.state;
|
2561
2659
|
const { model } = ctx.params;
|
2562
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2563
2660
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2564
2661
|
const document = await createOrUpdateDocument(ctx);
|
2565
2662
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2566
|
-
ctx.body = await
|
2663
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2567
2664
|
},
|
2568
2665
|
async delete(ctx) {
|
2569
2666
|
const { userAbility } = ctx.state;
|
@@ -2576,7 +2673,7 @@ const singleTypes = {
|
|
2576
2673
|
}
|
2577
2674
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2578
2675
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2579
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2676
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2580
2677
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2581
2678
|
populate,
|
2582
2679
|
locale
|
@@ -2599,7 +2696,6 @@ const singleTypes = {
|
|
2599
2696
|
const { model } = ctx.params;
|
2600
2697
|
const { query = {} } = ctx.request;
|
2601
2698
|
const documentManager2 = getService$1("document-manager");
|
2602
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2603
2699
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2604
2700
|
if (permissionChecker2.cannot.publish()) {
|
2605
2701
|
return ctx.forbidden();
|
@@ -2614,11 +2710,12 @@ const singleTypes = {
|
|
2614
2710
|
if (permissionChecker2.cannot.publish(document)) {
|
2615
2711
|
throw new strapiUtils.errors.ForbiddenError();
|
2616
2712
|
}
|
2617
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2618
|
-
|
2713
|
+
const { locale } = await getDocumentLocaleAndStatus(document);
|
2714
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2715
|
+
return publishResult.at(0);
|
2619
2716
|
});
|
2620
2717
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2621
|
-
ctx.body = await
|
2718
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2622
2719
|
},
|
2623
2720
|
async unpublish(ctx) {
|
2624
2721
|
const { userAbility } = ctx.state;
|
@@ -2628,7 +2725,6 @@ const singleTypes = {
|
|
2628
2725
|
query = {}
|
2629
2726
|
} = ctx.request;
|
2630
2727
|
const documentManager2 = getService$1("document-manager");
|
2631
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2632
2728
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2633
2729
|
if (permissionChecker2.cannot.unpublish()) {
|
2634
2730
|
return ctx.forbidden();
|
@@ -2637,7 +2733,7 @@ const singleTypes = {
|
|
2637
2733
|
return ctx.forbidden();
|
2638
2734
|
}
|
2639
2735
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2640
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2736
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2641
2737
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2642
2738
|
if (!document) {
|
2643
2739
|
return ctx.notFound();
|
@@ -2655,7 +2751,7 @@ const singleTypes = {
|
|
2655
2751
|
ctx.body = await strapiUtils.async.pipe(
|
2656
2752
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2657
2753
|
permissionChecker2.sanitizeOutput,
|
2658
|
-
(document2) =>
|
2754
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2659
2755
|
)(document);
|
2660
2756
|
});
|
2661
2757
|
},
|
@@ -2664,13 +2760,12 @@ const singleTypes = {
|
|
2664
2760
|
const { model } = ctx.params;
|
2665
2761
|
const { body, query = {} } = ctx.request;
|
2666
2762
|
const documentManager2 = getService$1("document-manager");
|
2667
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2668
2763
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2669
2764
|
if (permissionChecker2.cannot.discard()) {
|
2670
2765
|
return ctx.forbidden();
|
2671
2766
|
}
|
2672
2767
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2673
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2768
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2674
2769
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2675
2770
|
if (!document) {
|
2676
2771
|
return ctx.notFound();
|
@@ -2681,7 +2776,7 @@ const singleTypes = {
|
|
2681
2776
|
ctx.body = await strapiUtils.async.pipe(
|
2682
2777
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2683
2778
|
permissionChecker2.sanitizeOutput,
|
2684
|
-
(document2) =>
|
2779
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2685
2780
|
)(document);
|
2686
2781
|
},
|
2687
2782
|
async countDraftRelations(ctx) {
|
@@ -2690,7 +2785,7 @@ const singleTypes = {
|
|
2690
2785
|
const { query } = ctx.request;
|
2691
2786
|
const documentManager2 = getService$1("document-manager");
|
2692
2787
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2693
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2788
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2694
2789
|
if (permissionChecker2.cannot.read()) {
|
2695
2790
|
return ctx.forbidden();
|
2696
2791
|
}
|
@@ -2711,7 +2806,7 @@ const uid$1 = {
|
|
2711
2806
|
async generateUID(ctx) {
|
2712
2807
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2713
2808
|
const { query = {} } = ctx.request;
|
2714
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2809
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2715
2810
|
await validateUIDField(contentTypeUID, field);
|
2716
2811
|
const uidService = getService$1("uid");
|
2717
2812
|
ctx.body = {
|
@@ -2723,7 +2818,7 @@ const uid$1 = {
|
|
2723
2818
|
ctx.request.body
|
2724
2819
|
);
|
2725
2820
|
const { query = {} } = ctx.request;
|
2726
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2821
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2727
2822
|
await validateUIDField(contentTypeUID, field);
|
2728
2823
|
const uidService = getService$1("uid");
|
2729
2824
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3514,7 +3609,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3514
3609
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3515
3610
|
}
|
3516
3611
|
});
|
3517
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
|
3612
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
|
3518
3613
|
const { isAnyToMany } = strapiUtils__default.default.relations;
|
3519
3614
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
|
3520
3615
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3605,6 +3700,42 @@ const getDeepPopulate = (uid2, {
|
|
3605
3700
|
{}
|
3606
3701
|
);
|
3607
3702
|
};
|
3703
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3704
|
+
initialPopulate = {},
|
3705
|
+
countMany = false,
|
3706
|
+
countOne = false,
|
3707
|
+
maxLevel = Infinity
|
3708
|
+
} = {}, level = 1) => {
|
3709
|
+
if (level > maxLevel) {
|
3710
|
+
return {};
|
3711
|
+
}
|
3712
|
+
const model = strapi.getModel(uid2);
|
3713
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3714
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3715
|
+
return populateAcc;
|
3716
|
+
}
|
3717
|
+
if (isScalarAttribute(attribute)) {
|
3718
|
+
return fp.merge(populateAcc, {
|
3719
|
+
[attributeName]: true
|
3720
|
+
});
|
3721
|
+
}
|
3722
|
+
return fp.merge(
|
3723
|
+
populateAcc,
|
3724
|
+
getPopulateFor(
|
3725
|
+
attributeName,
|
3726
|
+
model,
|
3727
|
+
{
|
3728
|
+
// @ts-expect-error - improve types
|
3729
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3730
|
+
countMany,
|
3731
|
+
countOne,
|
3732
|
+
maxLevel
|
3733
|
+
},
|
3734
|
+
level
|
3735
|
+
)
|
3736
|
+
);
|
3737
|
+
}, {});
|
3738
|
+
};
|
3608
3739
|
const getDeepPopulateDraftCount = (uid2) => {
|
3609
3740
|
const model = strapi.getModel(uid2);
|
3610
3741
|
let hasRelations = false;
|
@@ -3626,22 +3757,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3626
3757
|
attribute.component
|
3627
3758
|
);
|
3628
3759
|
if (childHasRelations) {
|
3629
|
-
populateAcc[attributeName] = {
|
3760
|
+
populateAcc[attributeName] = {
|
3761
|
+
populate: populate2
|
3762
|
+
};
|
3630
3763
|
hasRelations = true;
|
3631
3764
|
}
|
3632
3765
|
break;
|
3633
3766
|
}
|
3634
3767
|
case "dynamiczone": {
|
3635
|
-
const
|
3636
|
-
const { populate:
|
3637
|
-
if (
|
3768
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3769
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3770
|
+
if (componentHasRelations) {
|
3638
3771
|
hasRelations = true;
|
3639
|
-
return
|
3772
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3640
3773
|
}
|
3641
3774
|
return acc;
|
3642
3775
|
}, {});
|
3643
|
-
if (!fp.isEmpty(
|
3644
|
-
populateAcc[attributeName] = {
|
3776
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
3777
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3645
3778
|
}
|
3646
3779
|
break;
|
3647
3780
|
}
|
@@ -3833,41 +3966,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3833
3966
|
"updatedBy",
|
3834
3967
|
"status"
|
3835
3968
|
];
|
3836
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
3969
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
3970
|
+
"id",
|
3971
|
+
"locale",
|
3972
|
+
"updatedAt",
|
3973
|
+
"createdAt",
|
3974
|
+
"status",
|
3975
|
+
"publishedAt",
|
3976
|
+
"documentId"
|
3977
|
+
];
|
3837
3978
|
const CONTENT_MANAGER_STATUS = {
|
3838
3979
|
PUBLISHED: "published",
|
3839
3980
|
DRAFT: "draft",
|
3840
3981
|
MODIFIED: "modified"
|
3841
3982
|
};
|
3842
|
-
const
|
3843
|
-
if (!
|
3983
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
3984
|
+
if (!version || !version.updatedAt) {
|
3844
3985
|
return false;
|
3845
3986
|
}
|
3846
|
-
const
|
3847
|
-
const
|
3848
|
-
|
3849
|
-
return difference <= threshold;
|
3987
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
3988
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
3989
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3850
3990
|
};
|
3851
3991
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3852
3992
|
/**
|
3853
3993
|
* Returns available locales of a document for the current status
|
3854
3994
|
*/
|
3855
|
-
getAvailableLocales(uid2, version, allVersions) {
|
3995
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3856
3996
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3857
3997
|
delete versionsByLocale[version.locale];
|
3858
|
-
|
3859
|
-
|
3860
|
-
|
3998
|
+
const model = strapi2.getModel(uid2);
|
3999
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4000
|
+
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4001
|
+
({ key }, { remove }) => {
|
4002
|
+
if (keysToKeep.includes(key)) {
|
4003
|
+
return;
|
4004
|
+
}
|
4005
|
+
remove(key);
|
4006
|
+
},
|
4007
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4008
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4009
|
+
localeVersion
|
4010
|
+
);
|
4011
|
+
const mappingResult = await strapiUtils.async.map(
|
4012
|
+
Object.values(versionsByLocale),
|
4013
|
+
async (localeVersions) => {
|
4014
|
+
const mappedLocaleVersions = await strapiUtils.async.map(
|
4015
|
+
localeVersions,
|
4016
|
+
traversalFunction
|
4017
|
+
);
|
4018
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4019
|
+
return mappedLocaleVersions[0];
|
4020
|
+
}
|
4021
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
4022
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
4023
|
+
if (!draftVersion) {
|
4024
|
+
return;
|
4025
|
+
}
|
4026
|
+
return {
|
4027
|
+
...draftVersion,
|
4028
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4029
|
+
};
|
3861
4030
|
}
|
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);
|
4031
|
+
);
|
4032
|
+
return mappingResult.filter(Boolean);
|
3871
4033
|
},
|
3872
4034
|
/**
|
3873
4035
|
* Returns available status of a document for the current locale
|
@@ -3905,26 +4067,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3905
4067
|
});
|
3906
4068
|
},
|
3907
4069
|
getStatus(version, otherDocumentStatuses) {
|
3908
|
-
|
3909
|
-
|
3910
|
-
|
4070
|
+
let draftVersion;
|
4071
|
+
let publishedVersion;
|
4072
|
+
if (version.publishedAt) {
|
4073
|
+
publishedVersion = version;
|
4074
|
+
} else {
|
4075
|
+
draftVersion = version;
|
3911
4076
|
}
|
3912
|
-
|
3913
|
-
|
3914
|
-
|
3915
|
-
|
3916
|
-
|
4077
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4078
|
+
if (otherVersion?.publishedAt) {
|
4079
|
+
publishedVersion = otherVersion;
|
4080
|
+
} else if (otherVersion) {
|
4081
|
+
draftVersion = otherVersion;
|
3917
4082
|
}
|
3918
|
-
if (
|
4083
|
+
if (!draftVersion)
|
3919
4084
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3920
|
-
|
3921
|
-
|
4085
|
+
if (!publishedVersion)
|
4086
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4087
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4088
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3922
4089
|
},
|
4090
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4091
|
+
// We could refactor this so the locales are only loaded when they're
|
4092
|
+
// needed. e.g. in the bulk locale action modal.
|
3923
4093
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4094
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3924
4095
|
const versions = await strapi2.db.query(uid2).findMany({
|
3925
4096
|
where: { documentId: version.documentId },
|
3926
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3927
4097
|
populate: {
|
4098
|
+
// Populate only fields that require validation for bulk locale actions
|
4099
|
+
...populate,
|
4100
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3928
4101
|
createdBy: {
|
3929
4102
|
select: ["id", "firstname", "lastname", "email"]
|
3930
4103
|
},
|
@@ -3933,7 +4106,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3933
4106
|
}
|
3934
4107
|
}
|
3935
4108
|
});
|
3936
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4109
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3937
4110
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3938
4111
|
return {
|
3939
4112
|
availableLocales: availableLocalesResult,
|
@@ -3946,8 +4119,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3946
4119
|
* - Available status of the document for the current locale
|
3947
4120
|
*/
|
3948
4121
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3949
|
-
if (!document)
|
4122
|
+
if (!document) {
|
3950
4123
|
return document;
|
4124
|
+
}
|
3951
4125
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
3952
4126
|
if (!hasDraftAndPublish) {
|
3953
4127
|
opts.availableStatus = false;
|
@@ -3997,26 +4171,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
3997
4171
|
}, 0);
|
3998
4172
|
};
|
3999
4173
|
const { ApplicationError } = strapiUtils.errors;
|
4000
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4001
4174
|
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
4002
4175
|
const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
|
4003
4176
|
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
4177
|
const documentManager = ({ strapi: strapi2 }) => {
|
4021
4178
|
return {
|
4022
4179
|
async findOne(id, uid2, opts = {}) {
|
@@ -4035,6 +4192,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4035
4192
|
} else if (opts.locale && opts.locale !== "*") {
|
4036
4193
|
where.locale = opts.locale;
|
4037
4194
|
}
|
4195
|
+
if (typeof opts.isPublished === "boolean") {
|
4196
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4197
|
+
}
|
4038
4198
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4039
4199
|
},
|
4040
4200
|
async findMany(opts, uid2) {
|
@@ -4042,20 +4202,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4042
4202
|
return strapi2.documents(uid2).findMany(params);
|
4043
4203
|
},
|
4044
4204
|
async findPage(opts, uid2) {
|
4045
|
-
const
|
4046
|
-
|
4205
|
+
const params = strapiUtils.pagination.withDefaultPagination(opts || {}, {
|
4206
|
+
maxLimit: 1e3
|
4207
|
+
});
|
4047
4208
|
const [documents, total = 0] = await Promise.all([
|
4048
|
-
strapi2.documents(uid2).findMany(
|
4049
|
-
strapi2.documents(uid2).count(
|
4209
|
+
strapi2.documents(uid2).findMany(params),
|
4210
|
+
strapi2.documents(uid2).count(params)
|
4050
4211
|
]);
|
4051
4212
|
return {
|
4052
4213
|
results: documents,
|
4053
|
-
pagination:
|
4054
|
-
page,
|
4055
|
-
pageSize,
|
4056
|
-
pageCount: Math.ceil(total / pageSize),
|
4057
|
-
total
|
4058
|
-
}
|
4214
|
+
pagination: strapiUtils.pagination.transformPagedPaginationInfo(params, total)
|
4059
4215
|
};
|
4060
4216
|
},
|
4061
4217
|
async create(uid2, opts = {}) {
|
@@ -4101,70 +4257,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4101
4257
|
return {};
|
4102
4258
|
},
|
4103
4259
|
// FIXME: handle relations
|
4104
|
-
async deleteMany(
|
4105
|
-
const
|
4106
|
-
|
4107
|
-
|
4108
|
-
}
|
4109
|
-
return { count: docs.length };
|
4260
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4261
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4262
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4263
|
+
});
|
4264
|
+
return { count: deletedEntries.length };
|
4110
4265
|
},
|
4111
4266
|
async publish(id, uid2, opts = {}) {
|
4112
4267
|
const populate = await buildDeepPopulate(uid2);
|
4113
4268
|
const params = { ...opts, populate };
|
4114
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4269
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4115
4270
|
},
|
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
|
4271
|
+
async publishMany(uid2, documentIds, locale) {
|
4272
|
+
return strapi2.db.transaction(async () => {
|
4273
|
+
const results = await Promise.all(
|
4274
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4275
|
+
);
|
4276
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4277
|
+
return publishedEntitiesCount;
|
4142
4278
|
});
|
4143
|
-
await Promise.all(
|
4144
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4145
|
-
);
|
4146
|
-
return publishedEntitiesCount;
|
4147
4279
|
},
|
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
|
4280
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4281
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4282
|
+
return Promise.all(
|
4283
|
+
documentIds.map(
|
4284
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4285
|
+
)
|
4286
|
+
);
|
4163
4287
|
});
|
4164
|
-
|
4165
|
-
|
4166
|
-
);
|
4167
|
-
return unpublishedEntitiesCount;
|
4288
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4289
|
+
return { count: unpublishedEntitiesCount };
|
4168
4290
|
},
|
4169
4291
|
async unpublish(id, uid2, opts = {}) {
|
4170
4292
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4189,16 +4311,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4189
4311
|
}
|
4190
4312
|
return sumDraftCounts(document, uid2);
|
4191
4313
|
},
|
4192
|
-
async countManyEntriesDraftRelations(
|
4314
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4193
4315
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4194
4316
|
if (!hasRelations) {
|
4195
4317
|
return 0;
|
4196
4318
|
}
|
4319
|
+
let localeFilter = {};
|
4320
|
+
if (locale) {
|
4321
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4322
|
+
}
|
4197
4323
|
const entities = await strapi2.db.query(uid2).findMany({
|
4198
4324
|
populate,
|
4199
4325
|
where: {
|
4200
|
-
|
4201
|
-
...
|
4326
|
+
documentId: { $in: documentIds },
|
4327
|
+
...localeFilter
|
4202
4328
|
}
|
4203
4329
|
});
|
4204
4330
|
const totalNumberDraftRelations = entities.reduce(
|