@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.e8d8fc824d0f6a695b2a9ebaa4680ed21c3645ca
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js → ComponentConfigurationPage-BlzvDpbX.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-BlzvDpbX.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-DaPOlQaD.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-DaPOlQaD.mjs.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-DacbqQ_f.mjs → EditConfigurationPage-BZPXItXo.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-BZPXItXo.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js → EditConfigurationPage-uy-v43AR.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-uy-v43AR.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-DT6A4ayX.js} +102 -54
- package/dist/_chunks/EditViewPage-DT6A4ayX.js.map +1 -0
- package/dist/_chunks/EditViewPage-oOLeTySr.mjs +254 -0
- package/dist/_chunks/EditViewPage-oOLeTySr.mjs.map +1 -0
- package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-D7dv2aUX.mjs} +1192 -896
- package/dist/_chunks/Field-D7dv2aUX.mjs.map +1 -0
- package/dist/_chunks/{Field-DmVKIAOo.js → Field-kYFVIGiP.js} +1238 -943
- package/dist/_chunks/Field-kYFVIGiP.js.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-BxR6sc29.mjs} +67 -46
- package/dist/_chunks/Form-BxR6sc29.mjs.map +1 -0
- package/dist/_chunks/{Form-CPZC9vWa.js → Form-CCijSg3V.js} +68 -49
- package/dist/_chunks/Form-CCijSg3V.js.map +1 -0
- package/dist/_chunks/{History-DeAPlvtv.js → History-BMndx49M.js} +182 -147
- package/dist/_chunks/History-BMndx49M.js.map +1 -0
- package/dist/_chunks/{History-Dmr9fmUA.mjs → History-D8F7aYQU.mjs} +181 -144
- package/dist/_chunks/History-D8F7aYQU.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-DouY1EWM.js} +72 -63
- package/dist/_chunks/ListConfigurationPage-DouY1EWM.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-DqAdSPwC.mjs} +68 -57
- package/dist/_chunks/ListConfigurationPage-DqAdSPwC.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-BPVmh9pq.js} +179 -164
- package/dist/_chunks/ListViewPage-BPVmh9pq.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-C73F0jPh.mjs} +175 -159
- package/dist/_chunks/ListViewPage-C73F0jPh.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-B5w7iJOF.mjs} +3 -3
- package/dist/_chunks/NoContentTypePage-B5w7iJOF.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BwcL--4H.js} +3 -3
- package/dist/_chunks/NoContentTypePage-BwcL--4H.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-BMFKVcwJ.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-BMFKVcwJ.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-UnEgMGK4.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-UnEgMGK4.mjs.map} +1 -1
- package/dist/_chunks/Preview-B7PR3Ok_.js +312 -0
- package/dist/_chunks/Preview-B7PR3Ok_.js.map +1 -0
- package/dist/_chunks/Preview-DECOhK0D.mjs +294 -0
- package/dist/_chunks/Preview-DECOhK0D.mjs.map +1 -0
- package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-DinMQJ4B.mjs} +138 -94
- package/dist/_chunks/Relations-DinMQJ4B.mjs.map +1 -0
- package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-lndx3aQk.js} +142 -100
- package/dist/_chunks/Relations-lndx3aQk.js.map +1 -0
- package/dist/_chunks/{en-C-V1_90f.js → en-BK8Xyl5I.js} +38 -18
- package/dist/_chunks/{en-C-V1_90f.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-MBPul9Su.mjs → en-Dtk_ot79.mjs} +38 -18
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Dtk_ot79.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-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-CwRRo1V9.mjs → index-C2SagWVW.mjs} +2070 -988
- package/dist/_chunks/index-C2SagWVW.mjs.map +1 -0
- package/dist/_chunks/{index-C6AH2hEl.js → index-Cnw4gqee.js} +2047 -966
- package/dist/_chunks/index-Cnw4gqee.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-jIDzX0Fp.mjs → layout-DY_D9MGA.mjs} +46 -28
- package/dist/_chunks/layout-DY_D9MGA.mjs.map +1 -0
- package/dist/_chunks/{layout-B_SXLhqf.js → layout-ivwIVPnV.js} +47 -32
- package/dist/_chunks/layout-ivwIVPnV.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-iBMa_OFG.js → relations-B7C7O_Pv.js} +6 -7
- package/dist/_chunks/relations-B7C7O_Pv.js.map +1 -0
- package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-Boc5Y9kX.mjs} +6 -7
- package/dist/_chunks/relations-Boc5Y9kX.mjs.map +1 -0
- package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.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/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +9 -7
- package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +6 -5
- package/dist/admin/src/exports.d.ts +2 -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 +37 -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 +2 -2
- 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/Field.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/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/Header.d.ts +11 -11
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- package/dist/admin/src/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 +886 -480
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +892 -485
- 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/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 +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +22 -42
- 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 +13 -12
- 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 +22 -42
- 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 -21
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DDS6H9HO.mjs +0 -203
- package/dist/_chunks/EditViewPage-DDS6H9HO.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
- package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
- package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
- package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
- package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
- package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
- package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
- package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
- package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
- package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
- package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
- package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
- package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
- package/dist/_chunks/layout-jIDzX0Fp.mjs.map +0 -1
- package/dist/_chunks/relations-CuvIgCqI.mjs.map +0 -1
- package/dist/_chunks/relations-iBMa_OFG.js.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/_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.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1,
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy
|
1
|
+
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, pagination } from "@strapi/utils";
|
2
|
+
import { pick, omit, difference, castArray, mergeWith, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -7,10 +7,10 @@ import isNil from "lodash/isNil";
|
|
7
7
|
import _, { intersection as intersection$1, difference as difference$1 } from "lodash";
|
8
8
|
import qs from "qs";
|
9
9
|
import slugify from "@sindresorhus/slugify";
|
10
|
-
const getService$
|
10
|
+
const getService$2 = (name) => {
|
11
11
|
return strapi.plugin("content-manager").service(name);
|
12
12
|
};
|
13
|
-
function getService(strapi2, name) {
|
13
|
+
function getService$1(strapi2, name) {
|
14
14
|
return strapi2.service(`plugin::content-manager.${name}`);
|
15
15
|
}
|
16
16
|
const historyRestoreVersionSchema = yup.object().shape({
|
@@ -46,7 +46,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
46
46
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
47
47
|
throw new errors.ForbiddenError("contentType and documentId are required");
|
48
48
|
}
|
49
|
-
const permissionChecker2 = getService$
|
49
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
50
50
|
userAbility: ctx.state.userAbility,
|
51
51
|
model: ctx.query.contentType
|
52
52
|
});
|
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
54
54
|
return ctx.forbidden();
|
55
55
|
}
|
56
56
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
57
|
-
const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
|
57
|
+
const { results, pagination: pagination2 } = await getService$1(strapi2, "history").findVersionsPage({
|
58
58
|
query: {
|
59
59
|
...query,
|
60
60
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -73,20 +73,20 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
73
73
|
);
|
74
74
|
return {
|
75
75
|
data: sanitizedResults,
|
76
|
-
meta: { pagination }
|
76
|
+
meta: { pagination: pagination2 }
|
77
77
|
};
|
78
78
|
},
|
79
79
|
async restoreVersion(ctx) {
|
80
80
|
const request = ctx.request;
|
81
81
|
await validateRestoreVersion(request.body, "contentType is required");
|
82
|
-
const permissionChecker2 = getService$
|
82
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
83
83
|
userAbility: ctx.state.userAbility,
|
84
84
|
model: request.body.contentType
|
85
85
|
});
|
86
86
|
if (permissionChecker2.cannot.update()) {
|
87
87
|
throw new errors.ForbiddenError();
|
88
88
|
}
|
89
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
89
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
90
90
|
request.params.versionId
|
91
91
|
);
|
92
92
|
return {
|
@@ -95,7 +95,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
95
95
|
}
|
96
96
|
};
|
97
97
|
};
|
98
|
-
const controllers$
|
98
|
+
const controllers$2 = {
|
99
99
|
"history-version": createHistoryVersionController
|
100
100
|
/**
|
101
101
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -141,8 +141,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
141
141
|
};
|
142
142
|
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
143
143
|
if (Array.isArray(versionRelationData)) {
|
144
|
-
if (versionRelationData.length === 0)
|
145
|
-
return versionRelationData;
|
144
|
+
if (versionRelationData.length === 0) return versionRelationData;
|
146
145
|
const existingAndMissingRelations = await Promise.all(
|
147
146
|
versionRelationData.map((relation) => {
|
148
147
|
return strapi2.documents(attribute.target).findOne({
|
@@ -173,10 +172,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
173
172
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
174
173
|
};
|
175
174
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
175
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
176
176
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
177
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
177
178
|
const getLocaleDictionary = async () => {
|
178
|
-
if (!localesService)
|
179
|
-
return {};
|
179
|
+
if (!localesService) return {};
|
180
180
|
const locales = await localesService.find() || [];
|
181
181
|
return locales.reduce(
|
182
182
|
(acc, locale) => {
|
@@ -200,31 +200,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
200
200
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
201
201
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
202
202
|
};
|
203
|
-
const
|
203
|
+
const getComponentFields = (componentUID) => {
|
204
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
205
|
+
(fieldsAcc, [key, attribute]) => {
|
206
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
207
|
+
fieldsAcc.push(key);
|
208
|
+
}
|
209
|
+
return fieldsAcc;
|
210
|
+
},
|
211
|
+
[]
|
212
|
+
);
|
213
|
+
};
|
214
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
204
215
|
const model = strapi2.getModel(uid2);
|
205
216
|
const attributes = Object.entries(model.attributes);
|
217
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
206
218
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
207
219
|
switch (attribute.type) {
|
208
220
|
case "relation": {
|
221
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
222
|
+
if (isMorphRelation) {
|
223
|
+
break;
|
224
|
+
}
|
209
225
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
210
226
|
if (isVisible2) {
|
211
|
-
acc[attributeName] = {
|
227
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
212
228
|
}
|
213
229
|
break;
|
214
230
|
}
|
215
231
|
case "media": {
|
216
|
-
acc[attributeName] = {
|
232
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
217
233
|
break;
|
218
234
|
}
|
219
235
|
case "component": {
|
220
236
|
const populate = getDeepPopulate2(attribute.component);
|
221
|
-
acc[attributeName] = {
|
237
|
+
acc[attributeName] = {
|
238
|
+
populate,
|
239
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
240
|
+
};
|
222
241
|
break;
|
223
242
|
}
|
224
243
|
case "dynamiczone": {
|
225
244
|
const populatedComponents = (attribute.components || []).reduce(
|
226
245
|
(acc2, componentUID) => {
|
227
|
-
acc2[componentUID] = {
|
246
|
+
acc2[componentUID] = {
|
247
|
+
populate: getDeepPopulate2(componentUID),
|
248
|
+
[fieldSelector]: getComponentFields(componentUID)
|
249
|
+
};
|
228
250
|
return acc2;
|
229
251
|
},
|
230
252
|
{}
|
@@ -286,6 +308,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
286
308
|
getRelationRestoreValue,
|
287
309
|
getMediaRestoreValue,
|
288
310
|
getDefaultLocale,
|
311
|
+
isLocalizedContentType,
|
289
312
|
getLocaleDictionary,
|
290
313
|
getRetentionDays,
|
291
314
|
getVersionStatus,
|
@@ -308,8 +331,14 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
308
331
|
});
|
309
332
|
},
|
310
333
|
async findVersionsPage(params) {
|
311
|
-
const
|
312
|
-
const
|
334
|
+
const model = strapi2.getModel(params.query.contentType);
|
335
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
336
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
337
|
+
let locale = null;
|
338
|
+
if (isLocalizedContentType) {
|
339
|
+
locale = params.query.locale || defaultLocale;
|
340
|
+
}
|
341
|
+
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
313
342
|
query.findPage({
|
314
343
|
...params.query,
|
315
344
|
where: {
|
@@ -330,7 +359,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
330
359
|
const attributeValue = entry.data[attributeKey];
|
331
360
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
332
361
|
if (attributeSchema.type === "media") {
|
333
|
-
const permissionChecker2 = getService$
|
362
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
334
363
|
userAbility: params.state.userAbility,
|
335
364
|
model: "plugin::upload.file"
|
336
365
|
});
|
@@ -353,7 +382,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
353
382
|
if (userToPopulate == null) {
|
354
383
|
return null;
|
355
384
|
}
|
356
|
-
return strapi2.query("admin::user").findOne({
|
385
|
+
return strapi2.query("admin::user").findOne({
|
386
|
+
where: {
|
387
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
388
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
389
|
+
}
|
390
|
+
});
|
357
391
|
})
|
358
392
|
);
|
359
393
|
return {
|
@@ -366,7 +400,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
366
400
|
[attributeKey]: adminUsers
|
367
401
|
};
|
368
402
|
}
|
369
|
-
const permissionChecker2 = getService$
|
403
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
370
404
|
userAbility: params.state.userAbility,
|
371
405
|
model: attributeSchema.target
|
372
406
|
});
|
@@ -408,7 +442,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
408
442
|
);
|
409
443
|
return {
|
410
444
|
results: formattedResults,
|
411
|
-
pagination
|
445
|
+
pagination: pagination2
|
412
446
|
};
|
413
447
|
},
|
414
448
|
async restoreVersion(versionId) {
|
@@ -464,13 +498,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
464
498
|
}
|
465
499
|
};
|
466
500
|
};
|
501
|
+
const shouldCreateHistoryVersion = (context) => {
|
502
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
503
|
+
return false;
|
504
|
+
}
|
505
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
509
|
+
return false;
|
510
|
+
}
|
511
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
512
|
+
return false;
|
513
|
+
}
|
514
|
+
return true;
|
515
|
+
};
|
516
|
+
const getSchemas = (uid2) => {
|
517
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
518
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
519
|
+
(currentComponentSchemas, key) => {
|
520
|
+
const fieldSchema = attributesSchema[key];
|
521
|
+
if (fieldSchema.type === "component") {
|
522
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
523
|
+
return {
|
524
|
+
...currentComponentSchemas,
|
525
|
+
[fieldSchema.component]: componentSchema
|
526
|
+
};
|
527
|
+
}
|
528
|
+
return currentComponentSchemas;
|
529
|
+
},
|
530
|
+
{}
|
531
|
+
);
|
532
|
+
return {
|
533
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
534
|
+
componentsSchemas
|
535
|
+
};
|
536
|
+
};
|
467
537
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
538
|
const state = {
|
469
539
|
deleteExpiredJob: null,
|
470
540
|
isInitialized: false
|
471
541
|
};
|
472
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
473
|
-
const historyService = getService(strapi2, "history");
|
474
542
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
475
543
|
return {
|
476
544
|
async bootstrap() {
|
@@ -478,65 +546,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
478
546
|
return;
|
479
547
|
}
|
480
548
|
strapi2.documents.use(async (context, next) => {
|
481
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
482
|
-
return next();
|
483
|
-
}
|
484
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
485
|
-
return next();
|
486
|
-
}
|
487
|
-
const contentTypeUid = context.contentType.uid;
|
488
|
-
if (!contentTypeUid.startsWith("api::")) {
|
489
|
-
return next();
|
490
|
-
}
|
491
549
|
const result = await next();
|
492
|
-
|
550
|
+
if (!shouldCreateHistoryVersion(context)) {
|
551
|
+
return result;
|
552
|
+
}
|
553
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
493
554
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
494
|
-
const
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
555
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
556
|
+
if (!locales.length) {
|
557
|
+
return result;
|
558
|
+
}
|
559
|
+
const uid2 = context.contentType.uid;
|
560
|
+
const schemas = getSchemas(uid2);
|
561
|
+
const model = strapi2.getModel(uid2);
|
562
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
563
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
564
|
+
where: {
|
565
|
+
documentId,
|
566
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
567
|
+
...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
568
|
+
},
|
569
|
+
populate: serviceUtils.getDeepPopulate(
|
570
|
+
uid2,
|
571
|
+
true
|
572
|
+
/* use database syntax */
|
573
|
+
)
|
499
574
|
});
|
500
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
501
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
502
|
-
const componentsSchemas = Object.keys(
|
503
|
-
attributesSchema
|
504
|
-
).reduce((currentComponentSchemas, key) => {
|
505
|
-
const fieldSchema = attributesSchema[key];
|
506
|
-
if (fieldSchema.type === "component") {
|
507
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
508
|
-
return {
|
509
|
-
...currentComponentSchemas,
|
510
|
-
[fieldSchema.component]: componentSchema
|
511
|
-
};
|
512
|
-
}
|
513
|
-
return currentComponentSchemas;
|
514
|
-
}, {});
|
515
575
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
516
|
-
onCommit(() => {
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
576
|
+
onCommit(async () => {
|
577
|
+
for (const entry of localeEntries) {
|
578
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
579
|
+
await getService$1(strapi2, "history").createVersion({
|
580
|
+
contentType: uid2,
|
581
|
+
data: omit(FIELDS_TO_IGNORE, entry),
|
582
|
+
relatedDocumentId: documentId,
|
583
|
+
locale: entry.locale,
|
584
|
+
status,
|
585
|
+
...schemas
|
586
|
+
});
|
587
|
+
}
|
526
588
|
});
|
527
589
|
});
|
528
590
|
return result;
|
529
591
|
});
|
530
|
-
|
531
|
-
|
532
|
-
const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
|
592
|
+
state.deleteExpiredJob = scheduleJob("historyDaily", "0 0 * * *", () => {
|
593
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
533
594
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
534
|
-
query.deleteMany({
|
595
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
535
596
|
where: {
|
536
597
|
created_at: {
|
537
|
-
$lt: expirationDate
|
598
|
+
$lt: expirationDate
|
538
599
|
}
|
539
600
|
}
|
601
|
+
}).catch((error) => {
|
602
|
+
if (error instanceof Error) {
|
603
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
604
|
+
}
|
540
605
|
});
|
541
606
|
});
|
542
607
|
state.isInitialized = true;
|
@@ -548,17 +613,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
548
613
|
}
|
549
614
|
};
|
550
615
|
};
|
551
|
-
const services$
|
616
|
+
const services$2 = {
|
552
617
|
history: createHistoryService,
|
553
618
|
lifecycles: createLifecyclesService
|
554
619
|
};
|
555
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
620
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
556
621
|
const historyVersionRouter = {
|
557
622
|
type: "admin",
|
558
623
|
routes: [
|
559
624
|
{
|
560
625
|
method: "GET",
|
561
|
-
info,
|
626
|
+
info: info$1,
|
562
627
|
path: "/history-versions",
|
563
628
|
handler: "history-version.findMany",
|
564
629
|
config: {
|
@@ -567,7 +632,7 @@ const historyVersionRouter = {
|
|
567
632
|
},
|
568
633
|
{
|
569
634
|
method: "PUT",
|
570
|
-
info,
|
635
|
+
info: info$1,
|
571
636
|
path: "/history-versions/:versionId/restore",
|
572
637
|
handler: "history-version.restoreVersion",
|
573
638
|
config: {
|
@@ -576,7 +641,7 @@ const historyVersionRouter = {
|
|
576
641
|
}
|
577
642
|
]
|
578
643
|
};
|
579
|
-
const routes$
|
644
|
+
const routes$2 = {
|
580
645
|
"history-version": historyVersionRouter
|
581
646
|
};
|
582
647
|
const historyVersion = {
|
@@ -623,21 +688,21 @@ const historyVersion = {
|
|
623
688
|
}
|
624
689
|
}
|
625
690
|
};
|
626
|
-
const getFeature = () => {
|
691
|
+
const getFeature$1 = () => {
|
627
692
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
628
693
|
return {
|
629
694
|
register({ strapi: strapi2 }) {
|
630
695
|
strapi2.get("models").add(historyVersion);
|
631
696
|
},
|
632
697
|
bootstrap({ strapi: strapi2 }) {
|
633
|
-
getService(strapi2, "lifecycles").bootstrap();
|
698
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
634
699
|
},
|
635
700
|
destroy({ strapi: strapi2 }) {
|
636
|
-
getService(strapi2, "lifecycles").destroy();
|
701
|
+
getService$1(strapi2, "lifecycles").destroy();
|
637
702
|
},
|
638
|
-
controllers: controllers$
|
639
|
-
services: services$
|
640
|
-
routes: routes$
|
703
|
+
controllers: controllers$2,
|
704
|
+
services: services$2,
|
705
|
+
routes: routes$2
|
641
706
|
};
|
642
707
|
}
|
643
708
|
return {
|
@@ -646,9 +711,201 @@ const getFeature = () => {
|
|
646
711
|
}
|
647
712
|
};
|
648
713
|
};
|
649
|
-
const history = getFeature();
|
714
|
+
const history = getFeature$1();
|
715
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
716
|
+
const previewRouter = {
|
717
|
+
type: "admin",
|
718
|
+
routes: [
|
719
|
+
{
|
720
|
+
method: "GET",
|
721
|
+
info,
|
722
|
+
path: "/preview/url/:contentType",
|
723
|
+
handler: "preview.getPreviewUrl",
|
724
|
+
config: {
|
725
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
726
|
+
}
|
727
|
+
}
|
728
|
+
]
|
729
|
+
};
|
730
|
+
const routes$1 = {
|
731
|
+
preview: previewRouter
|
732
|
+
};
|
733
|
+
function getService(strapi2, name) {
|
734
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
735
|
+
}
|
736
|
+
const getPreviewUrlSchema = yup.object().shape({
|
737
|
+
// Will be undefined for single types
|
738
|
+
documentId: yup.string(),
|
739
|
+
locale: yup.string().nullable(),
|
740
|
+
status: yup.string()
|
741
|
+
}).required();
|
742
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
743
|
+
await validateYupSchema(getPreviewUrlSchema)(params);
|
744
|
+
const newParams = pick(["documentId", "locale", "status"], params);
|
745
|
+
const model = strapi2.getModel(uid2);
|
746
|
+
if (!model || model.modelType !== "contentType") {
|
747
|
+
throw new errors.ValidationError("Invalid content type");
|
748
|
+
}
|
749
|
+
const isSingleType = model?.kind === "singleType";
|
750
|
+
if (!isSingleType && !params.documentId) {
|
751
|
+
throw new errors.ValidationError("documentId is required for Collection Types");
|
752
|
+
}
|
753
|
+
if (isSingleType) {
|
754
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
755
|
+
if (!doc) {
|
756
|
+
throw new errors.NotFoundError("Document not found");
|
757
|
+
}
|
758
|
+
newParams.documentId = doc?.documentId;
|
759
|
+
}
|
760
|
+
if (!newParams.status) {
|
761
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
762
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
763
|
+
}
|
764
|
+
return newParams;
|
765
|
+
};
|
766
|
+
const createPreviewController = () => {
|
767
|
+
return {
|
768
|
+
/**
|
769
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
770
|
+
* in the Content Manager.
|
771
|
+
*/
|
772
|
+
async getPreviewUrl(ctx) {
|
773
|
+
const uid2 = ctx.params.contentType;
|
774
|
+
const query = ctx.request.query;
|
775
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
776
|
+
const previewService = getService(strapi, "preview");
|
777
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
778
|
+
if (!url) {
|
779
|
+
ctx.status = 204;
|
780
|
+
}
|
781
|
+
return {
|
782
|
+
data: { url }
|
783
|
+
};
|
784
|
+
}
|
785
|
+
};
|
786
|
+
};
|
787
|
+
const controllers$1 = {
|
788
|
+
preview: createPreviewController
|
789
|
+
/**
|
790
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
791
|
+
* passing a controller factory as the value, instead of a controller object directly
|
792
|
+
*/
|
793
|
+
};
|
794
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
795
|
+
const config = getService(strapi2, "preview-config");
|
796
|
+
return {
|
797
|
+
async getPreviewUrl(uid2, params) {
|
798
|
+
const handler = config.getPreviewHandler();
|
799
|
+
try {
|
800
|
+
return handler(uid2, params);
|
801
|
+
} catch (error) {
|
802
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
803
|
+
throw new errors.ApplicationError("Failed to get preview URL");
|
804
|
+
}
|
805
|
+
return;
|
806
|
+
}
|
807
|
+
};
|
808
|
+
};
|
809
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
810
|
+
const middlewares = strapi.config.get("middlewares");
|
811
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
812
|
+
if (currentMiddleware === middleware.name) {
|
813
|
+
return middleware;
|
814
|
+
}
|
815
|
+
if (currentMiddleware.name === middleware.name) {
|
816
|
+
return mergeWith(
|
817
|
+
(objValue, srcValue) => {
|
818
|
+
if (Array.isArray(objValue)) {
|
819
|
+
return objValue.concat(srcValue);
|
820
|
+
}
|
821
|
+
return void 0;
|
822
|
+
},
|
823
|
+
currentMiddleware,
|
824
|
+
middleware
|
825
|
+
);
|
826
|
+
}
|
827
|
+
return currentMiddleware;
|
828
|
+
});
|
829
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
830
|
+
};
|
831
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
832
|
+
return {
|
833
|
+
register() {
|
834
|
+
if (!this.isEnabled()) {
|
835
|
+
return;
|
836
|
+
}
|
837
|
+
const config = strapi2.config.get("admin.preview");
|
838
|
+
if (config.config?.allowedOrigins) {
|
839
|
+
extendMiddlewareConfiguration({
|
840
|
+
name: "strapi::security",
|
841
|
+
config: {
|
842
|
+
contentSecurityPolicy: {
|
843
|
+
directives: {
|
844
|
+
"frame-src": config.config.allowedOrigins
|
845
|
+
}
|
846
|
+
}
|
847
|
+
}
|
848
|
+
});
|
849
|
+
}
|
850
|
+
},
|
851
|
+
isEnabled() {
|
852
|
+
const config = strapi2.config.get("admin.preview");
|
853
|
+
if (!config) {
|
854
|
+
return false;
|
855
|
+
}
|
856
|
+
return config?.enabled ?? true;
|
857
|
+
},
|
858
|
+
/**
|
859
|
+
* Validate if the configuration is valid
|
860
|
+
*/
|
861
|
+
validate() {
|
862
|
+
if (!this.isEnabled()) {
|
863
|
+
return;
|
864
|
+
}
|
865
|
+
const handler = this.getPreviewHandler();
|
866
|
+
if (typeof handler !== "function") {
|
867
|
+
throw new errors.ValidationError(
|
868
|
+
"Preview configuration is invalid. Handler must be a function"
|
869
|
+
);
|
870
|
+
}
|
871
|
+
},
|
872
|
+
/**
|
873
|
+
* Utility to get the preview handler from the configuration
|
874
|
+
*/
|
875
|
+
getPreviewHandler() {
|
876
|
+
const config = strapi2.config.get("admin.preview");
|
877
|
+
const emptyHandler = () => {
|
878
|
+
return void 0;
|
879
|
+
};
|
880
|
+
if (!this.isEnabled()) {
|
881
|
+
return emptyHandler;
|
882
|
+
}
|
883
|
+
return config?.config?.handler || emptyHandler;
|
884
|
+
}
|
885
|
+
};
|
886
|
+
};
|
887
|
+
const services$1 = {
|
888
|
+
preview: createPreviewService,
|
889
|
+
"preview-config": createPreviewConfigService
|
890
|
+
};
|
891
|
+
const getFeature = () => {
|
892
|
+
return {
|
893
|
+
register() {
|
894
|
+
const config = getService(strapi, "preview-config");
|
895
|
+
config.validate();
|
896
|
+
config.register();
|
897
|
+
},
|
898
|
+
bootstrap() {
|
899
|
+
},
|
900
|
+
routes: routes$1,
|
901
|
+
controllers: controllers$1,
|
902
|
+
services: services$1
|
903
|
+
};
|
904
|
+
};
|
905
|
+
const preview = getFeature();
|
650
906
|
const register = async ({ strapi: strapi2 }) => {
|
651
907
|
await history.register?.({ strapi: strapi2 });
|
908
|
+
await preview.register?.({ strapi: strapi2 });
|
652
909
|
};
|
653
910
|
const ALLOWED_WEBHOOK_EVENTS = {
|
654
911
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -658,11 +915,12 @@ const bootstrap = async () => {
|
|
658
915
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
659
916
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
660
917
|
});
|
661
|
-
getService$
|
662
|
-
await getService$
|
663
|
-
await getService$
|
664
|
-
await getService$
|
918
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
919
|
+
await getService$2("components").syncConfigurations();
|
920
|
+
await getService$2("content-types").syncConfigurations();
|
921
|
+
await getService$2("permission").registerPermissions();
|
665
922
|
await history.bootstrap?.({ strapi });
|
923
|
+
await preview.bootstrap?.({ strapi });
|
666
924
|
};
|
667
925
|
const destroy = async ({ strapi: strapi2 }) => {
|
668
926
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1152,7 +1410,8 @@ const admin = {
|
|
1152
1410
|
};
|
1153
1411
|
const routes = {
|
1154
1412
|
admin,
|
1155
|
-
...history.routes ? history.routes : {}
|
1413
|
+
...history.routes ? history.routes : {},
|
1414
|
+
...preview.routes ? preview.routes : {}
|
1156
1415
|
};
|
1157
1416
|
const hasPermissionsSchema = yup$1.object({
|
1158
1417
|
actions: yup$1.array().of(yup$1.string()),
|
@@ -1163,6 +1422,11 @@ const { createPolicy } = policy;
|
|
1163
1422
|
const hasPermissions = createPolicy({
|
1164
1423
|
name: "plugin::content-manager.hasPermissions",
|
1165
1424
|
validator: validateHasPermissionsInput,
|
1425
|
+
/**
|
1426
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1427
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1428
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1429
|
+
*/
|
1166
1430
|
handler(ctx, config = {}) {
|
1167
1431
|
const { actions = [], hasAtLeastOne = false } = config;
|
1168
1432
|
const { userAbility } = ctx.state;
|
@@ -1210,8 +1474,7 @@ const isSortable = (schema, name) => {
|
|
1210
1474
|
if (!_.has(schema.attributes, name)) {
|
1211
1475
|
return false;
|
1212
1476
|
}
|
1213
|
-
if (schema.modelType === "component" && name === "id")
|
1214
|
-
return false;
|
1477
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1215
1478
|
const attribute = schema.attributes[name];
|
1216
1479
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1217
1480
|
return false;
|
@@ -1356,8 +1619,7 @@ const createDefaultSettings = async (schema) => {
|
|
1356
1619
|
};
|
1357
1620
|
};
|
1358
1621
|
const syncSettings = async (configuration, schema) => {
|
1359
|
-
if (isEmpty(configuration.settings))
|
1360
|
-
return createDefaultSettings(schema);
|
1622
|
+
if (isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1361
1623
|
const defaultField = getDefaultMainField(schema);
|
1362
1624
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1363
1625
|
return {
|
@@ -1404,7 +1666,7 @@ const createMetadasSchema = (schema) => {
|
|
1404
1666
|
if (!value) {
|
1405
1667
|
return yup$1.string();
|
1406
1668
|
}
|
1407
|
-
const targetSchema = getService$
|
1669
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1408
1670
|
schema.attributes[key].targetModel
|
1409
1671
|
);
|
1410
1672
|
if (!targetSchema) {
|
@@ -1452,7 +1714,7 @@ const { PaginationError, ValidationError } = errors;
|
|
1452
1714
|
const TYPES = ["singleType", "collectionType"];
|
1453
1715
|
const kindSchema = yup$1.string().oneOf(TYPES).nullable();
|
1454
1716
|
const bulkActionInputSchema = yup$1.object({
|
1455
|
-
|
1717
|
+
documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
|
1456
1718
|
}).required();
|
1457
1719
|
const generateUIDInputSchema = yup$1.object({
|
1458
1720
|
contentTypeUID: yup$1.string().required(),
|
@@ -1533,8 +1795,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1533
1795
|
}
|
1534
1796
|
switch (attribute.type) {
|
1535
1797
|
case "relation": {
|
1536
|
-
if (canCreate(attributePath))
|
1537
|
-
return body2;
|
1798
|
+
if (canCreate(attributePath)) return body2;
|
1538
1799
|
return set(attributePath, { set: [] }, body2);
|
1539
1800
|
}
|
1540
1801
|
case "component": {
|
@@ -1544,29 +1805,62 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1544
1805
|
]);
|
1545
1806
|
}
|
1546
1807
|
default: {
|
1547
|
-
if (canCreate(attributePath))
|
1548
|
-
return body2;
|
1808
|
+
if (canCreate(attributePath)) return body2;
|
1549
1809
|
return set(attributePath, null, body2);
|
1550
1810
|
}
|
1551
1811
|
}
|
1552
1812
|
}, body);
|
1553
1813
|
};
|
1554
|
-
const
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1814
|
+
const singleLocaleSchema = yup$1.string().nullable();
|
1815
|
+
const multipleLocaleSchema = yup$1.lazy(
|
1816
|
+
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1817
|
+
);
|
1818
|
+
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1819
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1820
|
+
const { allowMultipleLocales } = opts;
|
1821
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1822
|
+
const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1823
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1824
|
+
const schema = yup$1.object().shape({
|
1825
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1826
|
+
status: statusSchema
|
1827
|
+
});
|
1828
|
+
try {
|
1829
|
+
await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1830
|
+
return { locale, status, ...rest };
|
1831
|
+
} catch (error) {
|
1832
|
+
throw new errors.ValidationError(`Validation error: ${error.message}`);
|
1561
1833
|
}
|
1562
|
-
|
1834
|
+
};
|
1835
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1836
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1837
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1838
|
+
let {
|
1839
|
+
meta: { availableLocales, availableStatus }
|
1840
|
+
} = serviceOutput;
|
1841
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1842
|
+
availableLocales = await async.map(
|
1843
|
+
availableLocales,
|
1844
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1845
|
+
);
|
1846
|
+
availableStatus = await async.map(
|
1847
|
+
availableStatus,
|
1848
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1849
|
+
);
|
1850
|
+
return {
|
1851
|
+
...serviceOutput,
|
1852
|
+
meta: {
|
1853
|
+
availableLocales,
|
1854
|
+
availableStatus
|
1855
|
+
}
|
1856
|
+
};
|
1563
1857
|
};
|
1564
1858
|
const createDocument = async (ctx, opts) => {
|
1565
1859
|
const { userAbility, user } = ctx.state;
|
1566
1860
|
const { model } = ctx.params;
|
1567
1861
|
const { body } = ctx.request;
|
1568
|
-
const documentManager2 = getService$
|
1569
|
-
const permissionChecker2 = getService$
|
1862
|
+
const documentManager2 = getService$2("document-manager");
|
1863
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1570
1864
|
if (permissionChecker2.cannot.create()) {
|
1571
1865
|
throw new errors.ForbiddenError();
|
1572
1866
|
}
|
@@ -1574,7 +1868,7 @@ const createDocument = async (ctx, opts) => {
|
|
1574
1868
|
const setCreator = setCreatorFields({ user });
|
1575
1869
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1576
1870
|
const sanitizedBody = await sanitizeFn(body);
|
1577
|
-
const { locale, status
|
1871
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1578
1872
|
return documentManager2.create(model, {
|
1579
1873
|
data: sanitizedBody,
|
1580
1874
|
locale,
|
@@ -1586,14 +1880,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1586
1880
|
const { userAbility, user } = ctx.state;
|
1587
1881
|
const { id, model } = ctx.params;
|
1588
1882
|
const { body } = ctx.request;
|
1589
|
-
const documentManager2 = getService$
|
1590
|
-
const permissionChecker2 = getService$
|
1883
|
+
const documentManager2 = getService$2("document-manager");
|
1884
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1591
1885
|
if (permissionChecker2.cannot.update()) {
|
1592
1886
|
throw new errors.ForbiddenError();
|
1593
1887
|
}
|
1594
1888
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1595
|
-
const populate = await getService$
|
1596
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1889
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1890
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1597
1891
|
const [documentVersion, documentExists] = await Promise.all([
|
1598
1892
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1599
1893
|
documentManager2.exists(model, id)
|
@@ -1609,7 +1903,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1609
1903
|
throw new errors.ForbiddenError();
|
1610
1904
|
}
|
1611
1905
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1612
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1906
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1613
1907
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1614
1908
|
const sanitizedBody = await sanitizeFn(body);
|
1615
1909
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1623,16 +1917,16 @@ const collectionTypes = {
|
|
1623
1917
|
const { userAbility } = ctx.state;
|
1624
1918
|
const { model } = ctx.params;
|
1625
1919
|
const { query } = ctx.request;
|
1626
|
-
const documentMetadata2 = getService$
|
1627
|
-
const documentManager2 = getService$
|
1628
|
-
const permissionChecker2 = getService$
|
1920
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1921
|
+
const documentManager2 = getService$2("document-manager");
|
1922
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1629
1923
|
if (permissionChecker2.cannot.read()) {
|
1630
1924
|
return ctx.forbidden();
|
1631
1925
|
}
|
1632
1926
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1633
|
-
const populate = await getService$
|
1634
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1635
|
-
const { results: documents, pagination } = await documentManager2.findPage(
|
1927
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1928
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1929
|
+
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1636
1930
|
{ ...permissionQuery, populate, locale, status },
|
1637
1931
|
model
|
1638
1932
|
);
|
@@ -1653,21 +1947,20 @@ const collectionTypes = {
|
|
1653
1947
|
);
|
1654
1948
|
ctx.body = {
|
1655
1949
|
results,
|
1656
|
-
pagination
|
1950
|
+
pagination: pagination2
|
1657
1951
|
};
|
1658
1952
|
},
|
1659
1953
|
async findOne(ctx) {
|
1660
1954
|
const { userAbility } = ctx.state;
|
1661
1955
|
const { model, id } = ctx.params;
|
1662
|
-
const documentManager2 = getService$
|
1663
|
-
const
|
1664
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1956
|
+
const documentManager2 = getService$2("document-manager");
|
1957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1665
1958
|
if (permissionChecker2.cannot.read()) {
|
1666
1959
|
return ctx.forbidden();
|
1667
1960
|
}
|
1668
1961
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1669
|
-
const populate = await getService$
|
1670
|
-
const { locale, status
|
1962
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1963
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1671
1964
|
const version = await documentManager2.findOne(id, model, {
|
1672
1965
|
populate,
|
1673
1966
|
locale,
|
@@ -1678,9 +1971,11 @@ const collectionTypes = {
|
|
1678
1971
|
if (!exists) {
|
1679
1972
|
return ctx.notFound();
|
1680
1973
|
}
|
1681
|
-
const { meta } = await
|
1974
|
+
const { meta } = await formatDocumentWithMetadata(
|
1975
|
+
permissionChecker2,
|
1682
1976
|
model,
|
1683
|
-
|
1977
|
+
// @ts-expect-error TODO: fix
|
1978
|
+
{ documentId: id, locale, publishedAt: null },
|
1684
1979
|
{ availableLocales: true, availableStatus: false }
|
1685
1980
|
);
|
1686
1981
|
ctx.body = { data: {}, meta };
|
@@ -1690,20 +1985,19 @@ const collectionTypes = {
|
|
1690
1985
|
return ctx.forbidden();
|
1691
1986
|
}
|
1692
1987
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1693
|
-
ctx.body = await
|
1988
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1694
1989
|
},
|
1695
1990
|
async create(ctx) {
|
1696
1991
|
const { userAbility } = ctx.state;
|
1697
1992
|
const { model } = ctx.params;
|
1698
|
-
const
|
1699
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1993
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1700
1994
|
const [totalEntries, document] = await Promise.all([
|
1701
1995
|
strapi.db.query(model).count(),
|
1702
1996
|
createDocument(ctx)
|
1703
1997
|
]);
|
1704
1998
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1705
1999
|
ctx.status = 201;
|
1706
|
-
ctx.body = await
|
2000
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1707
2001
|
// Empty metadata as it's not relevant for a new document
|
1708
2002
|
availableLocales: false,
|
1709
2003
|
availableStatus: false
|
@@ -1717,25 +2011,23 @@ const collectionTypes = {
|
|
1717
2011
|
async update(ctx) {
|
1718
2012
|
const { userAbility } = ctx.state;
|
1719
2013
|
const { model } = ctx.params;
|
1720
|
-
const
|
1721
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2014
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1722
2015
|
const updatedVersion = await updateDocument(ctx);
|
1723
2016
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1724
|
-
ctx.body = await
|
2017
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1725
2018
|
},
|
1726
2019
|
async clone(ctx) {
|
1727
2020
|
const { userAbility, user } = ctx.state;
|
1728
2021
|
const { model, sourceId: id } = ctx.params;
|
1729
2022
|
const { body } = ctx.request;
|
1730
|
-
const documentManager2 = getService$
|
1731
|
-
const
|
1732
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2023
|
+
const documentManager2 = getService$2("document-manager");
|
2024
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1733
2025
|
if (permissionChecker2.cannot.create()) {
|
1734
2026
|
return ctx.forbidden();
|
1735
2027
|
}
|
1736
2028
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1737
|
-
const populate = await getService$
|
1738
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2029
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2030
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1739
2031
|
const document = await documentManager2.findOne(id, model, {
|
1740
2032
|
populate,
|
1741
2033
|
locale,
|
@@ -1751,7 +2043,7 @@ const collectionTypes = {
|
|
1751
2043
|
const sanitizedBody = await sanitizeFn(body);
|
1752
2044
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1753
2045
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1754
|
-
ctx.body = await
|
2046
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1755
2047
|
// Empty metadata as it's not relevant for a new document
|
1756
2048
|
availableLocales: false,
|
1757
2049
|
availableStatus: false
|
@@ -1773,14 +2065,14 @@ const collectionTypes = {
|
|
1773
2065
|
async delete(ctx) {
|
1774
2066
|
const { userAbility } = ctx.state;
|
1775
2067
|
const { id, model } = ctx.params;
|
1776
|
-
const documentManager2 = getService$
|
1777
|
-
const permissionChecker2 = getService$
|
2068
|
+
const documentManager2 = getService$2("document-manager");
|
2069
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1778
2070
|
if (permissionChecker2.cannot.delete()) {
|
1779
2071
|
return ctx.forbidden();
|
1780
2072
|
}
|
1781
2073
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1782
|
-
const populate = await getService$
|
1783
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
2074
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2075
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1784
2076
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1785
2077
|
if (documentLocales.length === 0) {
|
1786
2078
|
return ctx.notFound();
|
@@ -1801,44 +2093,75 @@ const collectionTypes = {
|
|
1801
2093
|
const { userAbility } = ctx.state;
|
1802
2094
|
const { id, model } = ctx.params;
|
1803
2095
|
const { body } = ctx.request;
|
1804
|
-
const documentManager2 = getService$
|
1805
|
-
const
|
1806
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2096
|
+
const documentManager2 = getService$2("document-manager");
|
2097
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1807
2098
|
if (permissionChecker2.cannot.publish()) {
|
1808
2099
|
return ctx.forbidden();
|
1809
2100
|
}
|
1810
2101
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1811
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1812
|
-
const populate = await getService$
|
1813
|
-
|
2103
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2104
|
+
let document;
|
2105
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2106
|
+
const isCreate = isNil$1(id);
|
2107
|
+
if (isCreate) {
|
2108
|
+
if (permissionChecker2.cannot.create()) {
|
2109
|
+
throw new errors.ForbiddenError();
|
2110
|
+
}
|
2111
|
+
document = await createDocument(ctx, { populate });
|
2112
|
+
}
|
2113
|
+
const isUpdate = !isCreate;
|
2114
|
+
if (isUpdate) {
|
2115
|
+
const documentExists = documentManager2.exists(model, id);
|
2116
|
+
if (!documentExists) {
|
2117
|
+
throw new errors.NotFoundError("Document not found");
|
2118
|
+
}
|
2119
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2120
|
+
if (!document) {
|
2121
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2122
|
+
throw new errors.ForbiddenError();
|
2123
|
+
}
|
2124
|
+
document = await updateDocument(ctx);
|
2125
|
+
} else if (permissionChecker2.can.update(document)) {
|
2126
|
+
await updateDocument(ctx);
|
2127
|
+
}
|
2128
|
+
}
|
1814
2129
|
if (permissionChecker2.cannot.publish(document)) {
|
1815
2130
|
throw new errors.ForbiddenError();
|
1816
2131
|
}
|
1817
|
-
const
|
1818
|
-
return documentManager2.publish(document.documentId, model, {
|
2132
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1819
2133
|
locale
|
1820
2134
|
// TODO: Allow setting creator fields on publish
|
1821
2135
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1822
2136
|
});
|
2137
|
+
if (!publishResult || publishResult.length === 0) {
|
2138
|
+
throw new errors.NotFoundError("Document not found or already published.");
|
2139
|
+
}
|
2140
|
+
return publishResult[0];
|
1823
2141
|
});
|
1824
2142
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1825
|
-
ctx.body = await
|
2143
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1826
2144
|
},
|
1827
2145
|
async bulkPublish(ctx) {
|
1828
2146
|
const { userAbility } = ctx.state;
|
1829
2147
|
const { model } = ctx.params;
|
1830
2148
|
const { body } = ctx.request;
|
1831
|
-
const {
|
2149
|
+
const { documentIds } = body;
|
1832
2150
|
await validateBulkActionInput(body);
|
1833
|
-
const documentManager2 = getService$
|
1834
|
-
const permissionChecker2 = getService$
|
2151
|
+
const documentManager2 = getService$2("document-manager");
|
2152
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1835
2153
|
if (permissionChecker2.cannot.publish()) {
|
1836
2154
|
return ctx.forbidden();
|
1837
2155
|
}
|
1838
2156
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1839
|
-
const populate = await getService$
|
1840
|
-
const
|
1841
|
-
|
2157
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2158
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2159
|
+
allowMultipleLocales: true
|
2160
|
+
});
|
2161
|
+
const entityPromises = documentIds.map(
|
2162
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
2163
|
+
);
|
2164
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1842
2165
|
for (const entity of entities) {
|
1843
2166
|
if (!entity) {
|
1844
2167
|
return ctx.notFound();
|
@@ -1847,24 +2170,27 @@ const collectionTypes = {
|
|
1847
2170
|
return ctx.forbidden();
|
1848
2171
|
}
|
1849
2172
|
}
|
1850
|
-
const
|
2173
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1851
2174
|
ctx.body = { count };
|
1852
2175
|
},
|
1853
2176
|
async bulkUnpublish(ctx) {
|
1854
2177
|
const { userAbility } = ctx.state;
|
1855
2178
|
const { model } = ctx.params;
|
1856
2179
|
const { body } = ctx.request;
|
1857
|
-
const {
|
2180
|
+
const { documentIds } = body;
|
1858
2181
|
await validateBulkActionInput(body);
|
1859
|
-
const documentManager2 = getService$
|
1860
|
-
const permissionChecker2 = getService$
|
2182
|
+
const documentManager2 = getService$2("document-manager");
|
2183
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1861
2184
|
if (permissionChecker2.cannot.unpublish()) {
|
1862
2185
|
return ctx.forbidden();
|
1863
2186
|
}
|
1864
|
-
const
|
1865
|
-
|
1866
|
-
|
1867
|
-
const
|
2187
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2188
|
+
allowMultipleLocales: true
|
2189
|
+
});
|
2190
|
+
const entityPromises = documentIds.map(
|
2191
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
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,7 +2199,8 @@ const collectionTypes = {
|
|
1873
2199
|
return ctx.forbidden();
|
1874
2200
|
}
|
1875
2201
|
}
|
1876
|
-
const
|
2202
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
2203
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1877
2204
|
ctx.body = { count };
|
1878
2205
|
},
|
1879
2206
|
async unpublish(ctx) {
|
@@ -1882,9 +2209,8 @@ const collectionTypes = {
|
|
1882
2209
|
const {
|
1883
2210
|
body: { discardDraft, ...body }
|
1884
2211
|
} = ctx.request;
|
1885
|
-
const documentManager2 = getService$
|
1886
|
-
const
|
1887
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2212
|
+
const documentManager2 = getService$2("document-manager");
|
2213
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1888
2214
|
if (permissionChecker2.cannot.unpublish()) {
|
1889
2215
|
return ctx.forbidden();
|
1890
2216
|
}
|
@@ -1892,8 +2218,8 @@ const collectionTypes = {
|
|
1892
2218
|
return ctx.forbidden();
|
1893
2219
|
}
|
1894
2220
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1895
|
-
const populate = await getService$
|
1896
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2221
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2222
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1897
2223
|
const document = await documentManager2.findOne(id, model, {
|
1898
2224
|
populate,
|
1899
2225
|
locale,
|
@@ -1915,7 +2241,7 @@ const collectionTypes = {
|
|
1915
2241
|
ctx.body = await async.pipe(
|
1916
2242
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1917
2243
|
permissionChecker2.sanitizeOutput,
|
1918
|
-
(document2) =>
|
2244
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1919
2245
|
)(document);
|
1920
2246
|
});
|
1921
2247
|
},
|
@@ -1923,15 +2249,14 @@ const collectionTypes = {
|
|
1923
2249
|
const { userAbility } = ctx.state;
|
1924
2250
|
const { id, model } = ctx.params;
|
1925
2251
|
const { body } = ctx.request;
|
1926
|
-
const documentManager2 = getService$
|
1927
|
-
const
|
1928
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2252
|
+
const documentManager2 = getService$2("document-manager");
|
2253
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1929
2254
|
if (permissionChecker2.cannot.discard()) {
|
1930
2255
|
return ctx.forbidden();
|
1931
2256
|
}
|
1932
2257
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1933
|
-
const populate = await getService$
|
1934
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2258
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2259
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1935
2260
|
const document = await documentManager2.findOne(id, model, {
|
1936
2261
|
populate,
|
1937
2262
|
locale,
|
@@ -1946,42 +2271,50 @@ const collectionTypes = {
|
|
1946
2271
|
ctx.body = await async.pipe(
|
1947
2272
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1948
2273
|
permissionChecker2.sanitizeOutput,
|
1949
|
-
(document2) =>
|
2274
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1950
2275
|
)(document);
|
1951
2276
|
},
|
1952
2277
|
async bulkDelete(ctx) {
|
1953
2278
|
const { userAbility } = ctx.state;
|
1954
2279
|
const { model } = ctx.params;
|
1955
2280
|
const { query, body } = ctx.request;
|
1956
|
-
const {
|
2281
|
+
const { documentIds } = body;
|
1957
2282
|
await validateBulkActionInput(body);
|
1958
|
-
const documentManager2 = getService$
|
1959
|
-
const permissionChecker2 = getService$
|
2283
|
+
const documentManager2 = getService$2("document-manager");
|
2284
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1960
2285
|
if (permissionChecker2.cannot.delete()) {
|
1961
2286
|
return ctx.forbidden();
|
1962
2287
|
}
|
1963
2288
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1964
|
-
const
|
1965
|
-
const
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
2289
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2290
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2291
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2292
|
+
populate,
|
2293
|
+
locale
|
2294
|
+
});
|
2295
|
+
if (documentLocales.length === 0) {
|
2296
|
+
return ctx.notFound();
|
2297
|
+
}
|
2298
|
+
for (const document of documentLocales) {
|
2299
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2300
|
+
return ctx.forbidden();
|
1969
2301
|
}
|
1970
|
-
}
|
1971
|
-
const
|
2302
|
+
}
|
2303
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2304
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1972
2305
|
ctx.body = { count };
|
1973
2306
|
},
|
1974
2307
|
async countDraftRelations(ctx) {
|
1975
2308
|
const { userAbility } = ctx.state;
|
1976
2309
|
const { model, id } = ctx.params;
|
1977
|
-
const documentManager2 = getService$
|
1978
|
-
const permissionChecker2 = getService$
|
2310
|
+
const documentManager2 = getService$2("document-manager");
|
2311
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1979
2312
|
if (permissionChecker2.cannot.read()) {
|
1980
2313
|
return ctx.forbidden();
|
1981
2314
|
}
|
1982
2315
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1983
|
-
const populate = await getService$
|
1984
|
-
const { locale, status
|
2316
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2317
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1985
2318
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1986
2319
|
if (!entity) {
|
1987
2320
|
return ctx.notFound();
|
@@ -1996,24 +2329,24 @@ const collectionTypes = {
|
|
1996
2329
|
},
|
1997
2330
|
async countManyEntriesDraftRelations(ctx) {
|
1998
2331
|
const { userAbility } = ctx.state;
|
1999
|
-
const ids = ctx.request.query.
|
2332
|
+
const ids = ctx.request.query.documentIds;
|
2000
2333
|
const locale = ctx.request.query.locale;
|
2001
2334
|
const { model } = ctx.params;
|
2002
|
-
const documentManager2 = getService$
|
2003
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2004
2337
|
if (permissionChecker2.cannot.read()) {
|
2005
2338
|
return ctx.forbidden();
|
2006
2339
|
}
|
2007
|
-
const
|
2340
|
+
const documents = await documentManager2.findMany(
|
2008
2341
|
{
|
2009
2342
|
filters: {
|
2010
|
-
|
2343
|
+
documentId: ids
|
2011
2344
|
},
|
2012
2345
|
locale
|
2013
2346
|
},
|
2014
2347
|
model
|
2015
2348
|
);
|
2016
|
-
if (!
|
2349
|
+
if (!documents) {
|
2017
2350
|
return ctx.notFound();
|
2018
2351
|
}
|
2019
2352
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2024,13 +2357,13 @@ const collectionTypes = {
|
|
2024
2357
|
};
|
2025
2358
|
const components$1 = {
|
2026
2359
|
findComponents(ctx) {
|
2027
|
-
const components2 = getService$
|
2028
|
-
const { toDto } = getService$
|
2360
|
+
const components2 = getService$2("components").findAllComponents();
|
2361
|
+
const { toDto } = getService$2("data-mapper");
|
2029
2362
|
ctx.body = { data: components2.map(toDto) };
|
2030
2363
|
},
|
2031
2364
|
async findComponentConfiguration(ctx) {
|
2032
2365
|
const { uid: uid2 } = ctx.params;
|
2033
|
-
const componentService = getService$
|
2366
|
+
const componentService = getService$2("components");
|
2034
2367
|
const component = componentService.findComponent(uid2);
|
2035
2368
|
if (!component) {
|
2036
2369
|
return ctx.notFound("component.notFound");
|
@@ -2047,7 +2380,7 @@ const components$1 = {
|
|
2047
2380
|
async updateComponentConfiguration(ctx) {
|
2048
2381
|
const { uid: uid2 } = ctx.params;
|
2049
2382
|
const { body } = ctx.request;
|
2050
|
-
const componentService = getService$
|
2383
|
+
const componentService = getService$2("components");
|
2051
2384
|
const component = componentService.findComponent(uid2);
|
2052
2385
|
if (!component) {
|
2053
2386
|
return ctx.notFound("component.notFound");
|
@@ -2081,12 +2414,12 @@ const contentTypes = {
|
|
2081
2414
|
} catch (error) {
|
2082
2415
|
return ctx.send({ error }, 400);
|
2083
2416
|
}
|
2084
|
-
const contentTypes2 = getService$
|
2085
|
-
const { toDto } = getService$
|
2417
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2418
|
+
const { toDto } = getService$2("data-mapper");
|
2086
2419
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2087
2420
|
},
|
2088
2421
|
async findContentTypesSettings(ctx) {
|
2089
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2422
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2090
2423
|
const contentTypes2 = await findAllContentTypes();
|
2091
2424
|
const configurations = await Promise.all(
|
2092
2425
|
contentTypes2.map(async (contentType) => {
|
@@ -2100,7 +2433,7 @@ const contentTypes = {
|
|
2100
2433
|
},
|
2101
2434
|
async findContentTypeConfiguration(ctx) {
|
2102
2435
|
const { uid: uid2 } = ctx.params;
|
2103
|
-
const contentTypeService = getService$
|
2436
|
+
const contentTypeService = getService$2("content-types");
|
2104
2437
|
const contentType = await contentTypeService.findContentType(uid2);
|
2105
2438
|
if (!contentType) {
|
2106
2439
|
return ctx.notFound("contentType.notFound");
|
@@ -2122,13 +2455,13 @@ const contentTypes = {
|
|
2122
2455
|
const { userAbility } = ctx.state;
|
2123
2456
|
const { uid: uid2 } = ctx.params;
|
2124
2457
|
const { body } = ctx.request;
|
2125
|
-
const contentTypeService = getService$
|
2126
|
-
const metricsService = getService$
|
2458
|
+
const contentTypeService = getService$2("content-types");
|
2459
|
+
const metricsService = getService$2("metrics");
|
2127
2460
|
const contentType = await contentTypeService.findContentType(uid2);
|
2128
2461
|
if (!contentType) {
|
2129
2462
|
return ctx.notFound("contentType.notFound");
|
2130
2463
|
}
|
2131
|
-
if (!getService$
|
2464
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2132
2465
|
return ctx.forbidden();
|
2133
2466
|
}
|
2134
2467
|
let input;
|
@@ -2161,10 +2494,10 @@ const contentTypes = {
|
|
2161
2494
|
};
|
2162
2495
|
const init = {
|
2163
2496
|
getInitData(ctx) {
|
2164
|
-
const { toDto } = getService$
|
2165
|
-
const { findAllComponents } = getService$
|
2166
|
-
const { getAllFieldSizes } = getService$
|
2167
|
-
const { findAllContentTypes } = getService$
|
2497
|
+
const { toDto } = getService$2("data-mapper");
|
2498
|
+
const { findAllComponents } = getService$2("components");
|
2499
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2500
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2168
2501
|
ctx.body = {
|
2169
2502
|
data: {
|
2170
2503
|
fieldSizes: getAllFieldSizes(),
|
@@ -2200,36 +2533,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2200
2533
|
params.filters.$and.push(filtersClause);
|
2201
2534
|
};
|
2202
2535
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2203
|
-
const permissionChecker2 = getService$
|
2536
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2204
2537
|
userAbility,
|
2205
2538
|
model: model.uid
|
2206
2539
|
});
|
2207
|
-
|
2540
|
+
const isMainFieldListable = isListable(model, mainField);
|
2541
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2542
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2208
2543
|
return "id";
|
2209
2544
|
}
|
2210
|
-
if (
|
2211
|
-
|
2212
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2213
|
-
userAbility,
|
2214
|
-
model: "plugin::users-permissions.user"
|
2215
|
-
});
|
2216
|
-
if (userPermissionChecker.can.read()) {
|
2217
|
-
return "name";
|
2218
|
-
}
|
2219
|
-
}
|
2220
|
-
return "id";
|
2545
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2546
|
+
return "name";
|
2221
2547
|
}
|
2222
2548
|
return mainField;
|
2223
2549
|
};
|
2224
|
-
const addStatusToRelations = async (
|
2225
|
-
if (!contentTypes$1.hasDraftAndPublish(strapi.
|
2550
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2551
|
+
if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2552
|
+
return relations2;
|
2553
|
+
}
|
2554
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2555
|
+
if (!relations2.length) {
|
2226
2556
|
return relations2;
|
2227
2557
|
}
|
2228
|
-
const
|
2229
|
-
const
|
2558
|
+
const firstRelation = relations2[0];
|
2559
|
+
const filters = {
|
2560
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2561
|
+
// NOTE: find the "opposite" status
|
2562
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2563
|
+
};
|
2564
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2565
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2566
|
+
filters
|
2567
|
+
});
|
2230
2568
|
return relations2.map((relation) => {
|
2231
|
-
const availableStatuses =
|
2232
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2569
|
+
const availableStatuses = availableStatus.filter(
|
2570
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2233
2571
|
);
|
2234
2572
|
return {
|
2235
2573
|
...relation,
|
@@ -2250,11 +2588,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2250
2588
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2251
2589
|
const isSourceLocalized = isLocalized(sourceModel);
|
2252
2590
|
const isTargetLocalized = isLocalized(targetModel);
|
2253
|
-
let validatedLocale = locale;
|
2254
|
-
if (!targetModel || !isTargetLocalized)
|
2255
|
-
validatedLocale = void 0;
|
2256
2591
|
return {
|
2257
|
-
locale
|
2592
|
+
locale,
|
2258
2593
|
isSourceLocalized,
|
2259
2594
|
isTargetLocalized
|
2260
2595
|
};
|
@@ -2263,8 +2598,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2263
2598
|
const sourceModel = strapi.getModel(sourceUid);
|
2264
2599
|
const isDP = contentTypes$1.hasDraftAndPublish;
|
2265
2600
|
const isSourceDP = isDP(sourceModel);
|
2266
|
-
if (!isSourceDP)
|
2267
|
-
return { status: void 0 };
|
2601
|
+
if (!isSourceDP) return { status: void 0 };
|
2268
2602
|
switch (status) {
|
2269
2603
|
case "published":
|
2270
2604
|
return { status: "published" };
|
@@ -2294,7 +2628,7 @@ const relations = {
|
|
2294
2628
|
ctx.request?.query?.locale
|
2295
2629
|
);
|
2296
2630
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2297
|
-
const permissionChecker2 = getService$
|
2631
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2298
2632
|
userAbility,
|
2299
2633
|
model
|
2300
2634
|
});
|
@@ -2319,7 +2653,7 @@ const relations = {
|
|
2319
2653
|
where.id = id;
|
2320
2654
|
}
|
2321
2655
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2322
|
-
const populate = await getService$
|
2656
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2323
2657
|
const currentEntity = await strapi.db.query(model).findOne({
|
2324
2658
|
where,
|
2325
2659
|
populate
|
@@ -2334,7 +2668,7 @@ const relations = {
|
|
2334
2668
|
}
|
2335
2669
|
entryId = currentEntity.id;
|
2336
2670
|
}
|
2337
|
-
const modelConfig = isComponent2 ? await getService$
|
2671
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2338
2672
|
const targetSchema = strapi.getModel(targetUid);
|
2339
2673
|
const mainField = flow(
|
2340
2674
|
prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2357,7 +2691,7 @@ const relations = {
|
|
2357
2691
|
attribute,
|
2358
2692
|
fieldsToSelect,
|
2359
2693
|
mainField,
|
2360
|
-
source: { schema: sourceSchema },
|
2694
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2361
2695
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2362
2696
|
sourceSchema,
|
2363
2697
|
targetSchema,
|
@@ -2379,7 +2713,8 @@ const relations = {
|
|
2379
2713
|
fieldsToSelect,
|
2380
2714
|
mainField,
|
2381
2715
|
source: {
|
2382
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2716
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2717
|
+
isLocalized: isSourceLocalized
|
2383
2718
|
},
|
2384
2719
|
target: {
|
2385
2720
|
schema: { uid: targetUid },
|
@@ -2387,7 +2722,7 @@ const relations = {
|
|
2387
2722
|
}
|
2388
2723
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2389
2724
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2390
|
-
const permissionChecker2 = getService$
|
2725
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2391
2726
|
userAbility: ctx.state.userAbility,
|
2392
2727
|
model: targetUid
|
2393
2728
|
});
|
@@ -2417,12 +2752,16 @@ const relations = {
|
|
2417
2752
|
} else {
|
2418
2753
|
where.id = id;
|
2419
2754
|
}
|
2420
|
-
|
2421
|
-
|
2755
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2756
|
+
if (!isEmpty(publishedAt)) {
|
2757
|
+
where[`${alias}.published_at`] = publishedAt;
|
2422
2758
|
}
|
2423
|
-
if (
|
2759
|
+
if (isTargetLocalized && locale) {
|
2424
2760
|
where[`${alias}.locale`] = locale;
|
2425
2761
|
}
|
2762
|
+
if (isSourceLocalized && locale) {
|
2763
|
+
where.locale = locale;
|
2764
|
+
}
|
2426
2765
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2427
2766
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2428
2767
|
}
|
@@ -2440,7 +2779,8 @@ const relations = {
|
|
2440
2779
|
id: { $notIn: uniq(idsToOmit) }
|
2441
2780
|
});
|
2442
2781
|
}
|
2443
|
-
const
|
2782
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2783
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2444
2784
|
ctx.body = {
|
2445
2785
|
...res,
|
2446
2786
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2455,29 +2795,39 @@ const relations = {
|
|
2455
2795
|
attribute,
|
2456
2796
|
targetField,
|
2457
2797
|
fieldsToSelect,
|
2458
|
-
|
2459
|
-
|
2460
|
-
}
|
2461
|
-
target: {
|
2462
|
-
schema: { uid: targetUid }
|
2463
|
-
}
|
2798
|
+
status,
|
2799
|
+
source: { schema: sourceSchema },
|
2800
|
+
target: { schema: targetSchema }
|
2464
2801
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2465
|
-
const
|
2802
|
+
const { uid: sourceUid } = sourceSchema;
|
2803
|
+
const { uid: targetUid } = targetSchema;
|
2804
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2466
2805
|
const dbQuery = strapi.db.query(sourceUid);
|
2467
2806
|
const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2807
|
+
const filters = {};
|
2808
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2809
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2810
|
+
if (status === "published") {
|
2811
|
+
filters.publishedAt = { $notNull: true };
|
2812
|
+
} else {
|
2813
|
+
filters.publishedAt = { $null: true };
|
2814
|
+
}
|
2815
|
+
}
|
2816
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2817
|
+
filters.publishedAt = { $null: true };
|
2818
|
+
}
|
2468
2819
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2469
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2820
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2470
2821
|
ordering: "desc",
|
2471
2822
|
page: ctx.request.query.page,
|
2472
|
-
pageSize: ctx.request.query.pageSize
|
2823
|
+
pageSize: ctx.request.query.pageSize,
|
2824
|
+
filters
|
2473
2825
|
});
|
2474
2826
|
const loadedIds = res.results.map((item) => item.id);
|
2475
2827
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2476
2828
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2477
2829
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2478
|
-
ordering: "desc"
|
2479
|
-
page: ctx.request.query.page,
|
2480
|
-
pageSize: ctx.request.query.pageSize
|
2830
|
+
ordering: "desc"
|
2481
2831
|
});
|
2482
2832
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2483
2833
|
ctx.body = {
|
@@ -2492,10 +2842,10 @@ const relations = {
|
|
2492
2842
|
}
|
2493
2843
|
};
|
2494
2844
|
const buildPopulateFromQuery = async (query, model) => {
|
2495
|
-
return getService$
|
2845
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2496
2846
|
};
|
2497
2847
|
const findDocument = async (query, uid2, opts = {}) => {
|
2498
|
-
const documentManager2 = getService$
|
2848
|
+
const documentManager2 = getService$2("document-manager");
|
2499
2849
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2500
2850
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2501
2851
|
};
|
@@ -2503,13 +2853,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2503
2853
|
const { user, userAbility } = ctx.state;
|
2504
2854
|
const { model } = ctx.params;
|
2505
2855
|
const { body, query } = ctx.request;
|
2506
|
-
const documentManager2 = getService$
|
2507
|
-
const permissionChecker2 = getService$
|
2856
|
+
const documentManager2 = getService$2("document-manager");
|
2857
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2508
2858
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2509
2859
|
throw new errors.ForbiddenError();
|
2510
2860
|
}
|
2511
2861
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2512
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2862
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2513
2863
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2514
2864
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2515
2865
|
// Find the first document to check if it exists
|
@@ -2545,13 +2895,12 @@ const singleTypes = {
|
|
2545
2895
|
const { userAbility } = ctx.state;
|
2546
2896
|
const { model } = ctx.params;
|
2547
2897
|
const { query = {} } = ctx.request;
|
2548
|
-
const permissionChecker2 = getService$
|
2549
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2898
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2550
2899
|
if (permissionChecker2.cannot.read()) {
|
2551
2900
|
return ctx.forbidden();
|
2552
2901
|
}
|
2553
2902
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2554
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2903
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2555
2904
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2556
2905
|
if (!version) {
|
2557
2906
|
if (permissionChecker2.cannot.create()) {
|
@@ -2561,9 +2910,11 @@ const singleTypes = {
|
|
2561
2910
|
if (!document) {
|
2562
2911
|
return ctx.notFound();
|
2563
2912
|
}
|
2564
|
-
const { meta } = await
|
2913
|
+
const { meta } = await formatDocumentWithMetadata(
|
2914
|
+
permissionChecker2,
|
2565
2915
|
model,
|
2566
|
-
|
2916
|
+
// @ts-expect-error - fix types
|
2917
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2567
2918
|
{ availableLocales: true, availableStatus: false }
|
2568
2919
|
);
|
2569
2920
|
ctx.body = { data: {}, meta };
|
@@ -2573,29 +2924,28 @@ const singleTypes = {
|
|
2573
2924
|
return ctx.forbidden();
|
2574
2925
|
}
|
2575
2926
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2576
|
-
ctx.body = await
|
2927
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2577
2928
|
},
|
2578
2929
|
async createOrUpdate(ctx) {
|
2579
2930
|
const { userAbility } = ctx.state;
|
2580
2931
|
const { model } = ctx.params;
|
2581
|
-
const
|
2582
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2932
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2583
2933
|
const document = await createOrUpdateDocument(ctx);
|
2584
2934
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2585
|
-
ctx.body = await
|
2935
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2586
2936
|
},
|
2587
2937
|
async delete(ctx) {
|
2588
2938
|
const { userAbility } = ctx.state;
|
2589
2939
|
const { model } = ctx.params;
|
2590
2940
|
const { query = {} } = ctx.request;
|
2591
|
-
const documentManager2 = getService$
|
2592
|
-
const permissionChecker2 = getService$
|
2941
|
+
const documentManager2 = getService$2("document-manager");
|
2942
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2593
2943
|
if (permissionChecker2.cannot.delete()) {
|
2594
2944
|
return ctx.forbidden();
|
2595
2945
|
}
|
2596
2946
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2597
2947
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2598
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2948
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2599
2949
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2600
2950
|
populate,
|
2601
2951
|
locale
|
@@ -2617,9 +2967,8 @@ const singleTypes = {
|
|
2617
2967
|
const { userAbility } = ctx.state;
|
2618
2968
|
const { model } = ctx.params;
|
2619
2969
|
const { query = {} } = ctx.request;
|
2620
|
-
const documentManager2 = getService$
|
2621
|
-
const
|
2622
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2623
2972
|
if (permissionChecker2.cannot.publish()) {
|
2624
2973
|
return ctx.forbidden();
|
2625
2974
|
}
|
@@ -2633,11 +2982,12 @@ const singleTypes = {
|
|
2633
2982
|
if (permissionChecker2.cannot.publish(document)) {
|
2634
2983
|
throw new errors.ForbiddenError();
|
2635
2984
|
}
|
2636
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2637
|
-
|
2985
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2986
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2987
|
+
return publishResult.at(0);
|
2638
2988
|
});
|
2639
2989
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2640
|
-
ctx.body = await
|
2990
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2641
2991
|
},
|
2642
2992
|
async unpublish(ctx) {
|
2643
2993
|
const { userAbility } = ctx.state;
|
@@ -2646,9 +2996,8 @@ const singleTypes = {
|
|
2646
2996
|
body: { discardDraft, ...body },
|
2647
2997
|
query = {}
|
2648
2998
|
} = ctx.request;
|
2649
|
-
const documentManager2 = getService$
|
2650
|
-
const
|
2651
|
-
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 });
|
2652
3001
|
if (permissionChecker2.cannot.unpublish()) {
|
2653
3002
|
return ctx.forbidden();
|
2654
3003
|
}
|
@@ -2656,7 +3005,7 @@ const singleTypes = {
|
|
2656
3005
|
return ctx.forbidden();
|
2657
3006
|
}
|
2658
3007
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2659
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3008
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2660
3009
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2661
3010
|
if (!document) {
|
2662
3011
|
return ctx.notFound();
|
@@ -2674,7 +3023,7 @@ const singleTypes = {
|
|
2674
3023
|
ctx.body = await async.pipe(
|
2675
3024
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2676
3025
|
permissionChecker2.sanitizeOutput,
|
2677
|
-
(document2) =>
|
3026
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2678
3027
|
)(document);
|
2679
3028
|
});
|
2680
3029
|
},
|
@@ -2682,14 +3031,13 @@ const singleTypes = {
|
|
2682
3031
|
const { userAbility } = ctx.state;
|
2683
3032
|
const { model } = ctx.params;
|
2684
3033
|
const { body, query = {} } = ctx.request;
|
2685
|
-
const documentManager2 = getService$
|
2686
|
-
const
|
2687
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
3034
|
+
const documentManager2 = getService$2("document-manager");
|
3035
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2688
3036
|
if (permissionChecker2.cannot.discard()) {
|
2689
3037
|
return ctx.forbidden();
|
2690
3038
|
}
|
2691
3039
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2692
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3040
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2693
3041
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2694
3042
|
if (!document) {
|
2695
3043
|
return ctx.notFound();
|
@@ -2700,16 +3048,16 @@ const singleTypes = {
|
|
2700
3048
|
ctx.body = await async.pipe(
|
2701
3049
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2702
3050
|
permissionChecker2.sanitizeOutput,
|
2703
|
-
(document2) =>
|
3051
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2704
3052
|
)(document);
|
2705
3053
|
},
|
2706
3054
|
async countDraftRelations(ctx) {
|
2707
3055
|
const { userAbility } = ctx.state;
|
2708
3056
|
const { model } = ctx.params;
|
2709
3057
|
const { query } = ctx.request;
|
2710
|
-
const documentManager2 = getService$
|
2711
|
-
const permissionChecker2 = getService$
|
2712
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3058
|
+
const documentManager2 = getService$2("document-manager");
|
3059
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3060
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2713
3061
|
if (permissionChecker2.cannot.read()) {
|
2714
3062
|
return ctx.forbidden();
|
2715
3063
|
}
|
@@ -2730,9 +3078,9 @@ const uid$1 = {
|
|
2730
3078
|
async generateUID(ctx) {
|
2731
3079
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2732
3080
|
const { query = {} } = ctx.request;
|
2733
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3081
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2734
3082
|
await validateUIDField(contentTypeUID, field);
|
2735
|
-
const uidService = getService$
|
3083
|
+
const uidService = getService$2("uid");
|
2736
3084
|
ctx.body = {
|
2737
3085
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2738
3086
|
};
|
@@ -2742,9 +3090,9 @@ const uid$1 = {
|
|
2742
3090
|
ctx.request.body
|
2743
3091
|
);
|
2744
3092
|
const { query = {} } = ctx.request;
|
2745
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3093
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2746
3094
|
await validateUIDField(contentTypeUID, field);
|
2747
|
-
const uidService = getService$
|
3095
|
+
const uidService = getService$2("uid");
|
2748
3096
|
const isAvailable = await uidService.checkUIDAvailability({
|
2749
3097
|
contentTypeUID,
|
2750
3098
|
field,
|
@@ -2765,7 +3113,8 @@ const controllers = {
|
|
2765
3113
|
relations,
|
2766
3114
|
"single-types": singleTypes,
|
2767
3115
|
uid: uid$1,
|
2768
|
-
...history.controllers ? history.controllers : {}
|
3116
|
+
...history.controllers ? history.controllers : {},
|
3117
|
+
...preview.controllers ? preview.controllers : {}
|
2769
3118
|
};
|
2770
3119
|
const keys = {
|
2771
3120
|
CONFIGURATION: "configuration"
|
@@ -2894,18 +3243,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2894
3243
|
_.set(updatedMeta, ["list", "searchable"], false);
|
2895
3244
|
_.set(acc, [key], updatedMeta);
|
2896
3245
|
}
|
2897
|
-
if (!_.has(edit, "mainField"))
|
2898
|
-
return acc;
|
3246
|
+
if (!_.has(edit, "mainField")) return acc;
|
2899
3247
|
if (!isRelation$1(attr)) {
|
2900
3248
|
_.set(updatedMeta, "edit", _.omit(edit, ["mainField"]));
|
2901
3249
|
_.set(acc, [key], updatedMeta);
|
2902
3250
|
return acc;
|
2903
3251
|
}
|
2904
|
-
if (edit.mainField === "id")
|
2905
|
-
return acc;
|
3252
|
+
if (edit.mainField === "id") return acc;
|
2906
3253
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2907
|
-
if (!targetSchema)
|
2908
|
-
return acc;
|
3254
|
+
if (!targetSchema) return acc;
|
2909
3255
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2910
3256
|
_.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2911
3257
|
_.set(acc, [key], updatedMeta);
|
@@ -2916,12 +3262,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2916
3262
|
return _.assign(metasWithDefaults, updatedMetas);
|
2917
3263
|
}
|
2918
3264
|
const getTargetSchema = (targetModel) => {
|
2919
|
-
return getService$
|
3265
|
+
return getService$2("content-types").findContentType(targetModel);
|
2920
3266
|
};
|
2921
3267
|
const DEFAULT_LIST_LENGTH = 4;
|
2922
3268
|
const MAX_ROW_SIZE = 12;
|
2923
3269
|
const isAllowedFieldSize = (type, size) => {
|
2924
|
-
const { getFieldSize } = getService$
|
3270
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2925
3271
|
const fieldSize = getFieldSize(type);
|
2926
3272
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2927
3273
|
return false;
|
@@ -2929,7 +3275,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2929
3275
|
return size <= MAX_ROW_SIZE;
|
2930
3276
|
};
|
2931
3277
|
const getDefaultFieldSize = (attribute) => {
|
2932
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3278
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2933
3279
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2934
3280
|
};
|
2935
3281
|
async function createDefaultLayouts(schema) {
|
@@ -2950,8 +3296,7 @@ function createDefaultEditLayout(schema) {
|
|
2950
3296
|
return appendToEditLayout([], keys2, schema);
|
2951
3297
|
}
|
2952
3298
|
function syncLayouts(configuration, schema) {
|
2953
|
-
if (_.isEmpty(configuration.layouts))
|
2954
|
-
return createDefaultLayouts(schema);
|
3299
|
+
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
2955
3300
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
2956
3301
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
2957
3302
|
const cleanEditRelations = editRelations.filter(
|
@@ -2962,9 +3307,8 @@ function syncLayouts(configuration, schema) {
|
|
2962
3307
|
for (const row of edit) {
|
2963
3308
|
const newRow = [];
|
2964
3309
|
for (const el of row) {
|
2965
|
-
if (!hasEditableAttribute(schema, el.name))
|
2966
|
-
|
2967
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3310
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3311
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
2968
3312
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
2969
3313
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
2970
3314
|
elementsToReAppend.push(el.name);
|
@@ -2994,8 +3338,7 @@ function syncLayouts(configuration, schema) {
|
|
2994
3338
|
};
|
2995
3339
|
}
|
2996
3340
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
2997
|
-
if (keysToAppend.length === 0)
|
2998
|
-
return layout;
|
3341
|
+
if (keysToAppend.length === 0) return layout;
|
2999
3342
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3000
3343
|
if (!layout[currentRowIndex]) {
|
3001
3344
|
layout[currentRowIndex] = [];
|
@@ -3104,17 +3447,17 @@ const configurationService$1 = createConfigurationService({
|
|
3104
3447
|
isComponent: true,
|
3105
3448
|
prefix: STORE_KEY_PREFIX,
|
3106
3449
|
getModels() {
|
3107
|
-
const { toContentManagerModel } = getService$
|
3450
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3108
3451
|
return mapValues(toContentManagerModel, strapi.components);
|
3109
3452
|
}
|
3110
3453
|
});
|
3111
3454
|
const components = ({ strapi: strapi2 }) => ({
|
3112
3455
|
findAllComponents() {
|
3113
|
-
const { toContentManagerModel } = getService$
|
3456
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3114
3457
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3115
3458
|
},
|
3116
3459
|
findComponent(uid2) {
|
3117
|
-
const { toContentManagerModel } = getService$
|
3460
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3118
3461
|
const component = strapi2.components[uid2];
|
3119
3462
|
return isNil$1(component) ? component : toContentManagerModel(component);
|
3120
3463
|
},
|
@@ -3165,17 +3508,17 @@ const configurationService = createConfigurationService({
|
|
3165
3508
|
storeUtils,
|
3166
3509
|
prefix: "content_types",
|
3167
3510
|
getModels() {
|
3168
|
-
const { toContentManagerModel } = getService$
|
3511
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3169
3512
|
return mapValues(toContentManagerModel, strapi.contentTypes);
|
3170
3513
|
}
|
3171
3514
|
});
|
3172
3515
|
const service = ({ strapi: strapi2 }) => ({
|
3173
3516
|
findAllContentTypes() {
|
3174
|
-
const { toContentManagerModel } = getService$
|
3517
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3175
3518
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3176
3519
|
},
|
3177
3520
|
findContentType(uid2) {
|
3178
|
-
const { toContentManagerModel } = getService$
|
3521
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3179
3522
|
const contentType = strapi2.contentTypes[uid2];
|
3180
3523
|
return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
|
3181
3524
|
},
|
@@ -3204,7 +3547,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3204
3547
|
return this.findConfiguration(contentType);
|
3205
3548
|
},
|
3206
3549
|
findComponentsConfigurations(contentType) {
|
3207
|
-
return getService$
|
3550
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3208
3551
|
},
|
3209
3552
|
syncConfigurations() {
|
3210
3553
|
return configurationService.syncConfigurations();
|
@@ -3385,12 +3728,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3385
3728
|
ability: userAbility,
|
3386
3729
|
model
|
3387
3730
|
});
|
3388
|
-
const
|
3731
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3732
|
+
const toSubject = (entity) => {
|
3733
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3734
|
+
};
|
3389
3735
|
const can = (action, entity, field) => {
|
3390
|
-
|
3736
|
+
const subject = toSubject(entity);
|
3737
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3738
|
+
return (
|
3739
|
+
// Test the original action to see if it passes
|
3740
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3741
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3742
|
+
);
|
3391
3743
|
};
|
3392
3744
|
const cannot = (action, entity, field) => {
|
3393
|
-
|
3745
|
+
const subject = toSubject(entity);
|
3746
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3747
|
+
return (
|
3748
|
+
// Test both the original action
|
3749
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3750
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3751
|
+
);
|
3394
3752
|
};
|
3395
3753
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3396
3754
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3461,7 +3819,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3461
3819
|
return userAbility.can(action);
|
3462
3820
|
},
|
3463
3821
|
async registerPermissions() {
|
3464
|
-
const displayedContentTypes = getService$
|
3822
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3465
3823
|
const contentTypesUids = displayedContentTypes.map(prop("uid"));
|
3466
3824
|
const actions = [
|
3467
3825
|
{
|
@@ -3533,7 +3891,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3533
3891
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3534
3892
|
}
|
3535
3893
|
});
|
3536
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
|
3894
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
|
3537
3895
|
const { isAnyToMany } = strapiUtils.relations;
|
3538
3896
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
|
3539
3897
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3546,6 +3904,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3546
3904
|
if (initialPopulate) {
|
3547
3905
|
return initialPopulate;
|
3548
3906
|
}
|
3907
|
+
if (attributeName === "localizations") {
|
3908
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3909
|
+
return {
|
3910
|
+
populate: validationPopulate.populate
|
3911
|
+
};
|
3912
|
+
}
|
3549
3913
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3550
3914
|
return true;
|
3551
3915
|
}
|
@@ -3605,6 +3969,9 @@ const getDeepPopulate = (uid2, {
|
|
3605
3969
|
return {};
|
3606
3970
|
}
|
3607
3971
|
const model = strapi.getModel(uid2);
|
3972
|
+
if (!model) {
|
3973
|
+
return {};
|
3974
|
+
}
|
3608
3975
|
return Object.keys(model.attributes).reduce(
|
3609
3976
|
(populateAcc, attributeName) => merge(
|
3610
3977
|
populateAcc,
|
@@ -3624,6 +3991,48 @@ const getDeepPopulate = (uid2, {
|
|
3624
3991
|
{}
|
3625
3992
|
);
|
3626
3993
|
};
|
3994
|
+
const getPopulateForValidation = (uid2) => {
|
3995
|
+
const model = strapi.getModel(uid2);
|
3996
|
+
if (!model) {
|
3997
|
+
return {};
|
3998
|
+
}
|
3999
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
4000
|
+
if (isScalarAttribute(attribute)) {
|
4001
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4002
|
+
populateAcc.fields = populateAcc.fields || [];
|
4003
|
+
populateAcc.fields.push(attributeName);
|
4004
|
+
}
|
4005
|
+
return populateAcc;
|
4006
|
+
}
|
4007
|
+
if (isComponent(attribute)) {
|
4008
|
+
const component = attribute.component;
|
4009
|
+
const componentResult = getPopulateForValidation(component);
|
4010
|
+
if (Object.keys(componentResult).length > 0) {
|
4011
|
+
populateAcc.populate = populateAcc.populate || {};
|
4012
|
+
populateAcc.populate[attributeName] = componentResult;
|
4013
|
+
}
|
4014
|
+
return populateAcc;
|
4015
|
+
}
|
4016
|
+
if (isDynamicZone(attribute)) {
|
4017
|
+
const components2 = attribute.components;
|
4018
|
+
const componentsResult = (components2 || []).reduce(
|
4019
|
+
(acc, componentUID) => {
|
4020
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4021
|
+
if (Object.keys(componentResult).length > 0) {
|
4022
|
+
acc[componentUID] = componentResult;
|
4023
|
+
}
|
4024
|
+
return acc;
|
4025
|
+
},
|
4026
|
+
{}
|
4027
|
+
);
|
4028
|
+
if (Object.keys(componentsResult).length > 0) {
|
4029
|
+
populateAcc.populate = populateAcc.populate || {};
|
4030
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4031
|
+
}
|
4032
|
+
}
|
4033
|
+
return populateAcc;
|
4034
|
+
}, {});
|
4035
|
+
};
|
3627
4036
|
const getDeepPopulateDraftCount = (uid2) => {
|
3628
4037
|
const model = strapi.getModel(uid2);
|
3629
4038
|
let hasRelations = false;
|
@@ -3631,6 +4040,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3631
4040
|
const attribute = model.attributes[attributeName];
|
3632
4041
|
switch (attribute.type) {
|
3633
4042
|
case "relation": {
|
4043
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4044
|
+
if (isMorphRelation) {
|
4045
|
+
break;
|
4046
|
+
}
|
3634
4047
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3635
4048
|
populateAcc[attributeName] = {
|
3636
4049
|
count: true,
|
@@ -3645,22 +4058,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3645
4058
|
attribute.component
|
3646
4059
|
);
|
3647
4060
|
if (childHasRelations) {
|
3648
|
-
populateAcc[attributeName] = {
|
4061
|
+
populateAcc[attributeName] = {
|
4062
|
+
populate: populate2
|
4063
|
+
};
|
3649
4064
|
hasRelations = true;
|
3650
4065
|
}
|
3651
4066
|
break;
|
3652
4067
|
}
|
3653
4068
|
case "dynamiczone": {
|
3654
|
-
const
|
3655
|
-
const { populate:
|
3656
|
-
if (
|
4069
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
4070
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
4071
|
+
if (componentHasRelations) {
|
3657
4072
|
hasRelations = true;
|
3658
|
-
return
|
4073
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3659
4074
|
}
|
3660
4075
|
return acc;
|
3661
4076
|
}, {});
|
3662
|
-
if (!isEmpty(
|
3663
|
-
populateAcc[attributeName] = {
|
4077
|
+
if (!isEmpty(dzPopulateFragment)) {
|
4078
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3664
4079
|
}
|
3665
4080
|
break;
|
3666
4081
|
}
|
@@ -3695,7 +4110,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3695
4110
|
return populateQuery;
|
3696
4111
|
};
|
3697
4112
|
const buildDeepPopulate = (uid2) => {
|
3698
|
-
return getService$
|
4113
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3699
4114
|
};
|
3700
4115
|
const populateBuilder = (uid2) => {
|
3701
4116
|
let getInitialPopulate = async () => {
|
@@ -3852,41 +4267,55 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3852
4267
|
"updatedBy",
|
3853
4268
|
"status"
|
3854
4269
|
];
|
3855
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
4270
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
4271
|
+
"id",
|
4272
|
+
"locale",
|
4273
|
+
"updatedAt",
|
4274
|
+
"createdAt",
|
4275
|
+
"publishedAt",
|
4276
|
+
"documentId"
|
4277
|
+
];
|
3856
4278
|
const CONTENT_MANAGER_STATUS = {
|
3857
4279
|
PUBLISHED: "published",
|
3858
4280
|
DRAFT: "draft",
|
3859
4281
|
MODIFIED: "modified"
|
3860
4282
|
};
|
3861
|
-
const
|
3862
|
-
if (!
|
4283
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
4284
|
+
if (!version || !version.updatedAt) {
|
3863
4285
|
return false;
|
3864
4286
|
}
|
3865
|
-
const
|
3866
|
-
const
|
3867
|
-
|
3868
|
-
return difference2 <= threshold;
|
4287
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
4288
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
4289
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3869
4290
|
};
|
3870
4291
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3871
4292
|
/**
|
3872
4293
|
* Returns available locales of a document for the current status
|
3873
4294
|
*/
|
3874
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4295
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3875
4296
|
const versionsByLocale = groupBy("locale", allVersions);
|
3876
|
-
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
3881
|
-
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
3885
|
-
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
4297
|
+
if (version.locale) {
|
4298
|
+
delete versionsByLocale[version.locale];
|
4299
|
+
}
|
4300
|
+
const model = strapi2.getModel(uid2);
|
4301
|
+
const mappingResult = await async.map(
|
4302
|
+
Object.values(versionsByLocale),
|
4303
|
+
async (localeVersions) => {
|
4304
|
+
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
4305
|
+
return localeVersions[0];
|
4306
|
+
}
|
4307
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4308
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4309
|
+
if (!draftVersion) {
|
4310
|
+
return;
|
4311
|
+
}
|
4312
|
+
return {
|
4313
|
+
...draftVersion,
|
4314
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4315
|
+
};
|
4316
|
+
}
|
4317
|
+
);
|
4318
|
+
return mappingResult.filter(Boolean);
|
3890
4319
|
},
|
3891
4320
|
/**
|
3892
4321
|
* Returns available status of a document for the current locale
|
@@ -3898,8 +4327,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3898
4327
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
3899
4328
|
return matchLocale && matchStatus;
|
3900
4329
|
});
|
3901
|
-
if (!availableStatus)
|
3902
|
-
return availableStatus;
|
4330
|
+
if (!availableStatus) return availableStatus;
|
3903
4331
|
return pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
3904
4332
|
},
|
3905
4333
|
/**
|
@@ -3909,50 +4337,62 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3909
4337
|
* @returns
|
3910
4338
|
*/
|
3911
4339
|
async getManyAvailableStatus(uid2, documents) {
|
3912
|
-
if (!documents.length)
|
3913
|
-
return [];
|
4340
|
+
if (!documents.length) return [];
|
3914
4341
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
3915
|
-
const
|
3916
|
-
|
3917
|
-
|
3918
|
-
|
3919
|
-
|
4342
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4343
|
+
return strapi2.query(uid2).findMany({
|
4344
|
+
where: {
|
4345
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4346
|
+
// NOTE: find the "opposite" status
|
4347
|
+
publishedAt: { $null: status === "published" },
|
4348
|
+
locale: { $in: locales }
|
3920
4349
|
},
|
3921
|
-
|
3922
|
-
locale,
|
3923
|
-
fields: ["documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4350
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
3924
4351
|
});
|
3925
4352
|
},
|
3926
4353
|
getStatus(version, otherDocumentStatuses) {
|
3927
|
-
|
3928
|
-
|
3929
|
-
|
3930
|
-
|
3931
|
-
|
3932
|
-
|
3933
|
-
if (!publishedVersion) {
|
3934
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
3935
|
-
}
|
4354
|
+
let draftVersion;
|
4355
|
+
let publishedVersion;
|
4356
|
+
if (version.publishedAt) {
|
4357
|
+
publishedVersion = version;
|
4358
|
+
} else {
|
4359
|
+
draftVersion = version;
|
3936
4360
|
}
|
3937
|
-
|
3938
|
-
|
4361
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4362
|
+
if (otherVersion?.publishedAt) {
|
4363
|
+
publishedVersion = otherVersion;
|
4364
|
+
} else if (otherVersion) {
|
4365
|
+
draftVersion = otherVersion;
|
3939
4366
|
}
|
3940
|
-
return CONTENT_MANAGER_STATUS.
|
4367
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4368
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4369
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4370
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3941
4371
|
},
|
4372
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4373
|
+
// We could refactor this so the locales are only loaded when they're
|
4374
|
+
// needed. e.g. in the bulk locale action modal.
|
3942
4375
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
3943
|
-
const
|
3944
|
-
|
3945
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
4376
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4377
|
+
const params = {
|
3946
4378
|
populate: {
|
4379
|
+
...populate,
|
4380
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3947
4381
|
createdBy: {
|
3948
4382
|
select: ["id", "firstname", "lastname", "email"]
|
3949
4383
|
},
|
3950
4384
|
updatedBy: {
|
3951
4385
|
select: ["id", "firstname", "lastname", "email"]
|
3952
4386
|
}
|
4387
|
+
},
|
4388
|
+
fields: uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4389
|
+
filters: {
|
4390
|
+
documentId: version.documentId
|
3953
4391
|
}
|
3954
|
-
}
|
3955
|
-
const
|
4392
|
+
};
|
4393
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4394
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4395
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
3956
4396
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3957
4397
|
return {
|
3958
4398
|
availableLocales: availableLocalesResult,
|
@@ -3965,13 +4405,30 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3965
4405
|
* - Available status of the document for the current locale
|
3966
4406
|
*/
|
3967
4407
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3968
|
-
if (!document)
|
3969
|
-
return
|
4408
|
+
if (!document) {
|
4409
|
+
return {
|
4410
|
+
data: document,
|
4411
|
+
meta: {
|
4412
|
+
availableLocales: [],
|
4413
|
+
availableStatus: []
|
4414
|
+
}
|
4415
|
+
};
|
4416
|
+
}
|
3970
4417
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
3971
4418
|
if (!hasDraftAndPublish) {
|
3972
4419
|
opts.availableStatus = false;
|
3973
4420
|
}
|
3974
4421
|
const meta = await this.getMetadata(uid2, document, opts);
|
4422
|
+
if (document.localizations) {
|
4423
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4424
|
+
document.localizations = document.localizations.map((d) => {
|
4425
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4426
|
+
return {
|
4427
|
+
...d,
|
4428
|
+
status: this.getStatus(d, status ? [status] : [])
|
4429
|
+
};
|
4430
|
+
});
|
4431
|
+
}
|
3975
4432
|
return {
|
3976
4433
|
data: {
|
3977
4434
|
...document,
|
@@ -4016,26 +4473,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
4016
4473
|
}, 0);
|
4017
4474
|
};
|
4018
4475
|
const { ApplicationError } = errors;
|
4019
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4020
4476
|
const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
|
4021
4477
|
const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
|
4022
4478
|
const omitIdField = omit("id");
|
4023
|
-
const emitEvent = async (uid2, event, document) => {
|
4024
|
-
const modelDef = strapi.getModel(uid2);
|
4025
|
-
const sanitizedDocument = await sanitize.sanitizers.defaultSanitizeOutput(
|
4026
|
-
{
|
4027
|
-
schema: modelDef,
|
4028
|
-
getModel(uid22) {
|
4029
|
-
return strapi.getModel(uid22);
|
4030
|
-
}
|
4031
|
-
},
|
4032
|
-
document
|
4033
|
-
);
|
4034
|
-
strapi.eventHub.emit(event, {
|
4035
|
-
model: modelDef.modelName,
|
4036
|
-
entry: sanitizedDocument
|
4037
|
-
});
|
4038
|
-
};
|
4039
4479
|
const documentManager = ({ strapi: strapi2 }) => {
|
4040
4480
|
return {
|
4041
4481
|
async findOne(id, uid2, opts = {}) {
|
@@ -4054,6 +4494,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4054
4494
|
} else if (opts.locale && opts.locale !== "*") {
|
4055
4495
|
where.locale = opts.locale;
|
4056
4496
|
}
|
4497
|
+
if (typeof opts.isPublished === "boolean") {
|
4498
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4499
|
+
}
|
4057
4500
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4058
4501
|
},
|
4059
4502
|
async findMany(opts, uid2) {
|
@@ -4061,20 +4504,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4061
4504
|
return strapi2.documents(uid2).findMany(params);
|
4062
4505
|
},
|
4063
4506
|
async findPage(opts, uid2) {
|
4064
|
-
const
|
4065
|
-
|
4507
|
+
const params = pagination.withDefaultPagination(opts || {}, {
|
4508
|
+
maxLimit: 1e3
|
4509
|
+
});
|
4066
4510
|
const [documents, total = 0] = await Promise.all([
|
4067
|
-
strapi2.documents(uid2).findMany(
|
4068
|
-
strapi2.documents(uid2).count(
|
4511
|
+
strapi2.documents(uid2).findMany(params),
|
4512
|
+
strapi2.documents(uid2).count(params)
|
4069
4513
|
]);
|
4070
4514
|
return {
|
4071
4515
|
results: documents,
|
4072
|
-
pagination:
|
4073
|
-
page,
|
4074
|
-
pageSize,
|
4075
|
-
pageCount: Math.ceil(total / pageSize),
|
4076
|
-
total
|
4077
|
-
}
|
4516
|
+
pagination: pagination.transformPagedPaginationInfo(params, total)
|
4078
4517
|
};
|
4079
4518
|
},
|
4080
4519
|
async create(uid2, opts = {}) {
|
@@ -4091,10 +4530,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4091
4530
|
async clone(id, body, uid2) {
|
4092
4531
|
const populate = await buildDeepPopulate(uid2);
|
4093
4532
|
const params = {
|
4094
|
-
data:
|
4095
|
-
...omitIdField(body),
|
4096
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4097
|
-
},
|
4533
|
+
data: omitIdField(body),
|
4098
4534
|
populate
|
4099
4535
|
};
|
4100
4536
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4120,70 +4556,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4120
4556
|
return {};
|
4121
4557
|
},
|
4122
4558
|
// FIXME: handle relations
|
4123
|
-
async deleteMany(
|
4124
|
-
const
|
4125
|
-
|
4126
|
-
|
4127
|
-
}
|
4128
|
-
return { count: docs.length };
|
4559
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4560
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4561
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4562
|
+
});
|
4563
|
+
return { count: deletedEntries.length };
|
4129
4564
|
},
|
4130
4565
|
async publish(id, uid2, opts = {}) {
|
4131
4566
|
const populate = await buildDeepPopulate(uid2);
|
4132
4567
|
const params = { ...opts, populate };
|
4133
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4568
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4134
4569
|
},
|
4135
|
-
async publishMany(
|
4136
|
-
|
4137
|
-
|
4138
|
-
|
4139
|
-
|
4140
|
-
|
4141
|
-
|
4142
|
-
strapi2.getModel(uid2),
|
4143
|
-
document,
|
4144
|
-
void 0,
|
4145
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4146
|
-
document
|
4147
|
-
);
|
4148
|
-
})
|
4149
|
-
);
|
4150
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4151
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4152
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4153
|
-
const populate = await buildDeepPopulate(uid2);
|
4154
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4155
|
-
where: filters,
|
4156
|
-
data
|
4157
|
-
});
|
4158
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4159
|
-
where: filters,
|
4160
|
-
populate
|
4570
|
+
async publishMany(uid2, documentIds, locale) {
|
4571
|
+
return strapi2.db.transaction(async () => {
|
4572
|
+
const results = await Promise.all(
|
4573
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4574
|
+
);
|
4575
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4576
|
+
return publishedEntitiesCount;
|
4161
4577
|
});
|
4162
|
-
await Promise.all(
|
4163
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4164
|
-
);
|
4165
|
-
return publishedEntitiesCount;
|
4166
4578
|
},
|
4167
|
-
async unpublishMany(
|
4168
|
-
|
4169
|
-
return
|
4170
|
-
|
4171
|
-
|
4172
|
-
|
4173
|
-
|
4174
|
-
const populate = await buildDeepPopulate(uid2);
|
4175
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4176
|
-
where: filters,
|
4177
|
-
data
|
4178
|
-
});
|
4179
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4180
|
-
where: filters,
|
4181
|
-
populate
|
4579
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4580
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4581
|
+
return Promise.all(
|
4582
|
+
documentIds.map(
|
4583
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4584
|
+
)
|
4585
|
+
);
|
4182
4586
|
});
|
4183
|
-
|
4184
|
-
|
4185
|
-
);
|
4186
|
-
return unpublishedEntitiesCount;
|
4587
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4588
|
+
return { count: unpublishedEntitiesCount };
|
4187
4589
|
},
|
4188
4590
|
async unpublish(id, uid2, opts = {}) {
|
4189
4591
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4208,16 +4610,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4208
4610
|
}
|
4209
4611
|
return sumDraftCounts(document, uid2);
|
4210
4612
|
},
|
4211
|
-
async countManyEntriesDraftRelations(
|
4613
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4212
4614
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4213
4615
|
if (!hasRelations) {
|
4214
4616
|
return 0;
|
4215
4617
|
}
|
4618
|
+
let localeFilter = {};
|
4619
|
+
if (locale) {
|
4620
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4621
|
+
}
|
4216
4622
|
const entities = await strapi2.db.query(uid2).findMany({
|
4217
4623
|
populate,
|
4218
4624
|
where: {
|
4219
|
-
|
4220
|
-
...
|
4625
|
+
documentId: { $in: documentIds },
|
4626
|
+
...localeFilter
|
4221
4627
|
}
|
4222
4628
|
});
|
4223
4629
|
const totalNumberDraftRelations = entities.reduce(
|
@@ -4240,7 +4646,8 @@ const services = {
|
|
4240
4646
|
permission,
|
4241
4647
|
"populate-builder": populateBuilder$1,
|
4242
4648
|
uid,
|
4243
|
-
...history.services ? history.services : {}
|
4649
|
+
...history.services ? history.services : {},
|
4650
|
+
...preview.services ? preview.services : {}
|
4244
4651
|
};
|
4245
4652
|
const index = () => {
|
4246
4653
|
return {
|