@strapi/content-manager 0.0.0-experimental.17b4116f461a49b8ce5386f7c8d79c511d40fb3b → 0.0.0-experimental.19d775295eb622de3e659110caf22fcd2cd5d10d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-B_99pmC0.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-B_99pmC0.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js → ComponentConfigurationPage-NeMPjY5M.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-NeMPjY5M.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-CRbtQEUV.js} +9 -4
- package/dist/_chunks/ComponentIcon-CRbtQEUV.js.map +1 -0
- package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
- package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs → EditConfigurationPage-B0kNlNoj.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-B0kNlNoj.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-n7_xHayb.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-n7_xHayb.js.map} +1 -1
- package/dist/_chunks/EditViewPage-BT7Achc-.js +209 -0
- package/dist/_chunks/EditViewPage-BT7Achc-.js.map +1 -0
- package/dist/_chunks/EditViewPage-DYXZs4_2.mjs +191 -0
- package/dist/_chunks/EditViewPage-DYXZs4_2.mjs.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-CQ67ZifP.js → Form-BRmk2Dp3.js} +68 -49
- package/dist/_chunks/Form-BRmk2Dp3.js.map +1 -0
- package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-D3paRF1F.mjs} +67 -46
- package/dist/_chunks/Form-D3paRF1F.mjs.map +1 -0
- package/dist/_chunks/{History-BLEnudTX.js → History-BQpDoOu8.js} +211 -148
- package/dist/_chunks/History-BQpDoOu8.js.map +1 -0
- package/dist/_chunks/{History-DKhZAPcK.mjs → History-CzQbTOwa.mjs} +204 -139
- package/dist/_chunks/History-CzQbTOwa.mjs.map +1 -0
- package/dist/_chunks/{Field-kVFO4ZKB.mjs → Input-ww3KFYZr.mjs} +1996 -1730
- package/dist/_chunks/Input-ww3KFYZr.mjs.map +1 -0
- package/dist/_chunks/{Field-kq1c2TF1.js → Input-yM6HnyQa.js} +2035 -1770
- package/dist/_chunks/Input-yM6HnyQa.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-B6NsS-0m.js} +72 -63
- package/dist/_chunks/ListConfigurationPage-B6NsS-0m.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-Bbw8w5cS.mjs} +68 -57
- package/dist/_chunks/ListConfigurationPage-Bbw8w5cS.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-DnOP55pM.mjs} +179 -160
- package/dist/_chunks/ListViewPage-DnOP55pM.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-Dt8OUTwO.js} +183 -165
- package/dist/_chunks/ListViewPage-Dt8OUTwO.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-CXKXHNMa.mjs} +3 -3
- package/dist/_chunks/NoContentTypePage-CXKXHNMa.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-Dgm-uj-6.js} +3 -3
- package/dist/_chunks/NoContentTypePage-Dgm-uj-6.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-CLbU5SOt.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-CLbU5SOt.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-kaj1rPiW.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-kaj1rPiW.mjs.map} +1 -1
- package/dist/_chunks/Preview-Bieh13Ro.mjs +287 -0
- package/dist/_chunks/Preview-Bieh13Ro.mjs.map +1 -0
- package/dist/_chunks/Preview-CbXHXqBg.js +305 -0
- package/dist/_chunks/Preview-CbXHXqBg.js.map +1 -0
- package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-7rWJcZ3_.mjs} +138 -94
- package/dist/_chunks/Relations-7rWJcZ3_.mjs.map +1 -0
- package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-CvifV6Y6.js} +142 -100
- package/dist/_chunks/Relations-CvifV6Y6.js.map +1 -0
- package/dist/_chunks/{en-C-V1_90f.js → en-BR48D_RH.js} +45 -18
- package/dist/_chunks/{en-C-V1_90f.js.map → en-BR48D_RH.js.map} +1 -1
- package/dist/_chunks/{en-MBPul9Su.mjs → en-D65uIF6Y.mjs} +45 -18
- package/dist/_chunks/{en-MBPul9Su.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-CAc9yTnx.mjs → index-BH2JnYpF.mjs} +2302 -995
- package/dist/_chunks/index-BH2JnYpF.mjs.map +1 -0
- package/dist/_chunks/{index-DNa1J4HE.js → index-DkJQjlak.js} +2273 -967
- package/dist/_chunks/index-DkJQjlak.js.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-BqtLA6Lb.js → layout-4BqLFW_b.js} +47 -32
- package/dist/_chunks/layout-4BqLFW_b.js.map +1 -0
- package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-bbOlPwLA.mjs} +46 -28
- package/dist/_chunks/layout-bbOlPwLA.mjs.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-mMFEcZRq.mjs → relations-HsflnFpO.mjs} +6 -7
- package/dist/_chunks/relations-HsflnFpO.mjs.map +1 -0
- package/dist/_chunks/{relations-BHY_KDJ_.js → relations-Yc0Z6A20.js} +6 -7
- package/dist/_chunks/relations-Yc0Z6A20.js.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/useDragAndDrop-BMtgCYzL.js.map +1 -0
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/useDragAndDrop-DJ6jqvZN.mjs.map +1 -0
- package/dist/_chunks/usePrev-CZGy2Vjf.mjs +29 -0
- package/dist/_chunks/usePrev-CZGy2Vjf.mjs.map +1 -0
- package/dist/_chunks/usePrev-D5J_2fEu.js +28 -0
- package/dist/_chunks/usePrev-D5J_2fEu.js.map +1 -0
- package/dist/admin/index.js +4 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +10 -7
- package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +7 -5
- package/dist/admin/src/exports.d.ts +3 -1
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +54 -9
- package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
- package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
- package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +12 -5
- 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/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +5 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/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/Relations.d.ts +30 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +16 -53
- 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/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- package/dist/admin/src/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 +2 -3
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +5 -5
- package/dist/admin/src/services/documents.d.ts +31 -20
- package/dist/admin/src/services/init.d.ts +2 -2
- package/dist/admin/src/services/relations.d.ts +3 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/api.d.ts +4 -18
- package/dist/admin/src/utils/validation.d.ts +5 -7
- package/dist/server/index.js +959 -543
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +960 -543
- 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/single-types.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +23 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/index.d.ts +1 -1
- package/dist/server/src/history/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 +21 -36
- 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 +11 -6
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +16 -35
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +21 -36
- 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 +8 -1
- 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 +17 -7
- 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/contracts/relations.d.ts +2 -2
- package/dist/shared/contracts/relations.d.ts.map +1 -1
- 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 +22 -22
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-KRG56aCq.js +0 -224
- package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
- package/dist/_chunks/EditViewPage-aUnqL-63.mjs +0 -203
- package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
- package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
- package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
- package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
- package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
- package/dist/_chunks/History-BLEnudTX.js.map +0 -1
- package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
- package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
- package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
- package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
- package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
- package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
- package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
- package/dist/_chunks/relations-BHY_KDJ_.js.map +0 -1
- package/dist/_chunks/relations-mMFEcZRq.mjs.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +0 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +0 -1
- package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
- package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
- package/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,31 +222,53 @@ 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": {
|
243
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
244
|
+
if (isMorphRelation) {
|
245
|
+
break;
|
246
|
+
}
|
235
247
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
248
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
249
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
250
|
}
|
239
251
|
break;
|
240
252
|
}
|
241
253
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
254
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
255
|
break;
|
244
256
|
}
|
245
257
|
case "component": {
|
246
258
|
const populate = getDeepPopulate2(attribute.component);
|
247
|
-
acc[attributeName] = {
|
259
|
+
acc[attributeName] = {
|
260
|
+
populate,
|
261
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
262
|
+
};
|
248
263
|
break;
|
249
264
|
}
|
250
265
|
case "dynamiczone": {
|
251
266
|
const populatedComponents = (attribute.components || []).reduce(
|
252
267
|
(acc2, componentUID) => {
|
253
|
-
acc2[componentUID] = {
|
268
|
+
acc2[componentUID] = {
|
269
|
+
populate: getDeepPopulate2(componentUID),
|
270
|
+
[fieldSelector]: getComponentFields(componentUID)
|
271
|
+
};
|
254
272
|
return acc2;
|
255
273
|
},
|
256
274
|
{}
|
@@ -312,6 +330,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
312
330
|
getRelationRestoreValue,
|
313
331
|
getMediaRestoreValue,
|
314
332
|
getDefaultLocale,
|
333
|
+
isLocalizedContentType,
|
315
334
|
getLocaleDictionary,
|
316
335
|
getRetentionDays,
|
317
336
|
getVersionStatus,
|
@@ -334,7 +353,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
353
|
});
|
335
354
|
},
|
336
355
|
async findVersionsPage(params) {
|
337
|
-
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
|
+
}
|
338
363
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
339
364
|
query.findPage({
|
340
365
|
...params.query,
|
@@ -350,78 +375,76 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
350
375
|
}),
|
351
376
|
serviceUtils.getLocaleDictionary()
|
352
377
|
]);
|
353
|
-
const
|
354
|
-
|
355
|
-
async (
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
model: "plugin::upload.file"
|
362
|
-
});
|
363
|
-
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
364
|
-
const sanitizedResults = await Promise.all(
|
365
|
-
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
366
|
-
);
|
367
|
-
return {
|
368
|
-
...await currentDataWithRelations,
|
369
|
-
[attributeKey]: {
|
370
|
-
results: sanitizedResults,
|
371
|
-
meta: response.meta
|
372
|
-
}
|
373
|
-
};
|
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");
|
374
386
|
}
|
375
|
-
if (
|
376
|
-
|
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") {
|
377
390
|
const adminUsers = await Promise.all(
|
378
|
-
|
391
|
+
currentValue.map((userToPopulate) => {
|
379
392
|
if (userToPopulate == null) {
|
380
393
|
return null;
|
381
394
|
}
|
382
|
-
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
|
+
});
|
383
401
|
})
|
384
402
|
);
|
385
|
-
|
386
|
-
...await currentDataWithRelations,
|
387
|
-
/**
|
388
|
-
* Ideally we would return the same "{results: [], meta: {}}" shape, however,
|
389
|
-
* when sanitizing the data as a whole in the controller before sending to the client,
|
390
|
-
* the data for admin relation user is completely sanitized if we return an object here as opposed to an array.
|
391
|
-
*/
|
392
|
-
[attributeKey]: adminUsers
|
393
|
-
};
|
403
|
+
utils.set(options.key, adminUsers);
|
394
404
|
}
|
395
|
-
const permissionChecker2 = getService$
|
405
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
396
406
|
userAbility: params.state.userAbility,
|
397
|
-
model:
|
407
|
+
model: options.attribute.target
|
398
408
|
});
|
399
409
|
const response = await serviceUtils.buildRelationReponse(
|
400
|
-
|
401
|
-
|
410
|
+
currentValue,
|
411
|
+
options.attribute
|
402
412
|
);
|
403
413
|
const sanitizedResults = await Promise.all(
|
404
414
|
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
405
415
|
);
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
416
|
+
utils.set(options.key, {
|
417
|
+
results: sanitizedResults,
|
418
|
+
meta: response.meta
|
419
|
+
});
|
420
|
+
}
|
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
|
+
});
|
413
434
|
}
|
414
|
-
return currentDataWithRelations;
|
415
435
|
},
|
416
|
-
|
436
|
+
{
|
437
|
+
schema,
|
438
|
+
getModel: strapi2.getModel.bind(strapi2)
|
439
|
+
},
|
440
|
+
entry.data
|
417
441
|
);
|
418
|
-
return entryWithRelations;
|
419
442
|
};
|
420
443
|
const formattedResults = await Promise.all(
|
421
444
|
results.map(async (result) => {
|
422
445
|
return {
|
423
446
|
...result,
|
424
|
-
data: await
|
447
|
+
data: await populateEntry(result),
|
425
448
|
meta: {
|
426
449
|
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
427
450
|
result.schema,
|
@@ -452,30 +475,44 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
452
475
|
// Clone to avoid mutating the original version data
|
453
476
|
structuredClone(version.data)
|
454
477
|
);
|
455
|
-
const
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
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
|
+
}
|
465
493
|
}
|
466
|
-
if (attribute.type === "relation" && // TODO: handle polymorphic relations
|
467
|
-
attribute.relation !== "morphToOne" && attribute.relation !== "morphToMany") {
|
468
|
-
|
469
|
-
|
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);
|
470
502
|
}
|
471
|
-
if (attribute.type === "media") {
|
472
|
-
|
473
|
-
|
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);
|
474
509
|
}
|
475
|
-
return previousRelationAttributes;
|
476
510
|
},
|
477
|
-
|
478
|
-
|
511
|
+
{
|
512
|
+
schema,
|
513
|
+
getModel: strapi2.getModel.bind(strapi2)
|
514
|
+
},
|
515
|
+
dataWithoutAddedAttributes
|
479
516
|
);
|
480
517
|
const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
481
518
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -490,13 +527,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
527
|
}
|
491
528
|
};
|
492
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
|
+
};
|
493
566
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
567
|
const state = {
|
495
568
|
deleteExpiredJob: null,
|
496
569
|
isInitialized: false
|
497
570
|
};
|
498
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
-
const historyService = getService(strapi2, "history");
|
500
571
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
572
|
return {
|
502
573
|
async bootstrap() {
|
@@ -504,65 +575,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
504
575
|
return;
|
505
576
|
}
|
506
577
|
strapi2.documents.use(async (context, next) => {
|
507
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
508
|
-
return next();
|
509
|
-
}
|
510
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
511
|
-
return next();
|
512
|
-
}
|
513
|
-
const contentTypeUid = context.contentType.uid;
|
514
|
-
if (!contentTypeUid.startsWith("api::")) {
|
515
|
-
return next();
|
516
|
-
}
|
517
578
|
const result = await next();
|
518
|
-
|
579
|
+
if (!shouldCreateHistoryVersion(context)) {
|
580
|
+
return result;
|
581
|
+
}
|
582
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
519
583
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
520
|
-
const
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
584
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
585
|
+
if (!locales.length) {
|
586
|
+
return result;
|
587
|
+
}
|
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
|
+
)
|
525
603
|
});
|
526
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
527
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
528
|
-
const componentsSchemas = Object.keys(
|
529
|
-
attributesSchema
|
530
|
-
).reduce((currentComponentSchemas, key) => {
|
531
|
-
const fieldSchema = attributesSchema[key];
|
532
|
-
if (fieldSchema.type === "component") {
|
533
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
534
|
-
return {
|
535
|
-
...currentComponentSchemas,
|
536
|
-
[fieldSchema.component]: componentSchema
|
537
|
-
};
|
538
|
-
}
|
539
|
-
return currentComponentSchemas;
|
540
|
-
}, {});
|
541
604
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
542
|
-
onCommit(() => {
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
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
|
+
}
|
552
617
|
});
|
553
618
|
});
|
554
619
|
return result;
|
555
620
|
});
|
556
|
-
|
557
|
-
|
558
|
-
const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
|
621
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
622
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
559
623
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
560
|
-
query.deleteMany({
|
624
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
561
625
|
where: {
|
562
626
|
created_at: {
|
563
|
-
$lt: expirationDate
|
627
|
+
$lt: expirationDate
|
564
628
|
}
|
565
629
|
}
|
630
|
+
}).catch((error) => {
|
631
|
+
if (error instanceof Error) {
|
632
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
633
|
+
}
|
566
634
|
});
|
567
635
|
});
|
568
636
|
state.isInitialized = true;
|
@@ -574,17 +642,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
574
642
|
}
|
575
643
|
};
|
576
644
|
};
|
577
|
-
const services$
|
645
|
+
const services$2 = {
|
578
646
|
history: createHistoryService,
|
579
647
|
lifecycles: createLifecyclesService
|
580
648
|
};
|
581
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
649
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
582
650
|
const historyVersionRouter = {
|
583
651
|
type: "admin",
|
584
652
|
routes: [
|
585
653
|
{
|
586
654
|
method: "GET",
|
587
|
-
info,
|
655
|
+
info: info$1,
|
588
656
|
path: "/history-versions",
|
589
657
|
handler: "history-version.findMany",
|
590
658
|
config: {
|
@@ -593,7 +661,7 @@ const historyVersionRouter = {
|
|
593
661
|
},
|
594
662
|
{
|
595
663
|
method: "PUT",
|
596
|
-
info,
|
664
|
+
info: info$1,
|
597
665
|
path: "/history-versions/:versionId/restore",
|
598
666
|
handler: "history-version.restoreVersion",
|
599
667
|
config: {
|
@@ -602,7 +670,7 @@ const historyVersionRouter = {
|
|
602
670
|
}
|
603
671
|
]
|
604
672
|
};
|
605
|
-
const routes$
|
673
|
+
const routes$2 = {
|
606
674
|
"history-version": historyVersionRouter
|
607
675
|
};
|
608
676
|
const historyVersion = {
|
@@ -649,21 +717,21 @@ const historyVersion = {
|
|
649
717
|
}
|
650
718
|
}
|
651
719
|
};
|
652
|
-
const getFeature = () => {
|
720
|
+
const getFeature$1 = () => {
|
653
721
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
654
722
|
return {
|
655
723
|
register({ strapi: strapi2 }) {
|
656
724
|
strapi2.get("models").add(historyVersion);
|
657
725
|
},
|
658
726
|
bootstrap({ strapi: strapi2 }) {
|
659
|
-
getService(strapi2, "lifecycles").bootstrap();
|
727
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
660
728
|
},
|
661
729
|
destroy({ strapi: strapi2 }) {
|
662
|
-
getService(strapi2, "lifecycles").destroy();
|
730
|
+
getService$1(strapi2, "lifecycles").destroy();
|
663
731
|
},
|
664
|
-
controllers: controllers$
|
665
|
-
services: services$
|
666
|
-
routes: routes$
|
732
|
+
controllers: controllers$2,
|
733
|
+
services: services$2,
|
734
|
+
routes: routes$2
|
667
735
|
};
|
668
736
|
}
|
669
737
|
return {
|
@@ -672,9 +740,201 @@ const getFeature = () => {
|
|
672
740
|
}
|
673
741
|
};
|
674
742
|
};
|
675
|
-
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();
|
676
935
|
const register = async ({ strapi: strapi2 }) => {
|
677
936
|
await history.register?.({ strapi: strapi2 });
|
937
|
+
await preview.register?.({ strapi: strapi2 });
|
678
938
|
};
|
679
939
|
const ALLOWED_WEBHOOK_EVENTS = {
|
680
940
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -684,11 +944,12 @@ const bootstrap = async () => {
|
|
684
944
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
685
945
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
686
946
|
});
|
687
|
-
getService$
|
688
|
-
await getService$
|
689
|
-
await getService$
|
690
|
-
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();
|
691
951
|
await history.bootstrap?.({ strapi });
|
952
|
+
await preview.bootstrap?.({ strapi });
|
692
953
|
};
|
693
954
|
const destroy = async ({ strapi: strapi2 }) => {
|
694
955
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1178,7 +1439,8 @@ const admin = {
|
|
1178
1439
|
};
|
1179
1440
|
const routes = {
|
1180
1441
|
admin,
|
1181
|
-
...history.routes ? history.routes : {}
|
1442
|
+
...history.routes ? history.routes : {},
|
1443
|
+
...preview.routes ? preview.routes : {}
|
1182
1444
|
};
|
1183
1445
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1184
1446
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1189,6 +1451,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1189
1451
|
const hasPermissions = createPolicy({
|
1190
1452
|
name: "plugin::content-manager.hasPermissions",
|
1191
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
|
+
*/
|
1192
1459
|
handler(ctx, config = {}) {
|
1193
1460
|
const { actions = [], hasAtLeastOne = false } = config;
|
1194
1461
|
const { userAbility } = ctx.state;
|
@@ -1236,8 +1503,7 @@ const isSortable = (schema, name) => {
|
|
1236
1503
|
if (!___default.default.has(schema.attributes, name)) {
|
1237
1504
|
return false;
|
1238
1505
|
}
|
1239
|
-
if (schema.modelType === "component" && name === "id")
|
1240
|
-
return false;
|
1506
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1241
1507
|
const attribute = schema.attributes[name];
|
1242
1508
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1243
1509
|
return false;
|
@@ -1382,8 +1648,7 @@ const createDefaultSettings = async (schema) => {
|
|
1382
1648
|
};
|
1383
1649
|
};
|
1384
1650
|
const syncSettings = async (configuration, schema) => {
|
1385
|
-
if (fp.isEmpty(configuration.settings))
|
1386
|
-
return createDefaultSettings(schema);
|
1651
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1387
1652
|
const defaultField = getDefaultMainField(schema);
|
1388
1653
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1389
1654
|
return {
|
@@ -1430,7 +1695,7 @@ const createMetadasSchema = (schema) => {
|
|
1430
1695
|
if (!value) {
|
1431
1696
|
return strapiUtils.yup.string();
|
1432
1697
|
}
|
1433
|
-
const targetSchema = getService$
|
1698
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1434
1699
|
schema.attributes[key].targetModel
|
1435
1700
|
);
|
1436
1701
|
if (!targetSchema) {
|
@@ -1478,7 +1743,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
|
|
1478
1743
|
const TYPES = ["singleType", "collectionType"];
|
1479
1744
|
const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
|
1480
1745
|
const bulkActionInputSchema = strapiUtils.yup.object({
|
1481
|
-
|
1746
|
+
documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
|
1482
1747
|
}).required();
|
1483
1748
|
const generateUIDInputSchema = strapiUtils.yup.object({
|
1484
1749
|
contentTypeUID: strapiUtils.yup.string().required(),
|
@@ -1559,8 +1824,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1559
1824
|
}
|
1560
1825
|
switch (attribute.type) {
|
1561
1826
|
case "relation": {
|
1562
|
-
if (canCreate(attributePath))
|
1563
|
-
return body2;
|
1827
|
+
if (canCreate(attributePath)) return body2;
|
1564
1828
|
return fp.set(attributePath, { set: [] }, body2);
|
1565
1829
|
}
|
1566
1830
|
case "component": {
|
@@ -1570,29 +1834,62 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1570
1834
|
]);
|
1571
1835
|
}
|
1572
1836
|
default: {
|
1573
|
-
if (canCreate(attributePath))
|
1574
|
-
return body2;
|
1837
|
+
if (canCreate(attributePath)) return body2;
|
1575
1838
|
return fp.set(attributePath, null, body2);
|
1576
1839
|
}
|
1577
1840
|
}
|
1578
1841
|
}, body);
|
1579
1842
|
};
|
1580
|
-
const
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1843
|
+
const singleLocaleSchema = strapiUtils.yup.string().nullable();
|
1844
|
+
const multipleLocaleSchema = strapiUtils.yup.lazy(
|
1845
|
+
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1846
|
+
);
|
1847
|
+
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1848
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1849
|
+
const { allowMultipleLocales } = opts;
|
1850
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1851
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1852
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1853
|
+
const schema = strapiUtils.yup.object().shape({
|
1854
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1855
|
+
status: statusSchema
|
1856
|
+
});
|
1857
|
+
try {
|
1858
|
+
await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1859
|
+
return { locale, status, ...rest };
|
1860
|
+
} catch (error) {
|
1861
|
+
throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
|
1587
1862
|
}
|
1588
|
-
|
1863
|
+
};
|
1864
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1865
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1866
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1867
|
+
let {
|
1868
|
+
meta: { availableLocales, availableStatus }
|
1869
|
+
} = serviceOutput;
|
1870
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1871
|
+
availableLocales = await strapiUtils.async.map(
|
1872
|
+
availableLocales,
|
1873
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1874
|
+
);
|
1875
|
+
availableStatus = await strapiUtils.async.map(
|
1876
|
+
availableStatus,
|
1877
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1878
|
+
);
|
1879
|
+
return {
|
1880
|
+
...serviceOutput,
|
1881
|
+
meta: {
|
1882
|
+
availableLocales,
|
1883
|
+
availableStatus
|
1884
|
+
}
|
1885
|
+
};
|
1589
1886
|
};
|
1590
1887
|
const createDocument = async (ctx, opts) => {
|
1591
1888
|
const { userAbility, user } = ctx.state;
|
1592
1889
|
const { model } = ctx.params;
|
1593
1890
|
const { body } = ctx.request;
|
1594
|
-
const documentManager2 = getService$
|
1595
|
-
const permissionChecker2 = getService$
|
1891
|
+
const documentManager2 = getService$2("document-manager");
|
1892
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1596
1893
|
if (permissionChecker2.cannot.create()) {
|
1597
1894
|
throw new strapiUtils.errors.ForbiddenError();
|
1598
1895
|
}
|
@@ -1600,7 +1897,7 @@ const createDocument = async (ctx, opts) => {
|
|
1600
1897
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1601
1898
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1602
1899
|
const sanitizedBody = await sanitizeFn(body);
|
1603
|
-
const { locale, status
|
1900
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1604
1901
|
return documentManager2.create(model, {
|
1605
1902
|
data: sanitizedBody,
|
1606
1903
|
locale,
|
@@ -1612,14 +1909,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1612
1909
|
const { userAbility, user } = ctx.state;
|
1613
1910
|
const { id, model } = ctx.params;
|
1614
1911
|
const { body } = ctx.request;
|
1615
|
-
const documentManager2 = getService$
|
1616
|
-
const permissionChecker2 = getService$
|
1912
|
+
const documentManager2 = getService$2("document-manager");
|
1913
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1617
1914
|
if (permissionChecker2.cannot.update()) {
|
1618
1915
|
throw new strapiUtils.errors.ForbiddenError();
|
1619
1916
|
}
|
1620
1917
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1621
|
-
const populate = await getService$
|
1622
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1918
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1919
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1623
1920
|
const [documentVersion, documentExists] = await Promise.all([
|
1624
1921
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1625
1922
|
documentManager2.exists(model, id)
|
@@ -1635,7 +1932,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1635
1932
|
throw new strapiUtils.errors.ForbiddenError();
|
1636
1933
|
}
|
1637
1934
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1638
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1935
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1639
1936
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1640
1937
|
const sanitizedBody = await sanitizeFn(body);
|
1641
1938
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1649,15 +1946,15 @@ const collectionTypes = {
|
|
1649
1946
|
const { userAbility } = ctx.state;
|
1650
1947
|
const { model } = ctx.params;
|
1651
1948
|
const { query } = ctx.request;
|
1652
|
-
const documentMetadata2 = getService$
|
1653
|
-
const documentManager2 = getService$
|
1654
|
-
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 });
|
1655
1952
|
if (permissionChecker2.cannot.read()) {
|
1656
1953
|
return ctx.forbidden();
|
1657
1954
|
}
|
1658
1955
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1659
|
-
const populate = await getService$
|
1660
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1956
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1957
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1661
1958
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1662
1959
|
{ ...permissionQuery, populate, locale, status },
|
1663
1960
|
model
|
@@ -1685,15 +1982,14 @@ const collectionTypes = {
|
|
1685
1982
|
async findOne(ctx) {
|
1686
1983
|
const { userAbility } = ctx.state;
|
1687
1984
|
const { model, id } = ctx.params;
|
1688
|
-
const documentManager2 = getService$
|
1689
|
-
const
|
1690
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1985
|
+
const documentManager2 = getService$2("document-manager");
|
1986
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1691
1987
|
if (permissionChecker2.cannot.read()) {
|
1692
1988
|
return ctx.forbidden();
|
1693
1989
|
}
|
1694
1990
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1695
|
-
const populate = await getService$
|
1696
|
-
const { locale, status
|
1991
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1992
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1697
1993
|
const version = await documentManager2.findOne(id, model, {
|
1698
1994
|
populate,
|
1699
1995
|
locale,
|
@@ -1704,9 +2000,11 @@ const collectionTypes = {
|
|
1704
2000
|
if (!exists) {
|
1705
2001
|
return ctx.notFound();
|
1706
2002
|
}
|
1707
|
-
const { meta } = await
|
2003
|
+
const { meta } = await formatDocumentWithMetadata(
|
2004
|
+
permissionChecker2,
|
1708
2005
|
model,
|
1709
|
-
|
2006
|
+
// @ts-expect-error TODO: fix
|
2007
|
+
{ documentId: id, locale, publishedAt: null },
|
1710
2008
|
{ availableLocales: true, availableStatus: false }
|
1711
2009
|
);
|
1712
2010
|
ctx.body = { data: {}, meta };
|
@@ -1716,20 +2014,19 @@ const collectionTypes = {
|
|
1716
2014
|
return ctx.forbidden();
|
1717
2015
|
}
|
1718
2016
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1719
|
-
ctx.body = await
|
2017
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1720
2018
|
},
|
1721
2019
|
async create(ctx) {
|
1722
2020
|
const { userAbility } = ctx.state;
|
1723
2021
|
const { model } = ctx.params;
|
1724
|
-
const
|
1725
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2022
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1726
2023
|
const [totalEntries, document] = await Promise.all([
|
1727
2024
|
strapi.db.query(model).count(),
|
1728
2025
|
createDocument(ctx)
|
1729
2026
|
]);
|
1730
2027
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1731
2028
|
ctx.status = 201;
|
1732
|
-
ctx.body = await
|
2029
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1733
2030
|
// Empty metadata as it's not relevant for a new document
|
1734
2031
|
availableLocales: false,
|
1735
2032
|
availableStatus: false
|
@@ -1743,25 +2040,23 @@ const collectionTypes = {
|
|
1743
2040
|
async update(ctx) {
|
1744
2041
|
const { userAbility } = ctx.state;
|
1745
2042
|
const { model } = ctx.params;
|
1746
|
-
const
|
1747
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2043
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1748
2044
|
const updatedVersion = await updateDocument(ctx);
|
1749
2045
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1750
|
-
ctx.body = await
|
2046
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1751
2047
|
},
|
1752
2048
|
async clone(ctx) {
|
1753
2049
|
const { userAbility, user } = ctx.state;
|
1754
2050
|
const { model, sourceId: id } = ctx.params;
|
1755
2051
|
const { body } = ctx.request;
|
1756
|
-
const documentManager2 = getService$
|
1757
|
-
const
|
1758
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2052
|
+
const documentManager2 = getService$2("document-manager");
|
2053
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1759
2054
|
if (permissionChecker2.cannot.create()) {
|
1760
2055
|
return ctx.forbidden();
|
1761
2056
|
}
|
1762
2057
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1763
|
-
const populate = await getService$
|
1764
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2058
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2059
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1765
2060
|
const document = await documentManager2.findOne(id, model, {
|
1766
2061
|
populate,
|
1767
2062
|
locale,
|
@@ -1777,7 +2072,7 @@ const collectionTypes = {
|
|
1777
2072
|
const sanitizedBody = await sanitizeFn(body);
|
1778
2073
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1779
2074
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1780
|
-
ctx.body = await
|
2075
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1781
2076
|
// Empty metadata as it's not relevant for a new document
|
1782
2077
|
availableLocales: false,
|
1783
2078
|
availableStatus: false
|
@@ -1799,14 +2094,14 @@ const collectionTypes = {
|
|
1799
2094
|
async delete(ctx) {
|
1800
2095
|
const { userAbility } = ctx.state;
|
1801
2096
|
const { id, model } = ctx.params;
|
1802
|
-
const documentManager2 = getService$
|
1803
|
-
const permissionChecker2 = getService$
|
2097
|
+
const documentManager2 = getService$2("document-manager");
|
2098
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1804
2099
|
if (permissionChecker2.cannot.delete()) {
|
1805
2100
|
return ctx.forbidden();
|
1806
2101
|
}
|
1807
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1808
|
-
const populate = await getService$
|
1809
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
2103
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2104
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1810
2105
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1811
2106
|
if (documentLocales.length === 0) {
|
1812
2107
|
return ctx.notFound();
|
@@ -1827,44 +2122,75 @@ const collectionTypes = {
|
|
1827
2122
|
const { userAbility } = ctx.state;
|
1828
2123
|
const { id, model } = ctx.params;
|
1829
2124
|
const { body } = ctx.request;
|
1830
|
-
const documentManager2 = getService$
|
1831
|
-
const
|
1832
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2125
|
+
const documentManager2 = getService$2("document-manager");
|
2126
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1833
2127
|
if (permissionChecker2.cannot.publish()) {
|
1834
2128
|
return ctx.forbidden();
|
1835
2129
|
}
|
1836
2130
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1837
2131
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1838
|
-
const populate = await getService$
|
1839
|
-
|
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
|
+
}
|
1840
2158
|
if (permissionChecker2.cannot.publish(document)) {
|
1841
2159
|
throw new strapiUtils.errors.ForbiddenError();
|
1842
2160
|
}
|
1843
|
-
const
|
1844
|
-
return documentManager2.publish(document.documentId, model, {
|
2161
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1845
2162
|
locale
|
1846
2163
|
// TODO: Allow setting creator fields on publish
|
1847
2164
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1848
2165
|
});
|
2166
|
+
if (!publishResult || publishResult.length === 0) {
|
2167
|
+
throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
|
2168
|
+
}
|
2169
|
+
return publishResult[0];
|
1849
2170
|
});
|
1850
2171
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1851
|
-
ctx.body = await
|
2172
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1852
2173
|
},
|
1853
2174
|
async bulkPublish(ctx) {
|
1854
2175
|
const { userAbility } = ctx.state;
|
1855
2176
|
const { model } = ctx.params;
|
1856
2177
|
const { body } = ctx.request;
|
1857
|
-
const {
|
2178
|
+
const { documentIds } = body;
|
1858
2179
|
await validateBulkActionInput(body);
|
1859
|
-
const documentManager2 = getService$
|
1860
|
-
const permissionChecker2 = getService$
|
2180
|
+
const documentManager2 = getService$2("document-manager");
|
2181
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1861
2182
|
if (permissionChecker2.cannot.publish()) {
|
1862
2183
|
return ctx.forbidden();
|
1863
2184
|
}
|
1864
2185
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1865
|
-
const populate = await getService$
|
1866
|
-
const
|
1867
|
-
|
2186
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2187
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2188
|
+
allowMultipleLocales: true
|
2189
|
+
});
|
2190
|
+
const entityPromises = documentIds.map(
|
2191
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
2192
|
+
);
|
2193
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1868
2194
|
for (const entity of entities) {
|
1869
2195
|
if (!entity) {
|
1870
2196
|
return ctx.notFound();
|
@@ -1873,24 +2199,27 @@ const collectionTypes = {
|
|
1873
2199
|
return ctx.forbidden();
|
1874
2200
|
}
|
1875
2201
|
}
|
1876
|
-
const
|
2202
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1877
2203
|
ctx.body = { count };
|
1878
2204
|
},
|
1879
2205
|
async bulkUnpublish(ctx) {
|
1880
2206
|
const { userAbility } = ctx.state;
|
1881
2207
|
const { model } = ctx.params;
|
1882
2208
|
const { body } = ctx.request;
|
1883
|
-
const {
|
2209
|
+
const { documentIds } = body;
|
1884
2210
|
await validateBulkActionInput(body);
|
1885
|
-
const documentManager2 = getService$
|
1886
|
-
const permissionChecker2 = getService$
|
2211
|
+
const documentManager2 = getService$2("document-manager");
|
2212
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1887
2213
|
if (permissionChecker2.cannot.unpublish()) {
|
1888
2214
|
return ctx.forbidden();
|
1889
2215
|
}
|
1890
|
-
const
|
1891
|
-
|
1892
|
-
|
1893
|
-
const
|
2216
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2217
|
+
allowMultipleLocales: true
|
2218
|
+
});
|
2219
|
+
const entityPromises = documentIds.map(
|
2220
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
2221
|
+
);
|
2222
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1894
2223
|
for (const entity of entities) {
|
1895
2224
|
if (!entity) {
|
1896
2225
|
return ctx.notFound();
|
@@ -1899,7 +2228,8 @@ const collectionTypes = {
|
|
1899
2228
|
return ctx.forbidden();
|
1900
2229
|
}
|
1901
2230
|
}
|
1902
|
-
const
|
2231
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
2232
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1903
2233
|
ctx.body = { count };
|
1904
2234
|
},
|
1905
2235
|
async unpublish(ctx) {
|
@@ -1908,9 +2238,8 @@ const collectionTypes = {
|
|
1908
2238
|
const {
|
1909
2239
|
body: { discardDraft, ...body }
|
1910
2240
|
} = ctx.request;
|
1911
|
-
const documentManager2 = getService$
|
1912
|
-
const
|
1913
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2241
|
+
const documentManager2 = getService$2("document-manager");
|
2242
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1914
2243
|
if (permissionChecker2.cannot.unpublish()) {
|
1915
2244
|
return ctx.forbidden();
|
1916
2245
|
}
|
@@ -1918,8 +2247,8 @@ const collectionTypes = {
|
|
1918
2247
|
return ctx.forbidden();
|
1919
2248
|
}
|
1920
2249
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1921
|
-
const populate = await getService$
|
1922
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2250
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2251
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1923
2252
|
const document = await documentManager2.findOne(id, model, {
|
1924
2253
|
populate,
|
1925
2254
|
locale,
|
@@ -1941,7 +2270,7 @@ const collectionTypes = {
|
|
1941
2270
|
ctx.body = await strapiUtils.async.pipe(
|
1942
2271
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1943
2272
|
permissionChecker2.sanitizeOutput,
|
1944
|
-
(document2) =>
|
2273
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1945
2274
|
)(document);
|
1946
2275
|
});
|
1947
2276
|
},
|
@@ -1949,15 +2278,14 @@ const collectionTypes = {
|
|
1949
2278
|
const { userAbility } = ctx.state;
|
1950
2279
|
const { id, model } = ctx.params;
|
1951
2280
|
const { body } = ctx.request;
|
1952
|
-
const documentManager2 = getService$
|
1953
|
-
const
|
1954
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2281
|
+
const documentManager2 = getService$2("document-manager");
|
2282
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1955
2283
|
if (permissionChecker2.cannot.discard()) {
|
1956
2284
|
return ctx.forbidden();
|
1957
2285
|
}
|
1958
2286
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1959
|
-
const populate = await getService$
|
1960
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2287
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2288
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1961
2289
|
const document = await documentManager2.findOne(id, model, {
|
1962
2290
|
populate,
|
1963
2291
|
locale,
|
@@ -1972,42 +2300,50 @@ const collectionTypes = {
|
|
1972
2300
|
ctx.body = await strapiUtils.async.pipe(
|
1973
2301
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1974
2302
|
permissionChecker2.sanitizeOutput,
|
1975
|
-
(document2) =>
|
2303
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1976
2304
|
)(document);
|
1977
2305
|
},
|
1978
2306
|
async bulkDelete(ctx) {
|
1979
2307
|
const { userAbility } = ctx.state;
|
1980
2308
|
const { model } = ctx.params;
|
1981
2309
|
const { query, body } = ctx.request;
|
1982
|
-
const {
|
2310
|
+
const { documentIds } = body;
|
1983
2311
|
await validateBulkActionInput(body);
|
1984
|
-
const documentManager2 = getService$
|
1985
|
-
const permissionChecker2 = getService$
|
2312
|
+
const documentManager2 = getService$2("document-manager");
|
2313
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1986
2314
|
if (permissionChecker2.cannot.delete()) {
|
1987
2315
|
return ctx.forbidden();
|
1988
2316
|
}
|
1989
2317
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1990
|
-
const
|
1991
|
-
const
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
2318
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2319
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2320
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2321
|
+
populate,
|
2322
|
+
locale
|
2323
|
+
});
|
2324
|
+
if (documentLocales.length === 0) {
|
2325
|
+
return ctx.notFound();
|
2326
|
+
}
|
2327
|
+
for (const document of documentLocales) {
|
2328
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2329
|
+
return ctx.forbidden();
|
1995
2330
|
}
|
1996
|
-
}
|
1997
|
-
const
|
2331
|
+
}
|
2332
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2333
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1998
2334
|
ctx.body = { count };
|
1999
2335
|
},
|
2000
2336
|
async countDraftRelations(ctx) {
|
2001
2337
|
const { userAbility } = ctx.state;
|
2002
2338
|
const { model, id } = ctx.params;
|
2003
|
-
const documentManager2 = getService$
|
2004
|
-
const permissionChecker2 = getService$
|
2339
|
+
const documentManager2 = getService$2("document-manager");
|
2340
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2005
2341
|
if (permissionChecker2.cannot.read()) {
|
2006
2342
|
return ctx.forbidden();
|
2007
2343
|
}
|
2008
2344
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2009
|
-
const populate = await getService$
|
2010
|
-
const { locale, status
|
2345
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2346
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2011
2347
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2012
2348
|
if (!entity) {
|
2013
2349
|
return ctx.notFound();
|
@@ -2022,24 +2358,24 @@ const collectionTypes = {
|
|
2022
2358
|
},
|
2023
2359
|
async countManyEntriesDraftRelations(ctx) {
|
2024
2360
|
const { userAbility } = ctx.state;
|
2025
|
-
const ids = ctx.request.query.
|
2361
|
+
const ids = ctx.request.query.documentIds;
|
2026
2362
|
const locale = ctx.request.query.locale;
|
2027
2363
|
const { model } = ctx.params;
|
2028
|
-
const documentManager2 = getService$
|
2029
|
-
const permissionChecker2 = getService$
|
2364
|
+
const documentManager2 = getService$2("document-manager");
|
2365
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2030
2366
|
if (permissionChecker2.cannot.read()) {
|
2031
2367
|
return ctx.forbidden();
|
2032
2368
|
}
|
2033
|
-
const
|
2369
|
+
const documents = await documentManager2.findMany(
|
2034
2370
|
{
|
2035
2371
|
filters: {
|
2036
|
-
|
2372
|
+
documentId: ids
|
2037
2373
|
},
|
2038
2374
|
locale
|
2039
2375
|
},
|
2040
2376
|
model
|
2041
2377
|
);
|
2042
|
-
if (!
|
2378
|
+
if (!documents) {
|
2043
2379
|
return ctx.notFound();
|
2044
2380
|
}
|
2045
2381
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2050,13 +2386,13 @@ const collectionTypes = {
|
|
2050
2386
|
};
|
2051
2387
|
const components$1 = {
|
2052
2388
|
findComponents(ctx) {
|
2053
|
-
const components2 = getService$
|
2054
|
-
const { toDto } = getService$
|
2389
|
+
const components2 = getService$2("components").findAllComponents();
|
2390
|
+
const { toDto } = getService$2("data-mapper");
|
2055
2391
|
ctx.body = { data: components2.map(toDto) };
|
2056
2392
|
},
|
2057
2393
|
async findComponentConfiguration(ctx) {
|
2058
2394
|
const { uid: uid2 } = ctx.params;
|
2059
|
-
const componentService = getService$
|
2395
|
+
const componentService = getService$2("components");
|
2060
2396
|
const component = componentService.findComponent(uid2);
|
2061
2397
|
if (!component) {
|
2062
2398
|
return ctx.notFound("component.notFound");
|
@@ -2073,7 +2409,7 @@ const components$1 = {
|
|
2073
2409
|
async updateComponentConfiguration(ctx) {
|
2074
2410
|
const { uid: uid2 } = ctx.params;
|
2075
2411
|
const { body } = ctx.request;
|
2076
|
-
const componentService = getService$
|
2412
|
+
const componentService = getService$2("components");
|
2077
2413
|
const component = componentService.findComponent(uid2);
|
2078
2414
|
if (!component) {
|
2079
2415
|
return ctx.notFound("component.notFound");
|
@@ -2107,12 +2443,12 @@ const contentTypes = {
|
|
2107
2443
|
} catch (error) {
|
2108
2444
|
return ctx.send({ error }, 400);
|
2109
2445
|
}
|
2110
|
-
const contentTypes2 = getService$
|
2111
|
-
const { toDto } = getService$
|
2446
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2447
|
+
const { toDto } = getService$2("data-mapper");
|
2112
2448
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2113
2449
|
},
|
2114
2450
|
async findContentTypesSettings(ctx) {
|
2115
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2451
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2116
2452
|
const contentTypes2 = await findAllContentTypes();
|
2117
2453
|
const configurations = await Promise.all(
|
2118
2454
|
contentTypes2.map(async (contentType) => {
|
@@ -2126,7 +2462,7 @@ const contentTypes = {
|
|
2126
2462
|
},
|
2127
2463
|
async findContentTypeConfiguration(ctx) {
|
2128
2464
|
const { uid: uid2 } = ctx.params;
|
2129
|
-
const contentTypeService = getService$
|
2465
|
+
const contentTypeService = getService$2("content-types");
|
2130
2466
|
const contentType = await contentTypeService.findContentType(uid2);
|
2131
2467
|
if (!contentType) {
|
2132
2468
|
return ctx.notFound("contentType.notFound");
|
@@ -2148,13 +2484,13 @@ const contentTypes = {
|
|
2148
2484
|
const { userAbility } = ctx.state;
|
2149
2485
|
const { uid: uid2 } = ctx.params;
|
2150
2486
|
const { body } = ctx.request;
|
2151
|
-
const contentTypeService = getService$
|
2152
|
-
const metricsService = getService$
|
2487
|
+
const contentTypeService = getService$2("content-types");
|
2488
|
+
const metricsService = getService$2("metrics");
|
2153
2489
|
const contentType = await contentTypeService.findContentType(uid2);
|
2154
2490
|
if (!contentType) {
|
2155
2491
|
return ctx.notFound("contentType.notFound");
|
2156
2492
|
}
|
2157
|
-
if (!getService$
|
2493
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2158
2494
|
return ctx.forbidden();
|
2159
2495
|
}
|
2160
2496
|
let input;
|
@@ -2187,10 +2523,10 @@ const contentTypes = {
|
|
2187
2523
|
};
|
2188
2524
|
const init = {
|
2189
2525
|
getInitData(ctx) {
|
2190
|
-
const { toDto } = getService$
|
2191
|
-
const { findAllComponents } = getService$
|
2192
|
-
const { getAllFieldSizes } = getService$
|
2193
|
-
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");
|
2194
2530
|
ctx.body = {
|
2195
2531
|
data: {
|
2196
2532
|
fieldSizes: getAllFieldSizes(),
|
@@ -2226,36 +2562,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2226
2562
|
params.filters.$and.push(filtersClause);
|
2227
2563
|
};
|
2228
2564
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2229
|
-
const permissionChecker2 = getService$
|
2565
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2230
2566
|
userAbility,
|
2231
2567
|
model: model.uid
|
2232
2568
|
});
|
2233
|
-
|
2569
|
+
const isMainFieldListable = isListable(model, mainField);
|
2570
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2571
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2234
2572
|
return "id";
|
2235
2573
|
}
|
2236
|
-
if (
|
2237
|
-
|
2238
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2239
|
-
userAbility,
|
2240
|
-
model: "plugin::users-permissions.user"
|
2241
|
-
});
|
2242
|
-
if (userPermissionChecker.can.read()) {
|
2243
|
-
return "name";
|
2244
|
-
}
|
2245
|
-
}
|
2246
|
-
return "id";
|
2574
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2575
|
+
return "name";
|
2247
2576
|
}
|
2248
2577
|
return mainField;
|
2249
2578
|
};
|
2250
|
-
const addStatusToRelations = async (
|
2251
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2579
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2580
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2581
|
+
return relations2;
|
2582
|
+
}
|
2583
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2584
|
+
if (!relations2.length) {
|
2252
2585
|
return relations2;
|
2253
2586
|
}
|
2254
|
-
const
|
2255
|
-
const
|
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
|
+
});
|
2256
2597
|
return relations2.map((relation) => {
|
2257
|
-
const availableStatuses =
|
2258
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2598
|
+
const availableStatuses = availableStatus.filter(
|
2599
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2259
2600
|
);
|
2260
2601
|
return {
|
2261
2602
|
...relation,
|
@@ -2276,11 +2617,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2276
2617
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2277
2618
|
const isSourceLocalized = isLocalized(sourceModel);
|
2278
2619
|
const isTargetLocalized = isLocalized(targetModel);
|
2279
|
-
let validatedLocale = locale;
|
2280
|
-
if (!targetModel || !isTargetLocalized)
|
2281
|
-
validatedLocale = void 0;
|
2282
2620
|
return {
|
2283
|
-
locale
|
2621
|
+
locale,
|
2284
2622
|
isSourceLocalized,
|
2285
2623
|
isTargetLocalized
|
2286
2624
|
};
|
@@ -2289,8 +2627,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2289
2627
|
const sourceModel = strapi.getModel(sourceUid);
|
2290
2628
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2291
2629
|
const isSourceDP = isDP(sourceModel);
|
2292
|
-
if (!isSourceDP)
|
2293
|
-
return { status: void 0 };
|
2630
|
+
if (!isSourceDP) return { status: void 0 };
|
2294
2631
|
switch (status) {
|
2295
2632
|
case "published":
|
2296
2633
|
return { status: "published" };
|
@@ -2320,7 +2657,7 @@ const relations = {
|
|
2320
2657
|
ctx.request?.query?.locale
|
2321
2658
|
);
|
2322
2659
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2323
|
-
const permissionChecker2 = getService$
|
2660
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2324
2661
|
userAbility,
|
2325
2662
|
model
|
2326
2663
|
});
|
@@ -2345,7 +2682,7 @@ const relations = {
|
|
2345
2682
|
where.id = id;
|
2346
2683
|
}
|
2347
2684
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2348
|
-
const populate = await getService$
|
2685
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2349
2686
|
const currentEntity = await strapi.db.query(model).findOne({
|
2350
2687
|
where,
|
2351
2688
|
populate
|
@@ -2360,7 +2697,7 @@ const relations = {
|
|
2360
2697
|
}
|
2361
2698
|
entryId = currentEntity.id;
|
2362
2699
|
}
|
2363
|
-
const modelConfig = isComponent2 ? await getService$
|
2700
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2364
2701
|
const targetSchema = strapi.getModel(targetUid);
|
2365
2702
|
const mainField = fp.flow(
|
2366
2703
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2383,7 +2720,7 @@ const relations = {
|
|
2383
2720
|
attribute,
|
2384
2721
|
fieldsToSelect,
|
2385
2722
|
mainField,
|
2386
|
-
source: { schema: sourceSchema },
|
2723
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2387
2724
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2388
2725
|
sourceSchema,
|
2389
2726
|
targetSchema,
|
@@ -2405,7 +2742,8 @@ const relations = {
|
|
2405
2742
|
fieldsToSelect,
|
2406
2743
|
mainField,
|
2407
2744
|
source: {
|
2408
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2745
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2746
|
+
isLocalized: isSourceLocalized
|
2409
2747
|
},
|
2410
2748
|
target: {
|
2411
2749
|
schema: { uid: targetUid },
|
@@ -2413,7 +2751,7 @@ const relations = {
|
|
2413
2751
|
}
|
2414
2752
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2415
2753
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2416
|
-
const permissionChecker2 = getService$
|
2754
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2417
2755
|
userAbility: ctx.state.userAbility,
|
2418
2756
|
model: targetUid
|
2419
2757
|
});
|
@@ -2443,12 +2781,16 @@ const relations = {
|
|
2443
2781
|
} else {
|
2444
2782
|
where.id = id;
|
2445
2783
|
}
|
2446
|
-
|
2447
|
-
|
2784
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2785
|
+
if (!fp.isEmpty(publishedAt)) {
|
2786
|
+
where[`${alias}.published_at`] = publishedAt;
|
2448
2787
|
}
|
2449
|
-
if (
|
2788
|
+
if (isTargetLocalized && locale) {
|
2450
2789
|
where[`${alias}.locale`] = locale;
|
2451
2790
|
}
|
2791
|
+
if (isSourceLocalized && locale) {
|
2792
|
+
where.locale = locale;
|
2793
|
+
}
|
2452
2794
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2453
2795
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2454
2796
|
}
|
@@ -2466,7 +2808,8 @@ const relations = {
|
|
2466
2808
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2467
2809
|
});
|
2468
2810
|
}
|
2469
|
-
const
|
2811
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2812
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2470
2813
|
ctx.body = {
|
2471
2814
|
...res,
|
2472
2815
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2481,29 +2824,39 @@ const relations = {
|
|
2481
2824
|
attribute,
|
2482
2825
|
targetField,
|
2483
2826
|
fieldsToSelect,
|
2484
|
-
|
2485
|
-
|
2486
|
-
}
|
2487
|
-
target: {
|
2488
|
-
schema: { uid: targetUid }
|
2489
|
-
}
|
2827
|
+
status,
|
2828
|
+
source: { schema: sourceSchema },
|
2829
|
+
target: { schema: targetSchema }
|
2490
2830
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2491
|
-
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 });
|
2492
2834
|
const dbQuery = strapi.db.query(sourceUid);
|
2493
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
|
+
}
|
2494
2848
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2495
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2849
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2496
2850
|
ordering: "desc",
|
2497
2851
|
page: ctx.request.query.page,
|
2498
|
-
pageSize: ctx.request.query.pageSize
|
2852
|
+
pageSize: ctx.request.query.pageSize,
|
2853
|
+
filters
|
2499
2854
|
});
|
2500
2855
|
const loadedIds = res.results.map((item) => item.id);
|
2501
2856
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2502
2857
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2503
2858
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2504
|
-
ordering: "desc"
|
2505
|
-
page: ctx.request.query.page,
|
2506
|
-
pageSize: ctx.request.query.pageSize
|
2859
|
+
ordering: "desc"
|
2507
2860
|
});
|
2508
2861
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2509
2862
|
ctx.body = {
|
@@ -2518,10 +2871,10 @@ const relations = {
|
|
2518
2871
|
}
|
2519
2872
|
};
|
2520
2873
|
const buildPopulateFromQuery = async (query, model) => {
|
2521
|
-
return getService$
|
2874
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2522
2875
|
};
|
2523
2876
|
const findDocument = async (query, uid2, opts = {}) => {
|
2524
|
-
const documentManager2 = getService$
|
2877
|
+
const documentManager2 = getService$2("document-manager");
|
2525
2878
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2526
2879
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2527
2880
|
};
|
@@ -2529,13 +2882,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2529
2882
|
const { user, userAbility } = ctx.state;
|
2530
2883
|
const { model } = ctx.params;
|
2531
2884
|
const { body, query } = ctx.request;
|
2532
|
-
const documentManager2 = getService$
|
2533
|
-
const permissionChecker2 = getService$
|
2885
|
+
const documentManager2 = getService$2("document-manager");
|
2886
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2534
2887
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2535
2888
|
throw new strapiUtils.errors.ForbiddenError();
|
2536
2889
|
}
|
2537
2890
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2538
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2891
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2539
2892
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2540
2893
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2541
2894
|
// Find the first document to check if it exists
|
@@ -2571,13 +2924,12 @@ const singleTypes = {
|
|
2571
2924
|
const { userAbility } = ctx.state;
|
2572
2925
|
const { model } = ctx.params;
|
2573
2926
|
const { query = {} } = ctx.request;
|
2574
|
-
const permissionChecker2 = getService$
|
2575
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2927
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2576
2928
|
if (permissionChecker2.cannot.read()) {
|
2577
2929
|
return ctx.forbidden();
|
2578
2930
|
}
|
2579
2931
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2580
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2932
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2581
2933
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2582
2934
|
if (!version) {
|
2583
2935
|
if (permissionChecker2.cannot.create()) {
|
@@ -2587,9 +2939,11 @@ const singleTypes = {
|
|
2587
2939
|
if (!document) {
|
2588
2940
|
return ctx.notFound();
|
2589
2941
|
}
|
2590
|
-
const { meta } = await
|
2942
|
+
const { meta } = await formatDocumentWithMetadata(
|
2943
|
+
permissionChecker2,
|
2591
2944
|
model,
|
2592
|
-
|
2945
|
+
// @ts-expect-error - fix types
|
2946
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2593
2947
|
{ availableLocales: true, availableStatus: false }
|
2594
2948
|
);
|
2595
2949
|
ctx.body = { data: {}, meta };
|
@@ -2599,29 +2953,28 @@ const singleTypes = {
|
|
2599
2953
|
return ctx.forbidden();
|
2600
2954
|
}
|
2601
2955
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2602
|
-
ctx.body = await
|
2956
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2603
2957
|
},
|
2604
2958
|
async createOrUpdate(ctx) {
|
2605
2959
|
const { userAbility } = ctx.state;
|
2606
2960
|
const { model } = ctx.params;
|
2607
|
-
const
|
2608
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2961
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2609
2962
|
const document = await createOrUpdateDocument(ctx);
|
2610
2963
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2611
|
-
ctx.body = await
|
2964
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2612
2965
|
},
|
2613
2966
|
async delete(ctx) {
|
2614
2967
|
const { userAbility } = ctx.state;
|
2615
2968
|
const { model } = ctx.params;
|
2616
2969
|
const { query = {} } = ctx.request;
|
2617
|
-
const documentManager2 = getService$
|
2618
|
-
const permissionChecker2 = getService$
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2619
2972
|
if (permissionChecker2.cannot.delete()) {
|
2620
2973
|
return ctx.forbidden();
|
2621
2974
|
}
|
2622
2975
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2623
2976
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2624
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2977
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2625
2978
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2626
2979
|
populate,
|
2627
2980
|
locale
|
@@ -2643,9 +2996,8 @@ const singleTypes = {
|
|
2643
2996
|
const { userAbility } = ctx.state;
|
2644
2997
|
const { model } = ctx.params;
|
2645
2998
|
const { query = {} } = ctx.request;
|
2646
|
-
const documentManager2 = getService$
|
2647
|
-
const
|
2648
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2999
|
+
const documentManager2 = getService$2("document-manager");
|
3000
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2649
3001
|
if (permissionChecker2.cannot.publish()) {
|
2650
3002
|
return ctx.forbidden();
|
2651
3003
|
}
|
@@ -2659,11 +3011,12 @@ const singleTypes = {
|
|
2659
3011
|
if (permissionChecker2.cannot.publish(document)) {
|
2660
3012
|
throw new strapiUtils.errors.ForbiddenError();
|
2661
3013
|
}
|
2662
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2663
|
-
|
3014
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
3015
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
3016
|
+
return publishResult.at(0);
|
2664
3017
|
});
|
2665
3018
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2666
|
-
ctx.body = await
|
3019
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2667
3020
|
},
|
2668
3021
|
async unpublish(ctx) {
|
2669
3022
|
const { userAbility } = ctx.state;
|
@@ -2672,9 +3025,8 @@ const singleTypes = {
|
|
2672
3025
|
body: { discardDraft, ...body },
|
2673
3026
|
query = {}
|
2674
3027
|
} = ctx.request;
|
2675
|
-
const documentManager2 = getService$
|
2676
|
-
const
|
2677
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
3028
|
+
const documentManager2 = getService$2("document-manager");
|
3029
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2678
3030
|
if (permissionChecker2.cannot.unpublish()) {
|
2679
3031
|
return ctx.forbidden();
|
2680
3032
|
}
|
@@ -2682,7 +3034,7 @@ const singleTypes = {
|
|
2682
3034
|
return ctx.forbidden();
|
2683
3035
|
}
|
2684
3036
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2685
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3037
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2686
3038
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2687
3039
|
if (!document) {
|
2688
3040
|
return ctx.notFound();
|
@@ -2700,7 +3052,7 @@ const singleTypes = {
|
|
2700
3052
|
ctx.body = await strapiUtils.async.pipe(
|
2701
3053
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2702
3054
|
permissionChecker2.sanitizeOutput,
|
2703
|
-
(document2) =>
|
3055
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2704
3056
|
)(document);
|
2705
3057
|
});
|
2706
3058
|
},
|
@@ -2708,14 +3060,13 @@ const singleTypes = {
|
|
2708
3060
|
const { userAbility } = ctx.state;
|
2709
3061
|
const { model } = ctx.params;
|
2710
3062
|
const { body, query = {} } = ctx.request;
|
2711
|
-
const documentManager2 = getService$
|
2712
|
-
const
|
2713
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
3063
|
+
const documentManager2 = getService$2("document-manager");
|
3064
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2714
3065
|
if (permissionChecker2.cannot.discard()) {
|
2715
3066
|
return ctx.forbidden();
|
2716
3067
|
}
|
2717
3068
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2718
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3069
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2719
3070
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2720
3071
|
if (!document) {
|
2721
3072
|
return ctx.notFound();
|
@@ -2726,16 +3077,16 @@ const singleTypes = {
|
|
2726
3077
|
ctx.body = await strapiUtils.async.pipe(
|
2727
3078
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2728
3079
|
permissionChecker2.sanitizeOutput,
|
2729
|
-
(document2) =>
|
3080
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2730
3081
|
)(document);
|
2731
3082
|
},
|
2732
3083
|
async countDraftRelations(ctx) {
|
2733
3084
|
const { userAbility } = ctx.state;
|
2734
3085
|
const { model } = ctx.params;
|
2735
3086
|
const { query } = ctx.request;
|
2736
|
-
const documentManager2 = getService$
|
2737
|
-
const permissionChecker2 = getService$
|
2738
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3087
|
+
const documentManager2 = getService$2("document-manager");
|
3088
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3089
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2739
3090
|
if (permissionChecker2.cannot.read()) {
|
2740
3091
|
return ctx.forbidden();
|
2741
3092
|
}
|
@@ -2756,9 +3107,9 @@ const uid$1 = {
|
|
2756
3107
|
async generateUID(ctx) {
|
2757
3108
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2758
3109
|
const { query = {} } = ctx.request;
|
2759
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3110
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2760
3111
|
await validateUIDField(contentTypeUID, field);
|
2761
|
-
const uidService = getService$
|
3112
|
+
const uidService = getService$2("uid");
|
2762
3113
|
ctx.body = {
|
2763
3114
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2764
3115
|
};
|
@@ -2768,9 +3119,9 @@ const uid$1 = {
|
|
2768
3119
|
ctx.request.body
|
2769
3120
|
);
|
2770
3121
|
const { query = {} } = ctx.request;
|
2771
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3122
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2772
3123
|
await validateUIDField(contentTypeUID, field);
|
2773
|
-
const uidService = getService$
|
3124
|
+
const uidService = getService$2("uid");
|
2774
3125
|
const isAvailable = await uidService.checkUIDAvailability({
|
2775
3126
|
contentTypeUID,
|
2776
3127
|
field,
|
@@ -2791,7 +3142,8 @@ const controllers = {
|
|
2791
3142
|
relations,
|
2792
3143
|
"single-types": singleTypes,
|
2793
3144
|
uid: uid$1,
|
2794
|
-
...history.controllers ? history.controllers : {}
|
3145
|
+
...history.controllers ? history.controllers : {},
|
3146
|
+
...preview.controllers ? preview.controllers : {}
|
2795
3147
|
};
|
2796
3148
|
const keys = {
|
2797
3149
|
CONFIGURATION: "configuration"
|
@@ -2920,18 +3272,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2920
3272
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2921
3273
|
___default.default.set(acc, [key], updatedMeta);
|
2922
3274
|
}
|
2923
|
-
if (!___default.default.has(edit, "mainField"))
|
2924
|
-
return acc;
|
3275
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2925
3276
|
if (!isRelation$1(attr)) {
|
2926
3277
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2927
3278
|
___default.default.set(acc, [key], updatedMeta);
|
2928
3279
|
return acc;
|
2929
3280
|
}
|
2930
|
-
if (edit.mainField === "id")
|
2931
|
-
return acc;
|
3281
|
+
if (edit.mainField === "id") return acc;
|
2932
3282
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2933
|
-
if (!targetSchema)
|
2934
|
-
return acc;
|
3283
|
+
if (!targetSchema) return acc;
|
2935
3284
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2936
3285
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2937
3286
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -2942,12 +3291,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2942
3291
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
2943
3292
|
}
|
2944
3293
|
const getTargetSchema = (targetModel) => {
|
2945
|
-
return getService$
|
3294
|
+
return getService$2("content-types").findContentType(targetModel);
|
2946
3295
|
};
|
2947
3296
|
const DEFAULT_LIST_LENGTH = 4;
|
2948
3297
|
const MAX_ROW_SIZE = 12;
|
2949
3298
|
const isAllowedFieldSize = (type, size) => {
|
2950
|
-
const { getFieldSize } = getService$
|
3299
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2951
3300
|
const fieldSize = getFieldSize(type);
|
2952
3301
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2953
3302
|
return false;
|
@@ -2955,7 +3304,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2955
3304
|
return size <= MAX_ROW_SIZE;
|
2956
3305
|
};
|
2957
3306
|
const getDefaultFieldSize = (attribute) => {
|
2958
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3307
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2959
3308
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2960
3309
|
};
|
2961
3310
|
async function createDefaultLayouts(schema) {
|
@@ -2976,8 +3325,7 @@ function createDefaultEditLayout(schema) {
|
|
2976
3325
|
return appendToEditLayout([], keys2, schema);
|
2977
3326
|
}
|
2978
3327
|
function syncLayouts(configuration, schema) {
|
2979
|
-
if (___default.default.isEmpty(configuration.layouts))
|
2980
|
-
return createDefaultLayouts(schema);
|
3328
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
2981
3329
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
2982
3330
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
2983
3331
|
const cleanEditRelations = editRelations.filter(
|
@@ -2988,9 +3336,8 @@ function syncLayouts(configuration, schema) {
|
|
2988
3336
|
for (const row of edit) {
|
2989
3337
|
const newRow = [];
|
2990
3338
|
for (const el of row) {
|
2991
|
-
if (!hasEditableAttribute(schema, el.name))
|
2992
|
-
|
2993
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3339
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3340
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
2994
3341
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
2995
3342
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
2996
3343
|
elementsToReAppend.push(el.name);
|
@@ -3020,8 +3367,7 @@ function syncLayouts(configuration, schema) {
|
|
3020
3367
|
};
|
3021
3368
|
}
|
3022
3369
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3023
|
-
if (keysToAppend.length === 0)
|
3024
|
-
return layout;
|
3370
|
+
if (keysToAppend.length === 0) return layout;
|
3025
3371
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3026
3372
|
if (!layout[currentRowIndex]) {
|
3027
3373
|
layout[currentRowIndex] = [];
|
@@ -3130,17 +3476,17 @@ const configurationService$1 = createConfigurationService({
|
|
3130
3476
|
isComponent: true,
|
3131
3477
|
prefix: STORE_KEY_PREFIX,
|
3132
3478
|
getModels() {
|
3133
|
-
const { toContentManagerModel } = getService$
|
3479
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3134
3480
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3135
3481
|
}
|
3136
3482
|
});
|
3137
3483
|
const components = ({ strapi: strapi2 }) => ({
|
3138
3484
|
findAllComponents() {
|
3139
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3140
3486
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3141
3487
|
},
|
3142
3488
|
findComponent(uid2) {
|
3143
|
-
const { toContentManagerModel } = getService$
|
3489
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3144
3490
|
const component = strapi2.components[uid2];
|
3145
3491
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3146
3492
|
},
|
@@ -3191,17 +3537,17 @@ const configurationService = createConfigurationService({
|
|
3191
3537
|
storeUtils,
|
3192
3538
|
prefix: "content_types",
|
3193
3539
|
getModels() {
|
3194
|
-
const { toContentManagerModel } = getService$
|
3540
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3195
3541
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3196
3542
|
}
|
3197
3543
|
});
|
3198
3544
|
const service = ({ strapi: strapi2 }) => ({
|
3199
3545
|
findAllContentTypes() {
|
3200
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3201
3547
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3202
3548
|
},
|
3203
3549
|
findContentType(uid2) {
|
3204
|
-
const { toContentManagerModel } = getService$
|
3550
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3205
3551
|
const contentType = strapi2.contentTypes[uid2];
|
3206
3552
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3207
3553
|
},
|
@@ -3230,7 +3576,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3230
3576
|
return this.findConfiguration(contentType);
|
3231
3577
|
},
|
3232
3578
|
findComponentsConfigurations(contentType) {
|
3233
|
-
return getService$
|
3579
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3234
3580
|
},
|
3235
3581
|
syncConfigurations() {
|
3236
3582
|
return configurationService.syncConfigurations();
|
@@ -3411,12 +3757,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3411
3757
|
ability: userAbility,
|
3412
3758
|
model
|
3413
3759
|
});
|
3414
|
-
const
|
3760
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3761
|
+
const toSubject = (entity) => {
|
3762
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3763
|
+
};
|
3415
3764
|
const can = (action, entity, field) => {
|
3416
|
-
|
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
|
+
);
|
3417
3772
|
};
|
3418
3773
|
const cannot = (action, entity, field) => {
|
3419
|
-
|
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
|
+
);
|
3420
3781
|
};
|
3421
3782
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3422
3783
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3487,7 +3848,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3487
3848
|
return userAbility.can(action);
|
3488
3849
|
},
|
3489
3850
|
async registerPermissions() {
|
3490
|
-
const displayedContentTypes = getService$
|
3851
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3491
3852
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3492
3853
|
const actions = [
|
3493
3854
|
{
|
@@ -3559,7 +3920,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3559
3920
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3560
3921
|
}
|
3561
3922
|
});
|
3562
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
|
3923
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
|
3563
3924
|
const { isAnyToMany } = strapiUtils__default.default.relations;
|
3564
3925
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
|
3565
3926
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3572,6 +3933,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3572
3933
|
if (initialPopulate) {
|
3573
3934
|
return initialPopulate;
|
3574
3935
|
}
|
3936
|
+
if (attributeName === "localizations") {
|
3937
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3938
|
+
return {
|
3939
|
+
populate: validationPopulate.populate
|
3940
|
+
};
|
3941
|
+
}
|
3575
3942
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3576
3943
|
return true;
|
3577
3944
|
}
|
@@ -3631,6 +3998,9 @@ const getDeepPopulate = (uid2, {
|
|
3631
3998
|
return {};
|
3632
3999
|
}
|
3633
4000
|
const model = strapi.getModel(uid2);
|
4001
|
+
if (!model) {
|
4002
|
+
return {};
|
4003
|
+
}
|
3634
4004
|
return Object.keys(model.attributes).reduce(
|
3635
4005
|
(populateAcc, attributeName) => fp.merge(
|
3636
4006
|
populateAcc,
|
@@ -3650,6 +4020,48 @@ const getDeepPopulate = (uid2, {
|
|
3650
4020
|
{}
|
3651
4021
|
);
|
3652
4022
|
};
|
4023
|
+
const getPopulateForValidation = (uid2) => {
|
4024
|
+
const model = strapi.getModel(uid2);
|
4025
|
+
if (!model) {
|
4026
|
+
return {};
|
4027
|
+
}
|
4028
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
4029
|
+
if (isScalarAttribute(attribute)) {
|
4030
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4031
|
+
populateAcc.fields = populateAcc.fields || [];
|
4032
|
+
populateAcc.fields.push(attributeName);
|
4033
|
+
}
|
4034
|
+
return populateAcc;
|
4035
|
+
}
|
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;
|
4044
|
+
}
|
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;
|
4054
|
+
},
|
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;
|
4063
|
+
}, {});
|
4064
|
+
};
|
3653
4065
|
const getDeepPopulateDraftCount = (uid2) => {
|
3654
4066
|
const model = strapi.getModel(uid2);
|
3655
4067
|
let hasRelations = false;
|
@@ -3657,6 +4069,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3657
4069
|
const attribute = model.attributes[attributeName];
|
3658
4070
|
switch (attribute.type) {
|
3659
4071
|
case "relation": {
|
4072
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4073
|
+
if (isMorphRelation) {
|
4074
|
+
break;
|
4075
|
+
}
|
3660
4076
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3661
4077
|
populateAcc[attributeName] = {
|
3662
4078
|
count: true,
|
@@ -3671,22 +4087,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3671
4087
|
attribute.component
|
3672
4088
|
);
|
3673
4089
|
if (childHasRelations) {
|
3674
|
-
populateAcc[attributeName] = {
|
4090
|
+
populateAcc[attributeName] = {
|
4091
|
+
populate: populate2
|
4092
|
+
};
|
3675
4093
|
hasRelations = true;
|
3676
4094
|
}
|
3677
4095
|
break;
|
3678
4096
|
}
|
3679
4097
|
case "dynamiczone": {
|
3680
|
-
const
|
3681
|
-
const { populate:
|
3682
|
-
if (
|
4098
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
4099
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
4100
|
+
if (componentHasRelations) {
|
3683
4101
|
hasRelations = true;
|
3684
|
-
return
|
4102
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3685
4103
|
}
|
3686
4104
|
return acc;
|
3687
4105
|
}, {});
|
3688
|
-
if (!fp.isEmpty(
|
3689
|
-
populateAcc[attributeName] = {
|
4106
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
4107
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3690
4108
|
}
|
3691
4109
|
break;
|
3692
4110
|
}
|
@@ -3721,7 +4139,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3721
4139
|
return populateQuery;
|
3722
4140
|
};
|
3723
4141
|
const buildDeepPopulate = (uid2) => {
|
3724
|
-
return getService$
|
4142
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3725
4143
|
};
|
3726
4144
|
const populateBuilder = (uid2) => {
|
3727
4145
|
let getInitialPopulate = async () => {
|
@@ -3878,41 +4296,55 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3878
4296
|
"updatedBy",
|
3879
4297
|
"status"
|
3880
4298
|
];
|
3881
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
4299
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
4300
|
+
"id",
|
4301
|
+
"locale",
|
4302
|
+
"updatedAt",
|
4303
|
+
"createdAt",
|
4304
|
+
"publishedAt",
|
4305
|
+
"documentId"
|
4306
|
+
];
|
3882
4307
|
const CONTENT_MANAGER_STATUS = {
|
3883
4308
|
PUBLISHED: "published",
|
3884
4309
|
DRAFT: "draft",
|
3885
4310
|
MODIFIED: "modified"
|
3886
4311
|
};
|
3887
|
-
const
|
3888
|
-
if (!
|
4312
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
4313
|
+
if (!version || !version.updatedAt) {
|
3889
4314
|
return false;
|
3890
4315
|
}
|
3891
|
-
const
|
3892
|
-
const
|
3893
|
-
|
3894
|
-
return difference <= threshold;
|
4316
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
4317
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
4318
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3895
4319
|
};
|
3896
4320
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3897
4321
|
/**
|
3898
4322
|
* Returns available locales of a document for the current status
|
3899
4323
|
*/
|
3900
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4324
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3901
4325
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3902
|
-
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
3906
|
-
|
3907
|
-
|
3908
|
-
|
3909
|
-
|
3910
|
-
|
3911
|
-
|
3912
|
-
|
3913
|
-
|
3914
|
-
|
3915
|
-
|
4326
|
+
if (version.locale) {
|
4327
|
+
delete versionsByLocale[version.locale];
|
4328
|
+
}
|
4329
|
+
const model = strapi2.getModel(uid2);
|
4330
|
+
const mappingResult = await strapiUtils.async.map(
|
4331
|
+
Object.values(versionsByLocale),
|
4332
|
+
async (localeVersions) => {
|
4333
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4334
|
+
return localeVersions[0];
|
4335
|
+
}
|
4336
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4337
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4338
|
+
if (!draftVersion) {
|
4339
|
+
return;
|
4340
|
+
}
|
4341
|
+
return {
|
4342
|
+
...draftVersion,
|
4343
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4344
|
+
};
|
4345
|
+
}
|
4346
|
+
);
|
4347
|
+
return mappingResult.filter(Boolean);
|
3916
4348
|
},
|
3917
4349
|
/**
|
3918
4350
|
* Returns available status of a document for the current locale
|
@@ -3924,8 +4356,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3924
4356
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
3925
4357
|
return matchLocale && matchStatus;
|
3926
4358
|
});
|
3927
|
-
if (!availableStatus)
|
3928
|
-
return availableStatus;
|
4359
|
+
if (!availableStatus) return availableStatus;
|
3929
4360
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
3930
4361
|
},
|
3931
4362
|
/**
|
@@ -3935,50 +4366,64 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3935
4366
|
* @returns
|
3936
4367
|
*/
|
3937
4368
|
async getManyAvailableStatus(uid2, documents) {
|
3938
|
-
if (!documents.length)
|
3939
|
-
return [];
|
4369
|
+
if (!documents.length) return [];
|
3940
4370
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
3941
|
-
const
|
3942
|
-
const
|
3943
|
-
|
3944
|
-
|
3945
|
-
|
3946
|
-
|
3947
|
-
|
3948
|
-
|
3949
|
-
|
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"]
|
3950
4382
|
});
|
3951
4383
|
},
|
3952
4384
|
getStatus(version, otherDocumentStatuses) {
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3959
|
-
if (!publishedVersion) {
|
3960
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
3961
|
-
}
|
4385
|
+
let draftVersion;
|
4386
|
+
let publishedVersion;
|
4387
|
+
if (version.publishedAt) {
|
4388
|
+
publishedVersion = version;
|
4389
|
+
} else {
|
4390
|
+
draftVersion = version;
|
3962
4391
|
}
|
3963
|
-
|
3964
|
-
|
4392
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4393
|
+
if (otherVersion?.publishedAt) {
|
4394
|
+
publishedVersion = otherVersion;
|
4395
|
+
} else if (otherVersion) {
|
4396
|
+
draftVersion = otherVersion;
|
3965
4397
|
}
|
3966
|
-
return CONTENT_MANAGER_STATUS.
|
4398
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4399
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4400
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4401
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3967
4402
|
},
|
4403
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4404
|
+
// We could refactor this so the locales are only loaded when they're
|
4405
|
+
// needed. e.g. in the bulk locale action modal.
|
3968
4406
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
3969
|
-
const
|
3970
|
-
|
3971
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
4407
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4408
|
+
const params = {
|
3972
4409
|
populate: {
|
4410
|
+
...populate,
|
4411
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3973
4412
|
createdBy: {
|
3974
4413
|
select: ["id", "firstname", "lastname", "email"]
|
3975
4414
|
},
|
3976
4415
|
updatedBy: {
|
3977
4416
|
select: ["id", "firstname", "lastname", "email"]
|
3978
4417
|
}
|
4418
|
+
},
|
4419
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4420
|
+
filters: {
|
4421
|
+
documentId: version.documentId
|
3979
4422
|
}
|
3980
|
-
}
|
3981
|
-
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) : [];
|
3982
4427
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3983
4428
|
return {
|
3984
4429
|
availableLocales: availableLocalesResult,
|
@@ -3991,13 +4436,30 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3991
4436
|
* - Available status of the document for the current locale
|
3992
4437
|
*/
|
3993
4438
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3994
|
-
if (!document)
|
3995
|
-
return
|
4439
|
+
if (!document) {
|
4440
|
+
return {
|
4441
|
+
data: document,
|
4442
|
+
meta: {
|
4443
|
+
availableLocales: [],
|
4444
|
+
availableStatus: []
|
4445
|
+
}
|
4446
|
+
};
|
4447
|
+
}
|
3996
4448
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
3997
4449
|
if (!hasDraftAndPublish) {
|
3998
4450
|
opts.availableStatus = false;
|
3999
4451
|
}
|
4000
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
|
+
}
|
4001
4463
|
return {
|
4002
4464
|
data: {
|
4003
4465
|
...document,
|
@@ -4042,26 +4504,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
4042
4504
|
}, 0);
|
4043
4505
|
};
|
4044
4506
|
const { ApplicationError } = strapiUtils.errors;
|
4045
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4046
4507
|
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
4047
4508
|
const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
|
4048
4509
|
const omitIdField = fp.omit("id");
|
4049
|
-
const emitEvent = async (uid2, event, document) => {
|
4050
|
-
const modelDef = strapi.getModel(uid2);
|
4051
|
-
const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
|
4052
|
-
{
|
4053
|
-
schema: modelDef,
|
4054
|
-
getModel(uid22) {
|
4055
|
-
return strapi.getModel(uid22);
|
4056
|
-
}
|
4057
|
-
},
|
4058
|
-
document
|
4059
|
-
);
|
4060
|
-
strapi.eventHub.emit(event, {
|
4061
|
-
model: modelDef.modelName,
|
4062
|
-
entry: sanitizedDocument
|
4063
|
-
});
|
4064
|
-
};
|
4065
4510
|
const documentManager = ({ strapi: strapi2 }) => {
|
4066
4511
|
return {
|
4067
4512
|
async findOne(id, uid2, opts = {}) {
|
@@ -4080,6 +4525,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4080
4525
|
} else if (opts.locale && opts.locale !== "*") {
|
4081
4526
|
where.locale = opts.locale;
|
4082
4527
|
}
|
4528
|
+
if (typeof opts.isPublished === "boolean") {
|
4529
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4530
|
+
}
|
4083
4531
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4084
4532
|
},
|
4085
4533
|
async findMany(opts, uid2) {
|
@@ -4113,10 +4561,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4113
4561
|
async clone(id, body, uid2) {
|
4114
4562
|
const populate = await buildDeepPopulate(uid2);
|
4115
4563
|
const params = {
|
4116
|
-
data:
|
4117
|
-
...omitIdField(body),
|
4118
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4119
|
-
},
|
4564
|
+
data: omitIdField(body),
|
4120
4565
|
populate
|
4121
4566
|
};
|
4122
4567
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4142,70 +4587,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4142
4587
|
return {};
|
4143
4588
|
},
|
4144
4589
|
// FIXME: handle relations
|
4145
|
-
async deleteMany(
|
4146
|
-
const
|
4147
|
-
|
4148
|
-
|
4149
|
-
}
|
4150
|
-
return { count: docs.length };
|
4590
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4591
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4592
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4593
|
+
});
|
4594
|
+
return { count: deletedEntries.length };
|
4151
4595
|
},
|
4152
4596
|
async publish(id, uid2, opts = {}) {
|
4153
4597
|
const populate = await buildDeepPopulate(uid2);
|
4154
4598
|
const params = { ...opts, populate };
|
4155
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4599
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4156
4600
|
},
|
4157
|
-
async publishMany(
|
4158
|
-
|
4159
|
-
|
4160
|
-
|
4161
|
-
|
4162
|
-
|
4163
|
-
|
4164
|
-
strapi2.getModel(uid2),
|
4165
|
-
document,
|
4166
|
-
void 0,
|
4167
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4168
|
-
document
|
4169
|
-
);
|
4170
|
-
})
|
4171
|
-
);
|
4172
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4173
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4174
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4175
|
-
const populate = await buildDeepPopulate(uid2);
|
4176
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4177
|
-
where: filters,
|
4178
|
-
data
|
4179
|
-
});
|
4180
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4181
|
-
where: filters,
|
4182
|
-
populate
|
4601
|
+
async publishMany(uid2, documentIds, locale) {
|
4602
|
+
return strapi2.db.transaction(async () => {
|
4603
|
+
const results = await Promise.all(
|
4604
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4605
|
+
);
|
4606
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4607
|
+
return publishedEntitiesCount;
|
4183
4608
|
});
|
4184
|
-
await Promise.all(
|
4185
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4186
|
-
);
|
4187
|
-
return publishedEntitiesCount;
|
4188
4609
|
},
|
4189
|
-
async unpublishMany(
|
4190
|
-
|
4191
|
-
return
|
4192
|
-
|
4193
|
-
|
4194
|
-
|
4195
|
-
|
4196
|
-
const populate = await buildDeepPopulate(uid2);
|
4197
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4198
|
-
where: filters,
|
4199
|
-
data
|
4200
|
-
});
|
4201
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4202
|
-
where: filters,
|
4203
|
-
populate
|
4610
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4611
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4612
|
+
return Promise.all(
|
4613
|
+
documentIds.map(
|
4614
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4615
|
+
)
|
4616
|
+
);
|
4204
4617
|
});
|
4205
|
-
|
4206
|
-
|
4207
|
-
);
|
4208
|
-
return unpublishedEntitiesCount;
|
4618
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4619
|
+
return { count: unpublishedEntitiesCount };
|
4209
4620
|
},
|
4210
4621
|
async unpublish(id, uid2, opts = {}) {
|
4211
4622
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4230,16 +4641,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4230
4641
|
}
|
4231
4642
|
return sumDraftCounts(document, uid2);
|
4232
4643
|
},
|
4233
|
-
async countManyEntriesDraftRelations(
|
4644
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4234
4645
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4235
4646
|
if (!hasRelations) {
|
4236
4647
|
return 0;
|
4237
4648
|
}
|
4649
|
+
let localeFilter = {};
|
4650
|
+
if (locale) {
|
4651
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4652
|
+
}
|
4238
4653
|
const entities = await strapi2.db.query(uid2).findMany({
|
4239
4654
|
populate,
|
4240
4655
|
where: {
|
4241
|
-
|
4242
|
-
...
|
4656
|
+
documentId: { $in: documentIds },
|
4657
|
+
...localeFilter
|
4243
4658
|
}
|
4244
4659
|
});
|
4245
4660
|
const totalNumberDraftRelations = entities.reduce(
|
@@ -4262,7 +4677,8 @@ const services = {
|
|
4262
4677
|
permission,
|
4263
4678
|
"populate-builder": populateBuilder$1,
|
4264
4679
|
uid,
|
4265
|
-
...history.services ? history.services : {}
|
4680
|
+
...history.services ? history.services : {},
|
4681
|
+
...preview.services ? preview.services : {}
|
4266
4682
|
};
|
4267
4683
|
const index = () => {
|
4268
4684
|
return {
|