@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.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1,
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy
|
1
|
+
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
|
2
|
+
import { pick, omit, difference, castArray, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
54
54
|
return ctx.forbidden();
|
55
55
|
}
|
56
56
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
57
|
-
const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
|
57
|
+
const { results, pagination: pagination2 } = await getService(strapi2, "history").findVersionsPage({
|
58
58
|
query: {
|
59
59
|
...query,
|
60
60
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -73,7 +73,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
73
73
|
);
|
74
74
|
return {
|
75
75
|
data: sanitizedResults,
|
76
|
-
meta: { pagination }
|
76
|
+
meta: { pagination: pagination2 }
|
77
77
|
};
|
78
78
|
},
|
79
79
|
async restoreVersion(ctx) {
|
@@ -200,20 +200,25 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
200
200
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
201
201
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
202
202
|
};
|
203
|
-
const getDeepPopulate2 = (uid2) => {
|
203
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
204
204
|
const model = strapi2.getModel(uid2);
|
205
205
|
const attributes = Object.entries(model.attributes);
|
206
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
206
207
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
207
208
|
switch (attribute.type) {
|
208
209
|
case "relation": {
|
210
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
211
|
+
if (isMorphRelation) {
|
212
|
+
break;
|
213
|
+
}
|
209
214
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
210
215
|
if (isVisible2) {
|
211
|
-
acc[attributeName] = {
|
216
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
212
217
|
}
|
213
218
|
break;
|
214
219
|
}
|
215
220
|
case "media": {
|
216
|
-
acc[attributeName] = {
|
221
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
217
222
|
break;
|
218
223
|
}
|
219
224
|
case "component": {
|
@@ -309,7 +314,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
309
314
|
},
|
310
315
|
async findVersionsPage(params) {
|
311
316
|
const locale = params.query.locale || await serviceUtils.getDefaultLocale();
|
312
|
-
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
317
|
+
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
313
318
|
query.findPage({
|
314
319
|
...params.query,
|
315
320
|
where: {
|
@@ -408,7 +413,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
408
413
|
);
|
409
414
|
return {
|
410
415
|
results: formattedResults,
|
411
|
-
pagination
|
416
|
+
pagination: pagination2
|
412
417
|
};
|
413
418
|
},
|
414
419
|
async restoreVersion(versionId) {
|
@@ -464,13 +469,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
464
469
|
}
|
465
470
|
};
|
466
471
|
};
|
472
|
+
const shouldCreateHistoryVersion = (context) => {
|
473
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
474
|
+
return false;
|
475
|
+
}
|
476
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
477
|
+
return false;
|
478
|
+
}
|
479
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
480
|
+
return false;
|
481
|
+
}
|
482
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
483
|
+
return false;
|
484
|
+
}
|
485
|
+
return true;
|
486
|
+
};
|
487
|
+
const getSchemas = (uid2) => {
|
488
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
489
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
490
|
+
(currentComponentSchemas, key) => {
|
491
|
+
const fieldSchema = attributesSchema[key];
|
492
|
+
if (fieldSchema.type === "component") {
|
493
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
494
|
+
return {
|
495
|
+
...currentComponentSchemas,
|
496
|
+
[fieldSchema.component]: componentSchema
|
497
|
+
};
|
498
|
+
}
|
499
|
+
return currentComponentSchemas;
|
500
|
+
},
|
501
|
+
{}
|
502
|
+
);
|
503
|
+
return {
|
504
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
505
|
+
componentsSchemas
|
506
|
+
};
|
507
|
+
};
|
467
508
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
509
|
const state = {
|
469
510
|
deleteExpiredJob: null,
|
470
511
|
isInitialized: false
|
471
512
|
};
|
472
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
473
|
-
const historyService = getService(strapi2, "history");
|
474
513
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
475
514
|
return {
|
476
515
|
async bootstrap() {
|
@@ -478,60 +517,51 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
478
517
|
return;
|
479
518
|
}
|
480
519
|
strapi2.documents.use(async (context, next) => {
|
481
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
482
|
-
return next();
|
483
|
-
}
|
484
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
485
|
-
return next();
|
486
|
-
}
|
487
|
-
const contentTypeUid = context.contentType.uid;
|
488
|
-
if (!contentTypeUid.startsWith("api::")) {
|
489
|
-
return next();
|
490
|
-
}
|
491
520
|
const result = await next();
|
492
|
-
|
521
|
+
if (!shouldCreateHistoryVersion(context)) {
|
522
|
+
return result;
|
523
|
+
}
|
524
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
493
525
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
494
|
-
const
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
526
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
527
|
+
if (!locales.length) {
|
528
|
+
return result;
|
529
|
+
}
|
530
|
+
const uid2 = context.contentType.uid;
|
531
|
+
const schemas = getSchemas(uid2);
|
532
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
533
|
+
where: {
|
534
|
+
documentId,
|
535
|
+
locale: { $in: locales },
|
536
|
+
publishedAt: null
|
537
|
+
},
|
538
|
+
populate: serviceUtils.getDeepPopulate(
|
539
|
+
uid2,
|
540
|
+
true
|
541
|
+
/* use database syntax */
|
542
|
+
)
|
499
543
|
});
|
500
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
501
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
502
|
-
const componentsSchemas = Object.keys(
|
503
|
-
attributesSchema
|
504
|
-
).reduce((currentComponentSchemas, key) => {
|
505
|
-
const fieldSchema = attributesSchema[key];
|
506
|
-
if (fieldSchema.type === "component") {
|
507
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
508
|
-
return {
|
509
|
-
...currentComponentSchemas,
|
510
|
-
[fieldSchema.component]: componentSchema
|
511
|
-
};
|
512
|
-
}
|
513
|
-
return currentComponentSchemas;
|
514
|
-
}, {});
|
515
544
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
516
|
-
onCommit(() => {
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
545
|
+
onCommit(async () => {
|
546
|
+
for (const entry of localeEntries) {
|
547
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
548
|
+
await getService(strapi2, "history").createVersion({
|
549
|
+
contentType: uid2,
|
550
|
+
data: omit(FIELDS_TO_IGNORE, entry),
|
551
|
+
relatedDocumentId: documentId,
|
552
|
+
locale: entry.locale,
|
553
|
+
status,
|
554
|
+
...schemas
|
555
|
+
});
|
556
|
+
}
|
526
557
|
});
|
527
558
|
});
|
528
559
|
return result;
|
529
560
|
});
|
530
|
-
const retentionDays = serviceUtils.getRetentionDays();
|
531
561
|
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
532
|
-
const retentionDaysInMilliseconds =
|
562
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
533
563
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
534
|
-
query.deleteMany({
|
564
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
535
565
|
where: {
|
536
566
|
created_at: {
|
537
567
|
$lt: expirationDate.toISOString()
|
@@ -1452,7 +1482,7 @@ const { PaginationError, ValidationError } = errors;
|
|
1452
1482
|
const TYPES = ["singleType", "collectionType"];
|
1453
1483
|
const kindSchema = yup$1.string().oneOf(TYPES).nullable();
|
1454
1484
|
const bulkActionInputSchema = yup$1.object({
|
1455
|
-
|
1485
|
+
documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
|
1456
1486
|
}).required();
|
1457
1487
|
const generateUIDInputSchema = yup$1.object({
|
1458
1488
|
contentTypeUID: yup$1.string().required(),
|
@@ -1551,15 +1581,49 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1551
1581
|
}
|
1552
1582
|
}, body);
|
1553
1583
|
};
|
1554
|
-
const
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1584
|
+
const singleLocaleSchema = yup$1.string().nullable();
|
1585
|
+
const multipleLocaleSchema = yup$1.lazy(
|
1586
|
+
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1587
|
+
);
|
1588
|
+
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1589
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1590
|
+
const { allowMultipleLocales } = opts;
|
1591
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1592
|
+
const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1593
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1594
|
+
const schema = yup$1.object().shape({
|
1595
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1596
|
+
status: statusSchema
|
1597
|
+
});
|
1598
|
+
try {
|
1599
|
+
await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1600
|
+
return { locale, status, ...rest };
|
1601
|
+
} catch (error) {
|
1602
|
+
throw new errors.ValidationError(`Validation error: ${error.message}`);
|
1561
1603
|
}
|
1562
|
-
|
1604
|
+
};
|
1605
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1606
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1607
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1608
|
+
let {
|
1609
|
+
meta: { availableLocales, availableStatus }
|
1610
|
+
} = serviceOutput;
|
1611
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1612
|
+
availableLocales = await async.map(
|
1613
|
+
availableLocales,
|
1614
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1615
|
+
);
|
1616
|
+
availableStatus = await async.map(
|
1617
|
+
availableStatus,
|
1618
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1619
|
+
);
|
1620
|
+
return {
|
1621
|
+
...serviceOutput,
|
1622
|
+
meta: {
|
1623
|
+
availableLocales,
|
1624
|
+
availableStatus
|
1625
|
+
}
|
1626
|
+
};
|
1563
1627
|
};
|
1564
1628
|
const createDocument = async (ctx, opts) => {
|
1565
1629
|
const { userAbility, user } = ctx.state;
|
@@ -1574,7 +1638,7 @@ const createDocument = async (ctx, opts) => {
|
|
1574
1638
|
const setCreator = setCreatorFields({ user });
|
1575
1639
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1576
1640
|
const sanitizedBody = await sanitizeFn(body);
|
1577
|
-
const { locale, status
|
1641
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1578
1642
|
return documentManager2.create(model, {
|
1579
1643
|
data: sanitizedBody,
|
1580
1644
|
locale,
|
@@ -1593,7 +1657,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1593
1657
|
}
|
1594
1658
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1595
1659
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1596
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1660
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1597
1661
|
const [documentVersion, documentExists] = await Promise.all([
|
1598
1662
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1599
1663
|
documentManager2.exists(model, id)
|
@@ -1631,8 +1695,8 @@ const collectionTypes = {
|
|
1631
1695
|
}
|
1632
1696
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1633
1697
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1634
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1635
|
-
const { results: documents, pagination } = await documentManager2.findPage(
|
1698
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1699
|
+
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1636
1700
|
{ ...permissionQuery, populate, locale, status },
|
1637
1701
|
model
|
1638
1702
|
);
|
@@ -1653,21 +1717,20 @@ const collectionTypes = {
|
|
1653
1717
|
);
|
1654
1718
|
ctx.body = {
|
1655
1719
|
results,
|
1656
|
-
pagination
|
1720
|
+
pagination: pagination2
|
1657
1721
|
};
|
1658
1722
|
},
|
1659
1723
|
async findOne(ctx) {
|
1660
1724
|
const { userAbility } = ctx.state;
|
1661
1725
|
const { model, id } = ctx.params;
|
1662
1726
|
const documentManager2 = getService$1("document-manager");
|
1663
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1664
1727
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1665
1728
|
if (permissionChecker2.cannot.read()) {
|
1666
1729
|
return ctx.forbidden();
|
1667
1730
|
}
|
1668
1731
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1669
1732
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1670
|
-
const { locale, status
|
1733
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1671
1734
|
const version = await documentManager2.findOne(id, model, {
|
1672
1735
|
populate,
|
1673
1736
|
locale,
|
@@ -1678,8 +1741,10 @@ const collectionTypes = {
|
|
1678
1741
|
if (!exists) {
|
1679
1742
|
return ctx.notFound();
|
1680
1743
|
}
|
1681
|
-
const { meta } = await
|
1744
|
+
const { meta } = await formatDocumentWithMetadata(
|
1745
|
+
permissionChecker2,
|
1682
1746
|
model,
|
1747
|
+
// @ts-expect-error TODO: fix
|
1683
1748
|
{ id, locale, publishedAt: null },
|
1684
1749
|
{ availableLocales: true, availableStatus: false }
|
1685
1750
|
);
|
@@ -1690,12 +1755,11 @@ const collectionTypes = {
|
|
1690
1755
|
return ctx.forbidden();
|
1691
1756
|
}
|
1692
1757
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1693
|
-
ctx.body = await
|
1758
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1694
1759
|
},
|
1695
1760
|
async create(ctx) {
|
1696
1761
|
const { userAbility } = ctx.state;
|
1697
1762
|
const { model } = ctx.params;
|
1698
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1699
1763
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1700
1764
|
const [totalEntries, document] = await Promise.all([
|
1701
1765
|
strapi.db.query(model).count(),
|
@@ -1703,7 +1767,7 @@ const collectionTypes = {
|
|
1703
1767
|
]);
|
1704
1768
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1705
1769
|
ctx.status = 201;
|
1706
|
-
ctx.body = await
|
1770
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1707
1771
|
// Empty metadata as it's not relevant for a new document
|
1708
1772
|
availableLocales: false,
|
1709
1773
|
availableStatus: false
|
@@ -1717,25 +1781,23 @@ const collectionTypes = {
|
|
1717
1781
|
async update(ctx) {
|
1718
1782
|
const { userAbility } = ctx.state;
|
1719
1783
|
const { model } = ctx.params;
|
1720
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1721
1784
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1722
1785
|
const updatedVersion = await updateDocument(ctx);
|
1723
1786
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1724
|
-
ctx.body = await
|
1787
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1725
1788
|
},
|
1726
1789
|
async clone(ctx) {
|
1727
1790
|
const { userAbility, user } = ctx.state;
|
1728
1791
|
const { model, sourceId: id } = ctx.params;
|
1729
1792
|
const { body } = ctx.request;
|
1730
1793
|
const documentManager2 = getService$1("document-manager");
|
1731
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1732
1794
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1733
1795
|
if (permissionChecker2.cannot.create()) {
|
1734
1796
|
return ctx.forbidden();
|
1735
1797
|
}
|
1736
1798
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1737
1799
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1738
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1800
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1739
1801
|
const document = await documentManager2.findOne(id, model, {
|
1740
1802
|
populate,
|
1741
1803
|
locale,
|
@@ -1751,7 +1813,7 @@ const collectionTypes = {
|
|
1751
1813
|
const sanitizedBody = await sanitizeFn(body);
|
1752
1814
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1753
1815
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1754
|
-
ctx.body = await
|
1816
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1755
1817
|
// Empty metadata as it's not relevant for a new document
|
1756
1818
|
availableLocales: false,
|
1757
1819
|
availableStatus: false
|
@@ -1780,7 +1842,7 @@ const collectionTypes = {
|
|
1780
1842
|
}
|
1781
1843
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1782
1844
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1783
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1845
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1784
1846
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1785
1847
|
if (documentLocales.length === 0) {
|
1786
1848
|
return ctx.notFound();
|
@@ -1802,7 +1864,6 @@ const collectionTypes = {
|
|
1802
1864
|
const { id, model } = ctx.params;
|
1803
1865
|
const { body } = ctx.request;
|
1804
1866
|
const documentManager2 = getService$1("document-manager");
|
1805
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1806
1867
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1807
1868
|
if (permissionChecker2.cannot.publish()) {
|
1808
1869
|
return ctx.forbidden();
|
@@ -1810,25 +1871,46 @@ const collectionTypes = {
|
|
1810
1871
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1811
1872
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1812
1873
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1813
|
-
|
1874
|
+
let document;
|
1875
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1876
|
+
const isCreate = isNil$1(id);
|
1877
|
+
if (isCreate) {
|
1878
|
+
if (permissionChecker2.cannot.create()) {
|
1879
|
+
throw new errors.ForbiddenError();
|
1880
|
+
}
|
1881
|
+
document = await createDocument(ctx, { populate });
|
1882
|
+
}
|
1883
|
+
const isUpdate = !isCreate;
|
1884
|
+
if (isUpdate) {
|
1885
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
1886
|
+
if (!document) {
|
1887
|
+
throw new errors.NotFoundError("Document not found");
|
1888
|
+
}
|
1889
|
+
if (permissionChecker2.can.update(document)) {
|
1890
|
+
await updateDocument(ctx);
|
1891
|
+
}
|
1892
|
+
}
|
1814
1893
|
if (permissionChecker2.cannot.publish(document)) {
|
1815
1894
|
throw new errors.ForbiddenError();
|
1816
1895
|
}
|
1817
|
-
const
|
1818
|
-
return documentManager2.publish(document.documentId, model, {
|
1896
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1819
1897
|
locale
|
1820
1898
|
// TODO: Allow setting creator fields on publish
|
1821
1899
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1822
1900
|
});
|
1901
|
+
if (!publishResult || publishResult.length === 0) {
|
1902
|
+
throw new errors.NotFoundError("Document not found or already published.");
|
1903
|
+
}
|
1904
|
+
return publishResult[0];
|
1823
1905
|
});
|
1824
1906
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1825
|
-
ctx.body = await
|
1907
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1826
1908
|
},
|
1827
1909
|
async bulkPublish(ctx) {
|
1828
1910
|
const { userAbility } = ctx.state;
|
1829
1911
|
const { model } = ctx.params;
|
1830
1912
|
const { body } = ctx.request;
|
1831
|
-
const {
|
1913
|
+
const { documentIds } = body;
|
1832
1914
|
await validateBulkActionInput(body);
|
1833
1915
|
const documentManager2 = getService$1("document-manager");
|
1834
1916
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1837,8 +1919,13 @@ const collectionTypes = {
|
|
1837
1919
|
}
|
1838
1920
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1839
1921
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1840
|
-
const
|
1841
|
-
|
1922
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1923
|
+
allowMultipleLocales: true
|
1924
|
+
});
|
1925
|
+
const entityPromises = documentIds.map(
|
1926
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1927
|
+
);
|
1928
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1842
1929
|
for (const entity of entities) {
|
1843
1930
|
if (!entity) {
|
1844
1931
|
return ctx.notFound();
|
@@ -1847,24 +1934,25 @@ const collectionTypes = {
|
|
1847
1934
|
return ctx.forbidden();
|
1848
1935
|
}
|
1849
1936
|
}
|
1850
|
-
const
|
1937
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1851
1938
|
ctx.body = { count };
|
1852
1939
|
},
|
1853
1940
|
async bulkUnpublish(ctx) {
|
1854
1941
|
const { userAbility } = ctx.state;
|
1855
1942
|
const { model } = ctx.params;
|
1856
1943
|
const { body } = ctx.request;
|
1857
|
-
const {
|
1944
|
+
const { documentIds } = body;
|
1858
1945
|
await validateBulkActionInput(body);
|
1859
1946
|
const documentManager2 = getService$1("document-manager");
|
1860
1947
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1861
1948
|
if (permissionChecker2.cannot.unpublish()) {
|
1862
1949
|
return ctx.forbidden();
|
1863
1950
|
}
|
1864
|
-
const
|
1865
|
-
const
|
1866
|
-
|
1867
|
-
|
1951
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1952
|
+
const entityPromises = documentIds.map(
|
1953
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1954
|
+
);
|
1955
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1868
1956
|
for (const entity of entities) {
|
1869
1957
|
if (!entity) {
|
1870
1958
|
return ctx.notFound();
|
@@ -1873,7 +1961,8 @@ const collectionTypes = {
|
|
1873
1961
|
return ctx.forbidden();
|
1874
1962
|
}
|
1875
1963
|
}
|
1876
|
-
const
|
1964
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1965
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1877
1966
|
ctx.body = { count };
|
1878
1967
|
},
|
1879
1968
|
async unpublish(ctx) {
|
@@ -1883,7 +1972,6 @@ const collectionTypes = {
|
|
1883
1972
|
body: { discardDraft, ...body }
|
1884
1973
|
} = ctx.request;
|
1885
1974
|
const documentManager2 = getService$1("document-manager");
|
1886
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1887
1975
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1888
1976
|
if (permissionChecker2.cannot.unpublish()) {
|
1889
1977
|
return ctx.forbidden();
|
@@ -1893,7 +1981,7 @@ const collectionTypes = {
|
|
1893
1981
|
}
|
1894
1982
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1895
1983
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1896
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1984
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1897
1985
|
const document = await documentManager2.findOne(id, model, {
|
1898
1986
|
populate,
|
1899
1987
|
locale,
|
@@ -1915,7 +2003,7 @@ const collectionTypes = {
|
|
1915
2003
|
ctx.body = await async.pipe(
|
1916
2004
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1917
2005
|
permissionChecker2.sanitizeOutput,
|
1918
|
-
(document2) =>
|
2006
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1919
2007
|
)(document);
|
1920
2008
|
});
|
1921
2009
|
},
|
@@ -1924,14 +2012,13 @@ const collectionTypes = {
|
|
1924
2012
|
const { id, model } = ctx.params;
|
1925
2013
|
const { body } = ctx.request;
|
1926
2014
|
const documentManager2 = getService$1("document-manager");
|
1927
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1928
2015
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1929
2016
|
if (permissionChecker2.cannot.discard()) {
|
1930
2017
|
return ctx.forbidden();
|
1931
2018
|
}
|
1932
2019
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1933
2020
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1934
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2021
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1935
2022
|
const document = await documentManager2.findOne(id, model, {
|
1936
2023
|
populate,
|
1937
2024
|
locale,
|
@@ -1946,14 +2033,14 @@ const collectionTypes = {
|
|
1946
2033
|
ctx.body = await async.pipe(
|
1947
2034
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1948
2035
|
permissionChecker2.sanitizeOutput,
|
1949
|
-
(document2) =>
|
2036
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1950
2037
|
)(document);
|
1951
2038
|
},
|
1952
2039
|
async bulkDelete(ctx) {
|
1953
2040
|
const { userAbility } = ctx.state;
|
1954
2041
|
const { model } = ctx.params;
|
1955
2042
|
const { query, body } = ctx.request;
|
1956
|
-
const {
|
2043
|
+
const { documentIds } = body;
|
1957
2044
|
await validateBulkActionInput(body);
|
1958
2045
|
const documentManager2 = getService$1("document-manager");
|
1959
2046
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1961,14 +2048,22 @@ const collectionTypes = {
|
|
1961
2048
|
return ctx.forbidden();
|
1962
2049
|
}
|
1963
2050
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1964
|
-
const
|
1965
|
-
const
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
2051
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2052
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2053
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2054
|
+
populate,
|
2055
|
+
locale
|
2056
|
+
});
|
2057
|
+
if (documentLocales.length === 0) {
|
2058
|
+
return ctx.notFound();
|
2059
|
+
}
|
2060
|
+
for (const document of documentLocales) {
|
2061
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2062
|
+
return ctx.forbidden();
|
1969
2063
|
}
|
1970
|
-
}
|
1971
|
-
const
|
2064
|
+
}
|
2065
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2066
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1972
2067
|
ctx.body = { count };
|
1973
2068
|
},
|
1974
2069
|
async countDraftRelations(ctx) {
|
@@ -1981,7 +2076,7 @@ const collectionTypes = {
|
|
1981
2076
|
}
|
1982
2077
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1983
2078
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1984
|
-
const { locale, status
|
2079
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1985
2080
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1986
2081
|
if (!entity) {
|
1987
2082
|
return ctx.notFound();
|
@@ -1996,7 +2091,7 @@ const collectionTypes = {
|
|
1996
2091
|
},
|
1997
2092
|
async countManyEntriesDraftRelations(ctx) {
|
1998
2093
|
const { userAbility } = ctx.state;
|
1999
|
-
const ids = ctx.request.query.
|
2094
|
+
const ids = ctx.request.query.documentIds;
|
2000
2095
|
const locale = ctx.request.query.locale;
|
2001
2096
|
const { model } = ctx.params;
|
2002
2097
|
const documentManager2 = getService$1("document-manager");
|
@@ -2004,16 +2099,16 @@ const collectionTypes = {
|
|
2004
2099
|
if (permissionChecker2.cannot.read()) {
|
2005
2100
|
return ctx.forbidden();
|
2006
2101
|
}
|
2007
|
-
const
|
2102
|
+
const documents = await documentManager2.findMany(
|
2008
2103
|
{
|
2009
2104
|
filters: {
|
2010
|
-
|
2105
|
+
documentId: ids
|
2011
2106
|
},
|
2012
2107
|
locale
|
2013
2108
|
},
|
2014
2109
|
model
|
2015
2110
|
);
|
2016
|
-
if (!
|
2111
|
+
if (!documents) {
|
2017
2112
|
return ctx.notFound();
|
2018
2113
|
}
|
2019
2114
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2509,7 +2604,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2509
2604
|
throw new errors.ForbiddenError();
|
2510
2605
|
}
|
2511
2606
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2512
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2607
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2513
2608
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2514
2609
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2515
2610
|
// Find the first document to check if it exists
|
@@ -2546,12 +2641,11 @@ const singleTypes = {
|
|
2546
2641
|
const { model } = ctx.params;
|
2547
2642
|
const { query = {} } = ctx.request;
|
2548
2643
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2549
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2550
2644
|
if (permissionChecker2.cannot.read()) {
|
2551
2645
|
return ctx.forbidden();
|
2552
2646
|
}
|
2553
2647
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2554
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2648
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2555
2649
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2556
2650
|
if (!version) {
|
2557
2651
|
if (permissionChecker2.cannot.create()) {
|
@@ -2561,8 +2655,10 @@ const singleTypes = {
|
|
2561
2655
|
if (!document) {
|
2562
2656
|
return ctx.notFound();
|
2563
2657
|
}
|
2564
|
-
const { meta } = await
|
2658
|
+
const { meta } = await formatDocumentWithMetadata(
|
2659
|
+
permissionChecker2,
|
2565
2660
|
model,
|
2661
|
+
// @ts-expect-error - fix types
|
2566
2662
|
{ id: document.documentId, locale, publishedAt: null },
|
2567
2663
|
{ availableLocales: true, availableStatus: false }
|
2568
2664
|
);
|
@@ -2573,16 +2669,15 @@ const singleTypes = {
|
|
2573
2669
|
return ctx.forbidden();
|
2574
2670
|
}
|
2575
2671
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2576
|
-
ctx.body = await
|
2672
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2577
2673
|
},
|
2578
2674
|
async createOrUpdate(ctx) {
|
2579
2675
|
const { userAbility } = ctx.state;
|
2580
2676
|
const { model } = ctx.params;
|
2581
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2582
2677
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2583
2678
|
const document = await createOrUpdateDocument(ctx);
|
2584
2679
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2585
|
-
ctx.body = await
|
2680
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2586
2681
|
},
|
2587
2682
|
async delete(ctx) {
|
2588
2683
|
const { userAbility } = ctx.state;
|
@@ -2595,7 +2690,7 @@ const singleTypes = {
|
|
2595
2690
|
}
|
2596
2691
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2597
2692
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2598
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2693
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2599
2694
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2600
2695
|
populate,
|
2601
2696
|
locale
|
@@ -2618,7 +2713,6 @@ const singleTypes = {
|
|
2618
2713
|
const { model } = ctx.params;
|
2619
2714
|
const { query = {} } = ctx.request;
|
2620
2715
|
const documentManager2 = getService$1("document-manager");
|
2621
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2622
2716
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2623
2717
|
if (permissionChecker2.cannot.publish()) {
|
2624
2718
|
return ctx.forbidden();
|
@@ -2633,11 +2727,12 @@ const singleTypes = {
|
|
2633
2727
|
if (permissionChecker2.cannot.publish(document)) {
|
2634
2728
|
throw new errors.ForbiddenError();
|
2635
2729
|
}
|
2636
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2637
|
-
|
2730
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2731
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2732
|
+
return publishResult.at(0);
|
2638
2733
|
});
|
2639
2734
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2640
|
-
ctx.body = await
|
2735
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2641
2736
|
},
|
2642
2737
|
async unpublish(ctx) {
|
2643
2738
|
const { userAbility } = ctx.state;
|
@@ -2647,7 +2742,6 @@ const singleTypes = {
|
|
2647
2742
|
query = {}
|
2648
2743
|
} = ctx.request;
|
2649
2744
|
const documentManager2 = getService$1("document-manager");
|
2650
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2651
2745
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2652
2746
|
if (permissionChecker2.cannot.unpublish()) {
|
2653
2747
|
return ctx.forbidden();
|
@@ -2656,7 +2750,7 @@ const singleTypes = {
|
|
2656
2750
|
return ctx.forbidden();
|
2657
2751
|
}
|
2658
2752
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2659
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2753
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2660
2754
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2661
2755
|
if (!document) {
|
2662
2756
|
return ctx.notFound();
|
@@ -2674,7 +2768,7 @@ const singleTypes = {
|
|
2674
2768
|
ctx.body = await async.pipe(
|
2675
2769
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2676
2770
|
permissionChecker2.sanitizeOutput,
|
2677
|
-
(document2) =>
|
2771
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2678
2772
|
)(document);
|
2679
2773
|
});
|
2680
2774
|
},
|
@@ -2683,13 +2777,12 @@ const singleTypes = {
|
|
2683
2777
|
const { model } = ctx.params;
|
2684
2778
|
const { body, query = {} } = ctx.request;
|
2685
2779
|
const documentManager2 = getService$1("document-manager");
|
2686
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2687
2780
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2688
2781
|
if (permissionChecker2.cannot.discard()) {
|
2689
2782
|
return ctx.forbidden();
|
2690
2783
|
}
|
2691
2784
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2692
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2785
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2693
2786
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2694
2787
|
if (!document) {
|
2695
2788
|
return ctx.notFound();
|
@@ -2700,7 +2793,7 @@ const singleTypes = {
|
|
2700
2793
|
ctx.body = await async.pipe(
|
2701
2794
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2702
2795
|
permissionChecker2.sanitizeOutput,
|
2703
|
-
(document2) =>
|
2796
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2704
2797
|
)(document);
|
2705
2798
|
},
|
2706
2799
|
async countDraftRelations(ctx) {
|
@@ -2709,7 +2802,7 @@ const singleTypes = {
|
|
2709
2802
|
const { query } = ctx.request;
|
2710
2803
|
const documentManager2 = getService$1("document-manager");
|
2711
2804
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2712
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2805
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2713
2806
|
if (permissionChecker2.cannot.read()) {
|
2714
2807
|
return ctx.forbidden();
|
2715
2808
|
}
|
@@ -2730,7 +2823,7 @@ const uid$1 = {
|
|
2730
2823
|
async generateUID(ctx) {
|
2731
2824
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2732
2825
|
const { query = {} } = ctx.request;
|
2733
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2826
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2734
2827
|
await validateUIDField(contentTypeUID, field);
|
2735
2828
|
const uidService = getService$1("uid");
|
2736
2829
|
ctx.body = {
|
@@ -2742,7 +2835,7 @@ const uid$1 = {
|
|
2742
2835
|
ctx.request.body
|
2743
2836
|
);
|
2744
2837
|
const { query = {} } = ctx.request;
|
2745
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2838
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2746
2839
|
await validateUIDField(contentTypeUID, field);
|
2747
2840
|
const uidService = getService$1("uid");
|
2748
2841
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3533,7 +3626,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3533
3626
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3534
3627
|
}
|
3535
3628
|
});
|
3536
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
|
3629
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
|
3537
3630
|
const { isAnyToMany } = strapiUtils.relations;
|
3538
3631
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
|
3539
3632
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3624,6 +3717,42 @@ const getDeepPopulate = (uid2, {
|
|
3624
3717
|
{}
|
3625
3718
|
);
|
3626
3719
|
};
|
3720
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3721
|
+
initialPopulate = {},
|
3722
|
+
countMany = false,
|
3723
|
+
countOne = false,
|
3724
|
+
maxLevel = Infinity
|
3725
|
+
} = {}, level = 1) => {
|
3726
|
+
if (level > maxLevel) {
|
3727
|
+
return {};
|
3728
|
+
}
|
3729
|
+
const model = strapi.getModel(uid2);
|
3730
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3731
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3732
|
+
return populateAcc;
|
3733
|
+
}
|
3734
|
+
if (isScalarAttribute(attribute)) {
|
3735
|
+
return merge(populateAcc, {
|
3736
|
+
[attributeName]: true
|
3737
|
+
});
|
3738
|
+
}
|
3739
|
+
return merge(
|
3740
|
+
populateAcc,
|
3741
|
+
getPopulateFor(
|
3742
|
+
attributeName,
|
3743
|
+
model,
|
3744
|
+
{
|
3745
|
+
// @ts-expect-error - improve types
|
3746
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3747
|
+
countMany,
|
3748
|
+
countOne,
|
3749
|
+
maxLevel
|
3750
|
+
},
|
3751
|
+
level
|
3752
|
+
)
|
3753
|
+
);
|
3754
|
+
}, {});
|
3755
|
+
};
|
3627
3756
|
const getDeepPopulateDraftCount = (uid2) => {
|
3628
3757
|
const model = strapi.getModel(uid2);
|
3629
3758
|
let hasRelations = false;
|
@@ -3631,6 +3760,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3631
3760
|
const attribute = model.attributes[attributeName];
|
3632
3761
|
switch (attribute.type) {
|
3633
3762
|
case "relation": {
|
3763
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3764
|
+
if (isMorphRelation) {
|
3765
|
+
break;
|
3766
|
+
}
|
3634
3767
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3635
3768
|
populateAcc[attributeName] = {
|
3636
3769
|
count: true,
|
@@ -3645,22 +3778,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3645
3778
|
attribute.component
|
3646
3779
|
);
|
3647
3780
|
if (childHasRelations) {
|
3648
|
-
populateAcc[attributeName] = {
|
3781
|
+
populateAcc[attributeName] = {
|
3782
|
+
populate: populate2
|
3783
|
+
};
|
3649
3784
|
hasRelations = true;
|
3650
3785
|
}
|
3651
3786
|
break;
|
3652
3787
|
}
|
3653
3788
|
case "dynamiczone": {
|
3654
|
-
const
|
3655
|
-
const { populate:
|
3656
|
-
if (
|
3789
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3790
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3791
|
+
if (componentHasRelations) {
|
3657
3792
|
hasRelations = true;
|
3658
|
-
return
|
3793
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3659
3794
|
}
|
3660
3795
|
return acc;
|
3661
3796
|
}, {});
|
3662
|
-
if (!isEmpty(
|
3663
|
-
populateAcc[attributeName] = {
|
3797
|
+
if (!isEmpty(dzPopulateFragment)) {
|
3798
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3664
3799
|
}
|
3665
3800
|
break;
|
3666
3801
|
}
|
@@ -3852,41 +3987,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3852
3987
|
"updatedBy",
|
3853
3988
|
"status"
|
3854
3989
|
];
|
3855
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
3990
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
3991
|
+
"id",
|
3992
|
+
"locale",
|
3993
|
+
"updatedAt",
|
3994
|
+
"createdAt",
|
3995
|
+
"status",
|
3996
|
+
"publishedAt",
|
3997
|
+
"documentId"
|
3998
|
+
];
|
3856
3999
|
const CONTENT_MANAGER_STATUS = {
|
3857
4000
|
PUBLISHED: "published",
|
3858
4001
|
DRAFT: "draft",
|
3859
4002
|
MODIFIED: "modified"
|
3860
4003
|
};
|
3861
|
-
const
|
3862
|
-
if (!
|
4004
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
4005
|
+
if (!version || !version.updatedAt) {
|
3863
4006
|
return false;
|
3864
4007
|
}
|
3865
|
-
const
|
3866
|
-
const
|
3867
|
-
|
3868
|
-
return difference2 <= threshold;
|
4008
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
4009
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
4010
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3869
4011
|
};
|
3870
4012
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3871
4013
|
/**
|
3872
4014
|
* Returns available locales of a document for the current status
|
3873
4015
|
*/
|
3874
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4016
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3875
4017
|
const versionsByLocale = groupBy("locale", allVersions);
|
3876
4018
|
delete versionsByLocale[version.locale];
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
4019
|
+
const model = strapi2.getModel(uid2);
|
4020
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4021
|
+
const traversalFunction = async (localeVersion) => traverseEntity(
|
4022
|
+
({ key }, { remove }) => {
|
4023
|
+
if (keysToKeep.includes(key)) {
|
4024
|
+
return;
|
4025
|
+
}
|
4026
|
+
remove(key);
|
4027
|
+
},
|
4028
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4029
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4030
|
+
localeVersion
|
4031
|
+
);
|
4032
|
+
const mappingResult = await async.map(
|
4033
|
+
Object.values(versionsByLocale),
|
4034
|
+
async (localeVersions) => {
|
4035
|
+
const mappedLocaleVersions = await async.map(
|
4036
|
+
localeVersions,
|
4037
|
+
traversalFunction
|
4038
|
+
);
|
4039
|
+
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
4040
|
+
return mappedLocaleVersions[0];
|
4041
|
+
}
|
4042
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
4043
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
4044
|
+
if (!draftVersion) {
|
4045
|
+
return;
|
4046
|
+
}
|
4047
|
+
return {
|
4048
|
+
...draftVersion,
|
4049
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4050
|
+
};
|
3880
4051
|
}
|
3881
|
-
|
3882
|
-
|
3883
|
-
if (!draftVersion)
|
3884
|
-
return;
|
3885
|
-
return {
|
3886
|
-
...pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
|
3887
|
-
status: this.getStatus(draftVersion, otherVersions)
|
3888
|
-
};
|
3889
|
-
}).filter(Boolean);
|
4052
|
+
);
|
4053
|
+
return mappingResult.filter(Boolean);
|
3890
4054
|
},
|
3891
4055
|
/**
|
3892
4056
|
* Returns available status of a document for the current locale
|
@@ -3924,26 +4088,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3924
4088
|
});
|
3925
4089
|
},
|
3926
4090
|
getStatus(version, otherDocumentStatuses) {
|
3927
|
-
|
3928
|
-
|
3929
|
-
|
4091
|
+
let draftVersion;
|
4092
|
+
let publishedVersion;
|
4093
|
+
if (version.publishedAt) {
|
4094
|
+
publishedVersion = version;
|
4095
|
+
} else {
|
4096
|
+
draftVersion = version;
|
3930
4097
|
}
|
3931
|
-
|
3932
|
-
|
3933
|
-
|
3934
|
-
|
3935
|
-
|
4098
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4099
|
+
if (otherVersion?.publishedAt) {
|
4100
|
+
publishedVersion = otherVersion;
|
4101
|
+
} else if (otherVersion) {
|
4102
|
+
draftVersion = otherVersion;
|
3936
4103
|
}
|
3937
|
-
if (
|
4104
|
+
if (!draftVersion)
|
3938
4105
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3939
|
-
|
3940
|
-
|
4106
|
+
if (!publishedVersion)
|
4107
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4108
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4109
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3941
4110
|
},
|
4111
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4112
|
+
// We could refactor this so the locales are only loaded when they're
|
4113
|
+
// needed. e.g. in the bulk locale action modal.
|
3942
4114
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4115
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3943
4116
|
const versions = await strapi2.db.query(uid2).findMany({
|
3944
4117
|
where: { documentId: version.documentId },
|
3945
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3946
4118
|
populate: {
|
4119
|
+
// Populate only fields that require validation for bulk locale actions
|
4120
|
+
...populate,
|
4121
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3947
4122
|
createdBy: {
|
3948
4123
|
select: ["id", "firstname", "lastname", "email"]
|
3949
4124
|
},
|
@@ -3952,7 +4127,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3952
4127
|
}
|
3953
4128
|
}
|
3954
4129
|
});
|
3955
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4130
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3956
4131
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3957
4132
|
return {
|
3958
4133
|
availableLocales: availableLocalesResult,
|
@@ -3965,8 +4140,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3965
4140
|
* - Available status of the document for the current locale
|
3966
4141
|
*/
|
3967
4142
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3968
|
-
if (!document)
|
3969
|
-
return
|
4143
|
+
if (!document) {
|
4144
|
+
return {
|
4145
|
+
data: document,
|
4146
|
+
meta: {
|
4147
|
+
availableLocales: [],
|
4148
|
+
availableStatus: []
|
4149
|
+
}
|
4150
|
+
};
|
4151
|
+
}
|
3970
4152
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
3971
4153
|
if (!hasDraftAndPublish) {
|
3972
4154
|
opts.availableStatus = false;
|
@@ -4016,26 +4198,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
4016
4198
|
}, 0);
|
4017
4199
|
};
|
4018
4200
|
const { ApplicationError } = errors;
|
4019
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4020
4201
|
const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
|
4021
4202
|
const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
|
4022
4203
|
const omitIdField = omit("id");
|
4023
|
-
const emitEvent = async (uid2, event, document) => {
|
4024
|
-
const modelDef = strapi.getModel(uid2);
|
4025
|
-
const sanitizedDocument = await sanitize.sanitizers.defaultSanitizeOutput(
|
4026
|
-
{
|
4027
|
-
schema: modelDef,
|
4028
|
-
getModel(uid22) {
|
4029
|
-
return strapi.getModel(uid22);
|
4030
|
-
}
|
4031
|
-
},
|
4032
|
-
document
|
4033
|
-
);
|
4034
|
-
strapi.eventHub.emit(event, {
|
4035
|
-
model: modelDef.modelName,
|
4036
|
-
entry: sanitizedDocument
|
4037
|
-
});
|
4038
|
-
};
|
4039
4204
|
const documentManager = ({ strapi: strapi2 }) => {
|
4040
4205
|
return {
|
4041
4206
|
async findOne(id, uid2, opts = {}) {
|
@@ -4054,6 +4219,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4054
4219
|
} else if (opts.locale && opts.locale !== "*") {
|
4055
4220
|
where.locale = opts.locale;
|
4056
4221
|
}
|
4222
|
+
if (typeof opts.isPublished === "boolean") {
|
4223
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4224
|
+
}
|
4057
4225
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4058
4226
|
},
|
4059
4227
|
async findMany(opts, uid2) {
|
@@ -4061,20 +4229,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4061
4229
|
return strapi2.documents(uid2).findMany(params);
|
4062
4230
|
},
|
4063
4231
|
async findPage(opts, uid2) {
|
4064
|
-
const
|
4065
|
-
|
4232
|
+
const params = pagination.withDefaultPagination(opts || {}, {
|
4233
|
+
maxLimit: 1e3
|
4234
|
+
});
|
4066
4235
|
const [documents, total = 0] = await Promise.all([
|
4067
|
-
strapi2.documents(uid2).findMany(
|
4068
|
-
strapi2.documents(uid2).count(
|
4236
|
+
strapi2.documents(uid2).findMany(params),
|
4237
|
+
strapi2.documents(uid2).count(params)
|
4069
4238
|
]);
|
4070
4239
|
return {
|
4071
4240
|
results: documents,
|
4072
|
-
pagination:
|
4073
|
-
page,
|
4074
|
-
pageSize,
|
4075
|
-
pageCount: Math.ceil(total / pageSize),
|
4076
|
-
total
|
4077
|
-
}
|
4241
|
+
pagination: pagination.transformPagedPaginationInfo(params, total)
|
4078
4242
|
};
|
4079
4243
|
},
|
4080
4244
|
async create(uid2, opts = {}) {
|
@@ -4091,10 +4255,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4091
4255
|
async clone(id, body, uid2) {
|
4092
4256
|
const populate = await buildDeepPopulate(uid2);
|
4093
4257
|
const params = {
|
4094
|
-
data:
|
4095
|
-
...omitIdField(body),
|
4096
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4097
|
-
},
|
4258
|
+
data: omitIdField(body),
|
4098
4259
|
populate
|
4099
4260
|
};
|
4100
4261
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4120,70 +4281,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4120
4281
|
return {};
|
4121
4282
|
},
|
4122
4283
|
// FIXME: handle relations
|
4123
|
-
async deleteMany(
|
4124
|
-
const
|
4125
|
-
|
4126
|
-
|
4127
|
-
}
|
4128
|
-
return { count: docs.length };
|
4284
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4285
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4286
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4287
|
+
});
|
4288
|
+
return { count: deletedEntries.length };
|
4129
4289
|
},
|
4130
4290
|
async publish(id, uid2, opts = {}) {
|
4131
4291
|
const populate = await buildDeepPopulate(uid2);
|
4132
4292
|
const params = { ...opts, populate };
|
4133
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4293
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4134
4294
|
},
|
4135
|
-
async publishMany(
|
4136
|
-
|
4137
|
-
|
4138
|
-
|
4139
|
-
|
4140
|
-
|
4141
|
-
|
4142
|
-
strapi2.getModel(uid2),
|
4143
|
-
document,
|
4144
|
-
void 0,
|
4145
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4146
|
-
document
|
4147
|
-
);
|
4148
|
-
})
|
4149
|
-
);
|
4150
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4151
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4152
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4153
|
-
const populate = await buildDeepPopulate(uid2);
|
4154
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4155
|
-
where: filters,
|
4156
|
-
data
|
4157
|
-
});
|
4158
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4159
|
-
where: filters,
|
4160
|
-
populate
|
4295
|
+
async publishMany(uid2, documentIds, locale) {
|
4296
|
+
return strapi2.db.transaction(async () => {
|
4297
|
+
const results = await Promise.all(
|
4298
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4299
|
+
);
|
4300
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4301
|
+
return publishedEntitiesCount;
|
4161
4302
|
});
|
4162
|
-
await Promise.all(
|
4163
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4164
|
-
);
|
4165
|
-
return publishedEntitiesCount;
|
4166
4303
|
},
|
4167
|
-
async unpublishMany(
|
4168
|
-
|
4169
|
-
return
|
4170
|
-
|
4171
|
-
|
4172
|
-
|
4173
|
-
|
4174
|
-
const populate = await buildDeepPopulate(uid2);
|
4175
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4176
|
-
where: filters,
|
4177
|
-
data
|
4178
|
-
});
|
4179
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4180
|
-
where: filters,
|
4181
|
-
populate
|
4304
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4305
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4306
|
+
return Promise.all(
|
4307
|
+
documentIds.map(
|
4308
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4309
|
+
)
|
4310
|
+
);
|
4182
4311
|
});
|
4183
|
-
|
4184
|
-
|
4185
|
-
);
|
4186
|
-
return unpublishedEntitiesCount;
|
4312
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4313
|
+
return { count: unpublishedEntitiesCount };
|
4187
4314
|
},
|
4188
4315
|
async unpublish(id, uid2, opts = {}) {
|
4189
4316
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4208,16 +4335,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4208
4335
|
}
|
4209
4336
|
return sumDraftCounts(document, uid2);
|
4210
4337
|
},
|
4211
|
-
async countManyEntriesDraftRelations(
|
4338
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4212
4339
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4213
4340
|
if (!hasRelations) {
|
4214
4341
|
return 0;
|
4215
4342
|
}
|
4343
|
+
let localeFilter = {};
|
4344
|
+
if (locale) {
|
4345
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4346
|
+
}
|
4216
4347
|
const entities = await strapi2.db.query(uid2).findMany({
|
4217
4348
|
populate,
|
4218
4349
|
where: {
|
4219
|
-
|
4220
|
-
...
|
4350
|
+
documentId: { $in: documentIds },
|
4351
|
+
...localeFilter
|
4221
4352
|
}
|
4222
4353
|
});
|
4223
4354
|
const totalNumberDraftRelations = entities.reduce(
|