@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.js
CHANGED
@@ -10,8 +10,7 @@ const qs = require("qs");
|
|
10
10
|
const slugify = require("@sindresorhus/slugify");
|
11
11
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
12
12
|
function _interopNamespace(e) {
|
13
|
-
if (e && e.__esModule)
|
14
|
-
return e;
|
13
|
+
if (e && e.__esModule) return e;
|
15
14
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
16
15
|
if (e) {
|
17
16
|
for (const k in e) {
|
@@ -33,10 +32,10 @@ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
|
|
33
32
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
34
33
|
const qs__default = /* @__PURE__ */ _interopDefault(qs);
|
35
34
|
const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
|
36
|
-
const getService$
|
35
|
+
const getService$2 = (name) => {
|
37
36
|
return strapi.plugin("content-manager").service(name);
|
38
37
|
};
|
39
|
-
function getService(strapi2, name) {
|
38
|
+
function getService$1(strapi2, name) {
|
40
39
|
return strapi2.service(`plugin::content-manager.${name}`);
|
41
40
|
}
|
42
41
|
const historyRestoreVersionSchema = yup__namespace.object().shape({
|
@@ -72,7 +71,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
72
71
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
73
72
|
throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
|
74
73
|
}
|
75
|
-
const permissionChecker2 = getService$
|
74
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
76
75
|
userAbility: ctx.state.userAbility,
|
77
76
|
model: ctx.query.contentType
|
78
77
|
});
|
@@ -80,7 +79,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
80
79
|
return ctx.forbidden();
|
81
80
|
}
|
82
81
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
83
|
-
const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
|
82
|
+
const { results, pagination } = await getService$1(strapi2, "history").findVersionsPage({
|
84
83
|
query: {
|
85
84
|
...query,
|
86
85
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -105,14 +104,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
105
104
|
async restoreVersion(ctx) {
|
106
105
|
const request = ctx.request;
|
107
106
|
await validateRestoreVersion(request.body, "contentType is required");
|
108
|
-
const permissionChecker2 = getService$
|
107
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
109
108
|
userAbility: ctx.state.userAbility,
|
110
109
|
model: request.body.contentType
|
111
110
|
});
|
112
111
|
if (permissionChecker2.cannot.update()) {
|
113
112
|
throw new strapiUtils.errors.ForbiddenError();
|
114
113
|
}
|
115
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
114
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
116
115
|
request.params.versionId
|
117
116
|
);
|
118
117
|
return {
|
@@ -121,7 +120,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
121
120
|
}
|
122
121
|
};
|
123
122
|
};
|
124
|
-
const controllers$
|
123
|
+
const controllers$2 = {
|
125
124
|
"history-version": createHistoryVersionController
|
126
125
|
/**
|
127
126
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -167,8 +166,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
167
166
|
};
|
168
167
|
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
169
168
|
if (Array.isArray(versionRelationData)) {
|
170
|
-
if (versionRelationData.length === 0)
|
171
|
-
return versionRelationData;
|
169
|
+
if (versionRelationData.length === 0) return versionRelationData;
|
172
170
|
const existingAndMissingRelations = await Promise.all(
|
173
171
|
versionRelationData.map((relation) => {
|
174
172
|
return strapi2.documents(attribute.target).findOne({
|
@@ -199,10 +197,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
199
197
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
200
198
|
};
|
201
199
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
200
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
202
201
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
202
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
203
203
|
const getLocaleDictionary = async () => {
|
204
|
-
if (!localesService)
|
205
|
-
return {};
|
204
|
+
if (!localesService) return {};
|
206
205
|
const locales = await localesService.find() || [];
|
207
206
|
return locales.reduce(
|
208
207
|
(acc, locale) => {
|
@@ -226,31 +225,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
225
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
226
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
227
|
};
|
229
|
-
const
|
228
|
+
const getComponentFields = (componentUID) => {
|
229
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
230
|
+
(fieldsAcc, [key, attribute]) => {
|
231
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
232
|
+
fieldsAcc.push(key);
|
233
|
+
}
|
234
|
+
return fieldsAcc;
|
235
|
+
},
|
236
|
+
[]
|
237
|
+
);
|
238
|
+
};
|
239
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
240
|
const model = strapi2.getModel(uid2);
|
231
241
|
const attributes = Object.entries(model.attributes);
|
242
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
243
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
244
|
switch (attribute.type) {
|
234
245
|
case "relation": {
|
246
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
247
|
+
if (isMorphRelation) {
|
248
|
+
break;
|
249
|
+
}
|
235
250
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
251
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
252
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
253
|
}
|
239
254
|
break;
|
240
255
|
}
|
241
256
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
257
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
258
|
break;
|
244
259
|
}
|
245
260
|
case "component": {
|
246
261
|
const populate = getDeepPopulate2(attribute.component);
|
247
|
-
acc[attributeName] = {
|
262
|
+
acc[attributeName] = {
|
263
|
+
populate,
|
264
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
265
|
+
};
|
248
266
|
break;
|
249
267
|
}
|
250
268
|
case "dynamiczone": {
|
251
269
|
const populatedComponents = (attribute.components || []).reduce(
|
252
270
|
(acc2, componentUID) => {
|
253
|
-
acc2[componentUID] = {
|
271
|
+
acc2[componentUID] = {
|
272
|
+
populate: getDeepPopulate2(componentUID),
|
273
|
+
[fieldSelector]: getComponentFields(componentUID)
|
274
|
+
};
|
254
275
|
return acc2;
|
255
276
|
},
|
256
277
|
{}
|
@@ -312,6 +333,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
312
333
|
getRelationRestoreValue,
|
313
334
|
getMediaRestoreValue,
|
314
335
|
getDefaultLocale,
|
336
|
+
isLocalizedContentType,
|
315
337
|
getLocaleDictionary,
|
316
338
|
getRetentionDays,
|
317
339
|
getVersionStatus,
|
@@ -334,7 +356,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
356
|
});
|
335
357
|
},
|
336
358
|
async findVersionsPage(params) {
|
337
|
-
const
|
359
|
+
const model = strapi2.getModel(params.query.contentType);
|
360
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
361
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
362
|
+
let locale = null;
|
363
|
+
if (isLocalizedContentType) {
|
364
|
+
locale = params.query.locale || defaultLocale;
|
365
|
+
}
|
338
366
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
339
367
|
query.findPage({
|
340
368
|
...params.query,
|
@@ -356,7 +384,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
356
384
|
const attributeValue = entry.data[attributeKey];
|
357
385
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
358
386
|
if (attributeSchema.type === "media") {
|
359
|
-
const permissionChecker2 = getService$
|
387
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
360
388
|
userAbility: params.state.userAbility,
|
361
389
|
model: "plugin::upload.file"
|
362
390
|
});
|
@@ -379,7 +407,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
379
407
|
if (userToPopulate == null) {
|
380
408
|
return null;
|
381
409
|
}
|
382
|
-
return strapi2.query("admin::user").findOne({
|
410
|
+
return strapi2.query("admin::user").findOne({
|
411
|
+
where: {
|
412
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
413
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
414
|
+
}
|
415
|
+
});
|
383
416
|
})
|
384
417
|
);
|
385
418
|
return {
|
@@ -392,7 +425,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
392
425
|
[attributeKey]: adminUsers
|
393
426
|
};
|
394
427
|
}
|
395
|
-
const permissionChecker2 = getService$
|
428
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
396
429
|
userAbility: params.state.userAbility,
|
397
430
|
model: attributeSchema.target
|
398
431
|
});
|
@@ -490,13 +523,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
523
|
}
|
491
524
|
};
|
492
525
|
};
|
526
|
+
const shouldCreateHistoryVersion = (context) => {
|
527
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
528
|
+
return false;
|
529
|
+
}
|
530
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
531
|
+
return false;
|
532
|
+
}
|
533
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
534
|
+
return false;
|
535
|
+
}
|
536
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
537
|
+
return false;
|
538
|
+
}
|
539
|
+
return true;
|
540
|
+
};
|
541
|
+
const getSchemas = (uid2) => {
|
542
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
543
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
544
|
+
(currentComponentSchemas, key) => {
|
545
|
+
const fieldSchema = attributesSchema[key];
|
546
|
+
if (fieldSchema.type === "component") {
|
547
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
548
|
+
return {
|
549
|
+
...currentComponentSchemas,
|
550
|
+
[fieldSchema.component]: componentSchema
|
551
|
+
};
|
552
|
+
}
|
553
|
+
return currentComponentSchemas;
|
554
|
+
},
|
555
|
+
{}
|
556
|
+
);
|
557
|
+
return {
|
558
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
559
|
+
componentsSchemas
|
560
|
+
};
|
561
|
+
};
|
493
562
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
563
|
const state = {
|
495
564
|
deleteExpiredJob: null,
|
496
565
|
isInitialized: false
|
497
566
|
};
|
498
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
-
const historyService = getService(strapi2, "history");
|
500
567
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
568
|
return {
|
502
569
|
async bootstrap() {
|
@@ -504,65 +571,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
504
571
|
return;
|
505
572
|
}
|
506
573
|
strapi2.documents.use(async (context, next) => {
|
507
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
508
|
-
return next();
|
509
|
-
}
|
510
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
511
|
-
return next();
|
512
|
-
}
|
513
|
-
const contentTypeUid = context.contentType.uid;
|
514
|
-
if (!contentTypeUid.startsWith("api::")) {
|
515
|
-
return next();
|
516
|
-
}
|
517
574
|
const result = await next();
|
518
|
-
|
575
|
+
if (!shouldCreateHistoryVersion(context)) {
|
576
|
+
return result;
|
577
|
+
}
|
578
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
519
579
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
520
|
-
const
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
580
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
581
|
+
if (!locales.length) {
|
582
|
+
return result;
|
583
|
+
}
|
584
|
+
const uid2 = context.contentType.uid;
|
585
|
+
const schemas = getSchemas(uid2);
|
586
|
+
const model = strapi2.getModel(uid2);
|
587
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
588
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
589
|
+
where: {
|
590
|
+
documentId,
|
591
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
592
|
+
...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
593
|
+
},
|
594
|
+
populate: serviceUtils.getDeepPopulate(
|
595
|
+
uid2,
|
596
|
+
true
|
597
|
+
/* use database syntax */
|
598
|
+
)
|
525
599
|
});
|
526
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
527
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
528
|
-
const componentsSchemas = Object.keys(
|
529
|
-
attributesSchema
|
530
|
-
).reduce((currentComponentSchemas, key) => {
|
531
|
-
const fieldSchema = attributesSchema[key];
|
532
|
-
if (fieldSchema.type === "component") {
|
533
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
534
|
-
return {
|
535
|
-
...currentComponentSchemas,
|
536
|
-
[fieldSchema.component]: componentSchema
|
537
|
-
};
|
538
|
-
}
|
539
|
-
return currentComponentSchemas;
|
540
|
-
}, {});
|
541
600
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
542
|
-
onCommit(() => {
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
601
|
+
onCommit(async () => {
|
602
|
+
for (const entry of localeEntries) {
|
603
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
604
|
+
await getService$1(strapi2, "history").createVersion({
|
605
|
+
contentType: uid2,
|
606
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
607
|
+
relatedDocumentId: documentId,
|
608
|
+
locale: entry.locale,
|
609
|
+
status,
|
610
|
+
...schemas
|
611
|
+
});
|
612
|
+
}
|
552
613
|
});
|
553
614
|
});
|
554
615
|
return result;
|
555
616
|
});
|
556
|
-
|
557
|
-
|
558
|
-
const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
|
617
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
618
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
559
619
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
560
|
-
query.deleteMany({
|
620
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
561
621
|
where: {
|
562
622
|
created_at: {
|
563
|
-
$lt: expirationDate
|
623
|
+
$lt: expirationDate
|
564
624
|
}
|
565
625
|
}
|
626
|
+
}).catch((error) => {
|
627
|
+
if (error instanceof Error) {
|
628
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
629
|
+
}
|
566
630
|
});
|
567
631
|
});
|
568
632
|
state.isInitialized = true;
|
@@ -574,17 +638,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
574
638
|
}
|
575
639
|
};
|
576
640
|
};
|
577
|
-
const services$
|
641
|
+
const services$2 = {
|
578
642
|
history: createHistoryService,
|
579
643
|
lifecycles: createLifecyclesService
|
580
644
|
};
|
581
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
645
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
582
646
|
const historyVersionRouter = {
|
583
647
|
type: "admin",
|
584
648
|
routes: [
|
585
649
|
{
|
586
650
|
method: "GET",
|
587
|
-
info,
|
651
|
+
info: info$1,
|
588
652
|
path: "/history-versions",
|
589
653
|
handler: "history-version.findMany",
|
590
654
|
config: {
|
@@ -593,7 +657,7 @@ const historyVersionRouter = {
|
|
593
657
|
},
|
594
658
|
{
|
595
659
|
method: "PUT",
|
596
|
-
info,
|
660
|
+
info: info$1,
|
597
661
|
path: "/history-versions/:versionId/restore",
|
598
662
|
handler: "history-version.restoreVersion",
|
599
663
|
config: {
|
@@ -602,7 +666,7 @@ const historyVersionRouter = {
|
|
602
666
|
}
|
603
667
|
]
|
604
668
|
};
|
605
|
-
const routes$
|
669
|
+
const routes$2 = {
|
606
670
|
"history-version": historyVersionRouter
|
607
671
|
};
|
608
672
|
const historyVersion = {
|
@@ -649,21 +713,21 @@ const historyVersion = {
|
|
649
713
|
}
|
650
714
|
}
|
651
715
|
};
|
652
|
-
const getFeature = () => {
|
716
|
+
const getFeature$1 = () => {
|
653
717
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
654
718
|
return {
|
655
719
|
register({ strapi: strapi2 }) {
|
656
720
|
strapi2.get("models").add(historyVersion);
|
657
721
|
},
|
658
722
|
bootstrap({ strapi: strapi2 }) {
|
659
|
-
getService(strapi2, "lifecycles").bootstrap();
|
723
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
660
724
|
},
|
661
725
|
destroy({ strapi: strapi2 }) {
|
662
|
-
getService(strapi2, "lifecycles").destroy();
|
726
|
+
getService$1(strapi2, "lifecycles").destroy();
|
663
727
|
},
|
664
|
-
controllers: controllers$
|
665
|
-
services: services$
|
666
|
-
routes: routes$
|
728
|
+
controllers: controllers$2,
|
729
|
+
services: services$2,
|
730
|
+
routes: routes$2
|
667
731
|
};
|
668
732
|
}
|
669
733
|
return {
|
@@ -672,9 +736,201 @@ const getFeature = () => {
|
|
672
736
|
}
|
673
737
|
};
|
674
738
|
};
|
675
|
-
const history = getFeature();
|
739
|
+
const history = getFeature$1();
|
740
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
741
|
+
const previewRouter = {
|
742
|
+
type: "admin",
|
743
|
+
routes: [
|
744
|
+
{
|
745
|
+
method: "GET",
|
746
|
+
info,
|
747
|
+
path: "/preview/url/:contentType",
|
748
|
+
handler: "preview.getPreviewUrl",
|
749
|
+
config: {
|
750
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
751
|
+
}
|
752
|
+
}
|
753
|
+
]
|
754
|
+
};
|
755
|
+
const routes$1 = {
|
756
|
+
preview: previewRouter
|
757
|
+
};
|
758
|
+
function getService(strapi2, name) {
|
759
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
760
|
+
}
|
761
|
+
const getPreviewUrlSchema = yup__namespace.object().shape({
|
762
|
+
// Will be undefined for single types
|
763
|
+
documentId: yup__namespace.string(),
|
764
|
+
locale: yup__namespace.string().nullable(),
|
765
|
+
status: yup__namespace.string()
|
766
|
+
}).required();
|
767
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
768
|
+
await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
|
769
|
+
const newParams = fp.pick(["documentId", "locale", "status"], params);
|
770
|
+
const model = strapi2.getModel(uid2);
|
771
|
+
if (!model || model.modelType !== "contentType") {
|
772
|
+
throw new strapiUtils.errors.ValidationError("Invalid content type");
|
773
|
+
}
|
774
|
+
const isSingleType = model?.kind === "singleType";
|
775
|
+
if (!isSingleType && !params.documentId) {
|
776
|
+
throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
|
777
|
+
}
|
778
|
+
if (isSingleType) {
|
779
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
780
|
+
if (!doc) {
|
781
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
782
|
+
}
|
783
|
+
newParams.documentId = doc?.documentId;
|
784
|
+
}
|
785
|
+
if (!newParams.status) {
|
786
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
787
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
788
|
+
}
|
789
|
+
return newParams;
|
790
|
+
};
|
791
|
+
const createPreviewController = () => {
|
792
|
+
return {
|
793
|
+
/**
|
794
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
795
|
+
* in the Content Manager.
|
796
|
+
*/
|
797
|
+
async getPreviewUrl(ctx) {
|
798
|
+
const uid2 = ctx.params.contentType;
|
799
|
+
const query = ctx.request.query;
|
800
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
801
|
+
const previewService = getService(strapi, "preview");
|
802
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
803
|
+
if (!url) {
|
804
|
+
ctx.status = 204;
|
805
|
+
}
|
806
|
+
return {
|
807
|
+
data: { url }
|
808
|
+
};
|
809
|
+
}
|
810
|
+
};
|
811
|
+
};
|
812
|
+
const controllers$1 = {
|
813
|
+
preview: createPreviewController
|
814
|
+
/**
|
815
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
816
|
+
* passing a controller factory as the value, instead of a controller object directly
|
817
|
+
*/
|
818
|
+
};
|
819
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
820
|
+
const config = getService(strapi2, "preview-config");
|
821
|
+
return {
|
822
|
+
async getPreviewUrl(uid2, params) {
|
823
|
+
const handler = config.getPreviewHandler();
|
824
|
+
try {
|
825
|
+
return handler(uid2, params);
|
826
|
+
} catch (error) {
|
827
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
828
|
+
throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
|
829
|
+
}
|
830
|
+
return;
|
831
|
+
}
|
832
|
+
};
|
833
|
+
};
|
834
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
835
|
+
const middlewares = strapi.config.get("middlewares");
|
836
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
837
|
+
if (currentMiddleware === middleware.name) {
|
838
|
+
return middleware;
|
839
|
+
}
|
840
|
+
if (currentMiddleware.name === middleware.name) {
|
841
|
+
return fp.mergeWith(
|
842
|
+
(objValue, srcValue) => {
|
843
|
+
if (Array.isArray(objValue)) {
|
844
|
+
return objValue.concat(srcValue);
|
845
|
+
}
|
846
|
+
return void 0;
|
847
|
+
},
|
848
|
+
currentMiddleware,
|
849
|
+
middleware
|
850
|
+
);
|
851
|
+
}
|
852
|
+
return currentMiddleware;
|
853
|
+
});
|
854
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
855
|
+
};
|
856
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
857
|
+
return {
|
858
|
+
register() {
|
859
|
+
if (!this.isEnabled()) {
|
860
|
+
return;
|
861
|
+
}
|
862
|
+
const config = strapi2.config.get("admin.preview");
|
863
|
+
if (config.config?.allowedOrigins) {
|
864
|
+
extendMiddlewareConfiguration({
|
865
|
+
name: "strapi::security",
|
866
|
+
config: {
|
867
|
+
contentSecurityPolicy: {
|
868
|
+
directives: {
|
869
|
+
"frame-src": config.config.allowedOrigins
|
870
|
+
}
|
871
|
+
}
|
872
|
+
}
|
873
|
+
});
|
874
|
+
}
|
875
|
+
},
|
876
|
+
isEnabled() {
|
877
|
+
const config = strapi2.config.get("admin.preview");
|
878
|
+
if (!config) {
|
879
|
+
return false;
|
880
|
+
}
|
881
|
+
return config?.enabled ?? true;
|
882
|
+
},
|
883
|
+
/**
|
884
|
+
* Validate if the configuration is valid
|
885
|
+
*/
|
886
|
+
validate() {
|
887
|
+
if (!this.isEnabled()) {
|
888
|
+
return;
|
889
|
+
}
|
890
|
+
const handler = this.getPreviewHandler();
|
891
|
+
if (typeof handler !== "function") {
|
892
|
+
throw new strapiUtils.errors.ValidationError(
|
893
|
+
"Preview configuration is invalid. Handler must be a function"
|
894
|
+
);
|
895
|
+
}
|
896
|
+
},
|
897
|
+
/**
|
898
|
+
* Utility to get the preview handler from the configuration
|
899
|
+
*/
|
900
|
+
getPreviewHandler() {
|
901
|
+
const config = strapi2.config.get("admin.preview");
|
902
|
+
const emptyHandler = () => {
|
903
|
+
return void 0;
|
904
|
+
};
|
905
|
+
if (!this.isEnabled()) {
|
906
|
+
return emptyHandler;
|
907
|
+
}
|
908
|
+
return config?.config?.handler || emptyHandler;
|
909
|
+
}
|
910
|
+
};
|
911
|
+
};
|
912
|
+
const services$1 = {
|
913
|
+
preview: createPreviewService,
|
914
|
+
"preview-config": createPreviewConfigService
|
915
|
+
};
|
916
|
+
const getFeature = () => {
|
917
|
+
return {
|
918
|
+
register() {
|
919
|
+
const config = getService(strapi, "preview-config");
|
920
|
+
config.validate();
|
921
|
+
config.register();
|
922
|
+
},
|
923
|
+
bootstrap() {
|
924
|
+
},
|
925
|
+
routes: routes$1,
|
926
|
+
controllers: controllers$1,
|
927
|
+
services: services$1
|
928
|
+
};
|
929
|
+
};
|
930
|
+
const preview = getFeature();
|
676
931
|
const register = async ({ strapi: strapi2 }) => {
|
677
932
|
await history.register?.({ strapi: strapi2 });
|
933
|
+
await preview.register?.({ strapi: strapi2 });
|
678
934
|
};
|
679
935
|
const ALLOWED_WEBHOOK_EVENTS = {
|
680
936
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -684,11 +940,12 @@ const bootstrap = async () => {
|
|
684
940
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
685
941
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
686
942
|
});
|
687
|
-
getService$
|
688
|
-
await getService$
|
689
|
-
await getService$
|
690
|
-
await getService$
|
943
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
944
|
+
await getService$2("components").syncConfigurations();
|
945
|
+
await getService$2("content-types").syncConfigurations();
|
946
|
+
await getService$2("permission").registerPermissions();
|
691
947
|
await history.bootstrap?.({ strapi });
|
948
|
+
await preview.bootstrap?.({ strapi });
|
692
949
|
};
|
693
950
|
const destroy = async ({ strapi: strapi2 }) => {
|
694
951
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1178,7 +1435,8 @@ const admin = {
|
|
1178
1435
|
};
|
1179
1436
|
const routes = {
|
1180
1437
|
admin,
|
1181
|
-
...history.routes ? history.routes : {}
|
1438
|
+
...history.routes ? history.routes : {},
|
1439
|
+
...preview.routes ? preview.routes : {}
|
1182
1440
|
};
|
1183
1441
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1184
1442
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1189,6 +1447,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1189
1447
|
const hasPermissions = createPolicy({
|
1190
1448
|
name: "plugin::content-manager.hasPermissions",
|
1191
1449
|
validator: validateHasPermissionsInput,
|
1450
|
+
/**
|
1451
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1452
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1453
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1454
|
+
*/
|
1192
1455
|
handler(ctx, config = {}) {
|
1193
1456
|
const { actions = [], hasAtLeastOne = false } = config;
|
1194
1457
|
const { userAbility } = ctx.state;
|
@@ -1236,8 +1499,7 @@ const isSortable = (schema, name) => {
|
|
1236
1499
|
if (!___default.default.has(schema.attributes, name)) {
|
1237
1500
|
return false;
|
1238
1501
|
}
|
1239
|
-
if (schema.modelType === "component" && name === "id")
|
1240
|
-
return false;
|
1502
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1241
1503
|
const attribute = schema.attributes[name];
|
1242
1504
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1243
1505
|
return false;
|
@@ -1382,8 +1644,7 @@ const createDefaultSettings = async (schema) => {
|
|
1382
1644
|
};
|
1383
1645
|
};
|
1384
1646
|
const syncSettings = async (configuration, schema) => {
|
1385
|
-
if (fp.isEmpty(configuration.settings))
|
1386
|
-
return createDefaultSettings(schema);
|
1647
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1387
1648
|
const defaultField = getDefaultMainField(schema);
|
1388
1649
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1389
1650
|
return {
|
@@ -1430,7 +1691,7 @@ const createMetadasSchema = (schema) => {
|
|
1430
1691
|
if (!value) {
|
1431
1692
|
return strapiUtils.yup.string();
|
1432
1693
|
}
|
1433
|
-
const targetSchema = getService$
|
1694
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1434
1695
|
schema.attributes[key].targetModel
|
1435
1696
|
);
|
1436
1697
|
if (!targetSchema) {
|
@@ -1478,7 +1739,7 @@ const { PaginationError, ValidationError } = strapiUtils.errors;
|
|
1478
1739
|
const TYPES = ["singleType", "collectionType"];
|
1479
1740
|
const kindSchema = strapiUtils.yup.string().oneOf(TYPES).nullable();
|
1480
1741
|
const bulkActionInputSchema = strapiUtils.yup.object({
|
1481
|
-
|
1742
|
+
documentIds: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()).min(1).required()
|
1482
1743
|
}).required();
|
1483
1744
|
const generateUIDInputSchema = strapiUtils.yup.object({
|
1484
1745
|
contentTypeUID: strapiUtils.yup.string().required(),
|
@@ -1559,8 +1820,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1559
1820
|
}
|
1560
1821
|
switch (attribute.type) {
|
1561
1822
|
case "relation": {
|
1562
|
-
if (canCreate(attributePath))
|
1563
|
-
return body2;
|
1823
|
+
if (canCreate(attributePath)) return body2;
|
1564
1824
|
return fp.set(attributePath, { set: [] }, body2);
|
1565
1825
|
}
|
1566
1826
|
case "component": {
|
@@ -1570,29 +1830,62 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1570
1830
|
]);
|
1571
1831
|
}
|
1572
1832
|
default: {
|
1573
|
-
if (canCreate(attributePath))
|
1574
|
-
return body2;
|
1833
|
+
if (canCreate(attributePath)) return body2;
|
1575
1834
|
return fp.set(attributePath, null, body2);
|
1576
1835
|
}
|
1577
1836
|
}
|
1578
1837
|
}, body);
|
1579
1838
|
};
|
1580
|
-
const
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1839
|
+
const singleLocaleSchema = strapiUtils.yup.string().nullable();
|
1840
|
+
const multipleLocaleSchema = strapiUtils.yup.lazy(
|
1841
|
+
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1842
|
+
);
|
1843
|
+
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1844
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1845
|
+
const { allowMultipleLocales } = opts;
|
1846
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1847
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1848
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1849
|
+
const schema = strapiUtils.yup.object().shape({
|
1850
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1851
|
+
status: statusSchema
|
1852
|
+
});
|
1853
|
+
try {
|
1854
|
+
await strapiUtils.validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1855
|
+
return { locale, status, ...rest };
|
1856
|
+
} catch (error) {
|
1857
|
+
throw new strapiUtils.errors.ValidationError(`Validation error: ${error.message}`);
|
1587
1858
|
}
|
1588
|
-
|
1859
|
+
};
|
1860
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1861
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1862
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1863
|
+
let {
|
1864
|
+
meta: { availableLocales, availableStatus }
|
1865
|
+
} = serviceOutput;
|
1866
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1867
|
+
availableLocales = await strapiUtils.async.map(
|
1868
|
+
availableLocales,
|
1869
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1870
|
+
);
|
1871
|
+
availableStatus = await strapiUtils.async.map(
|
1872
|
+
availableStatus,
|
1873
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1874
|
+
);
|
1875
|
+
return {
|
1876
|
+
...serviceOutput,
|
1877
|
+
meta: {
|
1878
|
+
availableLocales,
|
1879
|
+
availableStatus
|
1880
|
+
}
|
1881
|
+
};
|
1589
1882
|
};
|
1590
1883
|
const createDocument = async (ctx, opts) => {
|
1591
1884
|
const { userAbility, user } = ctx.state;
|
1592
1885
|
const { model } = ctx.params;
|
1593
1886
|
const { body } = ctx.request;
|
1594
|
-
const documentManager2 = getService$
|
1595
|
-
const permissionChecker2 = getService$
|
1887
|
+
const documentManager2 = getService$2("document-manager");
|
1888
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1596
1889
|
if (permissionChecker2.cannot.create()) {
|
1597
1890
|
throw new strapiUtils.errors.ForbiddenError();
|
1598
1891
|
}
|
@@ -1600,7 +1893,7 @@ const createDocument = async (ctx, opts) => {
|
|
1600
1893
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1601
1894
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1602
1895
|
const sanitizedBody = await sanitizeFn(body);
|
1603
|
-
const { locale, status
|
1896
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1604
1897
|
return documentManager2.create(model, {
|
1605
1898
|
data: sanitizedBody,
|
1606
1899
|
locale,
|
@@ -1612,14 +1905,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1612
1905
|
const { userAbility, user } = ctx.state;
|
1613
1906
|
const { id, model } = ctx.params;
|
1614
1907
|
const { body } = ctx.request;
|
1615
|
-
const documentManager2 = getService$
|
1616
|
-
const permissionChecker2 = getService$
|
1908
|
+
const documentManager2 = getService$2("document-manager");
|
1909
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1617
1910
|
if (permissionChecker2.cannot.update()) {
|
1618
1911
|
throw new strapiUtils.errors.ForbiddenError();
|
1619
1912
|
}
|
1620
1913
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1621
|
-
const populate = await getService$
|
1622
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1914
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1915
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1623
1916
|
const [documentVersion, documentExists] = await Promise.all([
|
1624
1917
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1625
1918
|
documentManager2.exists(model, id)
|
@@ -1635,7 +1928,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1635
1928
|
throw new strapiUtils.errors.ForbiddenError();
|
1636
1929
|
}
|
1637
1930
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1638
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1931
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1639
1932
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1640
1933
|
const sanitizedBody = await sanitizeFn(body);
|
1641
1934
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1649,15 +1942,15 @@ const collectionTypes = {
|
|
1649
1942
|
const { userAbility } = ctx.state;
|
1650
1943
|
const { model } = ctx.params;
|
1651
1944
|
const { query } = ctx.request;
|
1652
|
-
const documentMetadata2 = getService$
|
1653
|
-
const documentManager2 = getService$
|
1654
|
-
const permissionChecker2 = getService$
|
1945
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1946
|
+
const documentManager2 = getService$2("document-manager");
|
1947
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1655
1948
|
if (permissionChecker2.cannot.read()) {
|
1656
1949
|
return ctx.forbidden();
|
1657
1950
|
}
|
1658
1951
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1659
|
-
const populate = await getService$
|
1660
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1952
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1953
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1661
1954
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1662
1955
|
{ ...permissionQuery, populate, locale, status },
|
1663
1956
|
model
|
@@ -1685,15 +1978,14 @@ const collectionTypes = {
|
|
1685
1978
|
async findOne(ctx) {
|
1686
1979
|
const { userAbility } = ctx.state;
|
1687
1980
|
const { model, id } = ctx.params;
|
1688
|
-
const documentManager2 = getService$
|
1689
|
-
const
|
1690
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1981
|
+
const documentManager2 = getService$2("document-manager");
|
1982
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1691
1983
|
if (permissionChecker2.cannot.read()) {
|
1692
1984
|
return ctx.forbidden();
|
1693
1985
|
}
|
1694
1986
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1695
|
-
const populate = await getService$
|
1696
|
-
const { locale, status
|
1987
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1988
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1697
1989
|
const version = await documentManager2.findOne(id, model, {
|
1698
1990
|
populate,
|
1699
1991
|
locale,
|
@@ -1704,9 +1996,11 @@ const collectionTypes = {
|
|
1704
1996
|
if (!exists) {
|
1705
1997
|
return ctx.notFound();
|
1706
1998
|
}
|
1707
|
-
const { meta } = await
|
1999
|
+
const { meta } = await formatDocumentWithMetadata(
|
2000
|
+
permissionChecker2,
|
1708
2001
|
model,
|
1709
|
-
|
2002
|
+
// @ts-expect-error TODO: fix
|
2003
|
+
{ documentId: id, locale, publishedAt: null },
|
1710
2004
|
{ availableLocales: true, availableStatus: false }
|
1711
2005
|
);
|
1712
2006
|
ctx.body = { data: {}, meta };
|
@@ -1716,20 +2010,19 @@ const collectionTypes = {
|
|
1716
2010
|
return ctx.forbidden();
|
1717
2011
|
}
|
1718
2012
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1719
|
-
ctx.body = await
|
2013
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1720
2014
|
},
|
1721
2015
|
async create(ctx) {
|
1722
2016
|
const { userAbility } = ctx.state;
|
1723
2017
|
const { model } = ctx.params;
|
1724
|
-
const
|
1725
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2018
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1726
2019
|
const [totalEntries, document] = await Promise.all([
|
1727
2020
|
strapi.db.query(model).count(),
|
1728
2021
|
createDocument(ctx)
|
1729
2022
|
]);
|
1730
2023
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1731
2024
|
ctx.status = 201;
|
1732
|
-
ctx.body = await
|
2025
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1733
2026
|
// Empty metadata as it's not relevant for a new document
|
1734
2027
|
availableLocales: false,
|
1735
2028
|
availableStatus: false
|
@@ -1743,25 +2036,23 @@ const collectionTypes = {
|
|
1743
2036
|
async update(ctx) {
|
1744
2037
|
const { userAbility } = ctx.state;
|
1745
2038
|
const { model } = ctx.params;
|
1746
|
-
const
|
1747
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2039
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1748
2040
|
const updatedVersion = await updateDocument(ctx);
|
1749
2041
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1750
|
-
ctx.body = await
|
2042
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1751
2043
|
},
|
1752
2044
|
async clone(ctx) {
|
1753
2045
|
const { userAbility, user } = ctx.state;
|
1754
2046
|
const { model, sourceId: id } = ctx.params;
|
1755
2047
|
const { body } = ctx.request;
|
1756
|
-
const documentManager2 = getService$
|
1757
|
-
const
|
1758
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2048
|
+
const documentManager2 = getService$2("document-manager");
|
2049
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1759
2050
|
if (permissionChecker2.cannot.create()) {
|
1760
2051
|
return ctx.forbidden();
|
1761
2052
|
}
|
1762
2053
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1763
|
-
const populate = await getService$
|
1764
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2054
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2055
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1765
2056
|
const document = await documentManager2.findOne(id, model, {
|
1766
2057
|
populate,
|
1767
2058
|
locale,
|
@@ -1777,7 +2068,7 @@ const collectionTypes = {
|
|
1777
2068
|
const sanitizedBody = await sanitizeFn(body);
|
1778
2069
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1779
2070
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1780
|
-
ctx.body = await
|
2071
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1781
2072
|
// Empty metadata as it's not relevant for a new document
|
1782
2073
|
availableLocales: false,
|
1783
2074
|
availableStatus: false
|
@@ -1799,14 +2090,14 @@ const collectionTypes = {
|
|
1799
2090
|
async delete(ctx) {
|
1800
2091
|
const { userAbility } = ctx.state;
|
1801
2092
|
const { id, model } = ctx.params;
|
1802
|
-
const documentManager2 = getService$
|
1803
|
-
const permissionChecker2 = getService$
|
2093
|
+
const documentManager2 = getService$2("document-manager");
|
2094
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1804
2095
|
if (permissionChecker2.cannot.delete()) {
|
1805
2096
|
return ctx.forbidden();
|
1806
2097
|
}
|
1807
2098
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1808
|
-
const populate = await getService$
|
1809
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
2099
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2100
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1810
2101
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1811
2102
|
if (documentLocales.length === 0) {
|
1812
2103
|
return ctx.notFound();
|
@@ -1827,44 +2118,75 @@ const collectionTypes = {
|
|
1827
2118
|
const { userAbility } = ctx.state;
|
1828
2119
|
const { id, model } = ctx.params;
|
1829
2120
|
const { body } = ctx.request;
|
1830
|
-
const documentManager2 = getService$
|
1831
|
-
const
|
1832
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2121
|
+
const documentManager2 = getService$2("document-manager");
|
2122
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1833
2123
|
if (permissionChecker2.cannot.publish()) {
|
1834
2124
|
return ctx.forbidden();
|
1835
2125
|
}
|
1836
2126
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1837
2127
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1838
|
-
const populate = await getService$
|
1839
|
-
|
2128
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2129
|
+
let document;
|
2130
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2131
|
+
const isCreate = fp.isNil(id);
|
2132
|
+
if (isCreate) {
|
2133
|
+
if (permissionChecker2.cannot.create()) {
|
2134
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2135
|
+
}
|
2136
|
+
document = await createDocument(ctx, { populate });
|
2137
|
+
}
|
2138
|
+
const isUpdate = !isCreate;
|
2139
|
+
if (isUpdate) {
|
2140
|
+
const documentExists = documentManager2.exists(model, id);
|
2141
|
+
if (!documentExists) {
|
2142
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
2143
|
+
}
|
2144
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2145
|
+
if (!document) {
|
2146
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2147
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2148
|
+
}
|
2149
|
+
document = await updateDocument(ctx);
|
2150
|
+
} else if (permissionChecker2.can.update(document)) {
|
2151
|
+
await updateDocument(ctx);
|
2152
|
+
}
|
2153
|
+
}
|
1840
2154
|
if (permissionChecker2.cannot.publish(document)) {
|
1841
2155
|
throw new strapiUtils.errors.ForbiddenError();
|
1842
2156
|
}
|
1843
|
-
const
|
1844
|
-
return documentManager2.publish(document.documentId, model, {
|
2157
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1845
2158
|
locale
|
1846
2159
|
// TODO: Allow setting creator fields on publish
|
1847
2160
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1848
2161
|
});
|
2162
|
+
if (!publishResult || publishResult.length === 0) {
|
2163
|
+
throw new strapiUtils.errors.NotFoundError("Document not found or already published.");
|
2164
|
+
}
|
2165
|
+
return publishResult[0];
|
1849
2166
|
});
|
1850
2167
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1851
|
-
ctx.body = await
|
2168
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1852
2169
|
},
|
1853
2170
|
async bulkPublish(ctx) {
|
1854
2171
|
const { userAbility } = ctx.state;
|
1855
2172
|
const { model } = ctx.params;
|
1856
2173
|
const { body } = ctx.request;
|
1857
|
-
const {
|
2174
|
+
const { documentIds } = body;
|
1858
2175
|
await validateBulkActionInput(body);
|
1859
|
-
const documentManager2 = getService$
|
1860
|
-
const permissionChecker2 = getService$
|
2176
|
+
const documentManager2 = getService$2("document-manager");
|
2177
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1861
2178
|
if (permissionChecker2.cannot.publish()) {
|
1862
2179
|
return ctx.forbidden();
|
1863
2180
|
}
|
1864
2181
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1865
|
-
const populate = await getService$
|
1866
|
-
const
|
1867
|
-
|
2182
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2183
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2184
|
+
allowMultipleLocales: true
|
2185
|
+
});
|
2186
|
+
const entityPromises = documentIds.map(
|
2187
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
2188
|
+
);
|
2189
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1868
2190
|
for (const entity of entities) {
|
1869
2191
|
if (!entity) {
|
1870
2192
|
return ctx.notFound();
|
@@ -1873,24 +2195,27 @@ const collectionTypes = {
|
|
1873
2195
|
return ctx.forbidden();
|
1874
2196
|
}
|
1875
2197
|
}
|
1876
|
-
const
|
2198
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1877
2199
|
ctx.body = { count };
|
1878
2200
|
},
|
1879
2201
|
async bulkUnpublish(ctx) {
|
1880
2202
|
const { userAbility } = ctx.state;
|
1881
2203
|
const { model } = ctx.params;
|
1882
2204
|
const { body } = ctx.request;
|
1883
|
-
const {
|
2205
|
+
const { documentIds } = body;
|
1884
2206
|
await validateBulkActionInput(body);
|
1885
|
-
const documentManager2 = getService$
|
1886
|
-
const permissionChecker2 = getService$
|
2207
|
+
const documentManager2 = getService$2("document-manager");
|
2208
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1887
2209
|
if (permissionChecker2.cannot.unpublish()) {
|
1888
2210
|
return ctx.forbidden();
|
1889
2211
|
}
|
1890
|
-
const
|
1891
|
-
|
1892
|
-
|
1893
|
-
const
|
2212
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2213
|
+
allowMultipleLocales: true
|
2214
|
+
});
|
2215
|
+
const entityPromises = documentIds.map(
|
2216
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
2217
|
+
);
|
2218
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1894
2219
|
for (const entity of entities) {
|
1895
2220
|
if (!entity) {
|
1896
2221
|
return ctx.notFound();
|
@@ -1899,7 +2224,8 @@ const collectionTypes = {
|
|
1899
2224
|
return ctx.forbidden();
|
1900
2225
|
}
|
1901
2226
|
}
|
1902
|
-
const
|
2227
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
2228
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1903
2229
|
ctx.body = { count };
|
1904
2230
|
},
|
1905
2231
|
async unpublish(ctx) {
|
@@ -1908,9 +2234,8 @@ const collectionTypes = {
|
|
1908
2234
|
const {
|
1909
2235
|
body: { discardDraft, ...body }
|
1910
2236
|
} = ctx.request;
|
1911
|
-
const documentManager2 = getService$
|
1912
|
-
const
|
1913
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2237
|
+
const documentManager2 = getService$2("document-manager");
|
2238
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1914
2239
|
if (permissionChecker2.cannot.unpublish()) {
|
1915
2240
|
return ctx.forbidden();
|
1916
2241
|
}
|
@@ -1918,8 +2243,8 @@ const collectionTypes = {
|
|
1918
2243
|
return ctx.forbidden();
|
1919
2244
|
}
|
1920
2245
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1921
|
-
const populate = await getService$
|
1922
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2246
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2247
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1923
2248
|
const document = await documentManager2.findOne(id, model, {
|
1924
2249
|
populate,
|
1925
2250
|
locale,
|
@@ -1941,7 +2266,7 @@ const collectionTypes = {
|
|
1941
2266
|
ctx.body = await strapiUtils.async.pipe(
|
1942
2267
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1943
2268
|
permissionChecker2.sanitizeOutput,
|
1944
|
-
(document2) =>
|
2269
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1945
2270
|
)(document);
|
1946
2271
|
});
|
1947
2272
|
},
|
@@ -1949,15 +2274,14 @@ const collectionTypes = {
|
|
1949
2274
|
const { userAbility } = ctx.state;
|
1950
2275
|
const { id, model } = ctx.params;
|
1951
2276
|
const { body } = ctx.request;
|
1952
|
-
const documentManager2 = getService$
|
1953
|
-
const
|
1954
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2277
|
+
const documentManager2 = getService$2("document-manager");
|
2278
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1955
2279
|
if (permissionChecker2.cannot.discard()) {
|
1956
2280
|
return ctx.forbidden();
|
1957
2281
|
}
|
1958
2282
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1959
|
-
const populate = await getService$
|
1960
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2283
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2284
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1961
2285
|
const document = await documentManager2.findOne(id, model, {
|
1962
2286
|
populate,
|
1963
2287
|
locale,
|
@@ -1972,42 +2296,50 @@ const collectionTypes = {
|
|
1972
2296
|
ctx.body = await strapiUtils.async.pipe(
|
1973
2297
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1974
2298
|
permissionChecker2.sanitizeOutput,
|
1975
|
-
(document2) =>
|
2299
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1976
2300
|
)(document);
|
1977
2301
|
},
|
1978
2302
|
async bulkDelete(ctx) {
|
1979
2303
|
const { userAbility } = ctx.state;
|
1980
2304
|
const { model } = ctx.params;
|
1981
2305
|
const { query, body } = ctx.request;
|
1982
|
-
const {
|
2306
|
+
const { documentIds } = body;
|
1983
2307
|
await validateBulkActionInput(body);
|
1984
|
-
const documentManager2 = getService$
|
1985
|
-
const permissionChecker2 = getService$
|
2308
|
+
const documentManager2 = getService$2("document-manager");
|
2309
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1986
2310
|
if (permissionChecker2.cannot.delete()) {
|
1987
2311
|
return ctx.forbidden();
|
1988
2312
|
}
|
1989
2313
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1990
|
-
const
|
1991
|
-
const
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
2314
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2315
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2316
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2317
|
+
populate,
|
2318
|
+
locale
|
2319
|
+
});
|
2320
|
+
if (documentLocales.length === 0) {
|
2321
|
+
return ctx.notFound();
|
2322
|
+
}
|
2323
|
+
for (const document of documentLocales) {
|
2324
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2325
|
+
return ctx.forbidden();
|
1995
2326
|
}
|
1996
|
-
}
|
1997
|
-
const
|
2327
|
+
}
|
2328
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2329
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1998
2330
|
ctx.body = { count };
|
1999
2331
|
},
|
2000
2332
|
async countDraftRelations(ctx) {
|
2001
2333
|
const { userAbility } = ctx.state;
|
2002
2334
|
const { model, id } = ctx.params;
|
2003
|
-
const documentManager2 = getService$
|
2004
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2005
2337
|
if (permissionChecker2.cannot.read()) {
|
2006
2338
|
return ctx.forbidden();
|
2007
2339
|
}
|
2008
2340
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2009
|
-
const populate = await getService$
|
2010
|
-
const { locale, status
|
2341
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2342
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2011
2343
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2012
2344
|
if (!entity) {
|
2013
2345
|
return ctx.notFound();
|
@@ -2022,24 +2354,24 @@ const collectionTypes = {
|
|
2022
2354
|
},
|
2023
2355
|
async countManyEntriesDraftRelations(ctx) {
|
2024
2356
|
const { userAbility } = ctx.state;
|
2025
|
-
const ids = ctx.request.query.
|
2357
|
+
const ids = ctx.request.query.documentIds;
|
2026
2358
|
const locale = ctx.request.query.locale;
|
2027
2359
|
const { model } = ctx.params;
|
2028
|
-
const documentManager2 = getService$
|
2029
|
-
const permissionChecker2 = getService$
|
2360
|
+
const documentManager2 = getService$2("document-manager");
|
2361
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2030
2362
|
if (permissionChecker2.cannot.read()) {
|
2031
2363
|
return ctx.forbidden();
|
2032
2364
|
}
|
2033
|
-
const
|
2365
|
+
const documents = await documentManager2.findMany(
|
2034
2366
|
{
|
2035
2367
|
filters: {
|
2036
|
-
|
2368
|
+
documentId: ids
|
2037
2369
|
},
|
2038
2370
|
locale
|
2039
2371
|
},
|
2040
2372
|
model
|
2041
2373
|
);
|
2042
|
-
if (!
|
2374
|
+
if (!documents) {
|
2043
2375
|
return ctx.notFound();
|
2044
2376
|
}
|
2045
2377
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2050,13 +2382,13 @@ const collectionTypes = {
|
|
2050
2382
|
};
|
2051
2383
|
const components$1 = {
|
2052
2384
|
findComponents(ctx) {
|
2053
|
-
const components2 = getService$
|
2054
|
-
const { toDto } = getService$
|
2385
|
+
const components2 = getService$2("components").findAllComponents();
|
2386
|
+
const { toDto } = getService$2("data-mapper");
|
2055
2387
|
ctx.body = { data: components2.map(toDto) };
|
2056
2388
|
},
|
2057
2389
|
async findComponentConfiguration(ctx) {
|
2058
2390
|
const { uid: uid2 } = ctx.params;
|
2059
|
-
const componentService = getService$
|
2391
|
+
const componentService = getService$2("components");
|
2060
2392
|
const component = componentService.findComponent(uid2);
|
2061
2393
|
if (!component) {
|
2062
2394
|
return ctx.notFound("component.notFound");
|
@@ -2073,7 +2405,7 @@ const components$1 = {
|
|
2073
2405
|
async updateComponentConfiguration(ctx) {
|
2074
2406
|
const { uid: uid2 } = ctx.params;
|
2075
2407
|
const { body } = ctx.request;
|
2076
|
-
const componentService = getService$
|
2408
|
+
const componentService = getService$2("components");
|
2077
2409
|
const component = componentService.findComponent(uid2);
|
2078
2410
|
if (!component) {
|
2079
2411
|
return ctx.notFound("component.notFound");
|
@@ -2107,12 +2439,12 @@ const contentTypes = {
|
|
2107
2439
|
} catch (error) {
|
2108
2440
|
return ctx.send({ error }, 400);
|
2109
2441
|
}
|
2110
|
-
const contentTypes2 = getService$
|
2111
|
-
const { toDto } = getService$
|
2442
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2443
|
+
const { toDto } = getService$2("data-mapper");
|
2112
2444
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2113
2445
|
},
|
2114
2446
|
async findContentTypesSettings(ctx) {
|
2115
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2447
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2116
2448
|
const contentTypes2 = await findAllContentTypes();
|
2117
2449
|
const configurations = await Promise.all(
|
2118
2450
|
contentTypes2.map(async (contentType) => {
|
@@ -2126,7 +2458,7 @@ const contentTypes = {
|
|
2126
2458
|
},
|
2127
2459
|
async findContentTypeConfiguration(ctx) {
|
2128
2460
|
const { uid: uid2 } = ctx.params;
|
2129
|
-
const contentTypeService = getService$
|
2461
|
+
const contentTypeService = getService$2("content-types");
|
2130
2462
|
const contentType = await contentTypeService.findContentType(uid2);
|
2131
2463
|
if (!contentType) {
|
2132
2464
|
return ctx.notFound("contentType.notFound");
|
@@ -2148,13 +2480,13 @@ const contentTypes = {
|
|
2148
2480
|
const { userAbility } = ctx.state;
|
2149
2481
|
const { uid: uid2 } = ctx.params;
|
2150
2482
|
const { body } = ctx.request;
|
2151
|
-
const contentTypeService = getService$
|
2152
|
-
const metricsService = getService$
|
2483
|
+
const contentTypeService = getService$2("content-types");
|
2484
|
+
const metricsService = getService$2("metrics");
|
2153
2485
|
const contentType = await contentTypeService.findContentType(uid2);
|
2154
2486
|
if (!contentType) {
|
2155
2487
|
return ctx.notFound("contentType.notFound");
|
2156
2488
|
}
|
2157
|
-
if (!getService$
|
2489
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2158
2490
|
return ctx.forbidden();
|
2159
2491
|
}
|
2160
2492
|
let input;
|
@@ -2187,10 +2519,10 @@ const contentTypes = {
|
|
2187
2519
|
};
|
2188
2520
|
const init = {
|
2189
2521
|
getInitData(ctx) {
|
2190
|
-
const { toDto } = getService$
|
2191
|
-
const { findAllComponents } = getService$
|
2192
|
-
const { getAllFieldSizes } = getService$
|
2193
|
-
const { findAllContentTypes } = getService$
|
2522
|
+
const { toDto } = getService$2("data-mapper");
|
2523
|
+
const { findAllComponents } = getService$2("components");
|
2524
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2525
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2194
2526
|
ctx.body = {
|
2195
2527
|
data: {
|
2196
2528
|
fieldSizes: getAllFieldSizes(),
|
@@ -2226,36 +2558,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2226
2558
|
params.filters.$and.push(filtersClause);
|
2227
2559
|
};
|
2228
2560
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2229
|
-
const permissionChecker2 = getService$
|
2561
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2230
2562
|
userAbility,
|
2231
2563
|
model: model.uid
|
2232
2564
|
});
|
2233
|
-
|
2565
|
+
const isMainFieldListable = isListable(model, mainField);
|
2566
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2567
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2234
2568
|
return "id";
|
2235
2569
|
}
|
2236
|
-
if (
|
2237
|
-
|
2238
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2239
|
-
userAbility,
|
2240
|
-
model: "plugin::users-permissions.user"
|
2241
|
-
});
|
2242
|
-
if (userPermissionChecker.can.read()) {
|
2243
|
-
return "name";
|
2244
|
-
}
|
2245
|
-
}
|
2246
|
-
return "id";
|
2570
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2571
|
+
return "name";
|
2247
2572
|
}
|
2248
2573
|
return mainField;
|
2249
2574
|
};
|
2250
|
-
const addStatusToRelations = async (
|
2251
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2575
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2576
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2577
|
+
return relations2;
|
2578
|
+
}
|
2579
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2580
|
+
if (!relations2.length) {
|
2252
2581
|
return relations2;
|
2253
2582
|
}
|
2254
|
-
const
|
2255
|
-
const
|
2583
|
+
const firstRelation = relations2[0];
|
2584
|
+
const filters = {
|
2585
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2586
|
+
// NOTE: find the "opposite" status
|
2587
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2588
|
+
};
|
2589
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2590
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2591
|
+
filters
|
2592
|
+
});
|
2256
2593
|
return relations2.map((relation) => {
|
2257
|
-
const availableStatuses =
|
2258
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2594
|
+
const availableStatuses = availableStatus.filter(
|
2595
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2259
2596
|
);
|
2260
2597
|
return {
|
2261
2598
|
...relation,
|
@@ -2276,11 +2613,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2276
2613
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2277
2614
|
const isSourceLocalized = isLocalized(sourceModel);
|
2278
2615
|
const isTargetLocalized = isLocalized(targetModel);
|
2279
|
-
let validatedLocale = locale;
|
2280
|
-
if (!targetModel || !isTargetLocalized)
|
2281
|
-
validatedLocale = void 0;
|
2282
2616
|
return {
|
2283
|
-
locale
|
2617
|
+
locale,
|
2284
2618
|
isSourceLocalized,
|
2285
2619
|
isTargetLocalized
|
2286
2620
|
};
|
@@ -2289,8 +2623,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2289
2623
|
const sourceModel = strapi.getModel(sourceUid);
|
2290
2624
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2291
2625
|
const isSourceDP = isDP(sourceModel);
|
2292
|
-
if (!isSourceDP)
|
2293
|
-
return { status: void 0 };
|
2626
|
+
if (!isSourceDP) return { status: void 0 };
|
2294
2627
|
switch (status) {
|
2295
2628
|
case "published":
|
2296
2629
|
return { status: "published" };
|
@@ -2320,7 +2653,7 @@ const relations = {
|
|
2320
2653
|
ctx.request?.query?.locale
|
2321
2654
|
);
|
2322
2655
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2323
|
-
const permissionChecker2 = getService$
|
2656
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2324
2657
|
userAbility,
|
2325
2658
|
model
|
2326
2659
|
});
|
@@ -2345,7 +2678,7 @@ const relations = {
|
|
2345
2678
|
where.id = id;
|
2346
2679
|
}
|
2347
2680
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2348
|
-
const populate = await getService$
|
2681
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2349
2682
|
const currentEntity = await strapi.db.query(model).findOne({
|
2350
2683
|
where,
|
2351
2684
|
populate
|
@@ -2360,7 +2693,7 @@ const relations = {
|
|
2360
2693
|
}
|
2361
2694
|
entryId = currentEntity.id;
|
2362
2695
|
}
|
2363
|
-
const modelConfig = isComponent2 ? await getService$
|
2696
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2364
2697
|
const targetSchema = strapi.getModel(targetUid);
|
2365
2698
|
const mainField = fp.flow(
|
2366
2699
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2383,7 +2716,7 @@ const relations = {
|
|
2383
2716
|
attribute,
|
2384
2717
|
fieldsToSelect,
|
2385
2718
|
mainField,
|
2386
|
-
source: { schema: sourceSchema },
|
2719
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2387
2720
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2388
2721
|
sourceSchema,
|
2389
2722
|
targetSchema,
|
@@ -2405,7 +2738,8 @@ const relations = {
|
|
2405
2738
|
fieldsToSelect,
|
2406
2739
|
mainField,
|
2407
2740
|
source: {
|
2408
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2741
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2742
|
+
isLocalized: isSourceLocalized
|
2409
2743
|
},
|
2410
2744
|
target: {
|
2411
2745
|
schema: { uid: targetUid },
|
@@ -2413,7 +2747,7 @@ const relations = {
|
|
2413
2747
|
}
|
2414
2748
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2415
2749
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2416
|
-
const permissionChecker2 = getService$
|
2750
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2417
2751
|
userAbility: ctx.state.userAbility,
|
2418
2752
|
model: targetUid
|
2419
2753
|
});
|
@@ -2443,12 +2777,16 @@ const relations = {
|
|
2443
2777
|
} else {
|
2444
2778
|
where.id = id;
|
2445
2779
|
}
|
2446
|
-
|
2447
|
-
|
2780
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2781
|
+
if (!fp.isEmpty(publishedAt)) {
|
2782
|
+
where[`${alias}.published_at`] = publishedAt;
|
2448
2783
|
}
|
2449
|
-
if (
|
2784
|
+
if (isTargetLocalized && locale) {
|
2450
2785
|
where[`${alias}.locale`] = locale;
|
2451
2786
|
}
|
2787
|
+
if (isSourceLocalized && locale) {
|
2788
|
+
where.locale = locale;
|
2789
|
+
}
|
2452
2790
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2453
2791
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2454
2792
|
}
|
@@ -2466,7 +2804,8 @@ const relations = {
|
|
2466
2804
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2467
2805
|
});
|
2468
2806
|
}
|
2469
|
-
const
|
2807
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2808
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2470
2809
|
ctx.body = {
|
2471
2810
|
...res,
|
2472
2811
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2481,29 +2820,39 @@ const relations = {
|
|
2481
2820
|
attribute,
|
2482
2821
|
targetField,
|
2483
2822
|
fieldsToSelect,
|
2484
|
-
|
2485
|
-
|
2486
|
-
}
|
2487
|
-
target: {
|
2488
|
-
schema: { uid: targetUid }
|
2489
|
-
}
|
2823
|
+
status,
|
2824
|
+
source: { schema: sourceSchema },
|
2825
|
+
target: { schema: targetSchema }
|
2490
2826
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2491
|
-
const
|
2827
|
+
const { uid: sourceUid } = sourceSchema;
|
2828
|
+
const { uid: targetUid } = targetSchema;
|
2829
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2492
2830
|
const dbQuery = strapi.db.query(sourceUid);
|
2493
2831
|
const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2832
|
+
const filters = {};
|
2833
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2834
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2835
|
+
if (status === "published") {
|
2836
|
+
filters.publishedAt = { $notNull: true };
|
2837
|
+
} else {
|
2838
|
+
filters.publishedAt = { $null: true };
|
2839
|
+
}
|
2840
|
+
}
|
2841
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2842
|
+
filters.publishedAt = { $null: true };
|
2843
|
+
}
|
2494
2844
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2495
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2845
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2496
2846
|
ordering: "desc",
|
2497
2847
|
page: ctx.request.query.page,
|
2498
|
-
pageSize: ctx.request.query.pageSize
|
2848
|
+
pageSize: ctx.request.query.pageSize,
|
2849
|
+
filters
|
2499
2850
|
});
|
2500
2851
|
const loadedIds = res.results.map((item) => item.id);
|
2501
2852
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2502
2853
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2503
2854
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2504
|
-
ordering: "desc"
|
2505
|
-
page: ctx.request.query.page,
|
2506
|
-
pageSize: ctx.request.query.pageSize
|
2855
|
+
ordering: "desc"
|
2507
2856
|
});
|
2508
2857
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2509
2858
|
ctx.body = {
|
@@ -2518,10 +2867,10 @@ const relations = {
|
|
2518
2867
|
}
|
2519
2868
|
};
|
2520
2869
|
const buildPopulateFromQuery = async (query, model) => {
|
2521
|
-
return getService$
|
2870
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2522
2871
|
};
|
2523
2872
|
const findDocument = async (query, uid2, opts = {}) => {
|
2524
|
-
const documentManager2 = getService$
|
2873
|
+
const documentManager2 = getService$2("document-manager");
|
2525
2874
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2526
2875
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2527
2876
|
};
|
@@ -2529,13 +2878,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2529
2878
|
const { user, userAbility } = ctx.state;
|
2530
2879
|
const { model } = ctx.params;
|
2531
2880
|
const { body, query } = ctx.request;
|
2532
|
-
const documentManager2 = getService$
|
2533
|
-
const permissionChecker2 = getService$
|
2881
|
+
const documentManager2 = getService$2("document-manager");
|
2882
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2534
2883
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2535
2884
|
throw new strapiUtils.errors.ForbiddenError();
|
2536
2885
|
}
|
2537
2886
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2538
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2887
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2539
2888
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2540
2889
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2541
2890
|
// Find the first document to check if it exists
|
@@ -2571,13 +2920,12 @@ const singleTypes = {
|
|
2571
2920
|
const { userAbility } = ctx.state;
|
2572
2921
|
const { model } = ctx.params;
|
2573
2922
|
const { query = {} } = ctx.request;
|
2574
|
-
const permissionChecker2 = getService$
|
2575
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2923
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2576
2924
|
if (permissionChecker2.cannot.read()) {
|
2577
2925
|
return ctx.forbidden();
|
2578
2926
|
}
|
2579
2927
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2580
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2928
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2581
2929
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2582
2930
|
if (!version) {
|
2583
2931
|
if (permissionChecker2.cannot.create()) {
|
@@ -2587,9 +2935,11 @@ const singleTypes = {
|
|
2587
2935
|
if (!document) {
|
2588
2936
|
return ctx.notFound();
|
2589
2937
|
}
|
2590
|
-
const { meta } = await
|
2938
|
+
const { meta } = await formatDocumentWithMetadata(
|
2939
|
+
permissionChecker2,
|
2591
2940
|
model,
|
2592
|
-
|
2941
|
+
// @ts-expect-error - fix types
|
2942
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2593
2943
|
{ availableLocales: true, availableStatus: false }
|
2594
2944
|
);
|
2595
2945
|
ctx.body = { data: {}, meta };
|
@@ -2599,29 +2949,28 @@ const singleTypes = {
|
|
2599
2949
|
return ctx.forbidden();
|
2600
2950
|
}
|
2601
2951
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2602
|
-
ctx.body = await
|
2952
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2603
2953
|
},
|
2604
2954
|
async createOrUpdate(ctx) {
|
2605
2955
|
const { userAbility } = ctx.state;
|
2606
2956
|
const { model } = ctx.params;
|
2607
|
-
const
|
2608
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2609
2958
|
const document = await createOrUpdateDocument(ctx);
|
2610
2959
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2611
|
-
ctx.body = await
|
2960
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2612
2961
|
},
|
2613
2962
|
async delete(ctx) {
|
2614
2963
|
const { userAbility } = ctx.state;
|
2615
2964
|
const { model } = ctx.params;
|
2616
2965
|
const { query = {} } = ctx.request;
|
2617
|
-
const documentManager2 = getService$
|
2618
|
-
const permissionChecker2 = getService$
|
2966
|
+
const documentManager2 = getService$2("document-manager");
|
2967
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2619
2968
|
if (permissionChecker2.cannot.delete()) {
|
2620
2969
|
return ctx.forbidden();
|
2621
2970
|
}
|
2622
2971
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2623
2972
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2624
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2973
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2625
2974
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2626
2975
|
populate,
|
2627
2976
|
locale
|
@@ -2643,9 +2992,8 @@ const singleTypes = {
|
|
2643
2992
|
const { userAbility } = ctx.state;
|
2644
2993
|
const { model } = ctx.params;
|
2645
2994
|
const { query = {} } = ctx.request;
|
2646
|
-
const documentManager2 = getService$
|
2647
|
-
const
|
2648
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2995
|
+
const documentManager2 = getService$2("document-manager");
|
2996
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2649
2997
|
if (permissionChecker2.cannot.publish()) {
|
2650
2998
|
return ctx.forbidden();
|
2651
2999
|
}
|
@@ -2659,11 +3007,12 @@ const singleTypes = {
|
|
2659
3007
|
if (permissionChecker2.cannot.publish(document)) {
|
2660
3008
|
throw new strapiUtils.errors.ForbiddenError();
|
2661
3009
|
}
|
2662
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2663
|
-
|
3010
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
3011
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
3012
|
+
return publishResult.at(0);
|
2664
3013
|
});
|
2665
3014
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2666
|
-
ctx.body = await
|
3015
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2667
3016
|
},
|
2668
3017
|
async unpublish(ctx) {
|
2669
3018
|
const { userAbility } = ctx.state;
|
@@ -2672,9 +3021,8 @@ const singleTypes = {
|
|
2672
3021
|
body: { discardDraft, ...body },
|
2673
3022
|
query = {}
|
2674
3023
|
} = ctx.request;
|
2675
|
-
const documentManager2 = getService$
|
2676
|
-
const
|
2677
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
3024
|
+
const documentManager2 = getService$2("document-manager");
|
3025
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2678
3026
|
if (permissionChecker2.cannot.unpublish()) {
|
2679
3027
|
return ctx.forbidden();
|
2680
3028
|
}
|
@@ -2682,7 +3030,7 @@ const singleTypes = {
|
|
2682
3030
|
return ctx.forbidden();
|
2683
3031
|
}
|
2684
3032
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2685
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3033
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2686
3034
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2687
3035
|
if (!document) {
|
2688
3036
|
return ctx.notFound();
|
@@ -2700,7 +3048,7 @@ const singleTypes = {
|
|
2700
3048
|
ctx.body = await strapiUtils.async.pipe(
|
2701
3049
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2702
3050
|
permissionChecker2.sanitizeOutput,
|
2703
|
-
(document2) =>
|
3051
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2704
3052
|
)(document);
|
2705
3053
|
});
|
2706
3054
|
},
|
@@ -2708,14 +3056,13 @@ const singleTypes = {
|
|
2708
3056
|
const { userAbility } = ctx.state;
|
2709
3057
|
const { model } = ctx.params;
|
2710
3058
|
const { body, query = {} } = ctx.request;
|
2711
|
-
const documentManager2 = getService$
|
2712
|
-
const
|
2713
|
-
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
3059
|
+
const documentManager2 = getService$2("document-manager");
|
3060
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2714
3061
|
if (permissionChecker2.cannot.discard()) {
|
2715
3062
|
return ctx.forbidden();
|
2716
3063
|
}
|
2717
3064
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2718
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
3065
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2719
3066
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2720
3067
|
if (!document) {
|
2721
3068
|
return ctx.notFound();
|
@@ -2726,16 +3073,16 @@ const singleTypes = {
|
|
2726
3073
|
ctx.body = await strapiUtils.async.pipe(
|
2727
3074
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2728
3075
|
permissionChecker2.sanitizeOutput,
|
2729
|
-
(document2) =>
|
3076
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2730
3077
|
)(document);
|
2731
3078
|
},
|
2732
3079
|
async countDraftRelations(ctx) {
|
2733
3080
|
const { userAbility } = ctx.state;
|
2734
3081
|
const { model } = ctx.params;
|
2735
3082
|
const { query } = ctx.request;
|
2736
|
-
const documentManager2 = getService$
|
2737
|
-
const permissionChecker2 = getService$
|
2738
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3083
|
+
const documentManager2 = getService$2("document-manager");
|
3084
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3085
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2739
3086
|
if (permissionChecker2.cannot.read()) {
|
2740
3087
|
return ctx.forbidden();
|
2741
3088
|
}
|
@@ -2756,9 +3103,9 @@ const uid$1 = {
|
|
2756
3103
|
async generateUID(ctx) {
|
2757
3104
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2758
3105
|
const { query = {} } = ctx.request;
|
2759
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3106
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2760
3107
|
await validateUIDField(contentTypeUID, field);
|
2761
|
-
const uidService = getService$
|
3108
|
+
const uidService = getService$2("uid");
|
2762
3109
|
ctx.body = {
|
2763
3110
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2764
3111
|
};
|
@@ -2768,9 +3115,9 @@ const uid$1 = {
|
|
2768
3115
|
ctx.request.body
|
2769
3116
|
);
|
2770
3117
|
const { query = {} } = ctx.request;
|
2771
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
3118
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2772
3119
|
await validateUIDField(contentTypeUID, field);
|
2773
|
-
const uidService = getService$
|
3120
|
+
const uidService = getService$2("uid");
|
2774
3121
|
const isAvailable = await uidService.checkUIDAvailability({
|
2775
3122
|
contentTypeUID,
|
2776
3123
|
field,
|
@@ -2791,7 +3138,8 @@ const controllers = {
|
|
2791
3138
|
relations,
|
2792
3139
|
"single-types": singleTypes,
|
2793
3140
|
uid: uid$1,
|
2794
|
-
...history.controllers ? history.controllers : {}
|
3141
|
+
...history.controllers ? history.controllers : {},
|
3142
|
+
...preview.controllers ? preview.controllers : {}
|
2795
3143
|
};
|
2796
3144
|
const keys = {
|
2797
3145
|
CONFIGURATION: "configuration"
|
@@ -2920,18 +3268,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2920
3268
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2921
3269
|
___default.default.set(acc, [key], updatedMeta);
|
2922
3270
|
}
|
2923
|
-
if (!___default.default.has(edit, "mainField"))
|
2924
|
-
return acc;
|
3271
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2925
3272
|
if (!isRelation$1(attr)) {
|
2926
3273
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2927
3274
|
___default.default.set(acc, [key], updatedMeta);
|
2928
3275
|
return acc;
|
2929
3276
|
}
|
2930
|
-
if (edit.mainField === "id")
|
2931
|
-
return acc;
|
3277
|
+
if (edit.mainField === "id") return acc;
|
2932
3278
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2933
|
-
if (!targetSchema)
|
2934
|
-
return acc;
|
3279
|
+
if (!targetSchema) return acc;
|
2935
3280
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2936
3281
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2937
3282
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -2942,12 +3287,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2942
3287
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
2943
3288
|
}
|
2944
3289
|
const getTargetSchema = (targetModel) => {
|
2945
|
-
return getService$
|
3290
|
+
return getService$2("content-types").findContentType(targetModel);
|
2946
3291
|
};
|
2947
3292
|
const DEFAULT_LIST_LENGTH = 4;
|
2948
3293
|
const MAX_ROW_SIZE = 12;
|
2949
3294
|
const isAllowedFieldSize = (type, size) => {
|
2950
|
-
const { getFieldSize } = getService$
|
3295
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2951
3296
|
const fieldSize = getFieldSize(type);
|
2952
3297
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2953
3298
|
return false;
|
@@ -2955,7 +3300,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2955
3300
|
return size <= MAX_ROW_SIZE;
|
2956
3301
|
};
|
2957
3302
|
const getDefaultFieldSize = (attribute) => {
|
2958
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3303
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2959
3304
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2960
3305
|
};
|
2961
3306
|
async function createDefaultLayouts(schema) {
|
@@ -2976,8 +3321,7 @@ function createDefaultEditLayout(schema) {
|
|
2976
3321
|
return appendToEditLayout([], keys2, schema);
|
2977
3322
|
}
|
2978
3323
|
function syncLayouts(configuration, schema) {
|
2979
|
-
if (___default.default.isEmpty(configuration.layouts))
|
2980
|
-
return createDefaultLayouts(schema);
|
3324
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
2981
3325
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
2982
3326
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
2983
3327
|
const cleanEditRelations = editRelations.filter(
|
@@ -2988,9 +3332,8 @@ function syncLayouts(configuration, schema) {
|
|
2988
3332
|
for (const row of edit) {
|
2989
3333
|
const newRow = [];
|
2990
3334
|
for (const el of row) {
|
2991
|
-
if (!hasEditableAttribute(schema, el.name))
|
2992
|
-
|
2993
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3335
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3336
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
2994
3337
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
2995
3338
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
2996
3339
|
elementsToReAppend.push(el.name);
|
@@ -3020,8 +3363,7 @@ function syncLayouts(configuration, schema) {
|
|
3020
3363
|
};
|
3021
3364
|
}
|
3022
3365
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3023
|
-
if (keysToAppend.length === 0)
|
3024
|
-
return layout;
|
3366
|
+
if (keysToAppend.length === 0) return layout;
|
3025
3367
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3026
3368
|
if (!layout[currentRowIndex]) {
|
3027
3369
|
layout[currentRowIndex] = [];
|
@@ -3130,17 +3472,17 @@ const configurationService$1 = createConfigurationService({
|
|
3130
3472
|
isComponent: true,
|
3131
3473
|
prefix: STORE_KEY_PREFIX,
|
3132
3474
|
getModels() {
|
3133
|
-
const { toContentManagerModel } = getService$
|
3475
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3134
3476
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3135
3477
|
}
|
3136
3478
|
});
|
3137
3479
|
const components = ({ strapi: strapi2 }) => ({
|
3138
3480
|
findAllComponents() {
|
3139
|
-
const { toContentManagerModel } = getService$
|
3481
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3140
3482
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3141
3483
|
},
|
3142
3484
|
findComponent(uid2) {
|
3143
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3144
3486
|
const component = strapi2.components[uid2];
|
3145
3487
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3146
3488
|
},
|
@@ -3191,17 +3533,17 @@ const configurationService = createConfigurationService({
|
|
3191
3533
|
storeUtils,
|
3192
3534
|
prefix: "content_types",
|
3193
3535
|
getModels() {
|
3194
|
-
const { toContentManagerModel } = getService$
|
3536
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3195
3537
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3196
3538
|
}
|
3197
3539
|
});
|
3198
3540
|
const service = ({ strapi: strapi2 }) => ({
|
3199
3541
|
findAllContentTypes() {
|
3200
|
-
const { toContentManagerModel } = getService$
|
3542
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3201
3543
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3202
3544
|
},
|
3203
3545
|
findContentType(uid2) {
|
3204
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3205
3547
|
const contentType = strapi2.contentTypes[uid2];
|
3206
3548
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3207
3549
|
},
|
@@ -3230,7 +3572,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3230
3572
|
return this.findConfiguration(contentType);
|
3231
3573
|
},
|
3232
3574
|
findComponentsConfigurations(contentType) {
|
3233
|
-
return getService$
|
3575
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3234
3576
|
},
|
3235
3577
|
syncConfigurations() {
|
3236
3578
|
return configurationService.syncConfigurations();
|
@@ -3411,12 +3753,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3411
3753
|
ability: userAbility,
|
3412
3754
|
model
|
3413
3755
|
});
|
3414
|
-
const
|
3756
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3757
|
+
const toSubject = (entity) => {
|
3758
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3759
|
+
};
|
3415
3760
|
const can = (action, entity, field) => {
|
3416
|
-
|
3761
|
+
const subject = toSubject(entity);
|
3762
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3763
|
+
return (
|
3764
|
+
// Test the original action to see if it passes
|
3765
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3766
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3767
|
+
);
|
3417
3768
|
};
|
3418
3769
|
const cannot = (action, entity, field) => {
|
3419
|
-
|
3770
|
+
const subject = toSubject(entity);
|
3771
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3772
|
+
return (
|
3773
|
+
// Test both the original action
|
3774
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3775
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3776
|
+
);
|
3420
3777
|
};
|
3421
3778
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3422
3779
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3487,7 +3844,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3487
3844
|
return userAbility.can(action);
|
3488
3845
|
},
|
3489
3846
|
async registerPermissions() {
|
3490
|
-
const displayedContentTypes = getService$
|
3847
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3491
3848
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3492
3849
|
const actions = [
|
3493
3850
|
{
|
@@ -3559,7 +3916,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3559
3916
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3560
3917
|
}
|
3561
3918
|
});
|
3562
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils__default.default.contentTypes;
|
3919
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils__default.default.contentTypes;
|
3563
3920
|
const { isAnyToMany } = strapiUtils__default.default.relations;
|
3564
3921
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils__default.default.contentTypes.constants;
|
3565
3922
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3572,6 +3929,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3572
3929
|
if (initialPopulate) {
|
3573
3930
|
return initialPopulate;
|
3574
3931
|
}
|
3932
|
+
if (attributeName === "localizations") {
|
3933
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3934
|
+
return {
|
3935
|
+
populate: validationPopulate.populate
|
3936
|
+
};
|
3937
|
+
}
|
3575
3938
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3576
3939
|
return true;
|
3577
3940
|
}
|
@@ -3631,6 +3994,9 @@ const getDeepPopulate = (uid2, {
|
|
3631
3994
|
return {};
|
3632
3995
|
}
|
3633
3996
|
const model = strapi.getModel(uid2);
|
3997
|
+
if (!model) {
|
3998
|
+
return {};
|
3999
|
+
}
|
3634
4000
|
return Object.keys(model.attributes).reduce(
|
3635
4001
|
(populateAcc, attributeName) => fp.merge(
|
3636
4002
|
populateAcc,
|
@@ -3650,6 +4016,48 @@ const getDeepPopulate = (uid2, {
|
|
3650
4016
|
{}
|
3651
4017
|
);
|
3652
4018
|
};
|
4019
|
+
const getPopulateForValidation = (uid2) => {
|
4020
|
+
const model = strapi.getModel(uid2);
|
4021
|
+
if (!model) {
|
4022
|
+
return {};
|
4023
|
+
}
|
4024
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
4025
|
+
if (isScalarAttribute(attribute)) {
|
4026
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4027
|
+
populateAcc.fields = populateAcc.fields || [];
|
4028
|
+
populateAcc.fields.push(attributeName);
|
4029
|
+
}
|
4030
|
+
return populateAcc;
|
4031
|
+
}
|
4032
|
+
if (isComponent(attribute)) {
|
4033
|
+
const component = attribute.component;
|
4034
|
+
const componentResult = getPopulateForValidation(component);
|
4035
|
+
if (Object.keys(componentResult).length > 0) {
|
4036
|
+
populateAcc.populate = populateAcc.populate || {};
|
4037
|
+
populateAcc.populate[attributeName] = componentResult;
|
4038
|
+
}
|
4039
|
+
return populateAcc;
|
4040
|
+
}
|
4041
|
+
if (isDynamicZone(attribute)) {
|
4042
|
+
const components2 = attribute.components;
|
4043
|
+
const componentsResult = (components2 || []).reduce(
|
4044
|
+
(acc, componentUID) => {
|
4045
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4046
|
+
if (Object.keys(componentResult).length > 0) {
|
4047
|
+
acc[componentUID] = componentResult;
|
4048
|
+
}
|
4049
|
+
return acc;
|
4050
|
+
},
|
4051
|
+
{}
|
4052
|
+
);
|
4053
|
+
if (Object.keys(componentsResult).length > 0) {
|
4054
|
+
populateAcc.populate = populateAcc.populate || {};
|
4055
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4056
|
+
}
|
4057
|
+
}
|
4058
|
+
return populateAcc;
|
4059
|
+
}, {});
|
4060
|
+
};
|
3653
4061
|
const getDeepPopulateDraftCount = (uid2) => {
|
3654
4062
|
const model = strapi.getModel(uid2);
|
3655
4063
|
let hasRelations = false;
|
@@ -3657,6 +4065,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3657
4065
|
const attribute = model.attributes[attributeName];
|
3658
4066
|
switch (attribute.type) {
|
3659
4067
|
case "relation": {
|
4068
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4069
|
+
if (isMorphRelation) {
|
4070
|
+
break;
|
4071
|
+
}
|
3660
4072
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3661
4073
|
populateAcc[attributeName] = {
|
3662
4074
|
count: true,
|
@@ -3671,22 +4083,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3671
4083
|
attribute.component
|
3672
4084
|
);
|
3673
4085
|
if (childHasRelations) {
|
3674
|
-
populateAcc[attributeName] = {
|
4086
|
+
populateAcc[attributeName] = {
|
4087
|
+
populate: populate2
|
4088
|
+
};
|
3675
4089
|
hasRelations = true;
|
3676
4090
|
}
|
3677
4091
|
break;
|
3678
4092
|
}
|
3679
4093
|
case "dynamiczone": {
|
3680
|
-
const
|
3681
|
-
const { populate:
|
3682
|
-
if (
|
4094
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
4095
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
4096
|
+
if (componentHasRelations) {
|
3683
4097
|
hasRelations = true;
|
3684
|
-
return
|
4098
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3685
4099
|
}
|
3686
4100
|
return acc;
|
3687
4101
|
}, {});
|
3688
|
-
if (!fp.isEmpty(
|
3689
|
-
populateAcc[attributeName] = {
|
4102
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
4103
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3690
4104
|
}
|
3691
4105
|
break;
|
3692
4106
|
}
|
@@ -3721,7 +4135,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3721
4135
|
return populateQuery;
|
3722
4136
|
};
|
3723
4137
|
const buildDeepPopulate = (uid2) => {
|
3724
|
-
return getService$
|
4138
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3725
4139
|
};
|
3726
4140
|
const populateBuilder = (uid2) => {
|
3727
4141
|
let getInitialPopulate = async () => {
|
@@ -3878,41 +4292,55 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3878
4292
|
"updatedBy",
|
3879
4293
|
"status"
|
3880
4294
|
];
|
3881
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
4295
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
4296
|
+
"id",
|
4297
|
+
"locale",
|
4298
|
+
"updatedAt",
|
4299
|
+
"createdAt",
|
4300
|
+
"publishedAt",
|
4301
|
+
"documentId"
|
4302
|
+
];
|
3882
4303
|
const CONTENT_MANAGER_STATUS = {
|
3883
4304
|
PUBLISHED: "published",
|
3884
4305
|
DRAFT: "draft",
|
3885
4306
|
MODIFIED: "modified"
|
3886
4307
|
};
|
3887
|
-
const
|
3888
|
-
if (!
|
4308
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
4309
|
+
if (!version || !version.updatedAt) {
|
3889
4310
|
return false;
|
3890
4311
|
}
|
3891
|
-
const
|
3892
|
-
const
|
3893
|
-
|
3894
|
-
return difference <= threshold;
|
4312
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
4313
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
4314
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3895
4315
|
};
|
3896
4316
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3897
4317
|
/**
|
3898
4318
|
* Returns available locales of a document for the current status
|
3899
4319
|
*/
|
3900
|
-
getAvailableLocales(uid2, version, allVersions) {
|
4320
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3901
4321
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3902
|
-
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
3906
|
-
|
3907
|
-
|
3908
|
-
|
3909
|
-
|
3910
|
-
|
3911
|
-
|
3912
|
-
|
3913
|
-
|
3914
|
-
|
3915
|
-
|
4322
|
+
if (version.locale) {
|
4323
|
+
delete versionsByLocale[version.locale];
|
4324
|
+
}
|
4325
|
+
const model = strapi2.getModel(uid2);
|
4326
|
+
const mappingResult = await strapiUtils.async.map(
|
4327
|
+
Object.values(versionsByLocale),
|
4328
|
+
async (localeVersions) => {
|
4329
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4330
|
+
return localeVersions[0];
|
4331
|
+
}
|
4332
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4333
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4334
|
+
if (!draftVersion) {
|
4335
|
+
return;
|
4336
|
+
}
|
4337
|
+
return {
|
4338
|
+
...draftVersion,
|
4339
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4340
|
+
};
|
4341
|
+
}
|
4342
|
+
);
|
4343
|
+
return mappingResult.filter(Boolean);
|
3916
4344
|
},
|
3917
4345
|
/**
|
3918
4346
|
* Returns available status of a document for the current locale
|
@@ -3924,8 +4352,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3924
4352
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
3925
4353
|
return matchLocale && matchStatus;
|
3926
4354
|
});
|
3927
|
-
if (!availableStatus)
|
3928
|
-
return availableStatus;
|
4355
|
+
if (!availableStatus) return availableStatus;
|
3929
4356
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
3930
4357
|
},
|
3931
4358
|
/**
|
@@ -3935,50 +4362,62 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3935
4362
|
* @returns
|
3936
4363
|
*/
|
3937
4364
|
async getManyAvailableStatus(uid2, documents) {
|
3938
|
-
if (!documents.length)
|
3939
|
-
return [];
|
4365
|
+
if (!documents.length) return [];
|
3940
4366
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
3941
|
-
const
|
3942
|
-
|
3943
|
-
|
3944
|
-
|
3945
|
-
|
4367
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4368
|
+
return strapi2.query(uid2).findMany({
|
4369
|
+
where: {
|
4370
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4371
|
+
// NOTE: find the "opposite" status
|
4372
|
+
publishedAt: { $null: status === "published" },
|
4373
|
+
locale: { $in: locales }
|
3946
4374
|
},
|
3947
|
-
|
3948
|
-
locale,
|
3949
|
-
fields: ["documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4375
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
3950
4376
|
});
|
3951
4377
|
},
|
3952
4378
|
getStatus(version, otherDocumentStatuses) {
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3959
|
-
if (!publishedVersion) {
|
3960
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
3961
|
-
}
|
4379
|
+
let draftVersion;
|
4380
|
+
let publishedVersion;
|
4381
|
+
if (version.publishedAt) {
|
4382
|
+
publishedVersion = version;
|
4383
|
+
} else {
|
4384
|
+
draftVersion = version;
|
3962
4385
|
}
|
3963
|
-
|
3964
|
-
|
4386
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4387
|
+
if (otherVersion?.publishedAt) {
|
4388
|
+
publishedVersion = otherVersion;
|
4389
|
+
} else if (otherVersion) {
|
4390
|
+
draftVersion = otherVersion;
|
3965
4391
|
}
|
3966
|
-
return CONTENT_MANAGER_STATUS.
|
4392
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4393
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4394
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4395
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3967
4396
|
},
|
4397
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4398
|
+
// We could refactor this so the locales are only loaded when they're
|
4399
|
+
// needed. e.g. in the bulk locale action modal.
|
3968
4400
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
3969
|
-
const
|
3970
|
-
|
3971
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
4401
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4402
|
+
const params = {
|
3972
4403
|
populate: {
|
4404
|
+
...populate,
|
4405
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3973
4406
|
createdBy: {
|
3974
4407
|
select: ["id", "firstname", "lastname", "email"]
|
3975
4408
|
},
|
3976
4409
|
updatedBy: {
|
3977
4410
|
select: ["id", "firstname", "lastname", "email"]
|
3978
4411
|
}
|
4412
|
+
},
|
4413
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4414
|
+
filters: {
|
4415
|
+
documentId: version.documentId
|
3979
4416
|
}
|
3980
|
-
}
|
3981
|
-
const
|
4417
|
+
};
|
4418
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4419
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4420
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
3982
4421
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3983
4422
|
return {
|
3984
4423
|
availableLocales: availableLocalesResult,
|
@@ -3991,13 +4430,30 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3991
4430
|
* - Available status of the document for the current locale
|
3992
4431
|
*/
|
3993
4432
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3994
|
-
if (!document)
|
3995
|
-
return
|
4433
|
+
if (!document) {
|
4434
|
+
return {
|
4435
|
+
data: document,
|
4436
|
+
meta: {
|
4437
|
+
availableLocales: [],
|
4438
|
+
availableStatus: []
|
4439
|
+
}
|
4440
|
+
};
|
4441
|
+
}
|
3996
4442
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
3997
4443
|
if (!hasDraftAndPublish) {
|
3998
4444
|
opts.availableStatus = false;
|
3999
4445
|
}
|
4000
4446
|
const meta = await this.getMetadata(uid2, document, opts);
|
4447
|
+
if (document.localizations) {
|
4448
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4449
|
+
document.localizations = document.localizations.map((d) => {
|
4450
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4451
|
+
return {
|
4452
|
+
...d,
|
4453
|
+
status: this.getStatus(d, status ? [status] : [])
|
4454
|
+
};
|
4455
|
+
});
|
4456
|
+
}
|
4001
4457
|
return {
|
4002
4458
|
data: {
|
4003
4459
|
...document,
|
@@ -4042,26 +4498,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
4042
4498
|
}, 0);
|
4043
4499
|
};
|
4044
4500
|
const { ApplicationError } = strapiUtils.errors;
|
4045
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
4046
4501
|
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
4047
4502
|
const omitPublishedAtField = fp.omit(PUBLISHED_AT_ATTRIBUTE);
|
4048
4503
|
const omitIdField = fp.omit("id");
|
4049
|
-
const emitEvent = async (uid2, event, document) => {
|
4050
|
-
const modelDef = strapi.getModel(uid2);
|
4051
|
-
const sanitizedDocument = await strapiUtils.sanitize.sanitizers.defaultSanitizeOutput(
|
4052
|
-
{
|
4053
|
-
schema: modelDef,
|
4054
|
-
getModel(uid22) {
|
4055
|
-
return strapi.getModel(uid22);
|
4056
|
-
}
|
4057
|
-
},
|
4058
|
-
document
|
4059
|
-
);
|
4060
|
-
strapi.eventHub.emit(event, {
|
4061
|
-
model: modelDef.modelName,
|
4062
|
-
entry: sanitizedDocument
|
4063
|
-
});
|
4064
|
-
};
|
4065
4504
|
const documentManager = ({ strapi: strapi2 }) => {
|
4066
4505
|
return {
|
4067
4506
|
async findOne(id, uid2, opts = {}) {
|
@@ -4080,6 +4519,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4080
4519
|
} else if (opts.locale && opts.locale !== "*") {
|
4081
4520
|
where.locale = opts.locale;
|
4082
4521
|
}
|
4522
|
+
if (typeof opts.isPublished === "boolean") {
|
4523
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4524
|
+
}
|
4083
4525
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4084
4526
|
},
|
4085
4527
|
async findMany(opts, uid2) {
|
@@ -4087,20 +4529,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4087
4529
|
return strapi2.documents(uid2).findMany(params);
|
4088
4530
|
},
|
4089
4531
|
async findPage(opts, uid2) {
|
4090
|
-
const
|
4091
|
-
|
4532
|
+
const params = strapiUtils.pagination.withDefaultPagination(opts || {}, {
|
4533
|
+
maxLimit: 1e3
|
4534
|
+
});
|
4092
4535
|
const [documents, total = 0] = await Promise.all([
|
4093
|
-
strapi2.documents(uid2).findMany(
|
4094
|
-
strapi2.documents(uid2).count(
|
4536
|
+
strapi2.documents(uid2).findMany(params),
|
4537
|
+
strapi2.documents(uid2).count(params)
|
4095
4538
|
]);
|
4096
4539
|
return {
|
4097
4540
|
results: documents,
|
4098
|
-
pagination:
|
4099
|
-
page,
|
4100
|
-
pageSize,
|
4101
|
-
pageCount: Math.ceil(total / pageSize),
|
4102
|
-
total
|
4103
|
-
}
|
4541
|
+
pagination: strapiUtils.pagination.transformPagedPaginationInfo(params, total)
|
4104
4542
|
};
|
4105
4543
|
},
|
4106
4544
|
async create(uid2, opts = {}) {
|
@@ -4117,10 +4555,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4117
4555
|
async clone(id, body, uid2) {
|
4118
4556
|
const populate = await buildDeepPopulate(uid2);
|
4119
4557
|
const params = {
|
4120
|
-
data:
|
4121
|
-
...omitIdField(body),
|
4122
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4123
|
-
},
|
4558
|
+
data: omitIdField(body),
|
4124
4559
|
populate
|
4125
4560
|
};
|
4126
4561
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4146,70 +4581,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4146
4581
|
return {};
|
4147
4582
|
},
|
4148
4583
|
// FIXME: handle relations
|
4149
|
-
async deleteMany(
|
4150
|
-
const
|
4151
|
-
|
4152
|
-
|
4153
|
-
}
|
4154
|
-
return { count: docs.length };
|
4584
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4585
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4586
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4587
|
+
});
|
4588
|
+
return { count: deletedEntries.length };
|
4155
4589
|
},
|
4156
4590
|
async publish(id, uid2, opts = {}) {
|
4157
4591
|
const populate = await buildDeepPopulate(uid2);
|
4158
4592
|
const params = { ...opts, populate };
|
4159
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4593
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4160
4594
|
},
|
4161
|
-
async publishMany(
|
4162
|
-
|
4163
|
-
|
4164
|
-
|
4165
|
-
|
4166
|
-
|
4167
|
-
|
4168
|
-
strapi2.getModel(uid2),
|
4169
|
-
document,
|
4170
|
-
void 0,
|
4171
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4172
|
-
document
|
4173
|
-
);
|
4174
|
-
})
|
4175
|
-
);
|
4176
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4177
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4178
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4179
|
-
const populate = await buildDeepPopulate(uid2);
|
4180
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4181
|
-
where: filters,
|
4182
|
-
data
|
4183
|
-
});
|
4184
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4185
|
-
where: filters,
|
4186
|
-
populate
|
4595
|
+
async publishMany(uid2, documentIds, locale) {
|
4596
|
+
return strapi2.db.transaction(async () => {
|
4597
|
+
const results = await Promise.all(
|
4598
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4599
|
+
);
|
4600
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4601
|
+
return publishedEntitiesCount;
|
4187
4602
|
});
|
4188
|
-
await Promise.all(
|
4189
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4190
|
-
);
|
4191
|
-
return publishedEntitiesCount;
|
4192
4603
|
},
|
4193
|
-
async unpublishMany(
|
4194
|
-
|
4195
|
-
return
|
4196
|
-
|
4197
|
-
|
4198
|
-
|
4199
|
-
|
4200
|
-
const populate = await buildDeepPopulate(uid2);
|
4201
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4202
|
-
where: filters,
|
4203
|
-
data
|
4204
|
-
});
|
4205
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4206
|
-
where: filters,
|
4207
|
-
populate
|
4604
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4605
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4606
|
+
return Promise.all(
|
4607
|
+
documentIds.map(
|
4608
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4609
|
+
)
|
4610
|
+
);
|
4208
4611
|
});
|
4209
|
-
|
4210
|
-
|
4211
|
-
);
|
4212
|
-
return unpublishedEntitiesCount;
|
4612
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4613
|
+
return { count: unpublishedEntitiesCount };
|
4213
4614
|
},
|
4214
4615
|
async unpublish(id, uid2, opts = {}) {
|
4215
4616
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4234,16 +4635,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4234
4635
|
}
|
4235
4636
|
return sumDraftCounts(document, uid2);
|
4236
4637
|
},
|
4237
|
-
async countManyEntriesDraftRelations(
|
4638
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4238
4639
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4239
4640
|
if (!hasRelations) {
|
4240
4641
|
return 0;
|
4241
4642
|
}
|
4643
|
+
let localeFilter = {};
|
4644
|
+
if (locale) {
|
4645
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4646
|
+
}
|
4242
4647
|
const entities = await strapi2.db.query(uid2).findMany({
|
4243
4648
|
populate,
|
4244
4649
|
where: {
|
4245
|
-
|
4246
|
-
...
|
4650
|
+
documentId: { $in: documentIds },
|
4651
|
+
...localeFilter
|
4247
4652
|
}
|
4248
4653
|
});
|
4249
4654
|
const totalNumberDraftRelations = entities.reduce(
|
@@ -4266,7 +4671,8 @@ const services = {
|
|
4266
4671
|
permission,
|
4267
4672
|
"populate-builder": populateBuilder$1,
|
4268
4673
|
uid,
|
4269
|
-
...history.services ? history.services : {}
|
4674
|
+
...history.services ? history.services : {},
|
4675
|
+
...preview.services ? preview.services : {}
|
4270
4676
|
};
|
4271
4677
|
const index = () => {
|
4272
4678
|
return {
|