@strapi/content-manager 0.0.0-experimental.745741d19e90275ca6f7c928ca19f9bb0fd9d933 → 0.0.0-experimental.76d3543c13df7ef0095963ae2c20b792f179eef0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-CJPoOvy3.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-CJPoOvy3.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs → ComponentConfigurationPage-CcRDqD0e.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-CcRDqD0e.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-C1ddZ_zf.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-C1ddZ_zf.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-CF3lxOy2.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-CF3lxOy2.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-BPFcUbqi.mjs} +63 -12
- package/dist/_chunks/EditViewPage-BPFcUbqi.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-CDyTC6aU.js} +63 -13
- package/dist/_chunks/EditViewPage-CDyTC6aU.js.map +1 -0
- package/dist/_chunks/{Field-lsPFnAmH.js → Field-DuxAW9q2.js} +409 -260
- package/dist/_chunks/Field-DuxAW9q2.js.map +1 -0
- package/dist/_chunks/{Field-R5NbffTB.mjs → Field-fBnTwgU4.mjs} +405 -256
- package/dist/_chunks/Field-fBnTwgU4.mjs.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-BGl7PhlZ.mjs} +37 -18
- package/dist/_chunks/Form-BGl7PhlZ.mjs.map +1 -0
- package/dist/_chunks/{Form-CcGboku8.js → Form-DSGh_zkz.js} +39 -21
- package/dist/_chunks/Form-DSGh_zkz.js.map +1 -0
- package/dist/_chunks/{History-ByUPL3T3.mjs → History-DTYB9CSB.mjs} +66 -113
- package/dist/_chunks/History-DTYB9CSB.mjs.map +1 -0
- package/dist/_chunks/{History-Bsud8jwh.js → History-DrDJv698.js} +65 -113
- package/dist/_chunks/History-DrDJv698.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-qWx8r4D_.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-qWx8r4D_.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-zurIlUZ7.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-zurIlUZ7.js.map +1 -0
- package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-DTM2uO_S.js} +109 -78
- package/dist/_chunks/ListViewPage-DTM2uO_S.js.map +1 -0
- package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-GKpL5p8A.mjs} +106 -74
- package/dist/_chunks/ListViewPage-GKpL5p8A.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-B5Vc5Cal.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-B5Vc5Cal.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-BuZlNroO.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-BuZlNroO.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-BAZlWgJ4.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-BAZlWgJ4.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-DLzkS4Hy.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-DLzkS4Hy.js.map} +1 -1
- package/dist/_chunks/Preview-VOJ8RuQp.js +312 -0
- package/dist/_chunks/Preview-VOJ8RuQp.js.map +1 -0
- package/dist/_chunks/Preview-Zzjg2_K_.mjs +294 -0
- package/dist/_chunks/Preview-Zzjg2_K_.mjs.map +1 -0
- package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BVdRfDkW.mjs} +76 -42
- package/dist/_chunks/Relations-BVdRfDkW.mjs.map +1 -0
- package/dist/_chunks/{Relations-CghaPv2D.js → Relations-Dsj0boFJ.js} +76 -43
- package/dist/_chunks/Relations-Dsj0boFJ.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BzQmavmK.js} +37 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BzQmavmK.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-CSxLmrh1.mjs} +37 -18
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-CSxLmrh1.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-CaE6NG4a.mjs → index-Bu_-B7ZA.mjs} +1263 -772
- package/dist/_chunks/index-Bu_-B7ZA.mjs.map +1 -0
- package/dist/_chunks/{index-BOZx6IMg.js → index-Ct-GZ0iV.js} +1246 -755
- package/dist/_chunks/index-Ct-GZ0iV.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-Ciz224q5.js → layout-CDBEgRsM.js} +24 -12
- package/dist/_chunks/layout-CDBEgRsM.js.map +1 -0
- package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-COzAvgJh.mjs} +24 -11
- package/dist/_chunks/layout-COzAvgJh.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CP8sB2YZ.js → relations-BjiF1Aad.js} +6 -7
- package/dist/_chunks/relations-BjiF1Aad.js.map +1 -0
- package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-BtmMFBpM.mjs} +6 -7
- package/dist/_chunks/relations-BtmMFBpM.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- 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-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +6 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +2 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -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 +2 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +682 -360
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +683 -360
- 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/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +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 +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -15
- package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +0 -1
- package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +0 -1
- package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
- package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
- package/dist/_chunks/Form-BHmXSfyy.mjs.map +0 -1
- package/dist/_chunks/Form-CcGboku8.js.map +0 -1
- package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
- package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
- package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +0 -1
- package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +0 -1
- package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
- package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
- package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
- package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
- package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
- package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
- package/dist/_chunks/relations-CP8sB2YZ.js.map +0 -1
- package/dist/_chunks/relations-Cxc1cEv3.mjs.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.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,9 +225,21 @@ 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": {
|
@@ -238,23 +249,29 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
238
249
|
}
|
239
250
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
240
251
|
if (isVisible2) {
|
241
|
-
acc[attributeName] = {
|
252
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
242
253
|
}
|
243
254
|
break;
|
244
255
|
}
|
245
256
|
case "media": {
|
246
|
-
acc[attributeName] = {
|
257
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
247
258
|
break;
|
248
259
|
}
|
249
260
|
case "component": {
|
250
261
|
const populate = getDeepPopulate2(attribute.component);
|
251
|
-
acc[attributeName] = {
|
262
|
+
acc[attributeName] = {
|
263
|
+
populate,
|
264
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
265
|
+
};
|
252
266
|
break;
|
253
267
|
}
|
254
268
|
case "dynamiczone": {
|
255
269
|
const populatedComponents = (attribute.components || []).reduce(
|
256
270
|
(acc2, componentUID) => {
|
257
|
-
acc2[componentUID] = {
|
271
|
+
acc2[componentUID] = {
|
272
|
+
populate: getDeepPopulate2(componentUID),
|
273
|
+
[fieldSelector]: getComponentFields(componentUID)
|
274
|
+
};
|
258
275
|
return acc2;
|
259
276
|
},
|
260
277
|
{}
|
@@ -316,6 +333,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
316
333
|
getRelationRestoreValue,
|
317
334
|
getMediaRestoreValue,
|
318
335
|
getDefaultLocale,
|
336
|
+
isLocalizedContentType,
|
319
337
|
getLocaleDictionary,
|
320
338
|
getRetentionDays,
|
321
339
|
getVersionStatus,
|
@@ -338,7 +356,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
338
356
|
});
|
339
357
|
},
|
340
358
|
async findVersionsPage(params) {
|
341
|
-
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
|
+
}
|
342
366
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
343
367
|
query.findPage({
|
344
368
|
...params.query,
|
@@ -360,7 +384,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
360
384
|
const attributeValue = entry.data[attributeKey];
|
361
385
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
362
386
|
if (attributeSchema.type === "media") {
|
363
|
-
const permissionChecker2 = getService$
|
387
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
364
388
|
userAbility: params.state.userAbility,
|
365
389
|
model: "plugin::upload.file"
|
366
390
|
});
|
@@ -383,7 +407,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
383
407
|
if (userToPopulate == null) {
|
384
408
|
return null;
|
385
409
|
}
|
386
|
-
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
|
+
});
|
387
416
|
})
|
388
417
|
);
|
389
418
|
return {
|
@@ -396,7 +425,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
396
425
|
[attributeKey]: adminUsers
|
397
426
|
};
|
398
427
|
}
|
399
|
-
const permissionChecker2 = getService$
|
428
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
400
429
|
userAbility: params.state.userAbility,
|
401
430
|
model: attributeSchema.target
|
402
431
|
});
|
@@ -494,6 +523,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
494
523
|
}
|
495
524
|
};
|
496
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
|
+
};
|
497
562
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
498
563
|
const state = {
|
499
564
|
deleteExpiredJob: null,
|
@@ -506,76 +571,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
506
571
|
return;
|
507
572
|
}
|
508
573
|
strapi2.documents.use(async (context, next) => {
|
509
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
510
|
-
return next();
|
511
|
-
}
|
512
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
513
|
-
return next();
|
514
|
-
}
|
515
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
516
|
-
return next();
|
517
|
-
}
|
518
|
-
const contentTypeUid = context.contentType.uid;
|
519
|
-
if (!contentTypeUid.startsWith("api::")) {
|
520
|
-
return next();
|
521
|
-
}
|
522
574
|
const result = await next();
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
575
|
+
if (!shouldCreateHistoryVersion(context)) {
|
576
|
+
return result;
|
577
|
+
}
|
578
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
527
579
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
528
|
-
const
|
529
|
-
if (
|
530
|
-
|
531
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
532
|
-
);
|
533
|
-
return next();
|
580
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
581
|
+
if (!locales.length) {
|
582
|
+
return result;
|
534
583
|
}
|
535
|
-
const
|
536
|
-
|
537
|
-
|
538
|
-
|
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
|
+
)
|
539
599
|
});
|
540
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
541
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
542
|
-
const componentsSchemas = Object.keys(
|
543
|
-
attributesSchema
|
544
|
-
).reduce((currentComponentSchemas, key) => {
|
545
|
-
const fieldSchema = attributesSchema[key];
|
546
|
-
if (fieldSchema.type === "component") {
|
547
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
548
|
-
return {
|
549
|
-
...currentComponentSchemas,
|
550
|
-
[fieldSchema.component]: componentSchema
|
551
|
-
};
|
552
|
-
}
|
553
|
-
return currentComponentSchemas;
|
554
|
-
}, {});
|
555
600
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
556
|
-
onCommit(() => {
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
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
|
+
}
|
566
613
|
});
|
567
614
|
});
|
568
615
|
return result;
|
569
616
|
});
|
570
|
-
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
617
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
571
618
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
572
619
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
573
620
|
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
574
621
|
where: {
|
575
622
|
created_at: {
|
576
|
-
$lt: expirationDate
|
623
|
+
$lt: expirationDate
|
577
624
|
}
|
578
625
|
}
|
626
|
+
}).catch((error) => {
|
627
|
+
if (error instanceof Error) {
|
628
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
629
|
+
}
|
579
630
|
});
|
580
631
|
});
|
581
632
|
state.isInitialized = true;
|
@@ -587,17 +638,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
587
638
|
}
|
588
639
|
};
|
589
640
|
};
|
590
|
-
const services$
|
641
|
+
const services$2 = {
|
591
642
|
history: createHistoryService,
|
592
643
|
lifecycles: createLifecyclesService
|
593
644
|
};
|
594
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
645
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
595
646
|
const historyVersionRouter = {
|
596
647
|
type: "admin",
|
597
648
|
routes: [
|
598
649
|
{
|
599
650
|
method: "GET",
|
600
|
-
info,
|
651
|
+
info: info$1,
|
601
652
|
path: "/history-versions",
|
602
653
|
handler: "history-version.findMany",
|
603
654
|
config: {
|
@@ -606,7 +657,7 @@ const historyVersionRouter = {
|
|
606
657
|
},
|
607
658
|
{
|
608
659
|
method: "PUT",
|
609
|
-
info,
|
660
|
+
info: info$1,
|
610
661
|
path: "/history-versions/:versionId/restore",
|
611
662
|
handler: "history-version.restoreVersion",
|
612
663
|
config: {
|
@@ -615,7 +666,7 @@ const historyVersionRouter = {
|
|
615
666
|
}
|
616
667
|
]
|
617
668
|
};
|
618
|
-
const routes$
|
669
|
+
const routes$2 = {
|
619
670
|
"history-version": historyVersionRouter
|
620
671
|
};
|
621
672
|
const historyVersion = {
|
@@ -662,21 +713,21 @@ const historyVersion = {
|
|
662
713
|
}
|
663
714
|
}
|
664
715
|
};
|
665
|
-
const getFeature = () => {
|
716
|
+
const getFeature$1 = () => {
|
666
717
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
667
718
|
return {
|
668
719
|
register({ strapi: strapi2 }) {
|
669
720
|
strapi2.get("models").add(historyVersion);
|
670
721
|
},
|
671
722
|
bootstrap({ strapi: strapi2 }) {
|
672
|
-
getService(strapi2, "lifecycles").bootstrap();
|
723
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
673
724
|
},
|
674
725
|
destroy({ strapi: strapi2 }) {
|
675
|
-
getService(strapi2, "lifecycles").destroy();
|
726
|
+
getService$1(strapi2, "lifecycles").destroy();
|
676
727
|
},
|
677
|
-
controllers: controllers$
|
678
|
-
services: services$
|
679
|
-
routes: routes$
|
728
|
+
controllers: controllers$2,
|
729
|
+
services: services$2,
|
730
|
+
routes: routes$2
|
680
731
|
};
|
681
732
|
}
|
682
733
|
return {
|
@@ -685,9 +736,201 @@ const getFeature = () => {
|
|
685
736
|
}
|
686
737
|
};
|
687
738
|
};
|
688
|
-
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();
|
689
931
|
const register = async ({ strapi: strapi2 }) => {
|
690
932
|
await history.register?.({ strapi: strapi2 });
|
933
|
+
await preview.register?.({ strapi: strapi2 });
|
691
934
|
};
|
692
935
|
const ALLOWED_WEBHOOK_EVENTS = {
|
693
936
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -697,11 +940,12 @@ const bootstrap = async () => {
|
|
697
940
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
698
941
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
699
942
|
});
|
700
|
-
getService$
|
701
|
-
await getService$
|
702
|
-
await getService$
|
703
|
-
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();
|
704
947
|
await history.bootstrap?.({ strapi });
|
948
|
+
await preview.bootstrap?.({ strapi });
|
705
949
|
};
|
706
950
|
const destroy = async ({ strapi: strapi2 }) => {
|
707
951
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1191,7 +1435,8 @@ const admin = {
|
|
1191
1435
|
};
|
1192
1436
|
const routes = {
|
1193
1437
|
admin,
|
1194
|
-
...history.routes ? history.routes : {}
|
1438
|
+
...history.routes ? history.routes : {},
|
1439
|
+
...preview.routes ? preview.routes : {}
|
1195
1440
|
};
|
1196
1441
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1197
1442
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1202,6 +1447,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1202
1447
|
const hasPermissions = createPolicy({
|
1203
1448
|
name: "plugin::content-manager.hasPermissions",
|
1204
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
|
+
*/
|
1205
1455
|
handler(ctx, config = {}) {
|
1206
1456
|
const { actions = [], hasAtLeastOne = false } = config;
|
1207
1457
|
const { userAbility } = ctx.state;
|
@@ -1249,8 +1499,7 @@ const isSortable = (schema, name) => {
|
|
1249
1499
|
if (!___default.default.has(schema.attributes, name)) {
|
1250
1500
|
return false;
|
1251
1501
|
}
|
1252
|
-
if (schema.modelType === "component" && name === "id")
|
1253
|
-
return false;
|
1502
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1254
1503
|
const attribute = schema.attributes[name];
|
1255
1504
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1256
1505
|
return false;
|
@@ -1395,8 +1644,7 @@ const createDefaultSettings = async (schema) => {
|
|
1395
1644
|
};
|
1396
1645
|
};
|
1397
1646
|
const syncSettings = async (configuration, schema) => {
|
1398
|
-
if (fp.isEmpty(configuration.settings))
|
1399
|
-
return createDefaultSettings(schema);
|
1647
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1400
1648
|
const defaultField = getDefaultMainField(schema);
|
1401
1649
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1402
1650
|
return {
|
@@ -1443,7 +1691,7 @@ const createMetadasSchema = (schema) => {
|
|
1443
1691
|
if (!value) {
|
1444
1692
|
return strapiUtils.yup.string();
|
1445
1693
|
}
|
1446
|
-
const targetSchema = getService$
|
1694
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1447
1695
|
schema.attributes[key].targetModel
|
1448
1696
|
);
|
1449
1697
|
if (!targetSchema) {
|
@@ -1572,8 +1820,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1572
1820
|
}
|
1573
1821
|
switch (attribute.type) {
|
1574
1822
|
case "relation": {
|
1575
|
-
if (canCreate(attributePath))
|
1576
|
-
return body2;
|
1823
|
+
if (canCreate(attributePath)) return body2;
|
1577
1824
|
return fp.set(attributePath, { set: [] }, body2);
|
1578
1825
|
}
|
1579
1826
|
case "component": {
|
@@ -1583,8 +1830,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1583
1830
|
]);
|
1584
1831
|
}
|
1585
1832
|
default: {
|
1586
|
-
if (canCreate(attributePath))
|
1587
|
-
return body2;
|
1833
|
+
if (canCreate(attributePath)) return body2;
|
1588
1834
|
return fp.set(attributePath, null, body2);
|
1589
1835
|
}
|
1590
1836
|
}
|
@@ -1595,9 +1841,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
|
|
1595
1841
|
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1596
1842
|
);
|
1597
1843
|
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1598
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1844
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1599
1845
|
const { allowMultipleLocales } = opts;
|
1600
|
-
const { locale, status, ...rest } = request || {};
|
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;
|
1601
1849
|
const schema = strapiUtils.yup.object().shape({
|
1602
1850
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1603
1851
|
status: statusSchema
|
@@ -1610,7 +1858,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1610
1858
|
}
|
1611
1859
|
};
|
1612
1860
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1613
|
-
const documentMetadata2 = getService$
|
1861
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1614
1862
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1615
1863
|
let {
|
1616
1864
|
meta: { availableLocales, availableStatus }
|
@@ -1636,8 +1884,8 @@ const createDocument = async (ctx, opts) => {
|
|
1636
1884
|
const { userAbility, user } = ctx.state;
|
1637
1885
|
const { model } = ctx.params;
|
1638
1886
|
const { body } = ctx.request;
|
1639
|
-
const documentManager2 = getService$
|
1640
|
-
const permissionChecker2 = getService$
|
1887
|
+
const documentManager2 = getService$2("document-manager");
|
1888
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1641
1889
|
if (permissionChecker2.cannot.create()) {
|
1642
1890
|
throw new strapiUtils.errors.ForbiddenError();
|
1643
1891
|
}
|
@@ -1645,7 +1893,7 @@ const createDocument = async (ctx, opts) => {
|
|
1645
1893
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1646
1894
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1647
1895
|
const sanitizedBody = await sanitizeFn(body);
|
1648
|
-
const { locale, status
|
1896
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1649
1897
|
return documentManager2.create(model, {
|
1650
1898
|
data: sanitizedBody,
|
1651
1899
|
locale,
|
@@ -1657,14 +1905,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1657
1905
|
const { userAbility, user } = ctx.state;
|
1658
1906
|
const { id, model } = ctx.params;
|
1659
1907
|
const { body } = ctx.request;
|
1660
|
-
const documentManager2 = getService$
|
1661
|
-
const permissionChecker2 = getService$
|
1908
|
+
const documentManager2 = getService$2("document-manager");
|
1909
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1662
1910
|
if (permissionChecker2.cannot.update()) {
|
1663
1911
|
throw new strapiUtils.errors.ForbiddenError();
|
1664
1912
|
}
|
1665
1913
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1666
|
-
const populate = await getService$
|
1667
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1914
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1915
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1668
1916
|
const [documentVersion, documentExists] = await Promise.all([
|
1669
1917
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1670
1918
|
documentManager2.exists(model, id)
|
@@ -1680,7 +1928,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1680
1928
|
throw new strapiUtils.errors.ForbiddenError();
|
1681
1929
|
}
|
1682
1930
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1683
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1931
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1684
1932
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1685
1933
|
const sanitizedBody = await sanitizeFn(body);
|
1686
1934
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1694,15 +1942,15 @@ const collectionTypes = {
|
|
1694
1942
|
const { userAbility } = ctx.state;
|
1695
1943
|
const { model } = ctx.params;
|
1696
1944
|
const { query } = ctx.request;
|
1697
|
-
const documentMetadata2 = getService$
|
1698
|
-
const documentManager2 = getService$
|
1699
|
-
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 });
|
1700
1948
|
if (permissionChecker2.cannot.read()) {
|
1701
1949
|
return ctx.forbidden();
|
1702
1950
|
}
|
1703
1951
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1704
|
-
const populate = await getService$
|
1705
|
-
const { locale, status } = await 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);
|
1706
1954
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1707
1955
|
{ ...permissionQuery, populate, locale, status },
|
1708
1956
|
model
|
@@ -1730,14 +1978,14 @@ const collectionTypes = {
|
|
1730
1978
|
async findOne(ctx) {
|
1731
1979
|
const { userAbility } = ctx.state;
|
1732
1980
|
const { model, id } = ctx.params;
|
1733
|
-
const documentManager2 = getService$
|
1734
|
-
const permissionChecker2 = getService$
|
1981
|
+
const documentManager2 = getService$2("document-manager");
|
1982
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1735
1983
|
if (permissionChecker2.cannot.read()) {
|
1736
1984
|
return ctx.forbidden();
|
1737
1985
|
}
|
1738
1986
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1739
|
-
const populate = await getService$
|
1740
|
-
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);
|
1741
1989
|
const version = await documentManager2.findOne(id, model, {
|
1742
1990
|
populate,
|
1743
1991
|
locale,
|
@@ -1752,7 +2000,7 @@ const collectionTypes = {
|
|
1752
2000
|
permissionChecker2,
|
1753
2001
|
model,
|
1754
2002
|
// @ts-expect-error TODO: fix
|
1755
|
-
{ id, locale, publishedAt: null },
|
2003
|
+
{ documentId: id, locale, publishedAt: null },
|
1756
2004
|
{ availableLocales: true, availableStatus: false }
|
1757
2005
|
);
|
1758
2006
|
ctx.body = { data: {}, meta };
|
@@ -1767,7 +2015,7 @@ const collectionTypes = {
|
|
1767
2015
|
async create(ctx) {
|
1768
2016
|
const { userAbility } = ctx.state;
|
1769
2017
|
const { model } = ctx.params;
|
1770
|
-
const permissionChecker2 = getService$
|
2018
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1771
2019
|
const [totalEntries, document] = await Promise.all([
|
1772
2020
|
strapi.db.query(model).count(),
|
1773
2021
|
createDocument(ctx)
|
@@ -1788,7 +2036,7 @@ const collectionTypes = {
|
|
1788
2036
|
async update(ctx) {
|
1789
2037
|
const { userAbility } = ctx.state;
|
1790
2038
|
const { model } = ctx.params;
|
1791
|
-
const permissionChecker2 = getService$
|
2039
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1792
2040
|
const updatedVersion = await updateDocument(ctx);
|
1793
2041
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1794
2042
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1797,14 +2045,14 @@ const collectionTypes = {
|
|
1797
2045
|
const { userAbility, user } = ctx.state;
|
1798
2046
|
const { model, sourceId: id } = ctx.params;
|
1799
2047
|
const { body } = ctx.request;
|
1800
|
-
const documentManager2 = getService$
|
1801
|
-
const permissionChecker2 = getService$
|
2048
|
+
const documentManager2 = getService$2("document-manager");
|
2049
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1802
2050
|
if (permissionChecker2.cannot.create()) {
|
1803
2051
|
return ctx.forbidden();
|
1804
2052
|
}
|
1805
2053
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1806
|
-
const populate = await getService$
|
1807
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2054
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2055
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1808
2056
|
const document = await documentManager2.findOne(id, model, {
|
1809
2057
|
populate,
|
1810
2058
|
locale,
|
@@ -1842,14 +2090,14 @@ const collectionTypes = {
|
|
1842
2090
|
async delete(ctx) {
|
1843
2091
|
const { userAbility } = ctx.state;
|
1844
2092
|
const { id, model } = ctx.params;
|
1845
|
-
const documentManager2 = getService$
|
1846
|
-
const permissionChecker2 = getService$
|
2093
|
+
const documentManager2 = getService$2("document-manager");
|
2094
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1847
2095
|
if (permissionChecker2.cannot.delete()) {
|
1848
2096
|
return ctx.forbidden();
|
1849
2097
|
}
|
1850
2098
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1851
|
-
const populate = await getService$
|
1852
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
2099
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2100
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1853
2101
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1854
2102
|
if (documentLocales.length === 0) {
|
1855
2103
|
return ctx.notFound();
|
@@ -1870,19 +2118,42 @@ const collectionTypes = {
|
|
1870
2118
|
const { userAbility } = ctx.state;
|
1871
2119
|
const { id, model } = ctx.params;
|
1872
2120
|
const { body } = ctx.request;
|
1873
|
-
const documentManager2 = getService$
|
1874
|
-
const permissionChecker2 = getService$
|
2121
|
+
const documentManager2 = getService$2("document-manager");
|
2122
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1875
2123
|
if (permissionChecker2.cannot.publish()) {
|
1876
2124
|
return ctx.forbidden();
|
1877
2125
|
}
|
1878
2126
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1879
2127
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1880
|
-
const populate = await getService$
|
1881
|
-
|
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
|
+
}
|
1882
2154
|
if (permissionChecker2.cannot.publish(document)) {
|
1883
2155
|
throw new strapiUtils.errors.ForbiddenError();
|
1884
2156
|
}
|
1885
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1886
2157
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1887
2158
|
locale
|
1888
2159
|
// TODO: Allow setting creator fields on publish
|
@@ -1902,14 +2173,16 @@ const collectionTypes = {
|
|
1902
2173
|
const { body } = ctx.request;
|
1903
2174
|
const { documentIds } = body;
|
1904
2175
|
await validateBulkActionInput(body);
|
1905
|
-
const documentManager2 = getService$
|
1906
|
-
const permissionChecker2 = getService$
|
2176
|
+
const documentManager2 = getService$2("document-manager");
|
2177
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1907
2178
|
if (permissionChecker2.cannot.publish()) {
|
1908
2179
|
return ctx.forbidden();
|
1909
2180
|
}
|
1910
2181
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1911
|
-
const populate = await getService$
|
1912
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
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
|
+
});
|
1913
2186
|
const entityPromises = documentIds.map(
|
1914
2187
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1915
2188
|
);
|
@@ -1931,12 +2204,14 @@ const collectionTypes = {
|
|
1931
2204
|
const { body } = ctx.request;
|
1932
2205
|
const { documentIds } = body;
|
1933
2206
|
await validateBulkActionInput(body);
|
1934
|
-
const documentManager2 = getService$
|
1935
|
-
const permissionChecker2 = getService$
|
2207
|
+
const documentManager2 = getService$2("document-manager");
|
2208
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1936
2209
|
if (permissionChecker2.cannot.unpublish()) {
|
1937
2210
|
return ctx.forbidden();
|
1938
2211
|
}
|
1939
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2212
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2213
|
+
allowMultipleLocales: true
|
2214
|
+
});
|
1940
2215
|
const entityPromises = documentIds.map(
|
1941
2216
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1942
2217
|
);
|
@@ -1959,8 +2234,8 @@ const collectionTypes = {
|
|
1959
2234
|
const {
|
1960
2235
|
body: { discardDraft, ...body }
|
1961
2236
|
} = ctx.request;
|
1962
|
-
const documentManager2 = getService$
|
1963
|
-
const permissionChecker2 = getService$
|
2237
|
+
const documentManager2 = getService$2("document-manager");
|
2238
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1964
2239
|
if (permissionChecker2.cannot.unpublish()) {
|
1965
2240
|
return ctx.forbidden();
|
1966
2241
|
}
|
@@ -1968,8 +2243,8 @@ const collectionTypes = {
|
|
1968
2243
|
return ctx.forbidden();
|
1969
2244
|
}
|
1970
2245
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1971
|
-
const populate = await getService$
|
1972
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2246
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2247
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1973
2248
|
const document = await documentManager2.findOne(id, model, {
|
1974
2249
|
populate,
|
1975
2250
|
locale,
|
@@ -1999,14 +2274,14 @@ const collectionTypes = {
|
|
1999
2274
|
const { userAbility } = ctx.state;
|
2000
2275
|
const { id, model } = ctx.params;
|
2001
2276
|
const { body } = ctx.request;
|
2002
|
-
const documentManager2 = getService$
|
2003
|
-
const permissionChecker2 = getService$
|
2277
|
+
const documentManager2 = getService$2("document-manager");
|
2278
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2004
2279
|
if (permissionChecker2.cannot.discard()) {
|
2005
2280
|
return ctx.forbidden();
|
2006
2281
|
}
|
2007
2282
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2008
|
-
const populate = await getService$
|
2009
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2283
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2284
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2010
2285
|
const document = await documentManager2.findOne(id, model, {
|
2011
2286
|
populate,
|
2012
2287
|
locale,
|
@@ -2030,14 +2305,14 @@ const collectionTypes = {
|
|
2030
2305
|
const { query, body } = ctx.request;
|
2031
2306
|
const { documentIds } = body;
|
2032
2307
|
await validateBulkActionInput(body);
|
2033
|
-
const documentManager2 = getService$
|
2034
|
-
const permissionChecker2 = getService$
|
2308
|
+
const documentManager2 = getService$2("document-manager");
|
2309
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2035
2310
|
if (permissionChecker2.cannot.delete()) {
|
2036
2311
|
return ctx.forbidden();
|
2037
2312
|
}
|
2038
2313
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2039
|
-
const populate = await getService$
|
2040
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2314
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2315
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2041
2316
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2042
2317
|
populate,
|
2043
2318
|
locale
|
@@ -2057,14 +2332,14 @@ const collectionTypes = {
|
|
2057
2332
|
async countDraftRelations(ctx) {
|
2058
2333
|
const { userAbility } = ctx.state;
|
2059
2334
|
const { model, id } = ctx.params;
|
2060
|
-
const documentManager2 = getService$
|
2061
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2062
2337
|
if (permissionChecker2.cannot.read()) {
|
2063
2338
|
return ctx.forbidden();
|
2064
2339
|
}
|
2065
2340
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2066
|
-
const populate = await getService$
|
2067
|
-
const { locale, status
|
2341
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2342
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2068
2343
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2069
2344
|
if (!entity) {
|
2070
2345
|
return ctx.notFound();
|
@@ -2082,8 +2357,8 @@ const collectionTypes = {
|
|
2082
2357
|
const ids = ctx.request.query.documentIds;
|
2083
2358
|
const locale = ctx.request.query.locale;
|
2084
2359
|
const { model } = ctx.params;
|
2085
|
-
const documentManager2 = getService$
|
2086
|
-
const permissionChecker2 = getService$
|
2360
|
+
const documentManager2 = getService$2("document-manager");
|
2361
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2087
2362
|
if (permissionChecker2.cannot.read()) {
|
2088
2363
|
return ctx.forbidden();
|
2089
2364
|
}
|
@@ -2107,13 +2382,13 @@ const collectionTypes = {
|
|
2107
2382
|
};
|
2108
2383
|
const components$1 = {
|
2109
2384
|
findComponents(ctx) {
|
2110
|
-
const components2 = getService$
|
2111
|
-
const { toDto } = getService$
|
2385
|
+
const components2 = getService$2("components").findAllComponents();
|
2386
|
+
const { toDto } = getService$2("data-mapper");
|
2112
2387
|
ctx.body = { data: components2.map(toDto) };
|
2113
2388
|
},
|
2114
2389
|
async findComponentConfiguration(ctx) {
|
2115
2390
|
const { uid: uid2 } = ctx.params;
|
2116
|
-
const componentService = getService$
|
2391
|
+
const componentService = getService$2("components");
|
2117
2392
|
const component = componentService.findComponent(uid2);
|
2118
2393
|
if (!component) {
|
2119
2394
|
return ctx.notFound("component.notFound");
|
@@ -2130,7 +2405,7 @@ const components$1 = {
|
|
2130
2405
|
async updateComponentConfiguration(ctx) {
|
2131
2406
|
const { uid: uid2 } = ctx.params;
|
2132
2407
|
const { body } = ctx.request;
|
2133
|
-
const componentService = getService$
|
2408
|
+
const componentService = getService$2("components");
|
2134
2409
|
const component = componentService.findComponent(uid2);
|
2135
2410
|
if (!component) {
|
2136
2411
|
return ctx.notFound("component.notFound");
|
@@ -2164,12 +2439,12 @@ const contentTypes = {
|
|
2164
2439
|
} catch (error) {
|
2165
2440
|
return ctx.send({ error }, 400);
|
2166
2441
|
}
|
2167
|
-
const contentTypes2 = getService$
|
2168
|
-
const { toDto } = getService$
|
2442
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2443
|
+
const { toDto } = getService$2("data-mapper");
|
2169
2444
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2170
2445
|
},
|
2171
2446
|
async findContentTypesSettings(ctx) {
|
2172
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2447
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2173
2448
|
const contentTypes2 = await findAllContentTypes();
|
2174
2449
|
const configurations = await Promise.all(
|
2175
2450
|
contentTypes2.map(async (contentType) => {
|
@@ -2183,7 +2458,7 @@ const contentTypes = {
|
|
2183
2458
|
},
|
2184
2459
|
async findContentTypeConfiguration(ctx) {
|
2185
2460
|
const { uid: uid2 } = ctx.params;
|
2186
|
-
const contentTypeService = getService$
|
2461
|
+
const contentTypeService = getService$2("content-types");
|
2187
2462
|
const contentType = await contentTypeService.findContentType(uid2);
|
2188
2463
|
if (!contentType) {
|
2189
2464
|
return ctx.notFound("contentType.notFound");
|
@@ -2205,13 +2480,13 @@ const contentTypes = {
|
|
2205
2480
|
const { userAbility } = ctx.state;
|
2206
2481
|
const { uid: uid2 } = ctx.params;
|
2207
2482
|
const { body } = ctx.request;
|
2208
|
-
const contentTypeService = getService$
|
2209
|
-
const metricsService = getService$
|
2483
|
+
const contentTypeService = getService$2("content-types");
|
2484
|
+
const metricsService = getService$2("metrics");
|
2210
2485
|
const contentType = await contentTypeService.findContentType(uid2);
|
2211
2486
|
if (!contentType) {
|
2212
2487
|
return ctx.notFound("contentType.notFound");
|
2213
2488
|
}
|
2214
|
-
if (!getService$
|
2489
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2215
2490
|
return ctx.forbidden();
|
2216
2491
|
}
|
2217
2492
|
let input;
|
@@ -2244,10 +2519,10 @@ const contentTypes = {
|
|
2244
2519
|
};
|
2245
2520
|
const init = {
|
2246
2521
|
getInitData(ctx) {
|
2247
|
-
const { toDto } = getService$
|
2248
|
-
const { findAllComponents } = getService$
|
2249
|
-
const { getAllFieldSizes } = getService$
|
2250
|
-
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");
|
2251
2526
|
ctx.body = {
|
2252
2527
|
data: {
|
2253
2528
|
fieldSizes: getAllFieldSizes(),
|
@@ -2283,36 +2558,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2283
2558
|
params.filters.$and.push(filtersClause);
|
2284
2559
|
};
|
2285
2560
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2286
|
-
const permissionChecker2 = getService$
|
2561
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2287
2562
|
userAbility,
|
2288
2563
|
model: model.uid
|
2289
2564
|
});
|
2290
|
-
|
2565
|
+
const isMainFieldListable = isListable(model, mainField);
|
2566
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2567
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2291
2568
|
return "id";
|
2292
2569
|
}
|
2293
|
-
if (
|
2294
|
-
|
2295
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2296
|
-
userAbility,
|
2297
|
-
model: "plugin::users-permissions.user"
|
2298
|
-
});
|
2299
|
-
if (userPermissionChecker.can.read()) {
|
2300
|
-
return "name";
|
2301
|
-
}
|
2302
|
-
}
|
2303
|
-
return "id";
|
2570
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2571
|
+
return "name";
|
2304
2572
|
}
|
2305
2573
|
return mainField;
|
2306
2574
|
};
|
2307
|
-
const addStatusToRelations = async (
|
2308
|
-
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) {
|
2309
2581
|
return relations2;
|
2310
2582
|
}
|
2311
|
-
const
|
2312
|
-
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
|
+
});
|
2313
2593
|
return relations2.map((relation) => {
|
2314
|
-
const availableStatuses =
|
2315
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2594
|
+
const availableStatuses = availableStatus.filter(
|
2595
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2316
2596
|
);
|
2317
2597
|
return {
|
2318
2598
|
...relation,
|
@@ -2333,11 +2613,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2333
2613
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2334
2614
|
const isSourceLocalized = isLocalized(sourceModel);
|
2335
2615
|
const isTargetLocalized = isLocalized(targetModel);
|
2336
|
-
let validatedLocale = locale;
|
2337
|
-
if (!targetModel || !isTargetLocalized)
|
2338
|
-
validatedLocale = void 0;
|
2339
2616
|
return {
|
2340
|
-
locale
|
2617
|
+
locale,
|
2341
2618
|
isSourceLocalized,
|
2342
2619
|
isTargetLocalized
|
2343
2620
|
};
|
@@ -2346,8 +2623,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2346
2623
|
const sourceModel = strapi.getModel(sourceUid);
|
2347
2624
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2348
2625
|
const isSourceDP = isDP(sourceModel);
|
2349
|
-
if (!isSourceDP)
|
2350
|
-
return { status: void 0 };
|
2626
|
+
if (!isSourceDP) return { status: void 0 };
|
2351
2627
|
switch (status) {
|
2352
2628
|
case "published":
|
2353
2629
|
return { status: "published" };
|
@@ -2377,7 +2653,7 @@ const relations = {
|
|
2377
2653
|
ctx.request?.query?.locale
|
2378
2654
|
);
|
2379
2655
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2380
|
-
const permissionChecker2 = getService$
|
2656
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2381
2657
|
userAbility,
|
2382
2658
|
model
|
2383
2659
|
});
|
@@ -2402,7 +2678,7 @@ const relations = {
|
|
2402
2678
|
where.id = id;
|
2403
2679
|
}
|
2404
2680
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2405
|
-
const populate = await getService$
|
2681
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2406
2682
|
const currentEntity = await strapi.db.query(model).findOne({
|
2407
2683
|
where,
|
2408
2684
|
populate
|
@@ -2417,7 +2693,7 @@ const relations = {
|
|
2417
2693
|
}
|
2418
2694
|
entryId = currentEntity.id;
|
2419
2695
|
}
|
2420
|
-
const modelConfig = isComponent2 ? await getService$
|
2696
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2421
2697
|
const targetSchema = strapi.getModel(targetUid);
|
2422
2698
|
const mainField = fp.flow(
|
2423
2699
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2440,7 +2716,7 @@ const relations = {
|
|
2440
2716
|
attribute,
|
2441
2717
|
fieldsToSelect,
|
2442
2718
|
mainField,
|
2443
|
-
source: { schema: sourceSchema },
|
2719
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2444
2720
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2445
2721
|
sourceSchema,
|
2446
2722
|
targetSchema,
|
@@ -2462,7 +2738,8 @@ const relations = {
|
|
2462
2738
|
fieldsToSelect,
|
2463
2739
|
mainField,
|
2464
2740
|
source: {
|
2465
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2741
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2742
|
+
isLocalized: isSourceLocalized
|
2466
2743
|
},
|
2467
2744
|
target: {
|
2468
2745
|
schema: { uid: targetUid },
|
@@ -2470,7 +2747,7 @@ const relations = {
|
|
2470
2747
|
}
|
2471
2748
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2472
2749
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2473
|
-
const permissionChecker2 = getService$
|
2750
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2474
2751
|
userAbility: ctx.state.userAbility,
|
2475
2752
|
model: targetUid
|
2476
2753
|
});
|
@@ -2500,12 +2777,16 @@ const relations = {
|
|
2500
2777
|
} else {
|
2501
2778
|
where.id = id;
|
2502
2779
|
}
|
2503
|
-
|
2504
|
-
|
2780
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2781
|
+
if (!fp.isEmpty(publishedAt)) {
|
2782
|
+
where[`${alias}.published_at`] = publishedAt;
|
2505
2783
|
}
|
2506
|
-
if (
|
2784
|
+
if (isTargetLocalized && locale) {
|
2507
2785
|
where[`${alias}.locale`] = locale;
|
2508
2786
|
}
|
2787
|
+
if (isSourceLocalized && locale) {
|
2788
|
+
where.locale = locale;
|
2789
|
+
}
|
2509
2790
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2510
2791
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2511
2792
|
}
|
@@ -2523,7 +2804,8 @@ const relations = {
|
|
2523
2804
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2524
2805
|
});
|
2525
2806
|
}
|
2526
|
-
const
|
2807
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2808
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2527
2809
|
ctx.body = {
|
2528
2810
|
...res,
|
2529
2811
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2538,29 +2820,39 @@ const relations = {
|
|
2538
2820
|
attribute,
|
2539
2821
|
targetField,
|
2540
2822
|
fieldsToSelect,
|
2541
|
-
|
2542
|
-
|
2543
|
-
}
|
2544
|
-
target: {
|
2545
|
-
schema: { uid: targetUid }
|
2546
|
-
}
|
2823
|
+
status,
|
2824
|
+
source: { schema: sourceSchema },
|
2825
|
+
target: { schema: targetSchema }
|
2547
2826
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2548
|
-
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 });
|
2549
2830
|
const dbQuery = strapi.db.query(sourceUid);
|
2550
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
|
+
}
|
2551
2844
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2552
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2845
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2553
2846
|
ordering: "desc",
|
2554
2847
|
page: ctx.request.query.page,
|
2555
|
-
pageSize: ctx.request.query.pageSize
|
2848
|
+
pageSize: ctx.request.query.pageSize,
|
2849
|
+
filters
|
2556
2850
|
});
|
2557
2851
|
const loadedIds = res.results.map((item) => item.id);
|
2558
2852
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2559
2853
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2560
2854
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2561
|
-
ordering: "desc"
|
2562
|
-
page: ctx.request.query.page,
|
2563
|
-
pageSize: ctx.request.query.pageSize
|
2855
|
+
ordering: "desc"
|
2564
2856
|
});
|
2565
2857
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2566
2858
|
ctx.body = {
|
@@ -2575,10 +2867,10 @@ const relations = {
|
|
2575
2867
|
}
|
2576
2868
|
};
|
2577
2869
|
const buildPopulateFromQuery = async (query, model) => {
|
2578
|
-
return getService$
|
2870
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2579
2871
|
};
|
2580
2872
|
const findDocument = async (query, uid2, opts = {}) => {
|
2581
|
-
const documentManager2 = getService$
|
2873
|
+
const documentManager2 = getService$2("document-manager");
|
2582
2874
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2583
2875
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2584
2876
|
};
|
@@ -2586,13 +2878,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2586
2878
|
const { user, userAbility } = ctx.state;
|
2587
2879
|
const { model } = ctx.params;
|
2588
2880
|
const { body, query } = ctx.request;
|
2589
|
-
const documentManager2 = getService$
|
2590
|
-
const permissionChecker2 = getService$
|
2881
|
+
const documentManager2 = getService$2("document-manager");
|
2882
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2591
2883
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2592
2884
|
throw new strapiUtils.errors.ForbiddenError();
|
2593
2885
|
}
|
2594
2886
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2595
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2887
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2596
2888
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2597
2889
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2598
2890
|
// Find the first document to check if it exists
|
@@ -2628,12 +2920,12 @@ const singleTypes = {
|
|
2628
2920
|
const { userAbility } = ctx.state;
|
2629
2921
|
const { model } = ctx.params;
|
2630
2922
|
const { query = {} } = ctx.request;
|
2631
|
-
const permissionChecker2 = getService$
|
2923
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2632
2924
|
if (permissionChecker2.cannot.read()) {
|
2633
2925
|
return ctx.forbidden();
|
2634
2926
|
}
|
2635
2927
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2636
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2928
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2637
2929
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2638
2930
|
if (!version) {
|
2639
2931
|
if (permissionChecker2.cannot.create()) {
|
@@ -2647,7 +2939,7 @@ const singleTypes = {
|
|
2647
2939
|
permissionChecker2,
|
2648
2940
|
model,
|
2649
2941
|
// @ts-expect-error - fix types
|
2650
|
-
{
|
2942
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2651
2943
|
{ availableLocales: true, availableStatus: false }
|
2652
2944
|
);
|
2653
2945
|
ctx.body = { data: {}, meta };
|
@@ -2662,7 +2954,7 @@ const singleTypes = {
|
|
2662
2954
|
async createOrUpdate(ctx) {
|
2663
2955
|
const { userAbility } = ctx.state;
|
2664
2956
|
const { model } = ctx.params;
|
2665
|
-
const permissionChecker2 = getService$
|
2957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2666
2958
|
const document = await createOrUpdateDocument(ctx);
|
2667
2959
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2668
2960
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2671,14 +2963,14 @@ const singleTypes = {
|
|
2671
2963
|
const { userAbility } = ctx.state;
|
2672
2964
|
const { model } = ctx.params;
|
2673
2965
|
const { query = {} } = ctx.request;
|
2674
|
-
const documentManager2 = getService$
|
2675
|
-
const permissionChecker2 = getService$
|
2966
|
+
const documentManager2 = getService$2("document-manager");
|
2967
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2676
2968
|
if (permissionChecker2.cannot.delete()) {
|
2677
2969
|
return ctx.forbidden();
|
2678
2970
|
}
|
2679
2971
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2680
2972
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2681
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2973
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2682
2974
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2683
2975
|
populate,
|
2684
2976
|
locale
|
@@ -2700,8 +2992,8 @@ const singleTypes = {
|
|
2700
2992
|
const { userAbility } = ctx.state;
|
2701
2993
|
const { model } = ctx.params;
|
2702
2994
|
const { query = {} } = ctx.request;
|
2703
|
-
const documentManager2 = getService$
|
2704
|
-
const permissionChecker2 = getService$
|
2995
|
+
const documentManager2 = getService$2("document-manager");
|
2996
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2705
2997
|
if (permissionChecker2.cannot.publish()) {
|
2706
2998
|
return ctx.forbidden();
|
2707
2999
|
}
|
@@ -2715,7 +3007,7 @@ const singleTypes = {
|
|
2715
3007
|
if (permissionChecker2.cannot.publish(document)) {
|
2716
3008
|
throw new strapiUtils.errors.ForbiddenError();
|
2717
3009
|
}
|
2718
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
3010
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2719
3011
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2720
3012
|
return publishResult.at(0);
|
2721
3013
|
});
|
@@ -2729,8 +3021,8 @@ const singleTypes = {
|
|
2729
3021
|
body: { discardDraft, ...body },
|
2730
3022
|
query = {}
|
2731
3023
|
} = ctx.request;
|
2732
|
-
const documentManager2 = getService$
|
2733
|
-
const permissionChecker2 = getService$
|
3024
|
+
const documentManager2 = getService$2("document-manager");
|
3025
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2734
3026
|
if (permissionChecker2.cannot.unpublish()) {
|
2735
3027
|
return ctx.forbidden();
|
2736
3028
|
}
|
@@ -2738,7 +3030,7 @@ const singleTypes = {
|
|
2738
3030
|
return ctx.forbidden();
|
2739
3031
|
}
|
2740
3032
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2741
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3033
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2742
3034
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2743
3035
|
if (!document) {
|
2744
3036
|
return ctx.notFound();
|
@@ -2764,13 +3056,13 @@ const singleTypes = {
|
|
2764
3056
|
const { userAbility } = ctx.state;
|
2765
3057
|
const { model } = ctx.params;
|
2766
3058
|
const { body, query = {} } = ctx.request;
|
2767
|
-
const documentManager2 = getService$
|
2768
|
-
const permissionChecker2 = getService$
|
3059
|
+
const documentManager2 = getService$2("document-manager");
|
3060
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2769
3061
|
if (permissionChecker2.cannot.discard()) {
|
2770
3062
|
return ctx.forbidden();
|
2771
3063
|
}
|
2772
3064
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2773
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3065
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2774
3066
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2775
3067
|
if (!document) {
|
2776
3068
|
return ctx.notFound();
|
@@ -2788,9 +3080,9 @@ const singleTypes = {
|
|
2788
3080
|
const { userAbility } = ctx.state;
|
2789
3081
|
const { model } = ctx.params;
|
2790
3082
|
const { query } = ctx.request;
|
2791
|
-
const documentManager2 = getService$
|
2792
|
-
const permissionChecker2 = getService$
|
2793
|
-
const { locale } = await 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);
|
2794
3086
|
if (permissionChecker2.cannot.read()) {
|
2795
3087
|
return ctx.forbidden();
|
2796
3088
|
}
|
@@ -2811,9 +3103,9 @@ const uid$1 = {
|
|
2811
3103
|
async generateUID(ctx) {
|
2812
3104
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2813
3105
|
const { query = {} } = ctx.request;
|
2814
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3106
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2815
3107
|
await validateUIDField(contentTypeUID, field);
|
2816
|
-
const uidService = getService$
|
3108
|
+
const uidService = getService$2("uid");
|
2817
3109
|
ctx.body = {
|
2818
3110
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2819
3111
|
};
|
@@ -2823,9 +3115,9 @@ const uid$1 = {
|
|
2823
3115
|
ctx.request.body
|
2824
3116
|
);
|
2825
3117
|
const { query = {} } = ctx.request;
|
2826
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3118
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2827
3119
|
await validateUIDField(contentTypeUID, field);
|
2828
|
-
const uidService = getService$
|
3120
|
+
const uidService = getService$2("uid");
|
2829
3121
|
const isAvailable = await uidService.checkUIDAvailability({
|
2830
3122
|
contentTypeUID,
|
2831
3123
|
field,
|
@@ -2846,7 +3138,8 @@ const controllers = {
|
|
2846
3138
|
relations,
|
2847
3139
|
"single-types": singleTypes,
|
2848
3140
|
uid: uid$1,
|
2849
|
-
...history.controllers ? history.controllers : {}
|
3141
|
+
...history.controllers ? history.controllers : {},
|
3142
|
+
...preview.controllers ? preview.controllers : {}
|
2850
3143
|
};
|
2851
3144
|
const keys = {
|
2852
3145
|
CONFIGURATION: "configuration"
|
@@ -2975,18 +3268,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2975
3268
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2976
3269
|
___default.default.set(acc, [key], updatedMeta);
|
2977
3270
|
}
|
2978
|
-
if (!___default.default.has(edit, "mainField"))
|
2979
|
-
return acc;
|
3271
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2980
3272
|
if (!isRelation$1(attr)) {
|
2981
3273
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2982
3274
|
___default.default.set(acc, [key], updatedMeta);
|
2983
3275
|
return acc;
|
2984
3276
|
}
|
2985
|
-
if (edit.mainField === "id")
|
2986
|
-
return acc;
|
3277
|
+
if (edit.mainField === "id") return acc;
|
2987
3278
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2988
|
-
if (!targetSchema)
|
2989
|
-
return acc;
|
3279
|
+
if (!targetSchema) return acc;
|
2990
3280
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2991
3281
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2992
3282
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -2997,12 +3287,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2997
3287
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
2998
3288
|
}
|
2999
3289
|
const getTargetSchema = (targetModel) => {
|
3000
|
-
return getService$
|
3290
|
+
return getService$2("content-types").findContentType(targetModel);
|
3001
3291
|
};
|
3002
3292
|
const DEFAULT_LIST_LENGTH = 4;
|
3003
3293
|
const MAX_ROW_SIZE = 12;
|
3004
3294
|
const isAllowedFieldSize = (type, size) => {
|
3005
|
-
const { getFieldSize } = getService$
|
3295
|
+
const { getFieldSize } = getService$2("field-sizes");
|
3006
3296
|
const fieldSize = getFieldSize(type);
|
3007
3297
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
3008
3298
|
return false;
|
@@ -3010,7 +3300,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
3010
3300
|
return size <= MAX_ROW_SIZE;
|
3011
3301
|
};
|
3012
3302
|
const getDefaultFieldSize = (attribute) => {
|
3013
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3303
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
3014
3304
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
3015
3305
|
};
|
3016
3306
|
async function createDefaultLayouts(schema) {
|
@@ -3031,8 +3321,7 @@ function createDefaultEditLayout(schema) {
|
|
3031
3321
|
return appendToEditLayout([], keys2, schema);
|
3032
3322
|
}
|
3033
3323
|
function syncLayouts(configuration, schema) {
|
3034
|
-
if (___default.default.isEmpty(configuration.layouts))
|
3035
|
-
return createDefaultLayouts(schema);
|
3324
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3036
3325
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3037
3326
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3038
3327
|
const cleanEditRelations = editRelations.filter(
|
@@ -3043,9 +3332,8 @@ function syncLayouts(configuration, schema) {
|
|
3043
3332
|
for (const row of edit) {
|
3044
3333
|
const newRow = [];
|
3045
3334
|
for (const el of row) {
|
3046
|
-
if (!hasEditableAttribute(schema, el.name))
|
3047
|
-
|
3048
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3335
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3336
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3049
3337
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3050
3338
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3051
3339
|
elementsToReAppend.push(el.name);
|
@@ -3075,8 +3363,7 @@ function syncLayouts(configuration, schema) {
|
|
3075
3363
|
};
|
3076
3364
|
}
|
3077
3365
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3078
|
-
if (keysToAppend.length === 0)
|
3079
|
-
return layout;
|
3366
|
+
if (keysToAppend.length === 0) return layout;
|
3080
3367
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3081
3368
|
if (!layout[currentRowIndex]) {
|
3082
3369
|
layout[currentRowIndex] = [];
|
@@ -3185,17 +3472,17 @@ const configurationService$1 = createConfigurationService({
|
|
3185
3472
|
isComponent: true,
|
3186
3473
|
prefix: STORE_KEY_PREFIX,
|
3187
3474
|
getModels() {
|
3188
|
-
const { toContentManagerModel } = getService$
|
3475
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3189
3476
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3190
3477
|
}
|
3191
3478
|
});
|
3192
3479
|
const components = ({ strapi: strapi2 }) => ({
|
3193
3480
|
findAllComponents() {
|
3194
|
-
const { toContentManagerModel } = getService$
|
3481
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3195
3482
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3196
3483
|
},
|
3197
3484
|
findComponent(uid2) {
|
3198
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3199
3486
|
const component = strapi2.components[uid2];
|
3200
3487
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3201
3488
|
},
|
@@ -3246,17 +3533,17 @@ const configurationService = createConfigurationService({
|
|
3246
3533
|
storeUtils,
|
3247
3534
|
prefix: "content_types",
|
3248
3535
|
getModels() {
|
3249
|
-
const { toContentManagerModel } = getService$
|
3536
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3250
3537
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3251
3538
|
}
|
3252
3539
|
});
|
3253
3540
|
const service = ({ strapi: strapi2 }) => ({
|
3254
3541
|
findAllContentTypes() {
|
3255
|
-
const { toContentManagerModel } = getService$
|
3542
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3256
3543
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3257
3544
|
},
|
3258
3545
|
findContentType(uid2) {
|
3259
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3260
3547
|
const contentType = strapi2.contentTypes[uid2];
|
3261
3548
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3262
3549
|
},
|
@@ -3285,7 +3572,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3285
3572
|
return this.findConfiguration(contentType);
|
3286
3573
|
},
|
3287
3574
|
findComponentsConfigurations(contentType) {
|
3288
|
-
return getService$
|
3575
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3289
3576
|
},
|
3290
3577
|
syncConfigurations() {
|
3291
3578
|
return configurationService.syncConfigurations();
|
@@ -3466,12 +3753,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3466
3753
|
ability: userAbility,
|
3467
3754
|
model
|
3468
3755
|
});
|
3469
|
-
const
|
3756
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3757
|
+
const toSubject = (entity) => {
|
3758
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3759
|
+
};
|
3470
3760
|
const can = (action, entity, field) => {
|
3471
|
-
|
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
|
+
);
|
3472
3768
|
};
|
3473
3769
|
const cannot = (action, entity, field) => {
|
3474
|
-
|
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
|
+
);
|
3475
3777
|
};
|
3476
3778
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3477
3779
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3542,7 +3844,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3542
3844
|
return userAbility.can(action);
|
3543
3845
|
},
|
3544
3846
|
async registerPermissions() {
|
3545
|
-
const displayedContentTypes = getService$
|
3847
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3546
3848
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3547
3849
|
const actions = [
|
3548
3850
|
{
|
@@ -3627,6 +3929,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3627
3929
|
if (initialPopulate) {
|
3628
3930
|
return initialPopulate;
|
3629
3931
|
}
|
3932
|
+
if (attributeName === "localizations") {
|
3933
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3934
|
+
return {
|
3935
|
+
populate: validationPopulate.populate
|
3936
|
+
};
|
3937
|
+
}
|
3630
3938
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3631
3939
|
return true;
|
3632
3940
|
}
|
@@ -3686,6 +3994,9 @@ const getDeepPopulate = (uid2, {
|
|
3686
3994
|
return {};
|
3687
3995
|
}
|
3688
3996
|
const model = strapi.getModel(uid2);
|
3997
|
+
if (!model) {
|
3998
|
+
return {};
|
3999
|
+
}
|
3689
4000
|
return Object.keys(model.attributes).reduce(
|
3690
4001
|
(populateAcc, attributeName) => fp.merge(
|
3691
4002
|
populateAcc,
|
@@ -3705,40 +4016,46 @@ const getDeepPopulate = (uid2, {
|
|
3705
4016
|
{}
|
3706
4017
|
);
|
3707
4018
|
};
|
3708
|
-
const
|
3709
|
-
|
3710
|
-
|
3711
|
-
countOne = false,
|
3712
|
-
maxLevel = Infinity
|
3713
|
-
} = {}, level = 1) => {
|
3714
|
-
if (level > maxLevel) {
|
4019
|
+
const getPopulateForValidation = (uid2) => {
|
4020
|
+
const model = strapi.getModel(uid2);
|
4021
|
+
if (!model) {
|
3715
4022
|
return {};
|
3716
4023
|
}
|
3717
|
-
const model = strapi.getModel(uid2);
|
3718
4024
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3719
|
-
if (
|
4025
|
+
if (isScalarAttribute(attribute)) {
|
4026
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4027
|
+
populateAcc.fields = populateAcc.fields || [];
|
4028
|
+
populateAcc.fields.push(attributeName);
|
4029
|
+
}
|
3720
4030
|
return populateAcc;
|
3721
4031
|
}
|
3722
|
-
if (
|
3723
|
-
|
3724
|
-
|
3725
|
-
|
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;
|
3726
4040
|
}
|
3727
|
-
|
3728
|
-
|
3729
|
-
|
3730
|
-
|
3731
|
-
|
3732
|
-
|
3733
|
-
|
3734
|
-
|
3735
|
-
|
3736
|
-
countOne,
|
3737
|
-
maxLevel
|
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;
|
3738
4050
|
},
|
3739
|
-
|
3740
|
-
)
|
3741
|
-
|
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;
|
3742
4059
|
}, {});
|
3743
4060
|
};
|
3744
4061
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3748,6 +4065,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3748
4065
|
const attribute = model.attributes[attributeName];
|
3749
4066
|
switch (attribute.type) {
|
3750
4067
|
case "relation": {
|
4068
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4069
|
+
if (isMorphRelation) {
|
4070
|
+
break;
|
4071
|
+
}
|
3751
4072
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3752
4073
|
populateAcc[attributeName] = {
|
3753
4074
|
count: true,
|
@@ -3814,7 +4135,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3814
4135
|
return populateQuery;
|
3815
4136
|
};
|
3816
4137
|
const buildDeepPopulate = (uid2) => {
|
3817
|
-
return getService$
|
4138
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3818
4139
|
};
|
3819
4140
|
const populateBuilder = (uid2) => {
|
3820
4141
|
let getInitialPopulate = async () => {
|
@@ -3976,7 +4297,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3976
4297
|
"locale",
|
3977
4298
|
"updatedAt",
|
3978
4299
|
"createdAt",
|
3979
|
-
"status",
|
3980
4300
|
"publishedAt",
|
3981
4301
|
"documentId"
|
3982
4302
|
];
|
@@ -3997,34 +4317,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3997
4317
|
/**
|
3998
4318
|
* Returns available locales of a document for the current status
|
3999
4319
|
*/
|
4000
|
-
async getAvailableLocales(uid2, version, allVersions
|
4320
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
4001
4321
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
4002
|
-
|
4322
|
+
if (version.locale) {
|
4323
|
+
delete versionsByLocale[version.locale];
|
4324
|
+
}
|
4003
4325
|
const model = strapi2.getModel(uid2);
|
4004
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4005
|
-
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4006
|
-
({ key }, { remove }) => {
|
4007
|
-
if (keysToKeep.includes(key)) {
|
4008
|
-
return;
|
4009
|
-
}
|
4010
|
-
remove(key);
|
4011
|
-
},
|
4012
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4013
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4014
|
-
localeVersion
|
4015
|
-
);
|
4016
4326
|
const mappingResult = await strapiUtils.async.map(
|
4017
4327
|
Object.values(versionsByLocale),
|
4018
4328
|
async (localeVersions) => {
|
4019
|
-
const mappedLocaleVersions = await strapiUtils.async.map(
|
4020
|
-
localeVersions,
|
4021
|
-
traversalFunction
|
4022
|
-
);
|
4023
4329
|
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4024
|
-
return
|
4330
|
+
return localeVersions[0];
|
4025
4331
|
}
|
4026
|
-
const draftVersion =
|
4027
|
-
const otherVersions =
|
4332
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4333
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4028
4334
|
if (!draftVersion) {
|
4029
4335
|
return;
|
4030
4336
|
}
|
@@ -4046,8 +4352,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4046
4352
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4047
4353
|
return matchLocale && matchStatus;
|
4048
4354
|
});
|
4049
|
-
if (!availableStatus)
|
4050
|
-
return availableStatus;
|
4355
|
+
if (!availableStatus) return availableStatus;
|
4051
4356
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4052
4357
|
},
|
4053
4358
|
/**
|
@@ -4057,18 +4362,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4057
4362
|
* @returns
|
4058
4363
|
*/
|
4059
4364
|
async getManyAvailableStatus(uid2, documents) {
|
4060
|
-
if (!documents.length)
|
4061
|
-
return [];
|
4365
|
+
if (!documents.length) return [];
|
4062
4366
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4063
|
-
const
|
4064
|
-
const
|
4065
|
-
|
4066
|
-
|
4067
|
-
|
4068
|
-
|
4069
|
-
|
4070
|
-
|
4071
|
-
|
4367
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4368
|
+
const where = {
|
4369
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4370
|
+
publishedAt: { $null: status === "published" }
|
4371
|
+
};
|
4372
|
+
if (locales.length) {
|
4373
|
+
where.locale = { $in: locales };
|
4374
|
+
}
|
4375
|
+
return strapi2.query(uid2).findMany({
|
4376
|
+
where,
|
4377
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4072
4378
|
});
|
4073
4379
|
},
|
4074
4380
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4085,10 +4391,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4085
4391
|
} else if (otherVersion) {
|
4086
4392
|
draftVersion = otherVersion;
|
4087
4393
|
}
|
4088
|
-
if (!draftVersion)
|
4089
|
-
|
4090
|
-
if (!publishedVersion)
|
4091
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4394
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4395
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4092
4396
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4093
4397
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4094
4398
|
},
|
@@ -4096,11 +4400,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4096
4400
|
// We could refactor this so the locales are only loaded when they're
|
4097
4401
|
// needed. e.g. in the bulk locale action modal.
|
4098
4402
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4099
|
-
const populate =
|
4100
|
-
const
|
4101
|
-
where: { documentId: version.documentId },
|
4403
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4404
|
+
const params = {
|
4102
4405
|
populate: {
|
4103
|
-
// Populate only fields that require validation for bulk locale actions
|
4104
4406
|
...populate,
|
4105
4407
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4106
4408
|
createdBy: {
|
@@ -4109,9 +4411,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4109
4411
|
updatedBy: {
|
4110
4412
|
select: ["id", "firstname", "lastname", "email"]
|
4111
4413
|
}
|
4414
|
+
},
|
4415
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4416
|
+
filters: {
|
4417
|
+
documentId: version.documentId
|
4112
4418
|
}
|
4113
|
-
}
|
4114
|
-
const
|
4419
|
+
};
|
4420
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4421
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4422
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
4115
4423
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4116
4424
|
return {
|
4117
4425
|
availableLocales: availableLocalesResult,
|
@@ -4125,13 +4433,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4125
4433
|
*/
|
4126
4434
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4127
4435
|
if (!document) {
|
4128
|
-
return
|
4436
|
+
return {
|
4437
|
+
data: document,
|
4438
|
+
meta: {
|
4439
|
+
availableLocales: [],
|
4440
|
+
availableStatus: []
|
4441
|
+
}
|
4442
|
+
};
|
4129
4443
|
}
|
4130
4444
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4131
4445
|
if (!hasDraftAndPublish) {
|
4132
4446
|
opts.availableStatus = false;
|
4133
4447
|
}
|
4134
4448
|
const meta = await this.getMetadata(uid2, document, opts);
|
4449
|
+
if (document.localizations) {
|
4450
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4451
|
+
document.localizations = document.localizations.map((d) => {
|
4452
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4453
|
+
return {
|
4454
|
+
...d,
|
4455
|
+
status: this.getStatus(d, status ? [status] : [])
|
4456
|
+
};
|
4457
|
+
});
|
4458
|
+
}
|
4135
4459
|
return {
|
4136
4460
|
data: {
|
4137
4461
|
...document,
|
@@ -4233,10 +4557,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4233
4557
|
async clone(id, body, uid2) {
|
4234
4558
|
const populate = await buildDeepPopulate(uid2);
|
4235
4559
|
const params = {
|
4236
|
-
data:
|
4237
|
-
...omitIdField(body),
|
4238
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4239
|
-
},
|
4560
|
+
data: omitIdField(body),
|
4240
4561
|
populate
|
4241
4562
|
};
|
4242
4563
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4352,7 +4673,8 @@ const services = {
|
|
4352
4673
|
permission,
|
4353
4674
|
"populate-builder": populateBuilder$1,
|
4354
4675
|
uid,
|
4355
|
-
...history.services ? history.services : {}
|
4676
|
+
...history.services ? history.services : {},
|
4677
|
+
...preview.services ? preview.services : {}
|
4356
4678
|
};
|
4357
4679
|
const index = () => {
|
4358
4680
|
return {
|