@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.f31889311d753b5f7d95198ae84d8fce1d156cd6
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-DjWJdz6Y.js → ComponentConfigurationPage-BNxtMIfV.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-BNxtMIfV.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-BWOQWCv2.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-BWOQWCv2.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-Dmv83RlS.js → EditConfigurationPage-D340bYlT.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-D340bYlT.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs → EditConfigurationPage-GTp-Ucnw.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-GTp-Ucnw.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-DDS6H9HO.mjs → EditViewPage-BVMS5hT-.mjs} +47 -47
- package/dist/_chunks/EditViewPage-BVMS5hT-.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-CXkmnAvI.js} +46 -48
- package/dist/_chunks/EditViewPage-CXkmnAvI.js.map +1 -0
- package/dist/_chunks/{Field-DmVKIAOo.js → Field-Ibi32diw.js} +953 -782
- package/dist/_chunks/Field-Ibi32diw.js.map +1 -0
- package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-nNgv5bpd.mjs} +901 -729
- package/dist/_chunks/Field-nNgv5bpd.mjs.map +1 -0
- package/dist/_chunks/{Form-CPZC9vWa.js → Form-Dhnh34ym.js} +39 -38
- package/dist/_chunks/Form-Dhnh34ym.js.map +1 -0
- package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-DodJsI2A.mjs} +39 -37
- package/dist/_chunks/Form-DodJsI2A.mjs.map +1 -0
- package/dist/_chunks/{History-DeAPlvtv.js → History-C9auUkDi.js} +149 -56
- package/dist/_chunks/History-C9auUkDi.js.map +1 -0
- package/dist/_chunks/{History-Dmr9fmUA.mjs → History-CKCSQXz_.mjs} +148 -54
- package/dist/_chunks/History-CKCSQXz_.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-Bg4rWUjX.js} +58 -59
- package/dist/_chunks/ListConfigurationPage-Bg4rWUjX.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-CKEC4ttG.mjs} +54 -54
- package/dist/_chunks/ListConfigurationPage-CKEC4ttG.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-B7_WJUjG.mjs} +93 -104
- package/dist/_chunks/ListViewPage-B7_WJUjG.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-C2gIeYHG.js} +98 -109
- package/dist/_chunks/ListViewPage-C2gIeYHG.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-Ckem6Ll6.mjs} +3 -3
- package/dist/_chunks/NoContentTypePage-Ckem6Ll6.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-DqgdUfyn.js} +3 -3
- package/dist/_chunks/NoContentTypePage-DqgdUfyn.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-BO-GEjA4.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-BO-GEjA4.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-CF29Q-sW.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-CF29Q-sW.js.map} +1 -1
- package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-C0uC9J4f.js} +70 -61
- package/dist/_chunks/Relations-C0uC9J4f.js.map +1 -0
- package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-DItV5eow.mjs} +66 -56
- package/dist/_chunks/Relations-DItV5eow.mjs.map +1 -0
- package/dist/_chunks/{en-MBPul9Su.mjs → en-BrCTWlZv.mjs} +11 -4
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
- package/dist/_chunks/{en-C-V1_90f.js → en-uOUIxfcQ.js} +11 -4
- package/dist/_chunks/{en-C-V1_90f.js.map → en-uOUIxfcQ.js.map} +1 -1
- package/dist/_chunks/{index-C6AH2hEl.js → index-Dd0nXyJF.js} +1649 -905
- package/dist/_chunks/index-Dd0nXyJF.js.map +1 -0
- package/dist/_chunks/{index-CwRRo1V9.mjs → index-DrNe6ctw.mjs} +1671 -926
- package/dist/_chunks/index-DrNe6ctw.mjs.map +1 -0
- package/dist/_chunks/{layout-jIDzX0Fp.mjs → layout-B3ez7kvr.mjs} +43 -26
- package/dist/_chunks/layout-B3ez7kvr.mjs.map +1 -0
- package/dist/_chunks/{layout-B_SXLhqf.js → layout-CLLtt_5O.js} +43 -28
- package/dist/_chunks/layout-CLLtt_5O.js.map +1 -0
- package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-B0hlsUU_.mjs} +2 -2
- package/dist/_chunks/{relations-CuvIgCqI.mjs.map → relations-B0hlsUU_.mjs.map} +1 -1
- package/dist/_chunks/{relations-iBMa_OFG.js → relations-bRxcNv1q.js} +2 -2
- package/dist/_chunks/{relations-iBMa_OFG.js.map → relations-bRxcNv1q.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/index.d.ts +3 -0
- 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/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -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 +30 -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 +392 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +400 -269
- 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/uid.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 +11 -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.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +1 -1
- package/dist/server/src/history/services/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-DDS6H9HO.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
- package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
- package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
- package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
- package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
- package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
- package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
- package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
- package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
- package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
- package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
- package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
- package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
- package/dist/_chunks/layout-jIDzX0Fp.mjs.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
@@ -226,20 +226,25 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
226
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
227
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
228
|
};
|
229
|
-
const getDeepPopulate2 = (uid2) => {
|
229
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
230
|
const model = strapi2.getModel(uid2);
|
231
231
|
const attributes = Object.entries(model.attributes);
|
232
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
233
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
234
|
switch (attribute.type) {
|
234
235
|
case "relation": {
|
236
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
237
|
+
if (isMorphRelation) {
|
238
|
+
break;
|
239
|
+
}
|
235
240
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
241
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
242
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
243
|
}
|
239
244
|
break;
|
240
245
|
}
|
241
246
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
247
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
248
|
break;
|
244
249
|
}
|
245
250
|
case "component": {
|
@@ -490,13 +495,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
495
|
}
|
491
496
|
};
|
492
497
|
};
|
498
|
+
const shouldCreateHistoryVersion = (context) => {
|
499
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
500
|
+
return false;
|
501
|
+
}
|
502
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
503
|
+
return false;
|
504
|
+
}
|
505
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
509
|
+
return false;
|
510
|
+
}
|
511
|
+
return true;
|
512
|
+
};
|
513
|
+
const getSchemas = (uid2) => {
|
514
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
515
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
516
|
+
(currentComponentSchemas, key) => {
|
517
|
+
const fieldSchema = attributesSchema[key];
|
518
|
+
if (fieldSchema.type === "component") {
|
519
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
520
|
+
return {
|
521
|
+
...currentComponentSchemas,
|
522
|
+
[fieldSchema.component]: componentSchema
|
523
|
+
};
|
524
|
+
}
|
525
|
+
return currentComponentSchemas;
|
526
|
+
},
|
527
|
+
{}
|
528
|
+
);
|
529
|
+
return {
|
530
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
531
|
+
componentsSchemas
|
532
|
+
};
|
533
|
+
};
|
493
534
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
535
|
const state = {
|
495
536
|
deleteExpiredJob: null,
|
496
537
|
isInitialized: false
|
497
538
|
};
|
498
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
-
const historyService = getService(strapi2, "history");
|
500
539
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
540
|
return {
|
502
541
|
async bootstrap() {
|
@@ -504,60 +543,51 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
504
543
|
return;
|
505
544
|
}
|
506
545
|
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 !== "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
546
|
const result = await next();
|
518
|
-
|
547
|
+
if (!shouldCreateHistoryVersion(context)) {
|
548
|
+
return result;
|
549
|
+
}
|
550
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
519
551
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
520
|
-
const
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
552
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
553
|
+
if (!locales.length) {
|
554
|
+
return result;
|
555
|
+
}
|
556
|
+
const uid2 = context.contentType.uid;
|
557
|
+
const schemas = getSchemas(uid2);
|
558
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
559
|
+
where: {
|
560
|
+
documentId,
|
561
|
+
locale: { $in: locales },
|
562
|
+
publishedAt: null
|
563
|
+
},
|
564
|
+
populate: serviceUtils.getDeepPopulate(
|
565
|
+
uid2,
|
566
|
+
true
|
567
|
+
/* use database syntax */
|
568
|
+
)
|
525
569
|
});
|
526
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
527
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
528
|
-
const componentsSchemas = Object.keys(
|
529
|
-
attributesSchema
|
530
|
-
).reduce((currentComponentSchemas, key) => {
|
531
|
-
const fieldSchema = attributesSchema[key];
|
532
|
-
if (fieldSchema.type === "component") {
|
533
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
534
|
-
return {
|
535
|
-
...currentComponentSchemas,
|
536
|
-
[fieldSchema.component]: componentSchema
|
537
|
-
};
|
538
|
-
}
|
539
|
-
return currentComponentSchemas;
|
540
|
-
}, {});
|
541
570
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
542
|
-
onCommit(() => {
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
571
|
+
onCommit(async () => {
|
572
|
+
for (const entry of localeEntries) {
|
573
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
574
|
+
await getService(strapi2, "history").createVersion({
|
575
|
+
contentType: uid2,
|
576
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
577
|
+
relatedDocumentId: documentId,
|
578
|
+
locale: entry.locale,
|
579
|
+
status,
|
580
|
+
...schemas
|
581
|
+
});
|
582
|
+
}
|
552
583
|
});
|
553
584
|
});
|
554
585
|
return result;
|
555
586
|
});
|
556
|
-
const retentionDays = serviceUtils.getRetentionDays();
|
557
587
|
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
558
|
-
const retentionDaysInMilliseconds =
|
588
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
559
589
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
560
|
-
query.deleteMany({
|
590
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
561
591
|
where: {
|
562
592
|
created_at: {
|
563
593
|
$lt: expirationDate.toISOString()
|
@@ -1478,7 +1508,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
|
|
1478
1508
|
const TYPES = ["singleType", "collectionType"];
|
1479
1509
|
const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
|
1480
1510
|
const bulkActionInputSchema = strapiUtils.yup.object({
|
1481
|
-
|
1511
|
+
documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
|
1482
1512
|
}).required();
|
1483
1513
|
const generateUIDInputSchema = strapiUtils.yup.object({
|
1484
1514
|
contentTypeUID: strapiUtils.yup.string().required(),
|
@@ -1577,15 +1607,49 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1577
1607
|
}
|
1578
1608
|
}, body);
|
1579
1609
|
};
|
1580
|
-
const
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1610
|
+
const singleLocaleSchema = strapiUtils.yup.string().nullable();
|
1611
|
+
const multipleLocaleSchema = strapiUtils.yup.lazy(
|
1612
|
+
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1613
|
+
);
|
1614
|
+
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1615
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1616
|
+
const { allowMultipleLocales } = opts;
|
1617
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1618
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1619
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1620
|
+
const schema = strapiUtils.yup.object().shape({
|
1621
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1622
|
+
status: statusSchema
|
1623
|
+
});
|
1624
|
+
try {
|
1625
|
+
await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1626
|
+
return { locale, status, ...rest };
|
1627
|
+
} catch (error) {
|
1628
|
+
throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
|
1587
1629
|
}
|
1588
|
-
|
1630
|
+
};
|
1631
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1632
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1633
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1634
|
+
let {
|
1635
|
+
meta: { availableLocales, availableStatus }
|
1636
|
+
} = serviceOutput;
|
1637
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1638
|
+
availableLocales = await strapiUtils.async.map(
|
1639
|
+
availableLocales,
|
1640
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1641
|
+
);
|
1642
|
+
availableStatus = await strapiUtils.async.map(
|
1643
|
+
availableStatus,
|
1644
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1645
|
+
);
|
1646
|
+
return {
|
1647
|
+
...serviceOutput,
|
1648
|
+
meta: {
|
1649
|
+
availableLocales,
|
1650
|
+
availableStatus
|
1651
|
+
}
|
1652
|
+
};
|
1589
1653
|
};
|
1590
1654
|
const createDocument = async (ctx, opts) => {
|
1591
1655
|
const { userAbility, user } = ctx.state;
|
@@ -1600,7 +1664,7 @@ const createDocument = async (ctx, opts) => {
|
|
1600
1664
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1601
1665
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1602
1666
|
const sanitizedBody = await sanitizeFn(body);
|
1603
|
-
const { locale, status
|
1667
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1604
1668
|
return documentManager2.create(model, {
|
1605
1669
|
data: sanitizedBody,
|
1606
1670
|
locale,
|
@@ -1619,7 +1683,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1619
1683
|
}
|
1620
1684
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1621
1685
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1622
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1686
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1623
1687
|
const [documentVersion, documentExists] = await Promise.all([
|
1624
1688
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1625
1689
|
documentManager2.exists(model, id)
|
@@ -1657,7 +1721,7 @@ const collectionTypes = {
|
|
1657
1721
|
}
|
1658
1722
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1659
1723
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1660
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1724
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1661
1725
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1662
1726
|
{ ...permissionQuery, populate, locale, status },
|
1663
1727
|
model
|
@@ -1686,14 +1750,13 @@ const collectionTypes = {
|
|
1686
1750
|
const { userAbility } = ctx.state;
|
1687
1751
|
const { model, id } = ctx.params;
|
1688
1752
|
const documentManager2 = getService$1("document-manager");
|
1689
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1690
1753
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1691
1754
|
if (permissionChecker2.cannot.read()) {
|
1692
1755
|
return ctx.forbidden();
|
1693
1756
|
}
|
1694
1757
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1695
1758
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1696
|
-
const { locale, status
|
1759
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1697
1760
|
const version = await documentManager2.findOne(id, model, {
|
1698
1761
|
populate,
|
1699
1762
|
locale,
|
@@ -1704,8 +1767,10 @@ const collectionTypes = {
|
|
1704
1767
|
if (!exists) {
|
1705
1768
|
return ctx.notFound();
|
1706
1769
|
}
|
1707
|
-
const { meta } = await
|
1770
|
+
const { meta } = await formatDocumentWithMetadata(
|
1771
|
+
permissionChecker2,
|
1708
1772
|
model,
|
1773
|
+
// @ts-expect-error TODO: fix
|
1709
1774
|
{ id, locale, publishedAt: null },
|
1710
1775
|
{ availableLocales: true, availableStatus: false }
|
1711
1776
|
);
|
@@ -1716,12 +1781,11 @@ const collectionTypes = {
|
|
1716
1781
|
return ctx.forbidden();
|
1717
1782
|
}
|
1718
1783
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1719
|
-
ctx.body = await
|
1784
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1720
1785
|
},
|
1721
1786
|
async create(ctx) {
|
1722
1787
|
const { userAbility } = ctx.state;
|
1723
1788
|
const { model } = ctx.params;
|
1724
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1725
1789
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1726
1790
|
const [totalEntries, document] = await Promise.all([
|
1727
1791
|
strapi.db.query(model).count(),
|
@@ -1729,7 +1793,7 @@ const collectionTypes = {
|
|
1729
1793
|
]);
|
1730
1794
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1731
1795
|
ctx.status = 201;
|
1732
|
-
ctx.body = await
|
1796
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1733
1797
|
// Empty metadata as it's not relevant for a new document
|
1734
1798
|
availableLocales: false,
|
1735
1799
|
availableStatus: false
|
@@ -1743,25 +1807,23 @@ const collectionTypes = {
|
|
1743
1807
|
async update(ctx) {
|
1744
1808
|
const { userAbility } = ctx.state;
|
1745
1809
|
const { model } = ctx.params;
|
1746
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1747
1810
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1748
1811
|
const updatedVersion = await updateDocument(ctx);
|
1749
1812
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1750
|
-
ctx.body = await
|
1813
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1751
1814
|
},
|
1752
1815
|
async clone(ctx) {
|
1753
1816
|
const { userAbility, user } = ctx.state;
|
1754
1817
|
const { model, sourceId: id } = ctx.params;
|
1755
1818
|
const { body } = ctx.request;
|
1756
1819
|
const documentManager2 = getService$1("document-manager");
|
1757
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1758
1820
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1759
1821
|
if (permissionChecker2.cannot.create()) {
|
1760
1822
|
return ctx.forbidden();
|
1761
1823
|
}
|
1762
1824
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1763
1825
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1764
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1826
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1765
1827
|
const document = await documentManager2.findOne(id, model, {
|
1766
1828
|
populate,
|
1767
1829
|
locale,
|
@@ -1777,7 +1839,7 @@ const collectionTypes = {
|
|
1777
1839
|
const sanitizedBody = await sanitizeFn(body);
|
1778
1840
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1779
1841
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1780
|
-
ctx.body = await
|
1842
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1781
1843
|
// Empty metadata as it's not relevant for a new document
|
1782
1844
|
availableLocales: false,
|
1783
1845
|
availableStatus: false
|
@@ -1806,7 +1868,7 @@ const collectionTypes = {
|
|
1806
1868
|
}
|
1807
1869
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1808
1870
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1809
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1871
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1810
1872
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1811
1873
|
if (documentLocales.length === 0) {
|
1812
1874
|
return ctx.notFound();
|
@@ -1828,7 +1890,6 @@ const collectionTypes = {
|
|
1828
1890
|
const { id, model } = ctx.params;
|
1829
1891
|
const { body } = ctx.request;
|
1830
1892
|
const documentManager2 = getService$1("document-manager");
|
1831
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1832
1893
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1833
1894
|
if (permissionChecker2.cannot.publish()) {
|
1834
1895
|
return ctx.forbidden();
|
@@ -1836,25 +1897,46 @@ const collectionTypes = {
|
|
1836
1897
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1837
1898
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1838
1899
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1839
|
-
|
1900
|
+
let document;
|
1901
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1902
|
+
const isCreate = fp.isNil(id);
|
1903
|
+
if (isCreate) {
|
1904
|
+
if (permissionChecker2.cannot.create()) {
|
1905
|
+
throw new strapiUtils.errors.ForbiddenError();
|
1906
|
+
}
|
1907
|
+
document = await createDocument(ctx, { populate });
|
1908
|
+
}
|
1909
|
+
const isUpdate = !isCreate;
|
1910
|
+
if (isUpdate) {
|
1911
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
1912
|
+
if (!document) {
|
1913
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
1914
|
+
}
|
1915
|
+
if (permissionChecker2.can.update(document)) {
|
1916
|
+
await updateDocument(ctx);
|
1917
|
+
}
|
1918
|
+
}
|
1840
1919
|
if (permissionChecker2.cannot.publish(document)) {
|
1841
1920
|
throw new strapiUtils.errors.ForbiddenError();
|
1842
1921
|
}
|
1843
|
-
const
|
1844
|
-
return documentManager2.publish(document.documentId, model, {
|
1922
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1845
1923
|
locale
|
1846
1924
|
// TODO: Allow setting creator fields on publish
|
1847
1925
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1848
1926
|
});
|
1927
|
+
if (!publishResult || publishResult.length === 0) {
|
1928
|
+
throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
|
1929
|
+
}
|
1930
|
+
return publishResult[0];
|
1849
1931
|
});
|
1850
1932
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1851
|
-
ctx.body = await
|
1933
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1852
1934
|
},
|
1853
1935
|
async bulkPublish(ctx) {
|
1854
1936
|
const { userAbility } = ctx.state;
|
1855
1937
|
const { model } = ctx.params;
|
1856
1938
|
const { body } = ctx.request;
|
1857
|
-
const {
|
1939
|
+
const { documentIds } = body;
|
1858
1940
|
await validateBulkActionInput(body);
|
1859
1941
|
const documentManager2 = getService$1("document-manager");
|
1860
1942
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1863,8 +1945,13 @@ const collectionTypes = {
|
|
1863
1945
|
}
|
1864
1946
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1865
1947
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1866
|
-
const
|
1867
|
-
|
1948
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1949
|
+
allowMultipleLocales: true
|
1950
|
+
});
|
1951
|
+
const entityPromises = documentIds.map(
|
1952
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1953
|
+
);
|
1954
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1868
1955
|
for (const entity of entities) {
|
1869
1956
|
if (!entity) {
|
1870
1957
|
return ctx.notFound();
|
@@ -1873,24 +1960,25 @@ const collectionTypes = {
|
|
1873
1960
|
return ctx.forbidden();
|
1874
1961
|
}
|
1875
1962
|
}
|
1876
|
-
const
|
1963
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1877
1964
|
ctx.body = { count };
|
1878
1965
|
},
|
1879
1966
|
async bulkUnpublish(ctx) {
|
1880
1967
|
const { userAbility } = ctx.state;
|
1881
1968
|
const { model } = ctx.params;
|
1882
1969
|
const { body } = ctx.request;
|
1883
|
-
const {
|
1970
|
+
const { documentIds } = body;
|
1884
1971
|
await validateBulkActionInput(body);
|
1885
1972
|
const documentManager2 = getService$1("document-manager");
|
1886
1973
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1887
1974
|
if (permissionChecker2.cannot.unpublish()) {
|
1888
1975
|
return ctx.forbidden();
|
1889
1976
|
}
|
1890
|
-
const
|
1891
|
-
const
|
1892
|
-
|
1893
|
-
|
1977
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1978
|
+
const entityPromises = documentIds.map(
|
1979
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1980
|
+
);
|
1981
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1894
1982
|
for (const entity of entities) {
|
1895
1983
|
if (!entity) {
|
1896
1984
|
return ctx.notFound();
|
@@ -1899,7 +1987,8 @@ const collectionTypes = {
|
|
1899
1987
|
return ctx.forbidden();
|
1900
1988
|
}
|
1901
1989
|
}
|
1902
|
-
const
|
1990
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1991
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1903
1992
|
ctx.body = { count };
|
1904
1993
|
},
|
1905
1994
|
async unpublish(ctx) {
|
@@ -1909,7 +1998,6 @@ const collectionTypes = {
|
|
1909
1998
|
body: { discardDraft, ...body }
|
1910
1999
|
} = ctx.request;
|
1911
2000
|
const documentManager2 = getService$1("document-manager");
|
1912
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1913
2001
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1914
2002
|
if (permissionChecker2.cannot.unpublish()) {
|
1915
2003
|
return ctx.forbidden();
|
@@ -1919,7 +2007,7 @@ const collectionTypes = {
|
|
1919
2007
|
}
|
1920
2008
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1921
2009
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1922
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2010
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1923
2011
|
const document = await documentManager2.findOne(id, model, {
|
1924
2012
|
populate,
|
1925
2013
|
locale,
|
@@ -1941,7 +2029,7 @@ const collectionTypes = {
|
|
1941
2029
|
ctx.body = await strapiUtils.async.pipe(
|
1942
2030
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1943
2031
|
permissionChecker2.sanitizeOutput,
|
1944
|
-
(document2) =>
|
2032
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1945
2033
|
)(document);
|
1946
2034
|
});
|
1947
2035
|
},
|
@@ -1950,14 +2038,13 @@ const collectionTypes = {
|
|
1950
2038
|
const { id, model } = ctx.params;
|
1951
2039
|
const { body } = ctx.request;
|
1952
2040
|
const documentManager2 = getService$1("document-manager");
|
1953
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1954
2041
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1955
2042
|
if (permissionChecker2.cannot.discard()) {
|
1956
2043
|
return ctx.forbidden();
|
1957
2044
|
}
|
1958
2045
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1959
2046
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1960
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2047
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1961
2048
|
const document = await documentManager2.findOne(id, model, {
|
1962
2049
|
populate,
|
1963
2050
|
locale,
|
@@ -1972,14 +2059,14 @@ const collectionTypes = {
|
|
1972
2059
|
ctx.body = await strapiUtils.async.pipe(
|
1973
2060
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1974
2061
|
permissionChecker2.sanitizeOutput,
|
1975
|
-
(document2) =>
|
2062
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1976
2063
|
)(document);
|
1977
2064
|
},
|
1978
2065
|
async bulkDelete(ctx) {
|
1979
2066
|
const { userAbility } = ctx.state;
|
1980
2067
|
const { model } = ctx.params;
|
1981
2068
|
const { query, body } = ctx.request;
|
1982
|
-
const {
|
2069
|
+
const { documentIds } = body;
|
1983
2070
|
await validateBulkActionInput(body);
|
1984
2071
|
const documentManager2 = getService$1("document-manager");
|
1985
2072
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1987,14 +2074,22 @@ const collectionTypes = {
|
|
1987
2074
|
return ctx.forbidden();
|
1988
2075
|
}
|
1989
2076
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1990
|
-
const
|
1991
|
-
const
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
2077
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2078
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2079
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2080
|
+
populate,
|
2081
|
+
locale
|
2082
|
+
});
|
2083
|
+
if (documentLocales.length === 0) {
|
2084
|
+
return ctx.notFound();
|
2085
|
+
}
|
2086
|
+
for (const document of documentLocales) {
|
2087
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2088
|
+
return ctx.forbidden();
|
1995
2089
|
}
|
1996
|
-
}
|
1997
|
-
const
|
2090
|
+
}
|
2091
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2092
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1998
2093
|
ctx.body = { count };
|
1999
2094
|
},
|
2000
2095
|
async countDraftRelations(ctx) {
|
@@ -2007,7 +2102,7 @@ const collectionTypes = {
|
|
2007
2102
|
}
|
2008
2103
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2009
2104
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2010
|
-
const { locale, status
|
2105
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2011
2106
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2012
2107
|
if (!entity) {
|
2013
2108
|
return ctx.notFound();
|
@@ -2022,7 +2117,7 @@ const collectionTypes = {
|
|
2022
2117
|
},
|
2023
2118
|
async countManyEntriesDraftRelations(ctx) {
|
2024
2119
|
const { userAbility } = ctx.state;
|
2025
|
-
const ids = ctx.request.query.
|
2120
|
+
const ids = ctx.request.query.documentIds;
|
2026
2121
|
const locale = ctx.request.query.locale;
|
2027
2122
|
const { model } = ctx.params;
|
2028
2123
|
const documentManager2 = getService$1("document-manager");
|
@@ -2030,16 +2125,16 @@ const collectionTypes = {
|
|
2030
2125
|
if (permissionChecker2.cannot.read()) {
|
2031
2126
|
return ctx.forbidden();
|
2032
2127
|
}
|
2033
|
-
const
|
2128
|
+
const documents = await documentManager2.findMany(
|
2034
2129
|
{
|
2035
2130
|
filters: {
|
2036
|
-
|
2131
|
+
documentId: ids
|
2037
2132
|
},
|
2038
2133
|
locale
|
2039
2134
|
},
|
2040
2135
|
model
|
2041
2136
|
);
|
2042
|
-
if (!
|
2137
|
+
if (!documents) {
|
2043
2138
|
return ctx.notFound();
|
2044
2139
|
}
|
2045
2140
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2535,7 +2630,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2535
2630
|
throw new strapiUtils.errors.ForbiddenError();
|
2536
2631
|
}
|
2537
2632
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2538
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2633
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2539
2634
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2540
2635
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2541
2636
|
// Find the first document to check if it exists
|
@@ -2572,12 +2667,11 @@ const singleTypes = {
|
|
2572
2667
|
const { model } = ctx.params;
|
2573
2668
|
const { query = {} } = ctx.request;
|
2574
2669
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2575
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2576
2670
|
if (permissionChecker2.cannot.read()) {
|
2577
2671
|
return ctx.forbidden();
|
2578
2672
|
}
|
2579
2673
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2580
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2674
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2581
2675
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2582
2676
|
if (!version) {
|
2583
2677
|
if (permissionChecker2.cannot.create()) {
|
@@ -2587,8 +2681,10 @@ const singleTypes = {
|
|
2587
2681
|
if (!document) {
|
2588
2682
|
return ctx.notFound();
|
2589
2683
|
}
|
2590
|
-
const { meta } = await
|
2684
|
+
const { meta } = await formatDocumentWithMetadata(
|
2685
|
+
permissionChecker2,
|
2591
2686
|
model,
|
2687
|
+
// @ts-expect-error - fix types
|
2592
2688
|
{ id: document.documentId, locale, publishedAt: null },
|
2593
2689
|
{ availableLocales: true, availableStatus: false }
|
2594
2690
|
);
|
@@ -2599,16 +2695,15 @@ const singleTypes = {
|
|
2599
2695
|
return ctx.forbidden();
|
2600
2696
|
}
|
2601
2697
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2602
|
-
ctx.body = await
|
2698
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2603
2699
|
},
|
2604
2700
|
async createOrUpdate(ctx) {
|
2605
2701
|
const { userAbility } = ctx.state;
|
2606
2702
|
const { model } = ctx.params;
|
2607
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2608
2703
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2609
2704
|
const document = await createOrUpdateDocument(ctx);
|
2610
2705
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2611
|
-
ctx.body = await
|
2706
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2612
2707
|
},
|
2613
2708
|
async delete(ctx) {
|
2614
2709
|
const { userAbility } = ctx.state;
|
@@ -2621,7 +2716,7 @@ const singleTypes = {
|
|
2621
2716
|
}
|
2622
2717
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2623
2718
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2624
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2719
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2625
2720
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2626
2721
|
populate,
|
2627
2722
|
locale
|
@@ -2644,7 +2739,6 @@ const singleTypes = {
|
|
2644
2739
|
const { model } = ctx.params;
|
2645
2740
|
const { query = {} } = ctx.request;
|
2646
2741
|
const documentManager2 = getService$1("document-manager");
|
2647
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2648
2742
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2649
2743
|
if (permissionChecker2.cannot.publish()) {
|
2650
2744
|
return ctx.forbidden();
|
@@ -2659,11 +2753,12 @@ const singleTypes = {
|
|
2659
2753
|
if (permissionChecker2.cannot.publish(document)) {
|
2660
2754
|
throw new strapiUtils.errors.ForbiddenError();
|
2661
2755
|
}
|
2662
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2663
|
-
|
2756
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2757
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2758
|
+
return publishResult.at(0);
|
2664
2759
|
});
|
2665
2760
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2666
|
-
ctx.body = await
|
2761
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2667
2762
|
},
|
2668
2763
|
async unpublish(ctx) {
|
2669
2764
|
const { userAbility } = ctx.state;
|
@@ -2673,7 +2768,6 @@ const singleTypes = {
|
|
2673
2768
|
query = {}
|
2674
2769
|
} = ctx.request;
|
2675
2770
|
const documentManager2 = getService$1("document-manager");
|
2676
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2677
2771
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2678
2772
|
if (permissionChecker2.cannot.unpublish()) {
|
2679
2773
|
return ctx.forbidden();
|
@@ -2682,7 +2776,7 @@ const singleTypes = {
|
|
2682
2776
|
return ctx.forbidden();
|
2683
2777
|
}
|
2684
2778
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2685
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2779
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2686
2780
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2687
2781
|
if (!document) {
|
2688
2782
|
return ctx.notFound();
|
@@ -2700,7 +2794,7 @@ const singleTypes = {
|
|
2700
2794
|
ctx.body = await strapiUtils.async.pipe(
|
2701
2795
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2702
2796
|
permissionChecker2.sanitizeOutput,
|
2703
|
-
(document2) =>
|
2797
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2704
2798
|
)(document);
|
2705
2799
|
});
|
2706
2800
|
},
|
@@ -2709,13 +2803,12 @@ const singleTypes = {
|
|
2709
2803
|
const { model } = ctx.params;
|
2710
2804
|
const { body, query = {} } = ctx.request;
|
2711
2805
|
const documentManager2 = getService$1("document-manager");
|
2712
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2713
2806
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2714
2807
|
if (permissionChecker2.cannot.discard()) {
|
2715
2808
|
return ctx.forbidden();
|
2716
2809
|
}
|
2717
2810
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2718
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2811
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2719
2812
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2720
2813
|
if (!document) {
|
2721
2814
|
return ctx.notFound();
|
@@ -2726,7 +2819,7 @@ const singleTypes = {
|
|
2726
2819
|
ctx.body = await strapiUtils.async.pipe(
|
2727
2820
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2728
2821
|
permissionChecker2.sanitizeOutput,
|
2729
|
-
(document2) =>
|
2822
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2730
2823
|
)(document);
|
2731
2824
|
},
|
2732
2825
|
async countDraftRelations(ctx) {
|
@@ -2735,7 +2828,7 @@ const singleTypes = {
|
|
2735
2828
|
const { query } = ctx.request;
|
2736
2829
|
const documentManager2 = getService$1("document-manager");
|
2737
2830
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2738
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2831
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2739
2832
|
if (permissionChecker2.cannot.read()) {
|
2740
2833
|
return ctx.forbidden();
|
2741
2834
|
}
|
@@ -2756,7 +2849,7 @@ const uid$1 = {
|
|
2756
2849
|
async generateUID(ctx) {
|
2757
2850
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2758
2851
|
const { query = {} } = ctx.request;
|
2759
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2852
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2760
2853
|
await validateUIDField(contentTypeUID, field);
|
2761
2854
|
const uidService = getService$1("uid");
|
2762
2855
|
ctx.body = {
|
@@ -2768,7 +2861,7 @@ const uid$1 = {
|
|
2768
2861
|
ctx.request.body
|
2769
2862
|
);
|
2770
2863
|
const { query = {} } = ctx.request;
|
2771
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2864
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2772
2865
|
await validateUIDField(contentTypeUID, field);
|
2773
2866
|
const uidService = getService$1("uid");
|
2774
2867
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3559,7 +3652,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3559
3652
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3560
3653
|
}
|
3561
3654
|
});
|
3562
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
|
3655
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
|
3563
3656
|
const { isAnyToMany } = strapiUtils__default.default.relations;
|
3564
3657
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
|
3565
3658
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3650,6 +3743,42 @@ const getDeepPopulate = (uid2, {
|
|
3650
3743
|
{}
|
3651
3744
|
);
|
3652
3745
|
};
|
3746
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3747
|
+
initialPopulate = {},
|
3748
|
+
countMany = false,
|
3749
|
+
countOne = false,
|
3750
|
+
maxLevel = Infinity
|
3751
|
+
} = {}, level = 1) => {
|
3752
|
+
if (level > maxLevel) {
|
3753
|
+
return {};
|
3754
|
+
}
|
3755
|
+
const model = strapi.getModel(uid2);
|
3756
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3757
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3758
|
+
return populateAcc;
|
3759
|
+
}
|
3760
|
+
if (isScalarAttribute(attribute)) {
|
3761
|
+
return fp.merge(populateAcc, {
|
3762
|
+
[attributeName]: true
|
3763
|
+
});
|
3764
|
+
}
|
3765
|
+
return fp.merge(
|
3766
|
+
populateAcc,
|
3767
|
+
getPopulateFor(
|
3768
|
+
attributeName,
|
3769
|
+
model,
|
3770
|
+
{
|
3771
|
+
// @ts-expect-error - improve types
|
3772
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3773
|
+
countMany,
|
3774
|
+
countOne,
|
3775
|
+
maxLevel
|
3776
|
+
},
|
3777
|
+
level
|
3778
|
+
)
|
3779
|
+
);
|
3780
|
+
}, {});
|
3781
|
+
};
|
3653
3782
|
const getDeepPopulateDraftCount = (uid2) => {
|
3654
3783
|
const model = strapi.getModel(uid2);
|
3655
3784
|
let hasRelations = false;
|
@@ -3657,6 +3786,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3657
3786
|
const attribute = model.attributes[attributeName];
|
3658
3787
|
switch (attribute.type) {
|
3659
3788
|
case "relation": {
|
3789
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3790
|
+
if (isMorphRelation) {
|
3791
|
+
break;
|
3792
|
+
}
|
3660
3793
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3661
3794
|
populateAcc[attributeName] = {
|
3662
3795
|
count: true,
|
@@ -3671,22 +3804,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3671
3804
|
attribute.component
|
3672
3805
|
);
|
3673
3806
|
if (childHasRelations) {
|
3674
|
-
populateAcc[attributeName] = {
|
3807
|
+
populateAcc[attributeName] = {
|
3808
|
+
populate: populate2
|
3809
|
+
};
|
3675
3810
|
hasRelations = true;
|
3676
3811
|
}
|
3677
3812
|
break;
|
3678
3813
|
}
|
3679
3814
|
case "dynamiczone": {
|
3680
|
-
const
|
3681
|
-
const { populate:
|
3682
|
-
if (
|
3815
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3816
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3817
|
+
if (componentHasRelations) {
|
3683
3818
|
hasRelations = true;
|
3684
|
-
return
|
3819
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3685
3820
|
}
|
3686
3821
|
return acc;
|
3687
3822
|
}, {});
|
3688
|
-
if (!fp.isEmpty(
|
3689
|
-
populateAcc[attributeName] = {
|
3823
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
3824
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3690
3825
|
}
|
3691
3826
|
break;
|
3692
3827
|
}
|
@@ -3878,41 +4013,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3878
4013
|
"updatedBy",
|
3879
4014
|
"status"
|
3880
4015
|
];
|
3881
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
4016
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
4017
|
+
"id",
|
4018
|
+
"locale",
|
4019
|
+
"updatedAt",
|
4020
|
+
"createdAt",
|
4021
|
+
"status",
|
4022
|
+
"publishedAt",
|
4023
|
+
"documentId"
|
4024
|
+
];
|
3882
4025
|
const CONTENT_MANAGER_STATUS = {
|
3883
4026
|
PUBLISHED: "published",
|
3884
4027
|
DRAFT: "draft",
|
3885
4028
|
MODIFIED: "modified"
|
3886
4029
|
};
|
3887
|
-
const
|
3888
|
-
if (!
|
4030
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
4031
|
+
if (!version || !version.updatedAt) {
|
3889
4032
|
return false;
|
3890
4033
|
}
|
3891
|
-
const
|
3892
|
-
const
|
3893
|
-
|
3894
|
-
return difference <= threshold;
|
4034
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
4035
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
4036
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3895
4037
|
};
|
3896
4038
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3897
4039
|
/**
|
3898
4040
|
* Returns available locales of a document for the current status
|
3899
4041
|
*/
|
3900
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4042
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3901
4043
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3902
4044
|
delete versionsByLocale[version.locale];
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
4045
|
+
const model = strapi2.getModel(uid2);
|
4046
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4047
|
+
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4048
|
+
({ key }, { remove }) => {
|
4049
|
+
if (keysToKeep.includes(key)) {
|
4050
|
+
return;
|
4051
|
+
}
|
4052
|
+
remove(key);
|
4053
|
+
},
|
4054
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4055
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4056
|
+
localeVersion
|
4057
|
+
);
|
4058
|
+
const mappingResult = await strapiUtils.async.map(
|
4059
|
+
Object.values(versionsByLocale),
|
4060
|
+
async (localeVersions) => {
|
4061
|
+
const mappedLocaleVersions = await strapiUtils.async.map(
|
4062
|
+
localeVersions,
|
4063
|
+
traversalFunction
|
4064
|
+
);
|
4065
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4066
|
+
return mappedLocaleVersions[0];
|
4067
|
+
}
|
4068
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
4069
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
4070
|
+
if (!draftVersion) {
|
4071
|
+
return;
|
4072
|
+
}
|
4073
|
+
return {
|
4074
|
+
...draftVersion,
|
4075
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4076
|
+
};
|
3906
4077
|
}
|
3907
|
-
|
3908
|
-
|
3909
|
-
if (!draftVersion)
|
3910
|
-
return;
|
3911
|
-
return {
|
3912
|
-
...fp.pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
|
3913
|
-
status: this.getStatus(draftVersion, otherVersions)
|
3914
|
-
};
|
3915
|
-
}).filter(Boolean);
|
4078
|
+
);
|
4079
|
+
return mappingResult.filter(Boolean);
|
3916
4080
|
},
|
3917
4081
|
/**
|
3918
4082
|
* Returns available status of a document for the current locale
|
@@ -3950,26 +4114,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3950
4114
|
});
|
3951
4115
|
},
|
3952
4116
|
getStatus(version, otherDocumentStatuses) {
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
4117
|
+
let draftVersion;
|
4118
|
+
let publishedVersion;
|
4119
|
+
if (version.publishedAt) {
|
4120
|
+
publishedVersion = version;
|
4121
|
+
} else {
|
4122
|
+
draftVersion = version;
|
3956
4123
|
}
|
3957
|
-
|
3958
|
-
|
3959
|
-
|
3960
|
-
|
3961
|
-
|
4124
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4125
|
+
if (otherVersion?.publishedAt) {
|
4126
|
+
publishedVersion = otherVersion;
|
4127
|
+
} else if (otherVersion) {
|
4128
|
+
draftVersion = otherVersion;
|
3962
4129
|
}
|
3963
|
-
if (
|
4130
|
+
if (!draftVersion)
|
3964
4131
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3965
|
-
|
3966
|
-
|
4132
|
+
if (!publishedVersion)
|
4133
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4134
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4135
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3967
4136
|
},
|
4137
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4138
|
+
// We could refactor this so the locales are only loaded when they're
|
4139
|
+
// needed. e.g. in the bulk locale action modal.
|
3968
4140
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4141
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3969
4142
|
const versions = await strapi2.db.query(uid2).findMany({
|
3970
4143
|
where: { documentId: version.documentId },
|
3971
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3972
4144
|
populate: {
|
4145
|
+
// Populate only fields that require validation for bulk locale actions
|
4146
|
+
...populate,
|
4147
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3973
4148
|
createdBy: {
|
3974
4149
|
select: ["id", "firstname", "lastname", "email"]
|
3975
4150
|
},
|
@@ -3978,7 +4153,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3978
4153
|
}
|
3979
4154
|
}
|
3980
4155
|
});
|
3981
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4156
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3982
4157
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3983
4158
|
return {
|
3984
4159
|
availableLocales: availableLocalesResult,
|
@@ -3991,8 +4166,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3991
4166
|
* - Available status of the document for the current locale
|
3992
4167
|
*/
|
3993
4168
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3994
|
-
if (!document)
|
3995
|
-
return
|
4169
|
+
if (!document) {
|
4170
|
+
return {
|
4171
|
+
data: document,
|
4172
|
+
meta: {
|
4173
|
+
availableLocales: [],
|
4174
|
+
availableStatus: []
|
4175
|
+
}
|
4176
|
+
};
|
4177
|
+
}
|
3996
4178
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
3997
4179
|
if (!hasDraftAndPublish) {
|
3998
4180
|
opts.availableStatus = false;
|
@@ -4042,26 +4224,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
4042
4224
|
}, 0);
|
4043
4225
|
};
|
4044
4226
|
const { ApplicationError } = strapiUtils.errors;
|
4045
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4046
4227
|
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
4047
4228
|
const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
|
4048
4229
|
const omitIdField = fp.omit("id");
|
4049
|
-
const emitEvent = async (uid2, event, document) => {
|
4050
|
-
const modelDef = strapi.getModel(uid2);
|
4051
|
-
const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
|
4052
|
-
{
|
4053
|
-
schema: modelDef,
|
4054
|
-
getModel(uid22) {
|
4055
|
-
return strapi.getModel(uid22);
|
4056
|
-
}
|
4057
|
-
},
|
4058
|
-
document
|
4059
|
-
);
|
4060
|
-
strapi.eventHub.emit(event, {
|
4061
|
-
model: modelDef.modelName,
|
4062
|
-
entry: sanitizedDocument
|
4063
|
-
});
|
4064
|
-
};
|
4065
4230
|
const documentManager = ({ strapi: strapi2 }) => {
|
4066
4231
|
return {
|
4067
4232
|
async findOne(id, uid2, opts = {}) {
|
@@ -4080,6 +4245,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4080
4245
|
} else if (opts.locale && opts.locale !== "*") {
|
4081
4246
|
where.locale = opts.locale;
|
4082
4247
|
}
|
4248
|
+
if (typeof opts.isPublished === "boolean") {
|
4249
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4250
|
+
}
|
4083
4251
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4084
4252
|
},
|
4085
4253
|
async findMany(opts, uid2) {
|
@@ -4087,20 +4255,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4087
4255
|
return strapi2.documents(uid2).findMany(params);
|
4088
4256
|
},
|
4089
4257
|
async findPage(opts, uid2) {
|
4090
|
-
const
|
4091
|
-
|
4258
|
+
const params = strapiUtils.pagination.withDefaultPagination(opts || {}, {
|
4259
|
+
maxLimit: 1e3
|
4260
|
+
});
|
4092
4261
|
const [documents, total = 0] = await Promise.all([
|
4093
|
-
strapi2.documents(uid2).findMany(
|
4094
|
-
strapi2.documents(uid2).count(
|
4262
|
+
strapi2.documents(uid2).findMany(params),
|
4263
|
+
strapi2.documents(uid2).count(params)
|
4095
4264
|
]);
|
4096
4265
|
return {
|
4097
4266
|
results: documents,
|
4098
|
-
pagination:
|
4099
|
-
page,
|
4100
|
-
pageSize,
|
4101
|
-
pageCount: Math.ceil(total / pageSize),
|
4102
|
-
total
|
4103
|
-
}
|
4267
|
+
pagination: strapiUtils.pagination.transformPagedPaginationInfo(params, total)
|
4104
4268
|
};
|
4105
4269
|
},
|
4106
4270
|
async create(uid2, opts = {}) {
|
@@ -4117,10 +4281,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4117
4281
|
async clone(id, body, uid2) {
|
4118
4282
|
const populate = await buildDeepPopulate(uid2);
|
4119
4283
|
const params = {
|
4120
|
-
data:
|
4121
|
-
...omitIdField(body),
|
4122
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4123
|
-
},
|
4284
|
+
data: omitIdField(body),
|
4124
4285
|
populate
|
4125
4286
|
};
|
4126
4287
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4146,70 +4307,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4146
4307
|
return {};
|
4147
4308
|
},
|
4148
4309
|
// FIXME: handle relations
|
4149
|
-
async deleteMany(
|
4150
|
-
const
|
4151
|
-
|
4152
|
-
|
4153
|
-
}
|
4154
|
-
return { count: docs.length };
|
4310
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4311
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4312
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4313
|
+
});
|
4314
|
+
return { count: deletedEntries.length };
|
4155
4315
|
},
|
4156
4316
|
async publish(id, uid2, opts = {}) {
|
4157
4317
|
const populate = await buildDeepPopulate(uid2);
|
4158
4318
|
const params = { ...opts, populate };
|
4159
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4319
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4160
4320
|
},
|
4161
|
-
async publishMany(
|
4162
|
-
|
4163
|
-
|
4164
|
-
|
4165
|
-
|
4166
|
-
|
4167
|
-
|
4168
|
-
strapi2.getModel(uid2),
|
4169
|
-
document,
|
4170
|
-
void 0,
|
4171
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4172
|
-
document
|
4173
|
-
);
|
4174
|
-
})
|
4175
|
-
);
|
4176
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4177
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4178
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4179
|
-
const populate = await buildDeepPopulate(uid2);
|
4180
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4181
|
-
where: filters,
|
4182
|
-
data
|
4183
|
-
});
|
4184
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4185
|
-
where: filters,
|
4186
|
-
populate
|
4321
|
+
async publishMany(uid2, documentIds, locale) {
|
4322
|
+
return strapi2.db.transaction(async () => {
|
4323
|
+
const results = await Promise.all(
|
4324
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4325
|
+
);
|
4326
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4327
|
+
return publishedEntitiesCount;
|
4187
4328
|
});
|
4188
|
-
await Promise.all(
|
4189
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4190
|
-
);
|
4191
|
-
return publishedEntitiesCount;
|
4192
4329
|
},
|
4193
|
-
async unpublishMany(
|
4194
|
-
|
4195
|
-
return
|
4196
|
-
|
4197
|
-
|
4198
|
-
|
4199
|
-
|
4200
|
-
const populate = await buildDeepPopulate(uid2);
|
4201
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4202
|
-
where: filters,
|
4203
|
-
data
|
4204
|
-
});
|
4205
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4206
|
-
where: filters,
|
4207
|
-
populate
|
4330
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4331
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4332
|
+
return Promise.all(
|
4333
|
+
documentIds.map(
|
4334
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4335
|
+
)
|
4336
|
+
);
|
4208
4337
|
});
|
4209
|
-
|
4210
|
-
|
4211
|
-
);
|
4212
|
-
return unpublishedEntitiesCount;
|
4338
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4339
|
+
return { count: unpublishedEntitiesCount };
|
4213
4340
|
},
|
4214
4341
|
async unpublish(id, uid2, opts = {}) {
|
4215
4342
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4234,16 +4361,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4234
4361
|
}
|
4235
4362
|
return sumDraftCounts(document, uid2);
|
4236
4363
|
},
|
4237
|
-
async countManyEntriesDraftRelations(
|
4364
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4238
4365
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4239
4366
|
if (!hasRelations) {
|
4240
4367
|
return 0;
|
4241
4368
|
}
|
4369
|
+
let localeFilter = {};
|
4370
|
+
if (locale) {
|
4371
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4372
|
+
}
|
4242
4373
|
const entities = await strapi2.db.query(uid2).findMany({
|
4243
4374
|
populate,
|
4244
4375
|
where: {
|
4245
|
-
|
4246
|
-
...
|
4376
|
+
documentId: { $in: documentIds },
|
4377
|
+
...localeFilter
|
4247
4378
|
}
|
4248
4379
|
});
|
4249
4380
|
const totalNumberDraftRelations = entities.reduce(
|