@strapi/content-manager 0.0.0-experimental.32c4b04580cc12400710050c8198e46b3644cfd4 → 0.0.0-experimental.332a7d5b6b1d23635d7e205657f0ff39ec133c9e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs → ComponentConfigurationPage-D4H-v0et.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs.map → ComponentConfigurationPage-D4H-v0et.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js → ComponentConfigurationPage-DdkVGfXC.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js.map → ComponentConfigurationPage-DdkVGfXC.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs → EditConfigurationPage-D1nvB7Br.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs.map → EditConfigurationPage-D1nvB7Br.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js → EditConfigurationPage-LYEvR4fW.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js.map → EditConfigurationPage-LYEvR4fW.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-BLsjc5F-.mjs → EditViewPage-Bcnff6Vd.mjs} +34 -46
- package/dist/_chunks/EditViewPage-Bcnff6Vd.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-C-ukDOB7.js → EditViewPage-DqelJ9UK.js} +36 -49
- package/dist/_chunks/EditViewPage-DqelJ9UK.js.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-CPYqIWDG.js → Form-CnHfBeiB.js} +39 -21
- package/dist/_chunks/Form-CnHfBeiB.js.map +1 -0
- package/dist/_chunks/{Form-Dg_GS5TQ.mjs → Form-CzPCJi3B.mjs} +37 -18
- package/dist/_chunks/Form-CzPCJi3B.mjs.map +1 -0
- package/dist/_chunks/{History-wrnHqf09.mjs → History-CcmSn3Mj.mjs} +71 -104
- package/dist/_chunks/History-CcmSn3Mj.mjs.map +1 -0
- package/dist/_chunks/{History-DNQkXANT.js → History-zArjENzj.js} +81 -115
- package/dist/_chunks/History-zArjENzj.js.map +1 -0
- package/dist/_chunks/{Field-Bfph5SOd.js → Input-CDHKQd7o.js} +1334 -1239
- package/dist/_chunks/Input-CDHKQd7o.js.map +1 -0
- package/dist/_chunks/{Field-Cs7duwWd.mjs → Input-aV8SSoTa.mjs} +1192 -1097
- package/dist/_chunks/Input-aV8SSoTa.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DScmJVkW.mjs → ListConfigurationPage-BPvzENJJ.mjs} +19 -8
- package/dist/_chunks/ListConfigurationPage-BPvzENJJ.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-CUQxfpjT.js → ListConfigurationPage-ByZAO_9H.js} +19 -9
- package/dist/_chunks/ListConfigurationPage-ByZAO_9H.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BsLiH2-2.js → ListViewPage-BVKBeQAA.js} +108 -74
- package/dist/_chunks/ListViewPage-BVKBeQAA.js.map +1 -0
- package/dist/_chunks/{ListViewPage-C4IvrMgY.mjs → ListViewPage-HljQVnFH.mjs} +109 -74
- package/dist/_chunks/ListViewPage-HljQVnFH.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js → NoContentTypePage-BV5zfDxr.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js.map → NoContentTypePage-BV5zfDxr.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs → NoContentTypePage-BfHaSM-K.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs.map → NoContentTypePage-BfHaSM-K.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs → NoPermissionsPage-D6ze2nQL.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs.map → NoPermissionsPage-D6ze2nQL.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js → NoPermissionsPage-vdNpc6jb.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js.map → NoPermissionsPage-vdNpc6jb.js.map} +1 -1
- package/dist/_chunks/Preview-DEHdENT1.js +305 -0
- package/dist/_chunks/Preview-DEHdENT1.js.map +1 -0
- package/dist/_chunks/Preview-vfWOtPG5.mjs +287 -0
- package/dist/_chunks/Preview-vfWOtPG5.mjs.map +1 -0
- package/dist/_chunks/{Relations-BZr8tL0R.mjs → Relations-B7_hbF0w.mjs} +79 -44
- package/dist/_chunks/Relations-B7_hbF0w.mjs.map +1 -0
- package/dist/_chunks/{Relations-CtELXYIK.js → Relations-DcoOBejP.js} +79 -45
- package/dist/_chunks/Relations-DcoOBejP.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BR48D_RH.js} +35 -15
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BR48D_RH.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-D65uIF6Y.mjs} +35 -15
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-D65uIF6Y.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-C43IbhA_.js} +16 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-C43IbhA_.js.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr-DBseuRuB.mjs} +16 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr-DBseuRuB.mjs.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-OerGjbAN.js → index-CxLSGwnk.js} +1304 -750
- package/dist/_chunks/index-CxLSGwnk.js.map +1 -0
- package/dist/_chunks/{index-c_5DdJi-.mjs → index-EH8ZtHd5.mjs} +1323 -769
- package/dist/_chunks/index-EH8ZtHd5.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-oPBiO7RY.mjs → layout-CxDMdJ13.mjs} +23 -10
- package/dist/_chunks/layout-CxDMdJ13.mjs.map +1 -0
- package/dist/_chunks/{layout-Ci7qHlFb.js → layout-DSeUTfMv.js} +23 -11
- package/dist/_chunks/layout-DSeUTfMv.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-BIdWFjdq.mjs → relations-B8_Uu38Q.mjs} +21 -8
- package/dist/_chunks/relations-B8_Uu38Q.mjs.map +1 -0
- package/dist/_chunks/{relations-COBpStiF.js → relations-S5nNKdN3.js} +20 -7
- package/dist/_chunks/relations-S5nNKdN3.js.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +6 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +2 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +49 -1
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +727 -406
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +728 -406
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts +3 -3
- 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 +8 -12
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -16
- package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +0 -1
- package/dist/_chunks/Field-Bfph5SOd.js.map +0 -1
- package/dist/_chunks/Field-Cs7duwWd.mjs.map +0 -1
- package/dist/_chunks/Form-CPYqIWDG.js.map +0 -1
- package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +0 -1
- package/dist/_chunks/History-DNQkXANT.js.map +0 -1
- package/dist/_chunks/History-wrnHqf09.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +0 -1
- package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +0 -1
- package/dist/_chunks/Relations-BZr8tL0R.mjs.map +0 -1
- package/dist/_chunks/Relations-CtELXYIK.js.map +0 -1
- package/dist/_chunks/index-OerGjbAN.js.map +0 -1
- package/dist/_chunks/index-c_5DdJi-.mjs.map +0 -1
- package/dist/_chunks/layout-Ci7qHlFb.js.map +0 -1
- package/dist/_chunks/layout-oPBiO7RY.mjs.map +0 -1
- package/dist/_chunks/relations-BIdWFjdq.mjs.map +0 -1
- package/dist/_chunks/relations-COBpStiF.js.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.js
CHANGED
@@ -10,8 +10,7 @@ const qs = require("qs");
|
|
10
10
|
const slugify = require("@sindresorhus/slugify");
|
11
11
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
12
12
|
function _interopNamespace(e) {
|
13
|
-
if (e && e.__esModule)
|
14
|
-
return e;
|
13
|
+
if (e && e.__esModule) return e;
|
15
14
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
16
15
|
if (e) {
|
17
16
|
for (const k in e) {
|
@@ -33,10 +32,10 @@ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
|
|
33
32
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
34
33
|
const qs__default = /* @__PURE__ */ _interopDefault(qs);
|
35
34
|
const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
|
36
|
-
const getService$
|
35
|
+
const getService$2 = (name) => {
|
37
36
|
return strapi.plugin("content-manager").service(name);
|
38
37
|
};
|
39
|
-
function getService(strapi2, name) {
|
38
|
+
function getService$1(strapi2, name) {
|
40
39
|
return strapi2.service(`plugin::content-manager.${name}`);
|
41
40
|
}
|
42
41
|
const historyRestoreVersionSchema = yup__namespace.object().shape({
|
@@ -72,7 +71,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
72
71
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
73
72
|
throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
|
74
73
|
}
|
75
|
-
const permissionChecker2 = getService$
|
74
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
76
75
|
userAbility: ctx.state.userAbility,
|
77
76
|
model: ctx.query.contentType
|
78
77
|
});
|
@@ -80,7 +79,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
80
79
|
return ctx.forbidden();
|
81
80
|
}
|
82
81
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
83
|
-
const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
|
82
|
+
const { results, pagination } = await getService$1(strapi2, "history").findVersionsPage({
|
84
83
|
query: {
|
85
84
|
...query,
|
86
85
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -105,14 +104,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
105
104
|
async restoreVersion(ctx) {
|
106
105
|
const request = ctx.request;
|
107
106
|
await validateRestoreVersion(request.body, "contentType is required");
|
108
|
-
const permissionChecker2 = getService$
|
107
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
109
108
|
userAbility: ctx.state.userAbility,
|
110
109
|
model: request.body.contentType
|
111
110
|
});
|
112
111
|
if (permissionChecker2.cannot.update()) {
|
113
112
|
throw new strapiUtils.errors.ForbiddenError();
|
114
113
|
}
|
115
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
114
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
116
115
|
request.params.versionId
|
117
116
|
);
|
118
117
|
return {
|
@@ -121,7 +120,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
121
120
|
}
|
122
121
|
};
|
123
122
|
};
|
124
|
-
const controllers$
|
123
|
+
const controllers$2 = {
|
125
124
|
"history-version": createHistoryVersionController
|
126
125
|
/**
|
127
126
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -167,8 +166,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
167
166
|
};
|
168
167
|
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
169
168
|
if (Array.isArray(versionRelationData)) {
|
170
|
-
if (versionRelationData.length === 0)
|
171
|
-
return versionRelationData;
|
169
|
+
if (versionRelationData.length === 0) return versionRelationData;
|
172
170
|
const existingAndMissingRelations = await Promise.all(
|
173
171
|
versionRelationData.map((relation) => {
|
174
172
|
return strapi2.documents(attribute.target).findOne({
|
@@ -177,19 +175,16 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
177
175
|
});
|
178
176
|
})
|
179
177
|
);
|
180
|
-
return existingAndMissingRelations.filter(
|
181
|
-
(relation) => relation !== null
|
182
|
-
);
|
178
|
+
return existingAndMissingRelations.filter((relation) => relation !== null);
|
183
179
|
}
|
184
180
|
return strapi2.documents(attribute.target).findOne({
|
185
181
|
documentId: versionRelationData.documentId,
|
186
182
|
locale: versionRelationData.locale || void 0
|
187
183
|
});
|
188
184
|
};
|
189
|
-
const getMediaRestoreValue = async (versionRelationData
|
190
|
-
if (
|
185
|
+
const getMediaRestoreValue = async (versionRelationData) => {
|
186
|
+
if (Array.isArray(versionRelationData)) {
|
191
187
|
const existingAndMissingMedias = await Promise.all(
|
192
|
-
// @ts-expect-error Fix the type definitions so this isn't any
|
193
188
|
versionRelationData.map((media) => {
|
194
189
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
195
190
|
})
|
@@ -199,10 +194,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
199
194
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
200
195
|
};
|
201
196
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
197
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
202
198
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
199
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
203
200
|
const getLocaleDictionary = async () => {
|
204
|
-
if (!localesService)
|
205
|
-
return {};
|
201
|
+
if (!localesService) return {};
|
206
202
|
const locales = await localesService.find() || [];
|
207
203
|
return locales.reduce(
|
208
204
|
(acc, locale) => {
|
@@ -226,9 +222,21 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
222
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
223
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
224
|
};
|
229
|
-
const
|
225
|
+
const getComponentFields = (componentUID) => {
|
226
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
227
|
+
(fieldsAcc, [key, attribute]) => {
|
228
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
229
|
+
fieldsAcc.push(key);
|
230
|
+
}
|
231
|
+
return fieldsAcc;
|
232
|
+
},
|
233
|
+
[]
|
234
|
+
);
|
235
|
+
};
|
236
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
237
|
const model = strapi2.getModel(uid2);
|
231
238
|
const attributes = Object.entries(model.attributes);
|
239
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
240
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
241
|
switch (attribute.type) {
|
234
242
|
case "relation": {
|
@@ -238,23 +246,29 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
238
246
|
}
|
239
247
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
240
248
|
if (isVisible2) {
|
241
|
-
acc[attributeName] = {
|
249
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
242
250
|
}
|
243
251
|
break;
|
244
252
|
}
|
245
253
|
case "media": {
|
246
|
-
acc[attributeName] = {
|
254
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
247
255
|
break;
|
248
256
|
}
|
249
257
|
case "component": {
|
250
258
|
const populate = getDeepPopulate2(attribute.component);
|
251
|
-
acc[attributeName] = {
|
259
|
+
acc[attributeName] = {
|
260
|
+
populate,
|
261
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
262
|
+
};
|
252
263
|
break;
|
253
264
|
}
|
254
265
|
case "dynamiczone": {
|
255
266
|
const populatedComponents = (attribute.components || []).reduce(
|
256
267
|
(acc2, componentUID) => {
|
257
|
-
acc2[componentUID] = {
|
268
|
+
acc2[componentUID] = {
|
269
|
+
populate: getDeepPopulate2(componentUID),
|
270
|
+
[fieldSelector]: getComponentFields(componentUID)
|
271
|
+
};
|
258
272
|
return acc2;
|
259
273
|
},
|
260
274
|
{}
|
@@ -316,6 +330,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
316
330
|
getRelationRestoreValue,
|
317
331
|
getMediaRestoreValue,
|
318
332
|
getDefaultLocale,
|
333
|
+
isLocalizedContentType,
|
319
334
|
getLocaleDictionary,
|
320
335
|
getRetentionDays,
|
321
336
|
getVersionStatus,
|
@@ -338,7 +353,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
338
353
|
});
|
339
354
|
},
|
340
355
|
async findVersionsPage(params) {
|
341
|
-
const
|
356
|
+
const schema = strapi2.getModel(params.query.contentType);
|
357
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);
|
358
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
359
|
+
let locale = null;
|
360
|
+
if (isLocalizedContentType) {
|
361
|
+
locale = params.query.locale || defaultLocale;
|
362
|
+
}
|
342
363
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
343
364
|
query.findPage({
|
344
365
|
...params.query,
|
@@ -354,78 +375,76 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
354
375
|
}),
|
355
376
|
serviceUtils.getLocaleDictionary()
|
356
377
|
]);
|
357
|
-
const
|
358
|
-
|
359
|
-
async (
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
model: "plugin::upload.file"
|
366
|
-
});
|
367
|
-
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
368
|
-
const sanitizedResults = await Promise.all(
|
369
|
-
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
370
|
-
);
|
371
|
-
return {
|
372
|
-
...await currentDataWithRelations,
|
373
|
-
[attributeKey]: {
|
374
|
-
results: sanitizedResults,
|
375
|
-
meta: response.meta
|
376
|
-
}
|
377
|
-
};
|
378
|
+
const populateEntry = async (entry) => {
|
379
|
+
return strapiUtils.traverseEntity(
|
380
|
+
async (options, utils) => {
|
381
|
+
if (!options.attribute) return;
|
382
|
+
if (!options.value) return;
|
383
|
+
const currentValue = Array.isArray(options.value) ? options.value : [options.value];
|
384
|
+
if (options.attribute.type === "component") {
|
385
|
+
utils.remove("id");
|
378
386
|
}
|
379
|
-
if (
|
380
|
-
|
387
|
+
if (options.attribute.type === "relation" && // TODO: handle polymorphic relations
|
388
|
+
options.attribute.relation !== "morphToOne" && options.attribute.relation !== "morphToMany") {
|
389
|
+
if (options.attribute.target === "admin::user") {
|
381
390
|
const adminUsers = await Promise.all(
|
382
|
-
|
391
|
+
currentValue.map((userToPopulate) => {
|
383
392
|
if (userToPopulate == null) {
|
384
393
|
return null;
|
385
394
|
}
|
386
|
-
return strapi2.query("admin::user").findOne({
|
395
|
+
return strapi2.query("admin::user").findOne({
|
396
|
+
where: {
|
397
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
398
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
399
|
+
}
|
400
|
+
});
|
387
401
|
})
|
388
402
|
);
|
389
|
-
|
390
|
-
...await currentDataWithRelations,
|
391
|
-
/**
|
392
|
-
* Ideally we would return the same "{results: [], meta: {}}" shape, however,
|
393
|
-
* when sanitizing the data as a whole in the controller before sending to the client,
|
394
|
-
* the data for admin relation user is completely sanitized if we return an object here as opposed to an array.
|
395
|
-
*/
|
396
|
-
[attributeKey]: adminUsers
|
397
|
-
};
|
403
|
+
utils.set(options.key, adminUsers);
|
398
404
|
}
|
399
|
-
const permissionChecker2 = getService$
|
405
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
400
406
|
userAbility: params.state.userAbility,
|
401
|
-
model:
|
407
|
+
model: options.attribute.target
|
402
408
|
});
|
403
409
|
const response = await serviceUtils.buildRelationReponse(
|
404
|
-
|
405
|
-
|
410
|
+
currentValue,
|
411
|
+
options.attribute
|
406
412
|
);
|
407
413
|
const sanitizedResults = await Promise.all(
|
408
414
|
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
409
415
|
);
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
meta: response.meta
|
415
|
-
}
|
416
|
-
};
|
416
|
+
utils.set(options.key, {
|
417
|
+
results: sanitizedResults,
|
418
|
+
meta: response.meta
|
419
|
+
});
|
417
420
|
}
|
418
|
-
|
421
|
+
if (options.attribute.type === "media") {
|
422
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
423
|
+
userAbility: params.state.userAbility,
|
424
|
+
model: "plugin::upload.file"
|
425
|
+
});
|
426
|
+
const response = await serviceUtils.buildMediaResponse(currentValue);
|
427
|
+
const sanitizedResults = await Promise.all(
|
428
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
429
|
+
);
|
430
|
+
utils.set(options.key, {
|
431
|
+
results: sanitizedResults,
|
432
|
+
meta: response.meta
|
433
|
+
});
|
434
|
+
}
|
435
|
+
},
|
436
|
+
{
|
437
|
+
schema,
|
438
|
+
getModel: strapi2.getModel.bind(strapi2)
|
419
439
|
},
|
420
|
-
|
440
|
+
entry.data
|
421
441
|
);
|
422
|
-
return entryWithRelations;
|
423
442
|
};
|
424
443
|
const formattedResults = await Promise.all(
|
425
444
|
results.map(async (result) => {
|
426
445
|
return {
|
427
446
|
...result,
|
428
|
-
data: await
|
447
|
+
data: await populateEntry(result),
|
429
448
|
meta: {
|
430
449
|
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
431
450
|
result.schema,
|
@@ -456,30 +475,44 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
456
475
|
// Clone to avoid mutating the original version data
|
457
476
|
structuredClone(version.data)
|
458
477
|
);
|
459
|
-
const
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
478
|
+
const schema = structuredClone(version.schema);
|
479
|
+
schema.attributes = fp.omit(FIELDS_TO_IGNORE, contentTypeSchemaAttributes);
|
480
|
+
const dataWithoutMissingRelations = await strapiUtils.traverseEntity(
|
481
|
+
async (options, utils) => {
|
482
|
+
if (!options.attribute) return;
|
483
|
+
if (options.attribute.type === "component") {
|
484
|
+
utils.remove("id");
|
485
|
+
if (options.attribute.repeatable && options.value === null) {
|
486
|
+
utils.set(options.key, []);
|
487
|
+
}
|
488
|
+
}
|
489
|
+
if (options.attribute.type === "dynamiczone") {
|
490
|
+
if (options.value === null) {
|
491
|
+
utils.set(options.key, []);
|
492
|
+
}
|
469
493
|
}
|
470
|
-
if (attribute.type === "relation" && // TODO: handle polymorphic relations
|
471
|
-
attribute.relation !== "morphToOne" && attribute.relation !== "morphToMany") {
|
472
|
-
|
473
|
-
|
494
|
+
if (options.attribute.type === "relation" && // TODO: handle polymorphic relations
|
495
|
+
options.attribute.relation !== "morphToOne" && options.attribute.relation !== "morphToMany") {
|
496
|
+
if (!options.value) return;
|
497
|
+
const data2 = await serviceUtils.getRelationRestoreValue(
|
498
|
+
options.value,
|
499
|
+
options.attribute
|
500
|
+
);
|
501
|
+
utils.set(options.key, data2);
|
474
502
|
}
|
475
|
-
if (attribute.type === "media") {
|
476
|
-
|
477
|
-
|
503
|
+
if (options.attribute.type === "media") {
|
504
|
+
if (!options.value) return;
|
505
|
+
const data2 = await serviceUtils.getMediaRestoreValue(
|
506
|
+
options.value
|
507
|
+
);
|
508
|
+
utils.set(options.key, data2);
|
478
509
|
}
|
479
|
-
return previousRelationAttributes;
|
480
510
|
},
|
481
|
-
|
482
|
-
|
511
|
+
{
|
512
|
+
schema,
|
513
|
+
getModel: strapi2.getModel.bind(strapi2)
|
514
|
+
},
|
515
|
+
dataWithoutAddedAttributes
|
483
516
|
);
|
484
517
|
const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
485
518
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -494,6 +527,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
494
527
|
}
|
495
528
|
};
|
496
529
|
};
|
530
|
+
const shouldCreateHistoryVersion = (context) => {
|
531
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
532
|
+
return false;
|
533
|
+
}
|
534
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
535
|
+
return false;
|
536
|
+
}
|
537
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
538
|
+
return false;
|
539
|
+
}
|
540
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
541
|
+
return false;
|
542
|
+
}
|
543
|
+
return true;
|
544
|
+
};
|
545
|
+
const getSchemas = (uid2) => {
|
546
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
547
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
548
|
+
(currentComponentSchemas, key) => {
|
549
|
+
const fieldSchema = attributesSchema[key];
|
550
|
+
if (fieldSchema.type === "component") {
|
551
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
552
|
+
return {
|
553
|
+
...currentComponentSchemas,
|
554
|
+
[fieldSchema.component]: componentSchema
|
555
|
+
};
|
556
|
+
}
|
557
|
+
return currentComponentSchemas;
|
558
|
+
},
|
559
|
+
{}
|
560
|
+
);
|
561
|
+
return {
|
562
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
563
|
+
componentsSchemas
|
564
|
+
};
|
565
|
+
};
|
497
566
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
498
567
|
const state = {
|
499
568
|
deleteExpiredJob: null,
|
@@ -506,76 +575,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
506
575
|
return;
|
507
576
|
}
|
508
577
|
strapi2.documents.use(async (context, next) => {
|
509
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
510
|
-
return next();
|
511
|
-
}
|
512
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
513
|
-
return next();
|
514
|
-
}
|
515
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
516
|
-
return next();
|
517
|
-
}
|
518
|
-
const contentTypeUid = context.contentType.uid;
|
519
|
-
if (!contentTypeUid.startsWith("api::")) {
|
520
|
-
return next();
|
521
|
-
}
|
522
578
|
const result = await next();
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
579
|
+
if (!shouldCreateHistoryVersion(context)) {
|
580
|
+
return result;
|
581
|
+
}
|
582
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
527
583
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
528
|
-
const
|
529
|
-
if (
|
530
|
-
|
531
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
532
|
-
);
|
533
|
-
return next();
|
584
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
585
|
+
if (!locales.length) {
|
586
|
+
return result;
|
534
587
|
}
|
535
|
-
const
|
536
|
-
|
537
|
-
|
538
|
-
|
588
|
+
const uid2 = context.contentType.uid;
|
589
|
+
const schemas = getSchemas(uid2);
|
590
|
+
const model = strapi2.getModel(uid2);
|
591
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
592
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
593
|
+
where: {
|
594
|
+
documentId,
|
595
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
596
|
+
...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
597
|
+
},
|
598
|
+
populate: serviceUtils.getDeepPopulate(
|
599
|
+
uid2,
|
600
|
+
true
|
601
|
+
/* use database syntax */
|
602
|
+
)
|
539
603
|
});
|
540
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
541
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
542
|
-
const componentsSchemas = Object.keys(
|
543
|
-
attributesSchema
|
544
|
-
).reduce((currentComponentSchemas, key) => {
|
545
|
-
const fieldSchema = attributesSchema[key];
|
546
|
-
if (fieldSchema.type === "component") {
|
547
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
548
|
-
return {
|
549
|
-
...currentComponentSchemas,
|
550
|
-
[fieldSchema.component]: componentSchema
|
551
|
-
};
|
552
|
-
}
|
553
|
-
return currentComponentSchemas;
|
554
|
-
}, {});
|
555
604
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
556
|
-
onCommit(() => {
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
605
|
+
onCommit(async () => {
|
606
|
+
for (const entry of localeEntries) {
|
607
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
608
|
+
await getService$1(strapi2, "history").createVersion({
|
609
|
+
contentType: uid2,
|
610
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
611
|
+
relatedDocumentId: documentId,
|
612
|
+
locale: entry.locale,
|
613
|
+
status,
|
614
|
+
...schemas
|
615
|
+
});
|
616
|
+
}
|
566
617
|
});
|
567
618
|
});
|
568
619
|
return result;
|
569
620
|
});
|
570
|
-
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
621
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
571
622
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
572
623
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
573
624
|
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
574
625
|
where: {
|
575
626
|
created_at: {
|
576
|
-
$lt: expirationDate
|
627
|
+
$lt: expirationDate
|
577
628
|
}
|
578
629
|
}
|
630
|
+
}).catch((error) => {
|
631
|
+
if (error instanceof Error) {
|
632
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
633
|
+
}
|
579
634
|
});
|
580
635
|
});
|
581
636
|
state.isInitialized = true;
|
@@ -587,17 +642,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
587
642
|
}
|
588
643
|
};
|
589
644
|
};
|
590
|
-
const services$
|
645
|
+
const services$2 = {
|
591
646
|
history: createHistoryService,
|
592
647
|
lifecycles: createLifecyclesService
|
593
648
|
};
|
594
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
649
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
595
650
|
const historyVersionRouter = {
|
596
651
|
type: "admin",
|
597
652
|
routes: [
|
598
653
|
{
|
599
654
|
method: "GET",
|
600
|
-
info,
|
655
|
+
info: info$1,
|
601
656
|
path: "/history-versions",
|
602
657
|
handler: "history-version.findMany",
|
603
658
|
config: {
|
@@ -606,7 +661,7 @@ const historyVersionRouter = {
|
|
606
661
|
},
|
607
662
|
{
|
608
663
|
method: "PUT",
|
609
|
-
info,
|
664
|
+
info: info$1,
|
610
665
|
path: "/history-versions/:versionId/restore",
|
611
666
|
handler: "history-version.restoreVersion",
|
612
667
|
config: {
|
@@ -615,7 +670,7 @@ const historyVersionRouter = {
|
|
615
670
|
}
|
616
671
|
]
|
617
672
|
};
|
618
|
-
const routes$
|
673
|
+
const routes$2 = {
|
619
674
|
"history-version": historyVersionRouter
|
620
675
|
};
|
621
676
|
const historyVersion = {
|
@@ -662,21 +717,21 @@ const historyVersion = {
|
|
662
717
|
}
|
663
718
|
}
|
664
719
|
};
|
665
|
-
const getFeature = () => {
|
720
|
+
const getFeature$1 = () => {
|
666
721
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
667
722
|
return {
|
668
723
|
register({ strapi: strapi2 }) {
|
669
724
|
strapi2.get("models").add(historyVersion);
|
670
725
|
},
|
671
726
|
bootstrap({ strapi: strapi2 }) {
|
672
|
-
getService(strapi2, "lifecycles").bootstrap();
|
727
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
673
728
|
},
|
674
729
|
destroy({ strapi: strapi2 }) {
|
675
|
-
getService(strapi2, "lifecycles").destroy();
|
730
|
+
getService$1(strapi2, "lifecycles").destroy();
|
676
731
|
},
|
677
|
-
controllers: controllers$
|
678
|
-
services: services$
|
679
|
-
routes: routes$
|
732
|
+
controllers: controllers$2,
|
733
|
+
services: services$2,
|
734
|
+
routes: routes$2
|
680
735
|
};
|
681
736
|
}
|
682
737
|
return {
|
@@ -685,9 +740,201 @@ const getFeature = () => {
|
|
685
740
|
}
|
686
741
|
};
|
687
742
|
};
|
688
|
-
const history = getFeature();
|
743
|
+
const history = getFeature$1();
|
744
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
745
|
+
const previewRouter = {
|
746
|
+
type: "admin",
|
747
|
+
routes: [
|
748
|
+
{
|
749
|
+
method: "GET",
|
750
|
+
info,
|
751
|
+
path: "/preview/url/:contentType",
|
752
|
+
handler: "preview.getPreviewUrl",
|
753
|
+
config: {
|
754
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
755
|
+
}
|
756
|
+
}
|
757
|
+
]
|
758
|
+
};
|
759
|
+
const routes$1 = {
|
760
|
+
preview: previewRouter
|
761
|
+
};
|
762
|
+
function getService(strapi2, name) {
|
763
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
764
|
+
}
|
765
|
+
const getPreviewUrlSchema = yup__namespace.object().shape({
|
766
|
+
// Will be undefined for single types
|
767
|
+
documentId: yup__namespace.string(),
|
768
|
+
locale: yup__namespace.string().nullable(),
|
769
|
+
status: yup__namespace.string()
|
770
|
+
}).required();
|
771
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
772
|
+
await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
|
773
|
+
const newParams = fp.pick(["documentId", "locale", "status"], params);
|
774
|
+
const model = strapi2.getModel(uid2);
|
775
|
+
if (!model || model.modelType !== "contentType") {
|
776
|
+
throw new strapiUtils.errors.ValidationError("Invalid content type");
|
777
|
+
}
|
778
|
+
const isSingleType = model?.kind === "singleType";
|
779
|
+
if (!isSingleType && !params.documentId) {
|
780
|
+
throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
|
781
|
+
}
|
782
|
+
if (isSingleType) {
|
783
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
784
|
+
if (!doc) {
|
785
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
786
|
+
}
|
787
|
+
newParams.documentId = doc?.documentId;
|
788
|
+
}
|
789
|
+
if (!newParams.status) {
|
790
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
791
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
792
|
+
}
|
793
|
+
return newParams;
|
794
|
+
};
|
795
|
+
const createPreviewController = () => {
|
796
|
+
return {
|
797
|
+
/**
|
798
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
799
|
+
* in the Content Manager.
|
800
|
+
*/
|
801
|
+
async getPreviewUrl(ctx) {
|
802
|
+
const uid2 = ctx.params.contentType;
|
803
|
+
const query = ctx.request.query;
|
804
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
805
|
+
const previewService = getService(strapi, "preview");
|
806
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
807
|
+
if (!url) {
|
808
|
+
ctx.status = 204;
|
809
|
+
}
|
810
|
+
return {
|
811
|
+
data: { url }
|
812
|
+
};
|
813
|
+
}
|
814
|
+
};
|
815
|
+
};
|
816
|
+
const controllers$1 = {
|
817
|
+
preview: createPreviewController
|
818
|
+
/**
|
819
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
820
|
+
* passing a controller factory as the value, instead of a controller object directly
|
821
|
+
*/
|
822
|
+
};
|
823
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
824
|
+
const config = getService(strapi2, "preview-config");
|
825
|
+
return {
|
826
|
+
async getPreviewUrl(uid2, params) {
|
827
|
+
const handler = config.getPreviewHandler();
|
828
|
+
try {
|
829
|
+
return handler(uid2, params);
|
830
|
+
} catch (error) {
|
831
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
832
|
+
throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
|
833
|
+
}
|
834
|
+
return;
|
835
|
+
}
|
836
|
+
};
|
837
|
+
};
|
838
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
839
|
+
const middlewares = strapi.config.get("middlewares");
|
840
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
841
|
+
if (currentMiddleware === middleware.name) {
|
842
|
+
return middleware;
|
843
|
+
}
|
844
|
+
if (currentMiddleware.name === middleware.name) {
|
845
|
+
return fp.mergeWith(
|
846
|
+
(objValue, srcValue) => {
|
847
|
+
if (Array.isArray(objValue)) {
|
848
|
+
return objValue.concat(srcValue);
|
849
|
+
}
|
850
|
+
return void 0;
|
851
|
+
},
|
852
|
+
currentMiddleware,
|
853
|
+
middleware
|
854
|
+
);
|
855
|
+
}
|
856
|
+
return currentMiddleware;
|
857
|
+
});
|
858
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
859
|
+
};
|
860
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
861
|
+
return {
|
862
|
+
register() {
|
863
|
+
if (!this.isEnabled()) {
|
864
|
+
return;
|
865
|
+
}
|
866
|
+
const config = strapi2.config.get("admin.preview");
|
867
|
+
if (config.config?.allowedOrigins) {
|
868
|
+
extendMiddlewareConfiguration({
|
869
|
+
name: "strapi::security",
|
870
|
+
config: {
|
871
|
+
contentSecurityPolicy: {
|
872
|
+
directives: {
|
873
|
+
"frame-src": config.config.allowedOrigins
|
874
|
+
}
|
875
|
+
}
|
876
|
+
}
|
877
|
+
});
|
878
|
+
}
|
879
|
+
},
|
880
|
+
isEnabled() {
|
881
|
+
const config = strapi2.config.get("admin.preview");
|
882
|
+
if (!config) {
|
883
|
+
return false;
|
884
|
+
}
|
885
|
+
return config?.enabled ?? true;
|
886
|
+
},
|
887
|
+
/**
|
888
|
+
* Validate if the configuration is valid
|
889
|
+
*/
|
890
|
+
validate() {
|
891
|
+
if (!this.isEnabled()) {
|
892
|
+
return;
|
893
|
+
}
|
894
|
+
const handler = this.getPreviewHandler();
|
895
|
+
if (typeof handler !== "function") {
|
896
|
+
throw new strapiUtils.errors.ValidationError(
|
897
|
+
"Preview configuration is invalid. Handler must be a function"
|
898
|
+
);
|
899
|
+
}
|
900
|
+
},
|
901
|
+
/**
|
902
|
+
* Utility to get the preview handler from the configuration
|
903
|
+
*/
|
904
|
+
getPreviewHandler() {
|
905
|
+
const config = strapi2.config.get("admin.preview");
|
906
|
+
const emptyHandler = () => {
|
907
|
+
return void 0;
|
908
|
+
};
|
909
|
+
if (!this.isEnabled()) {
|
910
|
+
return emptyHandler;
|
911
|
+
}
|
912
|
+
return config?.config?.handler || emptyHandler;
|
913
|
+
}
|
914
|
+
};
|
915
|
+
};
|
916
|
+
const services$1 = {
|
917
|
+
preview: createPreviewService,
|
918
|
+
"preview-config": createPreviewConfigService
|
919
|
+
};
|
920
|
+
const getFeature = () => {
|
921
|
+
return {
|
922
|
+
register() {
|
923
|
+
const config = getService(strapi, "preview-config");
|
924
|
+
config.validate();
|
925
|
+
config.register();
|
926
|
+
},
|
927
|
+
bootstrap() {
|
928
|
+
},
|
929
|
+
routes: routes$1,
|
930
|
+
controllers: controllers$1,
|
931
|
+
services: services$1
|
932
|
+
};
|
933
|
+
};
|
934
|
+
const preview = getFeature();
|
689
935
|
const register = async ({ strapi: strapi2 }) => {
|
690
936
|
await history.register?.({ strapi: strapi2 });
|
937
|
+
await preview.register?.({ strapi: strapi2 });
|
691
938
|
};
|
692
939
|
const ALLOWED_WEBHOOK_EVENTS = {
|
693
940
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -697,11 +944,12 @@ const bootstrap = async () => {
|
|
697
944
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
698
945
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
699
946
|
});
|
700
|
-
getService$
|
701
|
-
await getService$
|
702
|
-
await getService$
|
703
|
-
await getService$
|
947
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
948
|
+
await getService$2("components").syncConfigurations();
|
949
|
+
await getService$2("content-types").syncConfigurations();
|
950
|
+
await getService$2("permission").registerPermissions();
|
704
951
|
await history.bootstrap?.({ strapi });
|
952
|
+
await preview.bootstrap?.({ strapi });
|
705
953
|
};
|
706
954
|
const destroy = async ({ strapi: strapi2 }) => {
|
707
955
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1191,7 +1439,8 @@ const admin = {
|
|
1191
1439
|
};
|
1192
1440
|
const routes = {
|
1193
1441
|
admin,
|
1194
|
-
...history.routes ? history.routes : {}
|
1442
|
+
...history.routes ? history.routes : {},
|
1443
|
+
...preview.routes ? preview.routes : {}
|
1195
1444
|
};
|
1196
1445
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1197
1446
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1202,6 +1451,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1202
1451
|
const hasPermissions = createPolicy({
|
1203
1452
|
name: "plugin::content-manager.hasPermissions",
|
1204
1453
|
validator: validateHasPermissionsInput,
|
1454
|
+
/**
|
1455
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1456
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1457
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1458
|
+
*/
|
1205
1459
|
handler(ctx, config = {}) {
|
1206
1460
|
const { actions = [], hasAtLeastOne = false } = config;
|
1207
1461
|
const { userAbility } = ctx.state;
|
@@ -1249,8 +1503,7 @@ const isSortable = (schema, name) => {
|
|
1249
1503
|
if (!___default.default.has(schema.attributes, name)) {
|
1250
1504
|
return false;
|
1251
1505
|
}
|
1252
|
-
if (schema.modelType === "component" && name === "id")
|
1253
|
-
return false;
|
1506
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1254
1507
|
const attribute = schema.attributes[name];
|
1255
1508
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1256
1509
|
return false;
|
@@ -1395,8 +1648,7 @@ const createDefaultSettings = async (schema) => {
|
|
1395
1648
|
};
|
1396
1649
|
};
|
1397
1650
|
const syncSettings = async (configuration, schema) => {
|
1398
|
-
if (fp.isEmpty(configuration.settings))
|
1399
|
-
return createDefaultSettings(schema);
|
1651
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1400
1652
|
const defaultField = getDefaultMainField(schema);
|
1401
1653
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1402
1654
|
return {
|
@@ -1443,7 +1695,7 @@ const createMetadasSchema = (schema) => {
|
|
1443
1695
|
if (!value) {
|
1444
1696
|
return strapiUtils.yup.string();
|
1445
1697
|
}
|
1446
|
-
const targetSchema = getService$
|
1698
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1447
1699
|
schema.attributes[key].targetModel
|
1448
1700
|
);
|
1449
1701
|
if (!targetSchema) {
|
@@ -1572,8 +1824,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1572
1824
|
}
|
1573
1825
|
switch (attribute.type) {
|
1574
1826
|
case "relation": {
|
1575
|
-
if (canCreate(attributePath))
|
1576
|
-
return body2;
|
1827
|
+
if (canCreate(attributePath)) return body2;
|
1577
1828
|
return fp.set(attributePath, { set: [] }, body2);
|
1578
1829
|
}
|
1579
1830
|
case "component": {
|
@@ -1583,8 +1834,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1583
1834
|
]);
|
1584
1835
|
}
|
1585
1836
|
default: {
|
1586
|
-
if (canCreate(attributePath))
|
1587
|
-
return body2;
|
1837
|
+
if (canCreate(attributePath)) return body2;
|
1588
1838
|
return fp.set(attributePath, null, body2);
|
1589
1839
|
}
|
1590
1840
|
}
|
@@ -1612,7 +1862,7 @@ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultiple
|
|
1612
1862
|
}
|
1613
1863
|
};
|
1614
1864
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1615
|
-
const documentMetadata2 = getService$
|
1865
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1616
1866
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1617
1867
|
let {
|
1618
1868
|
meta: { availableLocales, availableStatus }
|
@@ -1638,8 +1888,8 @@ const createDocument = async (ctx, opts) => {
|
|
1638
1888
|
const { userAbility, user } = ctx.state;
|
1639
1889
|
const { model } = ctx.params;
|
1640
1890
|
const { body } = ctx.request;
|
1641
|
-
const documentManager2 = getService$
|
1642
|
-
const permissionChecker2 = getService$
|
1891
|
+
const documentManager2 = getService$2("document-manager");
|
1892
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1643
1893
|
if (permissionChecker2.cannot.create()) {
|
1644
1894
|
throw new strapiUtils.errors.ForbiddenError();
|
1645
1895
|
}
|
@@ -1659,13 +1909,13 @@ const updateDocument = async (ctx, opts) => {
|
|
1659
1909
|
const { userAbility, user } = ctx.state;
|
1660
1910
|
const { id, model } = ctx.params;
|
1661
1911
|
const { body } = ctx.request;
|
1662
|
-
const documentManager2 = getService$
|
1663
|
-
const permissionChecker2 = getService$
|
1912
|
+
const documentManager2 = getService$2("document-manager");
|
1913
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1664
1914
|
if (permissionChecker2.cannot.update()) {
|
1665
1915
|
throw new strapiUtils.errors.ForbiddenError();
|
1666
1916
|
}
|
1667
1917
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1668
|
-
const populate = await getService$
|
1918
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1669
1919
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1670
1920
|
const [documentVersion, documentExists] = await Promise.all([
|
1671
1921
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
@@ -1682,7 +1932,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1682
1932
|
throw new strapiUtils.errors.ForbiddenError();
|
1683
1933
|
}
|
1684
1934
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1685
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1935
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1686
1936
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1687
1937
|
const sanitizedBody = await sanitizeFn(body);
|
1688
1938
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1696,14 +1946,14 @@ const collectionTypes = {
|
|
1696
1946
|
const { userAbility } = ctx.state;
|
1697
1947
|
const { model } = ctx.params;
|
1698
1948
|
const { query } = ctx.request;
|
1699
|
-
const documentMetadata2 = getService$
|
1700
|
-
const documentManager2 = getService$
|
1701
|
-
const permissionChecker2 = getService$
|
1949
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1950
|
+
const documentManager2 = getService$2("document-manager");
|
1951
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1702
1952
|
if (permissionChecker2.cannot.read()) {
|
1703
1953
|
return ctx.forbidden();
|
1704
1954
|
}
|
1705
1955
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1706
|
-
const populate = await getService$
|
1956
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1707
1957
|
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1708
1958
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1709
1959
|
{ ...permissionQuery, populate, locale, status },
|
@@ -1732,13 +1982,13 @@ const collectionTypes = {
|
|
1732
1982
|
async findOne(ctx) {
|
1733
1983
|
const { userAbility } = ctx.state;
|
1734
1984
|
const { model, id } = ctx.params;
|
1735
|
-
const documentManager2 = getService$
|
1736
|
-
const permissionChecker2 = getService$
|
1985
|
+
const documentManager2 = getService$2("document-manager");
|
1986
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1737
1987
|
if (permissionChecker2.cannot.read()) {
|
1738
1988
|
return ctx.forbidden();
|
1739
1989
|
}
|
1740
1990
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1741
|
-
const populate = await getService$
|
1991
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1742
1992
|
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1743
1993
|
const version = await documentManager2.findOne(id, model, {
|
1744
1994
|
populate,
|
@@ -1754,7 +2004,7 @@ const collectionTypes = {
|
|
1754
2004
|
permissionChecker2,
|
1755
2005
|
model,
|
1756
2006
|
// @ts-expect-error TODO: fix
|
1757
|
-
{ id, locale, publishedAt: null },
|
2007
|
+
{ documentId: id, locale, publishedAt: null },
|
1758
2008
|
{ availableLocales: true, availableStatus: false }
|
1759
2009
|
);
|
1760
2010
|
ctx.body = { data: {}, meta };
|
@@ -1769,7 +2019,7 @@ const collectionTypes = {
|
|
1769
2019
|
async create(ctx) {
|
1770
2020
|
const { userAbility } = ctx.state;
|
1771
2021
|
const { model } = ctx.params;
|
1772
|
-
const permissionChecker2 = getService$
|
2022
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1773
2023
|
const [totalEntries, document] = await Promise.all([
|
1774
2024
|
strapi.db.query(model).count(),
|
1775
2025
|
createDocument(ctx)
|
@@ -1790,7 +2040,7 @@ const collectionTypes = {
|
|
1790
2040
|
async update(ctx) {
|
1791
2041
|
const { userAbility } = ctx.state;
|
1792
2042
|
const { model } = ctx.params;
|
1793
|
-
const permissionChecker2 = getService$
|
2043
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1794
2044
|
const updatedVersion = await updateDocument(ctx);
|
1795
2045
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1796
2046
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1799,13 +2049,13 @@ const collectionTypes = {
|
|
1799
2049
|
const { userAbility, user } = ctx.state;
|
1800
2050
|
const { model, sourceId: id } = ctx.params;
|
1801
2051
|
const { body } = ctx.request;
|
1802
|
-
const documentManager2 = getService$
|
1803
|
-
const permissionChecker2 = getService$
|
2052
|
+
const documentManager2 = getService$2("document-manager");
|
2053
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1804
2054
|
if (permissionChecker2.cannot.create()) {
|
1805
2055
|
return ctx.forbidden();
|
1806
2056
|
}
|
1807
2057
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1808
|
-
const populate = await getService$
|
2058
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1809
2059
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1810
2060
|
const document = await documentManager2.findOne(id, model, {
|
1811
2061
|
populate,
|
@@ -1844,13 +2094,13 @@ const collectionTypes = {
|
|
1844
2094
|
async delete(ctx) {
|
1845
2095
|
const { userAbility } = ctx.state;
|
1846
2096
|
const { id, model } = ctx.params;
|
1847
|
-
const documentManager2 = getService$
|
1848
|
-
const permissionChecker2 = getService$
|
2097
|
+
const documentManager2 = getService$2("document-manager");
|
2098
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1849
2099
|
if (permissionChecker2.cannot.delete()) {
|
1850
2100
|
return ctx.forbidden();
|
1851
2101
|
}
|
1852
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1853
|
-
const populate = await getService$
|
2103
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1854
2104
|
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1855
2105
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1856
2106
|
if (documentLocales.length === 0) {
|
@@ -1872,19 +2122,42 @@ const collectionTypes = {
|
|
1872
2122
|
const { userAbility } = ctx.state;
|
1873
2123
|
const { id, model } = ctx.params;
|
1874
2124
|
const { body } = ctx.request;
|
1875
|
-
const documentManager2 = getService$
|
1876
|
-
const permissionChecker2 = getService$
|
2125
|
+
const documentManager2 = getService$2("document-manager");
|
2126
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1877
2127
|
if (permissionChecker2.cannot.publish()) {
|
1878
2128
|
return ctx.forbidden();
|
1879
2129
|
}
|
1880
2130
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1881
2131
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1882
|
-
const populate = await getService$
|
1883
|
-
|
2132
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2133
|
+
let document;
|
2134
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2135
|
+
const isCreate = fp.isNil(id);
|
2136
|
+
if (isCreate) {
|
2137
|
+
if (permissionChecker2.cannot.create()) {
|
2138
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2139
|
+
}
|
2140
|
+
document = await createDocument(ctx, { populate });
|
2141
|
+
}
|
2142
|
+
const isUpdate = !isCreate;
|
2143
|
+
if (isUpdate) {
|
2144
|
+
const documentExists = documentManager2.exists(model, id);
|
2145
|
+
if (!documentExists) {
|
2146
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
2147
|
+
}
|
2148
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2149
|
+
if (!document) {
|
2150
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2151
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2152
|
+
}
|
2153
|
+
document = await updateDocument(ctx);
|
2154
|
+
} else if (permissionChecker2.can.update(document)) {
|
2155
|
+
await updateDocument(ctx);
|
2156
|
+
}
|
2157
|
+
}
|
1884
2158
|
if (permissionChecker2.cannot.publish(document)) {
|
1885
2159
|
throw new strapiUtils.errors.ForbiddenError();
|
1886
2160
|
}
|
1887
|
-
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1888
2161
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1889
2162
|
locale
|
1890
2163
|
// TODO: Allow setting creator fields on publish
|
@@ -1904,13 +2177,13 @@ const collectionTypes = {
|
|
1904
2177
|
const { body } = ctx.request;
|
1905
2178
|
const { documentIds } = body;
|
1906
2179
|
await validateBulkActionInput(body);
|
1907
|
-
const documentManager2 = getService$
|
1908
|
-
const permissionChecker2 = getService$
|
2180
|
+
const documentManager2 = getService$2("document-manager");
|
2181
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1909
2182
|
if (permissionChecker2.cannot.publish()) {
|
1910
2183
|
return ctx.forbidden();
|
1911
2184
|
}
|
1912
2185
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1913
|
-
const populate = await getService$
|
2186
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1914
2187
|
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1915
2188
|
allowMultipleLocales: true
|
1916
2189
|
});
|
@@ -1935,12 +2208,14 @@ const collectionTypes = {
|
|
1935
2208
|
const { body } = ctx.request;
|
1936
2209
|
const { documentIds } = body;
|
1937
2210
|
await validateBulkActionInput(body);
|
1938
|
-
const documentManager2 = getService$
|
1939
|
-
const permissionChecker2 = getService$
|
2211
|
+
const documentManager2 = getService$2("document-manager");
|
2212
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1940
2213
|
if (permissionChecker2.cannot.unpublish()) {
|
1941
2214
|
return ctx.forbidden();
|
1942
2215
|
}
|
1943
|
-
const { locale } = await getDocumentLocaleAndStatus(body, model
|
2216
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2217
|
+
allowMultipleLocales: true
|
2218
|
+
});
|
1944
2219
|
const entityPromises = documentIds.map(
|
1945
2220
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1946
2221
|
);
|
@@ -1963,8 +2238,8 @@ const collectionTypes = {
|
|
1963
2238
|
const {
|
1964
2239
|
body: { discardDraft, ...body }
|
1965
2240
|
} = ctx.request;
|
1966
|
-
const documentManager2 = getService$
|
1967
|
-
const permissionChecker2 = getService$
|
2241
|
+
const documentManager2 = getService$2("document-manager");
|
2242
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1968
2243
|
if (permissionChecker2.cannot.unpublish()) {
|
1969
2244
|
return ctx.forbidden();
|
1970
2245
|
}
|
@@ -1972,7 +2247,7 @@ const collectionTypes = {
|
|
1972
2247
|
return ctx.forbidden();
|
1973
2248
|
}
|
1974
2249
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1975
|
-
const populate = await getService$
|
2250
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1976
2251
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1977
2252
|
const document = await documentManager2.findOne(id, model, {
|
1978
2253
|
populate,
|
@@ -2003,13 +2278,13 @@ const collectionTypes = {
|
|
2003
2278
|
const { userAbility } = ctx.state;
|
2004
2279
|
const { id, model } = ctx.params;
|
2005
2280
|
const { body } = ctx.request;
|
2006
|
-
const documentManager2 = getService$
|
2007
|
-
const permissionChecker2 = getService$
|
2281
|
+
const documentManager2 = getService$2("document-manager");
|
2282
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2008
2283
|
if (permissionChecker2.cannot.discard()) {
|
2009
2284
|
return ctx.forbidden();
|
2010
2285
|
}
|
2011
2286
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2012
|
-
const populate = await getService$
|
2287
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2013
2288
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2014
2289
|
const document = await documentManager2.findOne(id, model, {
|
2015
2290
|
populate,
|
@@ -2034,13 +2309,13 @@ const collectionTypes = {
|
|
2034
2309
|
const { query, body } = ctx.request;
|
2035
2310
|
const { documentIds } = body;
|
2036
2311
|
await validateBulkActionInput(body);
|
2037
|
-
const documentManager2 = getService$
|
2038
|
-
const permissionChecker2 = getService$
|
2312
|
+
const documentManager2 = getService$2("document-manager");
|
2313
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2039
2314
|
if (permissionChecker2.cannot.delete()) {
|
2040
2315
|
return ctx.forbidden();
|
2041
2316
|
}
|
2042
2317
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2043
|
-
const populate = await getService$
|
2318
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2044
2319
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2045
2320
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2046
2321
|
populate,
|
@@ -2061,13 +2336,13 @@ const collectionTypes = {
|
|
2061
2336
|
async countDraftRelations(ctx) {
|
2062
2337
|
const { userAbility } = ctx.state;
|
2063
2338
|
const { model, id } = ctx.params;
|
2064
|
-
const documentManager2 = getService$
|
2065
|
-
const permissionChecker2 = getService$
|
2339
|
+
const documentManager2 = getService$2("document-manager");
|
2340
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2066
2341
|
if (permissionChecker2.cannot.read()) {
|
2067
2342
|
return ctx.forbidden();
|
2068
2343
|
}
|
2069
2344
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2070
|
-
const populate = await getService$
|
2345
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2071
2346
|
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2072
2347
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2073
2348
|
if (!entity) {
|
@@ -2086,8 +2361,8 @@ const collectionTypes = {
|
|
2086
2361
|
const ids = ctx.request.query.documentIds;
|
2087
2362
|
const locale = ctx.request.query.locale;
|
2088
2363
|
const { model } = ctx.params;
|
2089
|
-
const documentManager2 = getService$
|
2090
|
-
const permissionChecker2 = getService$
|
2364
|
+
const documentManager2 = getService$2("document-manager");
|
2365
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2091
2366
|
if (permissionChecker2.cannot.read()) {
|
2092
2367
|
return ctx.forbidden();
|
2093
2368
|
}
|
@@ -2111,13 +2386,13 @@ const collectionTypes = {
|
|
2111
2386
|
};
|
2112
2387
|
const components$1 = {
|
2113
2388
|
findComponents(ctx) {
|
2114
|
-
const components2 = getService$
|
2115
|
-
const { toDto } = getService$
|
2389
|
+
const components2 = getService$2("components").findAllComponents();
|
2390
|
+
const { toDto } = getService$2("data-mapper");
|
2116
2391
|
ctx.body = { data: components2.map(toDto) };
|
2117
2392
|
},
|
2118
2393
|
async findComponentConfiguration(ctx) {
|
2119
2394
|
const { uid: uid2 } = ctx.params;
|
2120
|
-
const componentService = getService$
|
2395
|
+
const componentService = getService$2("components");
|
2121
2396
|
const component = componentService.findComponent(uid2);
|
2122
2397
|
if (!component) {
|
2123
2398
|
return ctx.notFound("component.notFound");
|
@@ -2134,7 +2409,7 @@ const components$1 = {
|
|
2134
2409
|
async updateComponentConfiguration(ctx) {
|
2135
2410
|
const { uid: uid2 } = ctx.params;
|
2136
2411
|
const { body } = ctx.request;
|
2137
|
-
const componentService = getService$
|
2412
|
+
const componentService = getService$2("components");
|
2138
2413
|
const component = componentService.findComponent(uid2);
|
2139
2414
|
if (!component) {
|
2140
2415
|
return ctx.notFound("component.notFound");
|
@@ -2168,12 +2443,12 @@ const contentTypes = {
|
|
2168
2443
|
} catch (error) {
|
2169
2444
|
return ctx.send({ error }, 400);
|
2170
2445
|
}
|
2171
|
-
const contentTypes2 = getService$
|
2172
|
-
const { toDto } = getService$
|
2446
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2447
|
+
const { toDto } = getService$2("data-mapper");
|
2173
2448
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2174
2449
|
},
|
2175
2450
|
async findContentTypesSettings(ctx) {
|
2176
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2451
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2177
2452
|
const contentTypes2 = await findAllContentTypes();
|
2178
2453
|
const configurations = await Promise.all(
|
2179
2454
|
contentTypes2.map(async (contentType) => {
|
@@ -2187,7 +2462,7 @@ const contentTypes = {
|
|
2187
2462
|
},
|
2188
2463
|
async findContentTypeConfiguration(ctx) {
|
2189
2464
|
const { uid: uid2 } = ctx.params;
|
2190
|
-
const contentTypeService = getService$
|
2465
|
+
const contentTypeService = getService$2("content-types");
|
2191
2466
|
const contentType = await contentTypeService.findContentType(uid2);
|
2192
2467
|
if (!contentType) {
|
2193
2468
|
return ctx.notFound("contentType.notFound");
|
@@ -2209,13 +2484,13 @@ const contentTypes = {
|
|
2209
2484
|
const { userAbility } = ctx.state;
|
2210
2485
|
const { uid: uid2 } = ctx.params;
|
2211
2486
|
const { body } = ctx.request;
|
2212
|
-
const contentTypeService = getService$
|
2213
|
-
const metricsService = getService$
|
2487
|
+
const contentTypeService = getService$2("content-types");
|
2488
|
+
const metricsService = getService$2("metrics");
|
2214
2489
|
const contentType = await contentTypeService.findContentType(uid2);
|
2215
2490
|
if (!contentType) {
|
2216
2491
|
return ctx.notFound("contentType.notFound");
|
2217
2492
|
}
|
2218
|
-
if (!getService$
|
2493
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2219
2494
|
return ctx.forbidden();
|
2220
2495
|
}
|
2221
2496
|
let input;
|
@@ -2248,10 +2523,10 @@ const contentTypes = {
|
|
2248
2523
|
};
|
2249
2524
|
const init = {
|
2250
2525
|
getInitData(ctx) {
|
2251
|
-
const { toDto } = getService$
|
2252
|
-
const { findAllComponents } = getService$
|
2253
|
-
const { getAllFieldSizes } = getService$
|
2254
|
-
const { findAllContentTypes } = getService$
|
2526
|
+
const { toDto } = getService$2("data-mapper");
|
2527
|
+
const { findAllComponents } = getService$2("components");
|
2528
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2529
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2255
2530
|
ctx.body = {
|
2256
2531
|
data: {
|
2257
2532
|
fieldSizes: getAllFieldSizes(),
|
@@ -2287,36 +2562,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2287
2562
|
params.filters.$and.push(filtersClause);
|
2288
2563
|
};
|
2289
2564
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2290
|
-
const permissionChecker2 = getService$
|
2565
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2291
2566
|
userAbility,
|
2292
2567
|
model: model.uid
|
2293
2568
|
});
|
2294
|
-
|
2569
|
+
const isMainFieldListable = isListable(model, mainField);
|
2570
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2571
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2295
2572
|
return "id";
|
2296
2573
|
}
|
2297
|
-
if (
|
2298
|
-
|
2299
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2300
|
-
userAbility,
|
2301
|
-
model: "plugin::users-permissions.user"
|
2302
|
-
});
|
2303
|
-
if (userPermissionChecker.can.read()) {
|
2304
|
-
return "name";
|
2305
|
-
}
|
2306
|
-
}
|
2307
|
-
return "id";
|
2574
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2575
|
+
return "name";
|
2308
2576
|
}
|
2309
2577
|
return mainField;
|
2310
2578
|
};
|
2311
|
-
const addStatusToRelations = async (
|
2312
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2579
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2580
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2313
2581
|
return relations2;
|
2314
2582
|
}
|
2315
|
-
const documentMetadata2 = getService$
|
2316
|
-
|
2583
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2584
|
+
if (!relations2.length) {
|
2585
|
+
return relations2;
|
2586
|
+
}
|
2587
|
+
const firstRelation = relations2[0];
|
2588
|
+
const filters = {
|
2589
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2590
|
+
// NOTE: find the "opposite" status
|
2591
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2592
|
+
};
|
2593
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2594
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2595
|
+
filters
|
2596
|
+
});
|
2317
2597
|
return relations2.map((relation) => {
|
2318
|
-
const availableStatuses =
|
2319
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2598
|
+
const availableStatuses = availableStatus.filter(
|
2599
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2320
2600
|
);
|
2321
2601
|
return {
|
2322
2602
|
...relation,
|
@@ -2337,11 +2617,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2337
2617
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2338
2618
|
const isSourceLocalized = isLocalized(sourceModel);
|
2339
2619
|
const isTargetLocalized = isLocalized(targetModel);
|
2340
|
-
let validatedLocale = locale;
|
2341
|
-
if (!targetModel || !isTargetLocalized)
|
2342
|
-
validatedLocale = void 0;
|
2343
2620
|
return {
|
2344
|
-
locale
|
2621
|
+
locale,
|
2345
2622
|
isSourceLocalized,
|
2346
2623
|
isTargetLocalized
|
2347
2624
|
};
|
@@ -2350,8 +2627,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2350
2627
|
const sourceModel = strapi.getModel(sourceUid);
|
2351
2628
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2352
2629
|
const isSourceDP = isDP(sourceModel);
|
2353
|
-
if (!isSourceDP)
|
2354
|
-
return { status: void 0 };
|
2630
|
+
if (!isSourceDP) return { status: void 0 };
|
2355
2631
|
switch (status) {
|
2356
2632
|
case "published":
|
2357
2633
|
return { status: "published" };
|
@@ -2381,7 +2657,7 @@ const relations = {
|
|
2381
2657
|
ctx.request?.query?.locale
|
2382
2658
|
);
|
2383
2659
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2384
|
-
const permissionChecker2 = getService$
|
2660
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2385
2661
|
userAbility,
|
2386
2662
|
model
|
2387
2663
|
});
|
@@ -2406,7 +2682,7 @@ const relations = {
|
|
2406
2682
|
where.id = id;
|
2407
2683
|
}
|
2408
2684
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2409
|
-
const populate = await getService$
|
2685
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2410
2686
|
const currentEntity = await strapi.db.query(model).findOne({
|
2411
2687
|
where,
|
2412
2688
|
populate
|
@@ -2421,7 +2697,7 @@ const relations = {
|
|
2421
2697
|
}
|
2422
2698
|
entryId = currentEntity.id;
|
2423
2699
|
}
|
2424
|
-
const modelConfig = isComponent2 ? await getService$
|
2700
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2425
2701
|
const targetSchema = strapi.getModel(targetUid);
|
2426
2702
|
const mainField = fp.flow(
|
2427
2703
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2444,7 +2720,7 @@ const relations = {
|
|
2444
2720
|
attribute,
|
2445
2721
|
fieldsToSelect,
|
2446
2722
|
mainField,
|
2447
|
-
source: { schema: sourceSchema },
|
2723
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2448
2724
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2449
2725
|
sourceSchema,
|
2450
2726
|
targetSchema,
|
@@ -2466,7 +2742,8 @@ const relations = {
|
|
2466
2742
|
fieldsToSelect,
|
2467
2743
|
mainField,
|
2468
2744
|
source: {
|
2469
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2745
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2746
|
+
isLocalized: isSourceLocalized
|
2470
2747
|
},
|
2471
2748
|
target: {
|
2472
2749
|
schema: { uid: targetUid },
|
@@ -2474,7 +2751,7 @@ const relations = {
|
|
2474
2751
|
}
|
2475
2752
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2476
2753
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2477
|
-
const permissionChecker2 = getService$
|
2754
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2478
2755
|
userAbility: ctx.state.userAbility,
|
2479
2756
|
model: targetUid
|
2480
2757
|
});
|
@@ -2504,12 +2781,16 @@ const relations = {
|
|
2504
2781
|
} else {
|
2505
2782
|
where.id = id;
|
2506
2783
|
}
|
2507
|
-
|
2508
|
-
|
2784
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2785
|
+
if (!fp.isEmpty(publishedAt)) {
|
2786
|
+
where[`${alias}.published_at`] = publishedAt;
|
2509
2787
|
}
|
2510
|
-
if (
|
2788
|
+
if (isTargetLocalized && locale) {
|
2511
2789
|
where[`${alias}.locale`] = locale;
|
2512
2790
|
}
|
2791
|
+
if (isSourceLocalized && locale) {
|
2792
|
+
where.locale = locale;
|
2793
|
+
}
|
2513
2794
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2514
2795
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2515
2796
|
}
|
@@ -2527,7 +2808,8 @@ const relations = {
|
|
2527
2808
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2528
2809
|
});
|
2529
2810
|
}
|
2530
|
-
const
|
2811
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2812
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2531
2813
|
ctx.body = {
|
2532
2814
|
...res,
|
2533
2815
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2542,29 +2824,39 @@ const relations = {
|
|
2542
2824
|
attribute,
|
2543
2825
|
targetField,
|
2544
2826
|
fieldsToSelect,
|
2545
|
-
|
2546
|
-
|
2547
|
-
}
|
2548
|
-
target: {
|
2549
|
-
schema: { uid: targetUid }
|
2550
|
-
}
|
2827
|
+
status,
|
2828
|
+
source: { schema: sourceSchema },
|
2829
|
+
target: { schema: targetSchema }
|
2551
2830
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2552
|
-
const
|
2831
|
+
const { uid: sourceUid } = sourceSchema;
|
2832
|
+
const { uid: targetUid } = targetSchema;
|
2833
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2553
2834
|
const dbQuery = strapi.db.query(sourceUid);
|
2554
2835
|
const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2836
|
+
const filters = {};
|
2837
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2838
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2839
|
+
if (status === "published") {
|
2840
|
+
filters.publishedAt = { $notNull: true };
|
2841
|
+
} else {
|
2842
|
+
filters.publishedAt = { $null: true };
|
2843
|
+
}
|
2844
|
+
}
|
2845
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2846
|
+
filters.publishedAt = { $null: true };
|
2847
|
+
}
|
2555
2848
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2556
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2849
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2557
2850
|
ordering: "desc",
|
2558
2851
|
page: ctx.request.query.page,
|
2559
|
-
pageSize: ctx.request.query.pageSize
|
2852
|
+
pageSize: ctx.request.query.pageSize,
|
2853
|
+
filters
|
2560
2854
|
});
|
2561
2855
|
const loadedIds = res.results.map((item) => item.id);
|
2562
2856
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2563
2857
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2564
2858
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2565
|
-
ordering: "desc"
|
2566
|
-
page: ctx.request.query.page,
|
2567
|
-
pageSize: ctx.request.query.pageSize
|
2859
|
+
ordering: "desc"
|
2568
2860
|
});
|
2569
2861
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2570
2862
|
ctx.body = {
|
@@ -2579,10 +2871,10 @@ const relations = {
|
|
2579
2871
|
}
|
2580
2872
|
};
|
2581
2873
|
const buildPopulateFromQuery = async (query, model) => {
|
2582
|
-
return getService$
|
2874
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2583
2875
|
};
|
2584
2876
|
const findDocument = async (query, uid2, opts = {}) => {
|
2585
|
-
const documentManager2 = getService$
|
2877
|
+
const documentManager2 = getService$2("document-manager");
|
2586
2878
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2587
2879
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2588
2880
|
};
|
@@ -2590,8 +2882,8 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2590
2882
|
const { user, userAbility } = ctx.state;
|
2591
2883
|
const { model } = ctx.params;
|
2592
2884
|
const { body, query } = ctx.request;
|
2593
|
-
const documentManager2 = getService$
|
2594
|
-
const permissionChecker2 = getService$
|
2885
|
+
const documentManager2 = getService$2("document-manager");
|
2886
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2595
2887
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2596
2888
|
throw new strapiUtils.errors.ForbiddenError();
|
2597
2889
|
}
|
@@ -2632,7 +2924,7 @@ const singleTypes = {
|
|
2632
2924
|
const { userAbility } = ctx.state;
|
2633
2925
|
const { model } = ctx.params;
|
2634
2926
|
const { query = {} } = ctx.request;
|
2635
|
-
const permissionChecker2 = getService$
|
2927
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2636
2928
|
if (permissionChecker2.cannot.read()) {
|
2637
2929
|
return ctx.forbidden();
|
2638
2930
|
}
|
@@ -2651,7 +2943,7 @@ const singleTypes = {
|
|
2651
2943
|
permissionChecker2,
|
2652
2944
|
model,
|
2653
2945
|
// @ts-expect-error - fix types
|
2654
|
-
{
|
2946
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2655
2947
|
{ availableLocales: true, availableStatus: false }
|
2656
2948
|
);
|
2657
2949
|
ctx.body = { data: {}, meta };
|
@@ -2666,7 +2958,7 @@ const singleTypes = {
|
|
2666
2958
|
async createOrUpdate(ctx) {
|
2667
2959
|
const { userAbility } = ctx.state;
|
2668
2960
|
const { model } = ctx.params;
|
2669
|
-
const permissionChecker2 = getService$
|
2961
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2670
2962
|
const document = await createOrUpdateDocument(ctx);
|
2671
2963
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2672
2964
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2675,8 +2967,8 @@ const singleTypes = {
|
|
2675
2967
|
const { userAbility } = ctx.state;
|
2676
2968
|
const { model } = ctx.params;
|
2677
2969
|
const { query = {} } = ctx.request;
|
2678
|
-
const documentManager2 = getService$
|
2679
|
-
const permissionChecker2 = getService$
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2680
2972
|
if (permissionChecker2.cannot.delete()) {
|
2681
2973
|
return ctx.forbidden();
|
2682
2974
|
}
|
@@ -2704,8 +2996,8 @@ const singleTypes = {
|
|
2704
2996
|
const { userAbility } = ctx.state;
|
2705
2997
|
const { model } = ctx.params;
|
2706
2998
|
const { query = {} } = ctx.request;
|
2707
|
-
const documentManager2 = getService$
|
2708
|
-
const permissionChecker2 = getService$
|
2999
|
+
const documentManager2 = getService$2("document-manager");
|
3000
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2709
3001
|
if (permissionChecker2.cannot.publish()) {
|
2710
3002
|
return ctx.forbidden();
|
2711
3003
|
}
|
@@ -2733,8 +3025,8 @@ const singleTypes = {
|
|
2733
3025
|
body: { discardDraft, ...body },
|
2734
3026
|
query = {}
|
2735
3027
|
} = ctx.request;
|
2736
|
-
const documentManager2 = getService$
|
2737
|
-
const permissionChecker2 = getService$
|
3028
|
+
const documentManager2 = getService$2("document-manager");
|
3029
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2738
3030
|
if (permissionChecker2.cannot.unpublish()) {
|
2739
3031
|
return ctx.forbidden();
|
2740
3032
|
}
|
@@ -2768,8 +3060,8 @@ const singleTypes = {
|
|
2768
3060
|
const { userAbility } = ctx.state;
|
2769
3061
|
const { model } = ctx.params;
|
2770
3062
|
const { body, query = {} } = ctx.request;
|
2771
|
-
const documentManager2 = getService$
|
2772
|
-
const permissionChecker2 = getService$
|
3063
|
+
const documentManager2 = getService$2("document-manager");
|
3064
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2773
3065
|
if (permissionChecker2.cannot.discard()) {
|
2774
3066
|
return ctx.forbidden();
|
2775
3067
|
}
|
@@ -2792,8 +3084,8 @@ const singleTypes = {
|
|
2792
3084
|
const { userAbility } = ctx.state;
|
2793
3085
|
const { model } = ctx.params;
|
2794
3086
|
const { query } = ctx.request;
|
2795
|
-
const documentManager2 = getService$
|
2796
|
-
const permissionChecker2 = getService$
|
3087
|
+
const documentManager2 = getService$2("document-manager");
|
3088
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2797
3089
|
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2798
3090
|
if (permissionChecker2.cannot.read()) {
|
2799
3091
|
return ctx.forbidden();
|
@@ -2817,7 +3109,7 @@ const uid$1 = {
|
|
2817
3109
|
const { query = {} } = ctx.request;
|
2818
3110
|
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2819
3111
|
await validateUIDField(contentTypeUID, field);
|
2820
|
-
const uidService = getService$
|
3112
|
+
const uidService = getService$2("uid");
|
2821
3113
|
ctx.body = {
|
2822
3114
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2823
3115
|
};
|
@@ -2829,7 +3121,7 @@ const uid$1 = {
|
|
2829
3121
|
const { query = {} } = ctx.request;
|
2830
3122
|
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2831
3123
|
await validateUIDField(contentTypeUID, field);
|
2832
|
-
const uidService = getService$
|
3124
|
+
const uidService = getService$2("uid");
|
2833
3125
|
const isAvailable = await uidService.checkUIDAvailability({
|
2834
3126
|
contentTypeUID,
|
2835
3127
|
field,
|
@@ -2850,7 +3142,8 @@ const controllers = {
|
|
2850
3142
|
relations,
|
2851
3143
|
"single-types": singleTypes,
|
2852
3144
|
uid: uid$1,
|
2853
|
-
...history.controllers ? history.controllers : {}
|
3145
|
+
...history.controllers ? history.controllers : {},
|
3146
|
+
...preview.controllers ? preview.controllers : {}
|
2854
3147
|
};
|
2855
3148
|
const keys = {
|
2856
3149
|
CONFIGURATION: "configuration"
|
@@ -2979,18 +3272,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2979
3272
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2980
3273
|
___default.default.set(acc, [key], updatedMeta);
|
2981
3274
|
}
|
2982
|
-
if (!___default.default.has(edit, "mainField"))
|
2983
|
-
return acc;
|
3275
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2984
3276
|
if (!isRelation$1(attr)) {
|
2985
3277
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2986
3278
|
___default.default.set(acc, [key], updatedMeta);
|
2987
3279
|
return acc;
|
2988
3280
|
}
|
2989
|
-
if (edit.mainField === "id")
|
2990
|
-
return acc;
|
3281
|
+
if (edit.mainField === "id") return acc;
|
2991
3282
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2992
|
-
if (!targetSchema)
|
2993
|
-
return acc;
|
3283
|
+
if (!targetSchema) return acc;
|
2994
3284
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2995
3285
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2996
3286
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -3001,12 +3291,12 @@ async function syncMetadatas(configuration, schema) {
|
|
3001
3291
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
3002
3292
|
}
|
3003
3293
|
const getTargetSchema = (targetModel) => {
|
3004
|
-
return getService$
|
3294
|
+
return getService$2("content-types").findContentType(targetModel);
|
3005
3295
|
};
|
3006
3296
|
const DEFAULT_LIST_LENGTH = 4;
|
3007
3297
|
const MAX_ROW_SIZE = 12;
|
3008
3298
|
const isAllowedFieldSize = (type, size) => {
|
3009
|
-
const { getFieldSize } = getService$
|
3299
|
+
const { getFieldSize } = getService$2("field-sizes");
|
3010
3300
|
const fieldSize = getFieldSize(type);
|
3011
3301
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
3012
3302
|
return false;
|
@@ -3014,7 +3304,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
3014
3304
|
return size <= MAX_ROW_SIZE;
|
3015
3305
|
};
|
3016
3306
|
const getDefaultFieldSize = (attribute) => {
|
3017
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3307
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
3018
3308
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
3019
3309
|
};
|
3020
3310
|
async function createDefaultLayouts(schema) {
|
@@ -3035,8 +3325,7 @@ function createDefaultEditLayout(schema) {
|
|
3035
3325
|
return appendToEditLayout([], keys2, schema);
|
3036
3326
|
}
|
3037
3327
|
function syncLayouts(configuration, schema) {
|
3038
|
-
if (___default.default.isEmpty(configuration.layouts))
|
3039
|
-
return createDefaultLayouts(schema);
|
3328
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3040
3329
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3041
3330
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3042
3331
|
const cleanEditRelations = editRelations.filter(
|
@@ -3047,9 +3336,8 @@ function syncLayouts(configuration, schema) {
|
|
3047
3336
|
for (const row of edit) {
|
3048
3337
|
const newRow = [];
|
3049
3338
|
for (const el of row) {
|
3050
|
-
if (!hasEditableAttribute(schema, el.name))
|
3051
|
-
|
3052
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3339
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3340
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3053
3341
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3054
3342
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3055
3343
|
elementsToReAppend.push(el.name);
|
@@ -3079,8 +3367,7 @@ function syncLayouts(configuration, schema) {
|
|
3079
3367
|
};
|
3080
3368
|
}
|
3081
3369
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3082
|
-
if (keysToAppend.length === 0)
|
3083
|
-
return layout;
|
3370
|
+
if (keysToAppend.length === 0) return layout;
|
3084
3371
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3085
3372
|
if (!layout[currentRowIndex]) {
|
3086
3373
|
layout[currentRowIndex] = [];
|
@@ -3189,17 +3476,17 @@ const configurationService$1 = createConfigurationService({
|
|
3189
3476
|
isComponent: true,
|
3190
3477
|
prefix: STORE_KEY_PREFIX,
|
3191
3478
|
getModels() {
|
3192
|
-
const { toContentManagerModel } = getService$
|
3479
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3193
3480
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3194
3481
|
}
|
3195
3482
|
});
|
3196
3483
|
const components = ({ strapi: strapi2 }) => ({
|
3197
3484
|
findAllComponents() {
|
3198
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3199
3486
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3200
3487
|
},
|
3201
3488
|
findComponent(uid2) {
|
3202
|
-
const { toContentManagerModel } = getService$
|
3489
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3203
3490
|
const component = strapi2.components[uid2];
|
3204
3491
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3205
3492
|
},
|
@@ -3250,17 +3537,17 @@ const configurationService = createConfigurationService({
|
|
3250
3537
|
storeUtils,
|
3251
3538
|
prefix: "content_types",
|
3252
3539
|
getModels() {
|
3253
|
-
const { toContentManagerModel } = getService$
|
3540
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3254
3541
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3255
3542
|
}
|
3256
3543
|
});
|
3257
3544
|
const service = ({ strapi: strapi2 }) => ({
|
3258
3545
|
findAllContentTypes() {
|
3259
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3260
3547
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3261
3548
|
},
|
3262
3549
|
findContentType(uid2) {
|
3263
|
-
const { toContentManagerModel } = getService$
|
3550
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3264
3551
|
const contentType = strapi2.contentTypes[uid2];
|
3265
3552
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3266
3553
|
},
|
@@ -3289,7 +3576,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3289
3576
|
return this.findConfiguration(contentType);
|
3290
3577
|
},
|
3291
3578
|
findComponentsConfigurations(contentType) {
|
3292
|
-
return getService$
|
3579
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3293
3580
|
},
|
3294
3581
|
syncConfigurations() {
|
3295
3582
|
return configurationService.syncConfigurations();
|
@@ -3470,12 +3757,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3470
3757
|
ability: userAbility,
|
3471
3758
|
model
|
3472
3759
|
});
|
3473
|
-
const
|
3760
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3761
|
+
const toSubject = (entity) => {
|
3762
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3763
|
+
};
|
3474
3764
|
const can = (action, entity, field) => {
|
3475
|
-
|
3765
|
+
const subject = toSubject(entity);
|
3766
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3767
|
+
return (
|
3768
|
+
// Test the original action to see if it passes
|
3769
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3770
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3771
|
+
);
|
3476
3772
|
};
|
3477
3773
|
const cannot = (action, entity, field) => {
|
3478
|
-
|
3774
|
+
const subject = toSubject(entity);
|
3775
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3776
|
+
return (
|
3777
|
+
// Test both the original action
|
3778
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3779
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3780
|
+
);
|
3479
3781
|
};
|
3480
3782
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3481
3783
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3546,7 +3848,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3546
3848
|
return userAbility.can(action);
|
3547
3849
|
},
|
3548
3850
|
async registerPermissions() {
|
3549
|
-
const displayedContentTypes = getService$
|
3851
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3550
3852
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3551
3853
|
const actions = [
|
3552
3854
|
{
|
@@ -3631,6 +3933,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3631
3933
|
if (initialPopulate) {
|
3632
3934
|
return initialPopulate;
|
3633
3935
|
}
|
3936
|
+
if (attributeName === "localizations") {
|
3937
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3938
|
+
return {
|
3939
|
+
populate: validationPopulate.populate
|
3940
|
+
};
|
3941
|
+
}
|
3634
3942
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3635
3943
|
return true;
|
3636
3944
|
}
|
@@ -3690,6 +3998,9 @@ const getDeepPopulate = (uid2, {
|
|
3690
3998
|
return {};
|
3691
3999
|
}
|
3692
4000
|
const model = strapi.getModel(uid2);
|
4001
|
+
if (!model) {
|
4002
|
+
return {};
|
4003
|
+
}
|
3693
4004
|
return Object.keys(model.attributes).reduce(
|
3694
4005
|
(populateAcc, attributeName) => fp.merge(
|
3695
4006
|
populateAcc,
|
@@ -3709,40 +4020,46 @@ const getDeepPopulate = (uid2, {
|
|
3709
4020
|
{}
|
3710
4021
|
);
|
3711
4022
|
};
|
3712
|
-
const
|
3713
|
-
|
3714
|
-
|
3715
|
-
countOne = false,
|
3716
|
-
maxLevel = Infinity
|
3717
|
-
} = {}, level = 1) => {
|
3718
|
-
if (level > maxLevel) {
|
4023
|
+
const getPopulateForValidation = (uid2) => {
|
4024
|
+
const model = strapi.getModel(uid2);
|
4025
|
+
if (!model) {
|
3719
4026
|
return {};
|
3720
4027
|
}
|
3721
|
-
const model = strapi.getModel(uid2);
|
3722
4028
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3723
|
-
if (
|
4029
|
+
if (isScalarAttribute(attribute)) {
|
4030
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4031
|
+
populateAcc.fields = populateAcc.fields || [];
|
4032
|
+
populateAcc.fields.push(attributeName);
|
4033
|
+
}
|
3724
4034
|
return populateAcc;
|
3725
4035
|
}
|
3726
|
-
if (
|
3727
|
-
|
3728
|
-
|
3729
|
-
|
4036
|
+
if (isComponent(attribute)) {
|
4037
|
+
const component = attribute.component;
|
4038
|
+
const componentResult = getPopulateForValidation(component);
|
4039
|
+
if (Object.keys(componentResult).length > 0) {
|
4040
|
+
populateAcc.populate = populateAcc.populate || {};
|
4041
|
+
populateAcc.populate[attributeName] = componentResult;
|
4042
|
+
}
|
4043
|
+
return populateAcc;
|
3730
4044
|
}
|
3731
|
-
|
3732
|
-
|
3733
|
-
|
3734
|
-
|
3735
|
-
|
3736
|
-
|
3737
|
-
|
3738
|
-
|
3739
|
-
|
3740
|
-
countOne,
|
3741
|
-
maxLevel
|
4045
|
+
if (isDynamicZone(attribute)) {
|
4046
|
+
const components2 = attribute.components;
|
4047
|
+
const componentsResult = (components2 || []).reduce(
|
4048
|
+
(acc, componentUID) => {
|
4049
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4050
|
+
if (Object.keys(componentResult).length > 0) {
|
4051
|
+
acc[componentUID] = componentResult;
|
4052
|
+
}
|
4053
|
+
return acc;
|
3742
4054
|
},
|
3743
|
-
|
3744
|
-
)
|
3745
|
-
|
4055
|
+
{}
|
4056
|
+
);
|
4057
|
+
if (Object.keys(componentsResult).length > 0) {
|
4058
|
+
populateAcc.populate = populateAcc.populate || {};
|
4059
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4060
|
+
}
|
4061
|
+
}
|
4062
|
+
return populateAcc;
|
3746
4063
|
}, {});
|
3747
4064
|
};
|
3748
4065
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3822,7 +4139,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3822
4139
|
return populateQuery;
|
3823
4140
|
};
|
3824
4141
|
const buildDeepPopulate = (uid2) => {
|
3825
|
-
return getService$
|
4142
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3826
4143
|
};
|
3827
4144
|
const populateBuilder = (uid2) => {
|
3828
4145
|
let getInitialPopulate = async () => {
|
@@ -3984,7 +4301,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3984
4301
|
"locale",
|
3985
4302
|
"updatedAt",
|
3986
4303
|
"createdAt",
|
3987
|
-
"status",
|
3988
4304
|
"publishedAt",
|
3989
4305
|
"documentId"
|
3990
4306
|
];
|
@@ -4005,34 +4321,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4005
4321
|
/**
|
4006
4322
|
* Returns available locales of a document for the current status
|
4007
4323
|
*/
|
4008
|
-
async getAvailableLocales(uid2, version, allVersions
|
4324
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
4009
4325
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
4010
|
-
|
4326
|
+
if (version.locale) {
|
4327
|
+
delete versionsByLocale[version.locale];
|
4328
|
+
}
|
4011
4329
|
const model = strapi2.getModel(uid2);
|
4012
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4013
|
-
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4014
|
-
({ key }, { remove }) => {
|
4015
|
-
if (keysToKeep.includes(key)) {
|
4016
|
-
return;
|
4017
|
-
}
|
4018
|
-
remove(key);
|
4019
|
-
},
|
4020
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4021
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4022
|
-
localeVersion
|
4023
|
-
);
|
4024
4330
|
const mappingResult = await strapiUtils.async.map(
|
4025
4331
|
Object.values(versionsByLocale),
|
4026
4332
|
async (localeVersions) => {
|
4027
|
-
const mappedLocaleVersions = await strapiUtils.async.map(
|
4028
|
-
localeVersions,
|
4029
|
-
traversalFunction
|
4030
|
-
);
|
4031
4333
|
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4032
|
-
return
|
4334
|
+
return localeVersions[0];
|
4033
4335
|
}
|
4034
|
-
const draftVersion =
|
4035
|
-
const otherVersions =
|
4336
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4337
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4036
4338
|
if (!draftVersion) {
|
4037
4339
|
return;
|
4038
4340
|
}
|
@@ -4054,8 +4356,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4054
4356
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4055
4357
|
return matchLocale && matchStatus;
|
4056
4358
|
});
|
4057
|
-
if (!availableStatus)
|
4058
|
-
return availableStatus;
|
4359
|
+
if (!availableStatus) return availableStatus;
|
4059
4360
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4060
4361
|
},
|
4061
4362
|
/**
|
@@ -4065,18 +4366,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4065
4366
|
* @returns
|
4066
4367
|
*/
|
4067
4368
|
async getManyAvailableStatus(uid2, documents) {
|
4068
|
-
if (!documents.length)
|
4069
|
-
return [];
|
4369
|
+
if (!documents.length) return [];
|
4070
4370
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4071
|
-
const
|
4072
|
-
const
|
4073
|
-
|
4074
|
-
|
4075
|
-
|
4076
|
-
|
4077
|
-
|
4078
|
-
|
4079
|
-
|
4371
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4372
|
+
const where = {
|
4373
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4374
|
+
publishedAt: { $null: status === "published" }
|
4375
|
+
};
|
4376
|
+
if (locales.length) {
|
4377
|
+
where.locale = { $in: locales };
|
4378
|
+
}
|
4379
|
+
return strapi2.query(uid2).findMany({
|
4380
|
+
where,
|
4381
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4080
4382
|
});
|
4081
4383
|
},
|
4082
4384
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4093,10 +4395,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4093
4395
|
} else if (otherVersion) {
|
4094
4396
|
draftVersion = otherVersion;
|
4095
4397
|
}
|
4096
|
-
if (!draftVersion)
|
4097
|
-
|
4098
|
-
if (!publishedVersion)
|
4099
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4398
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4399
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4100
4400
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4101
4401
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4102
4402
|
},
|
@@ -4104,11 +4404,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4104
4404
|
// We could refactor this so the locales are only loaded when they're
|
4105
4405
|
// needed. e.g. in the bulk locale action modal.
|
4106
4406
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4107
|
-
const populate =
|
4108
|
-
const
|
4109
|
-
where: { documentId: version.documentId },
|
4407
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4408
|
+
const params = {
|
4110
4409
|
populate: {
|
4111
|
-
// Populate only fields that require validation for bulk locale actions
|
4112
4410
|
...populate,
|
4113
4411
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4114
4412
|
createdBy: {
|
@@ -4117,9 +4415,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4117
4415
|
updatedBy: {
|
4118
4416
|
select: ["id", "firstname", "lastname", "email"]
|
4119
4417
|
}
|
4418
|
+
},
|
4419
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4420
|
+
filters: {
|
4421
|
+
documentId: version.documentId
|
4120
4422
|
}
|
4121
|
-
}
|
4122
|
-
const
|
4423
|
+
};
|
4424
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4425
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4426
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
4123
4427
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4124
4428
|
return {
|
4125
4429
|
availableLocales: availableLocalesResult,
|
@@ -4133,13 +4437,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4133
4437
|
*/
|
4134
4438
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4135
4439
|
if (!document) {
|
4136
|
-
return
|
4440
|
+
return {
|
4441
|
+
data: document,
|
4442
|
+
meta: {
|
4443
|
+
availableLocales: [],
|
4444
|
+
availableStatus: []
|
4445
|
+
}
|
4446
|
+
};
|
4137
4447
|
}
|
4138
4448
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4139
4449
|
if (!hasDraftAndPublish) {
|
4140
4450
|
opts.availableStatus = false;
|
4141
4451
|
}
|
4142
4452
|
const meta = await this.getMetadata(uid2, document, opts);
|
4453
|
+
if (document.localizations) {
|
4454
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4455
|
+
document.localizations = document.localizations.map((d) => {
|
4456
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4457
|
+
return {
|
4458
|
+
...d,
|
4459
|
+
status: this.getStatus(d, status ? [status] : [])
|
4460
|
+
};
|
4461
|
+
});
|
4462
|
+
}
|
4143
4463
|
return {
|
4144
4464
|
data: {
|
4145
4465
|
...document,
|
@@ -4357,7 +4677,8 @@ const services = {
|
|
4357
4677
|
permission,
|
4358
4678
|
"populate-builder": populateBuilder$1,
|
4359
4679
|
uid,
|
4360
|
-
...history.services ? history.services : {}
|
4680
|
+
...history.services ? history.services : {},
|
4681
|
+
...preview.services ? preview.services : {}
|
4361
4682
|
};
|
4362
4683
|
const index = () => {
|
4363
4684
|
return {
|