@strapi/content-manager 0.0.0-experimental.d954d57341a6623992a0d211daaec8e245c3517d → 0.0.0-experimental.dad3c50630ca4fd9eccdcbe549ee632fc572e23d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js → ComponentConfigurationPage-BLWQy8ru.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js.map → ComponentConfigurationPage-BLWQy8ru.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs → ComponentConfigurationPage-CtIa3aa2.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs.map → ComponentConfigurationPage-CtIa3aa2.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-BwuIPOJG.mjs → EditConfigurationPage-DsPR2DVk.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs.map → EditConfigurationPage-DsPR2DVk.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js → EditConfigurationPage-RQkymxCy.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js.map → EditConfigurationPage-RQkymxCy.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DbcGfyqK.js → EditViewPage-B-kExt8C.js} +63 -13
- package/dist/_chunks/EditViewPage-B-kExt8C.js.map +1 -0
- package/dist/_chunks/{EditViewPage-0MiFkXa8.mjs → EditViewPage-BPyVuPfM.mjs} +63 -12
- package/dist/_chunks/EditViewPage-BPyVuPfM.mjs.map +1 -0
- package/dist/_chunks/{Field-BG1xu38N.js → Field-DPIsQRre.js} +680 -261
- package/dist/_chunks/Field-DPIsQRre.js.map +1 -0
- package/dist/_chunks/{Field-BDMSCcy5.mjs → Field-Dltnt1km.mjs} +676 -257
- package/dist/_chunks/Field-Dltnt1km.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-9BnFyUjy.js → Form-BFi4MXMT.js} +43 -22
- package/dist/_chunks/Form-BFi4MXMT.js.map +1 -0
- package/dist/_chunks/{Form-CPVWavB8.mjs → Form-C1IcWm1u.mjs} +41 -19
- package/dist/_chunks/Form-C1IcWm1u.mjs.map +1 -0
- package/dist/_chunks/{History-BVpd8LP3.mjs → History-04ChQ4pl.mjs} +108 -116
- package/dist/_chunks/History-04ChQ4pl.mjs.map +1 -0
- package/dist/_chunks/{History-BWWxLt2Z.js → History-wjcK4L0C.js} +107 -116
- package/dist/_chunks/History-wjcK4L0C.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DozVMKcR.mjs → ListConfigurationPage-BYqPYLSU.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-BYqPYLSU.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-6swzjdAZ.js → ListConfigurationPage-CRbxIC3J.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-CRbxIC3J.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BlzfjS2Q.js → ListViewPage-D5NY9183.js} +121 -81
- package/dist/_chunks/ListViewPage-D5NY9183.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Ds0ulgfG.mjs → ListViewPage-FU2LBuhl.mjs} +118 -77
- package/dist/_chunks/ListViewPage-FU2LBuhl.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js → NoContentTypePage-BgQVE_Qb.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js.map → NoContentTypePage-BgQVE_Qb.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs → NoContentTypePage-DCKUkwb8.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs.map → NoContentTypePage-DCKUkwb8.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js → NoPermissionsPage-C5jwn70o.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js.map → NoPermissionsPage-C5jwn70o.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs → NoPermissionsPage-jqve7C8l.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs.map → NoPermissionsPage-jqve7C8l.mjs.map} +1 -1
- package/dist/_chunks/Preview-BMYN548c.mjs +294 -0
- package/dist/_chunks/Preview-BMYN548c.mjs.map +1 -0
- package/dist/_chunks/Preview-DaOihysv.js +312 -0
- package/dist/_chunks/Preview-DaOihysv.js.map +1 -0
- package/dist/_chunks/{Relations-CcgFTcWo.js → Relations-CTGM7Hv5.js} +76 -43
- package/dist/_chunks/Relations-CTGM7Hv5.js.map +1 -0
- package/dist/_chunks/{Relations-Dnag3fhV.mjs → Relations-gscPkxjF.mjs} +76 -42
- package/dist/_chunks/Relations-gscPkxjF.mjs.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-CWpLBSt0.js → index-Ca7YWlAA.js} +1271 -746
- package/dist/_chunks/index-Ca7YWlAA.js.map +1 -0
- package/dist/_chunks/{index-JNNNKUHs.mjs → index-DqasUQ6Q.mjs} +1288 -763
- package/dist/_chunks/index-DqasUQ6Q.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout--iHdZzRk.js → layout-BW80JSCd.js} +27 -15
- package/dist/_chunks/layout-BW80JSCd.js.map +1 -0
- package/dist/_chunks/{layout-DC503LnF.mjs → layout-W3clJSCy.mjs} +28 -15
- package/dist/_chunks/layout-W3clJSCy.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-CTje5t-a.mjs → relations-BlDkoeWh.mjs} +6 -7
- package/dist/_chunks/relations-BlDkoeWh.mjs.map +1 -0
- package/dist/_chunks/{relations-BbHizA5K.js → relations-C9Usz9k5.js} +6 -7
- package/dist/_chunks/relations-C9Usz9k5.js.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 +5 -3
- 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 +5 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/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 +765 -437
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +766 -437
- 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/controllers/history-version.d.ts +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts +3 -3
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +8 -12
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -15
- package/dist/_chunks/EditViewPage-0MiFkXa8.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DbcGfyqK.js.map +0 -1
- package/dist/_chunks/Field-BDMSCcy5.mjs.map +0 -1
- package/dist/_chunks/Field-BG1xu38N.js.map +0 -1
- package/dist/_chunks/Form-9BnFyUjy.js.map +0 -1
- package/dist/_chunks/Form-CPVWavB8.mjs.map +0 -1
- package/dist/_chunks/History-BVpd8LP3.mjs.map +0 -1
- package/dist/_chunks/History-BWWxLt2Z.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-6swzjdAZ.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DozVMKcR.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BlzfjS2Q.js.map +0 -1
- package/dist/_chunks/ListViewPage-Ds0ulgfG.mjs.map +0 -1
- package/dist/_chunks/Relations-CcgFTcWo.js.map +0 -1
- package/dist/_chunks/Relations-Dnag3fhV.mjs.map +0 -1
- package/dist/_chunks/index-CWpLBSt0.js.map +0 -1
- package/dist/_chunks/index-JNNNKUHs.mjs.map +0 -1
- package/dist/_chunks/layout--iHdZzRk.js.map +0 -1
- package/dist/_chunks/layout-DC503LnF.mjs.map +0 -1
- package/dist/_chunks/relations-BbHizA5K.js.map +0 -1
- package/dist/_chunks/relations-CTje5t-a.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({
|
@@ -177,19 +175,16 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
177
175
|
});
|
178
176
|
})
|
179
177
|
);
|
180
|
-
return existingAndMissingRelations.filter(
|
181
|
-
(relation) => relation !== null
|
182
|
-
);
|
178
|
+
return existingAndMissingRelations.filter((relation) => relation !== null);
|
183
179
|
}
|
184
180
|
return strapi2.documents(attribute.target).findOne({
|
185
181
|
documentId: versionRelationData.documentId,
|
186
182
|
locale: versionRelationData.locale || void 0
|
187
183
|
});
|
188
184
|
};
|
189
|
-
const getMediaRestoreValue = async (versionRelationData
|
190
|
-
if (
|
185
|
+
const getMediaRestoreValue = async (versionRelationData) => {
|
186
|
+
if (Array.isArray(versionRelationData)) {
|
191
187
|
const existingAndMissingMedias = await Promise.all(
|
192
|
-
// @ts-expect-error Fix the type definitions so this isn't any
|
193
188
|
versionRelationData.map((media) => {
|
194
189
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
195
190
|
})
|
@@ -199,10 +194,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
199
194
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
200
195
|
};
|
201
196
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
197
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
202
198
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
199
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
203
200
|
const getLocaleDictionary = async () => {
|
204
|
-
if (!localesService)
|
205
|
-
return {};
|
201
|
+
if (!localesService) return {};
|
206
202
|
const locales = await localesService.find() || [];
|
207
203
|
return locales.reduce(
|
208
204
|
(acc, locale) => {
|
@@ -226,31 +222,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
222
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
223
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
224
|
};
|
229
|
-
const
|
225
|
+
const getComponentFields = (componentUID) => {
|
226
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
227
|
+
(fieldsAcc, [key, attribute]) => {
|
228
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
229
|
+
fieldsAcc.push(key);
|
230
|
+
}
|
231
|
+
return fieldsAcc;
|
232
|
+
},
|
233
|
+
[]
|
234
|
+
);
|
235
|
+
};
|
236
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
237
|
const model = strapi2.getModel(uid2);
|
231
238
|
const attributes = Object.entries(model.attributes);
|
239
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
240
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
241
|
switch (attribute.type) {
|
234
242
|
case "relation": {
|
243
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
244
|
+
if (isMorphRelation) {
|
245
|
+
break;
|
246
|
+
}
|
235
247
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
248
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
249
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
250
|
}
|
239
251
|
break;
|
240
252
|
}
|
241
253
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
254
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
255
|
break;
|
244
256
|
}
|
245
257
|
case "component": {
|
246
258
|
const populate = getDeepPopulate2(attribute.component);
|
247
|
-
acc[attributeName] = {
|
259
|
+
acc[attributeName] = {
|
260
|
+
populate,
|
261
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
262
|
+
};
|
248
263
|
break;
|
249
264
|
}
|
250
265
|
case "dynamiczone": {
|
251
266
|
const populatedComponents = (attribute.components || []).reduce(
|
252
267
|
(acc2, componentUID) => {
|
253
|
-
acc2[componentUID] = {
|
268
|
+
acc2[componentUID] = {
|
269
|
+
populate: getDeepPopulate2(componentUID),
|
270
|
+
[fieldSelector]: getComponentFields(componentUID)
|
271
|
+
};
|
254
272
|
return acc2;
|
255
273
|
},
|
256
274
|
{}
|
@@ -312,6 +330,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
312
330
|
getRelationRestoreValue,
|
313
331
|
getMediaRestoreValue,
|
314
332
|
getDefaultLocale,
|
333
|
+
isLocalizedContentType,
|
315
334
|
getLocaleDictionary,
|
316
335
|
getRetentionDays,
|
317
336
|
getVersionStatus,
|
@@ -334,7 +353,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
353
|
});
|
335
354
|
},
|
336
355
|
async findVersionsPage(params) {
|
337
|
-
const
|
356
|
+
const schema = strapi2.getModel(params.query.contentType);
|
357
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(schema);
|
358
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
359
|
+
let locale = null;
|
360
|
+
if (isLocalizedContentType) {
|
361
|
+
locale = params.query.locale || defaultLocale;
|
362
|
+
}
|
338
363
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
339
364
|
query.findPage({
|
340
365
|
...params.query,
|
@@ -350,78 +375,76 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
350
375
|
}),
|
351
376
|
serviceUtils.getLocaleDictionary()
|
352
377
|
]);
|
353
|
-
const
|
354
|
-
|
355
|
-
async (
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
model: "plugin::upload.file"
|
362
|
-
});
|
363
|
-
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
364
|
-
const sanitizedResults = await Promise.all(
|
365
|
-
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
366
|
-
);
|
367
|
-
return {
|
368
|
-
...await currentDataWithRelations,
|
369
|
-
[attributeKey]: {
|
370
|
-
results: sanitizedResults,
|
371
|
-
meta: response.meta
|
372
|
-
}
|
373
|
-
};
|
378
|
+
const populateEntry = async (entry) => {
|
379
|
+
return strapiUtils.traverseEntity(
|
380
|
+
async (options, utils) => {
|
381
|
+
if (!options.attribute) return;
|
382
|
+
if (!options.value) return;
|
383
|
+
const currentValue = Array.isArray(options.value) ? options.value : [options.value];
|
384
|
+
if (options.attribute.type === "component") {
|
385
|
+
utils.remove("id");
|
374
386
|
}
|
375
|
-
if (
|
376
|
-
|
387
|
+
if (options.attribute.type === "relation" && // TODO: handle polymorphic relations
|
388
|
+
options.attribute.relation !== "morphToOne" && options.attribute.relation !== "morphToMany") {
|
389
|
+
if (options.attribute.target === "admin::user") {
|
377
390
|
const adminUsers = await Promise.all(
|
378
|
-
|
391
|
+
currentValue.map((userToPopulate) => {
|
379
392
|
if (userToPopulate == null) {
|
380
393
|
return null;
|
381
394
|
}
|
382
|
-
return strapi2.query("admin::user").findOne({
|
395
|
+
return strapi2.query("admin::user").findOne({
|
396
|
+
where: {
|
397
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
398
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
399
|
+
}
|
400
|
+
});
|
383
401
|
})
|
384
402
|
);
|
385
|
-
|
386
|
-
...await currentDataWithRelations,
|
387
|
-
/**
|
388
|
-
* Ideally we would return the same "{results: [], meta: {}}" shape, however,
|
389
|
-
* when sanitizing the data as a whole in the controller before sending to the client,
|
390
|
-
* the data for admin relation user is completely sanitized if we return an object here as opposed to an array.
|
391
|
-
*/
|
392
|
-
[attributeKey]: adminUsers
|
393
|
-
};
|
403
|
+
utils.set(options.key, adminUsers);
|
394
404
|
}
|
395
|
-
const permissionChecker2 = getService$
|
405
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
396
406
|
userAbility: params.state.userAbility,
|
397
|
-
model:
|
407
|
+
model: options.attribute.target
|
398
408
|
});
|
399
409
|
const response = await serviceUtils.buildRelationReponse(
|
400
|
-
|
401
|
-
|
410
|
+
currentValue,
|
411
|
+
options.attribute
|
402
412
|
);
|
403
413
|
const sanitizedResults = await Promise.all(
|
404
414
|
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
405
415
|
);
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
meta: response.meta
|
411
|
-
}
|
412
|
-
};
|
416
|
+
utils.set(options.key, {
|
417
|
+
results: sanitizedResults,
|
418
|
+
meta: response.meta
|
419
|
+
});
|
413
420
|
}
|
414
|
-
|
421
|
+
if (options.attribute.type === "media") {
|
422
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
423
|
+
userAbility: params.state.userAbility,
|
424
|
+
model: "plugin::upload.file"
|
425
|
+
});
|
426
|
+
const response = await serviceUtils.buildMediaResponse(currentValue);
|
427
|
+
const sanitizedResults = await Promise.all(
|
428
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
429
|
+
);
|
430
|
+
utils.set(options.key, {
|
431
|
+
results: sanitizedResults,
|
432
|
+
meta: response.meta
|
433
|
+
});
|
434
|
+
}
|
435
|
+
},
|
436
|
+
{
|
437
|
+
schema,
|
438
|
+
getModel: strapi2.getModel.bind(strapi2)
|
415
439
|
},
|
416
|
-
|
440
|
+
entry.data
|
417
441
|
);
|
418
|
-
return entryWithRelations;
|
419
442
|
};
|
420
443
|
const formattedResults = await Promise.all(
|
421
444
|
results.map(async (result) => {
|
422
445
|
return {
|
423
446
|
...result,
|
424
|
-
data: await
|
447
|
+
data: await populateEntry(result),
|
425
448
|
meta: {
|
426
449
|
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
427
450
|
result.schema,
|
@@ -452,30 +475,44 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
452
475
|
// Clone to avoid mutating the original version data
|
453
476
|
structuredClone(version.data)
|
454
477
|
);
|
455
|
-
const
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
478
|
+
const schema = structuredClone(version.schema);
|
479
|
+
schema.attributes = fp.omit(FIELDS_TO_IGNORE, contentTypeSchemaAttributes);
|
480
|
+
const dataWithoutMissingRelations = await strapiUtils.traverseEntity(
|
481
|
+
async (options, utils) => {
|
482
|
+
if (!options.attribute) return;
|
483
|
+
if (options.attribute.type === "component") {
|
484
|
+
utils.remove("id");
|
485
|
+
if (options.attribute.repeatable && options.value === null) {
|
486
|
+
utils.set(options.key, []);
|
487
|
+
}
|
465
488
|
}
|
466
|
-
if (attribute.type === "
|
467
|
-
|
468
|
-
|
469
|
-
|
489
|
+
if (options.attribute.type === "dynamiczone") {
|
490
|
+
if (options.value === null) {
|
491
|
+
utils.set(options.key, []);
|
492
|
+
}
|
470
493
|
}
|
471
|
-
if (attribute.type === "
|
472
|
-
|
473
|
-
|
494
|
+
if (options.attribute.type === "relation" && // TODO: handle polymorphic relations
|
495
|
+
options.attribute.relation !== "morphToOne" && options.attribute.relation !== "morphToMany") {
|
496
|
+
if (!options.value) return;
|
497
|
+
const data2 = await serviceUtils.getRelationRestoreValue(
|
498
|
+
options.value,
|
499
|
+
options.attribute
|
500
|
+
);
|
501
|
+
utils.set(options.key, data2);
|
502
|
+
}
|
503
|
+
if (options.attribute.type === "media") {
|
504
|
+
if (!options.value) return;
|
505
|
+
const data2 = await serviceUtils.getMediaRestoreValue(
|
506
|
+
options.value
|
507
|
+
);
|
508
|
+
utils.set(options.key, data2);
|
474
509
|
}
|
475
|
-
return previousRelationAttributes;
|
476
510
|
},
|
477
|
-
|
478
|
-
|
511
|
+
{
|
512
|
+
schema,
|
513
|
+
getModel: strapi2.getModel.bind(strapi2)
|
514
|
+
},
|
515
|
+
dataWithoutAddedAttributes
|
479
516
|
);
|
480
517
|
const data = fp.omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
481
518
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -490,13 +527,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
527
|
}
|
491
528
|
};
|
492
529
|
};
|
530
|
+
const shouldCreateHistoryVersion = (context) => {
|
531
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
532
|
+
return false;
|
533
|
+
}
|
534
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
535
|
+
return false;
|
536
|
+
}
|
537
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
538
|
+
return false;
|
539
|
+
}
|
540
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
541
|
+
return false;
|
542
|
+
}
|
543
|
+
return true;
|
544
|
+
};
|
545
|
+
const getSchemas = (uid2) => {
|
546
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
547
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
548
|
+
(currentComponentSchemas, key) => {
|
549
|
+
const fieldSchema = attributesSchema[key];
|
550
|
+
if (fieldSchema.type === "component") {
|
551
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
552
|
+
return {
|
553
|
+
...currentComponentSchemas,
|
554
|
+
[fieldSchema.component]: componentSchema
|
555
|
+
};
|
556
|
+
}
|
557
|
+
return currentComponentSchemas;
|
558
|
+
},
|
559
|
+
{}
|
560
|
+
);
|
561
|
+
return {
|
562
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
563
|
+
componentsSchemas
|
564
|
+
};
|
565
|
+
};
|
493
566
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
567
|
const state = {
|
495
568
|
deleteExpiredJob: null,
|
496
569
|
isInitialized: false
|
497
570
|
};
|
498
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
-
const historyService = getService(strapi2, "history");
|
500
571
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
572
|
return {
|
502
573
|
async bootstrap() {
|
@@ -504,76 +575,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
504
575
|
return;
|
505
576
|
}
|
506
577
|
strapi2.documents.use(async (context, next) => {
|
507
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
508
|
-
return next();
|
509
|
-
}
|
510
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
511
|
-
return next();
|
512
|
-
}
|
513
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
514
|
-
return next();
|
515
|
-
}
|
516
|
-
const contentTypeUid = context.contentType.uid;
|
517
|
-
if (!contentTypeUid.startsWith("api::")) {
|
518
|
-
return next();
|
519
|
-
}
|
520
578
|
const result = await next();
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
579
|
+
if (!shouldCreateHistoryVersion(context)) {
|
580
|
+
return result;
|
581
|
+
}
|
582
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
525
583
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
526
|
-
const
|
527
|
-
if (
|
528
|
-
|
529
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
530
|
-
);
|
531
|
-
return next();
|
584
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
585
|
+
if (!locales.length) {
|
586
|
+
return result;
|
532
587
|
}
|
533
|
-
const
|
534
|
-
|
535
|
-
|
536
|
-
|
588
|
+
const uid2 = context.contentType.uid;
|
589
|
+
const schemas = getSchemas(uid2);
|
590
|
+
const model = strapi2.getModel(uid2);
|
591
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
592
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
593
|
+
where: {
|
594
|
+
documentId,
|
595
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
596
|
+
...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
597
|
+
},
|
598
|
+
populate: serviceUtils.getDeepPopulate(
|
599
|
+
uid2,
|
600
|
+
true
|
601
|
+
/* use database syntax */
|
602
|
+
)
|
537
603
|
});
|
538
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
539
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
540
|
-
const componentsSchemas = Object.keys(
|
541
|
-
attributesSchema
|
542
|
-
).reduce((currentComponentSchemas, key) => {
|
543
|
-
const fieldSchema = attributesSchema[key];
|
544
|
-
if (fieldSchema.type === "component") {
|
545
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
546
|
-
return {
|
547
|
-
...currentComponentSchemas,
|
548
|
-
[fieldSchema.component]: componentSchema
|
549
|
-
};
|
550
|
-
}
|
551
|
-
return currentComponentSchemas;
|
552
|
-
}, {});
|
553
604
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
554
|
-
onCommit(() => {
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
605
|
+
onCommit(async () => {
|
606
|
+
for (const entry of localeEntries) {
|
607
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
608
|
+
await getService$1(strapi2, "history").createVersion({
|
609
|
+
contentType: uid2,
|
610
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
611
|
+
relatedDocumentId: documentId,
|
612
|
+
locale: entry.locale,
|
613
|
+
status,
|
614
|
+
...schemas
|
615
|
+
});
|
616
|
+
}
|
564
617
|
});
|
565
618
|
});
|
566
619
|
return result;
|
567
620
|
});
|
568
|
-
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
621
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
569
622
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
570
623
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
571
|
-
query.deleteMany({
|
624
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
572
625
|
where: {
|
573
626
|
created_at: {
|
574
|
-
$lt: expirationDate
|
627
|
+
$lt: expirationDate
|
575
628
|
}
|
576
629
|
}
|
630
|
+
}).catch((error) => {
|
631
|
+
if (error instanceof Error) {
|
632
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
633
|
+
}
|
577
634
|
});
|
578
635
|
});
|
579
636
|
state.isInitialized = true;
|
@@ -585,17 +642,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
585
642
|
}
|
586
643
|
};
|
587
644
|
};
|
588
|
-
const services$
|
645
|
+
const services$2 = {
|
589
646
|
history: createHistoryService,
|
590
647
|
lifecycles: createLifecyclesService
|
591
648
|
};
|
592
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
649
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
593
650
|
const historyVersionRouter = {
|
594
651
|
type: "admin",
|
595
652
|
routes: [
|
596
653
|
{
|
597
654
|
method: "GET",
|
598
|
-
info,
|
655
|
+
info: info$1,
|
599
656
|
path: "/history-versions",
|
600
657
|
handler: "history-version.findMany",
|
601
658
|
config: {
|
@@ -604,7 +661,7 @@ const historyVersionRouter = {
|
|
604
661
|
},
|
605
662
|
{
|
606
663
|
method: "PUT",
|
607
|
-
info,
|
664
|
+
info: info$1,
|
608
665
|
path: "/history-versions/:versionId/restore",
|
609
666
|
handler: "history-version.restoreVersion",
|
610
667
|
config: {
|
@@ -613,7 +670,7 @@ const historyVersionRouter = {
|
|
613
670
|
}
|
614
671
|
]
|
615
672
|
};
|
616
|
-
const routes$
|
673
|
+
const routes$2 = {
|
617
674
|
"history-version": historyVersionRouter
|
618
675
|
};
|
619
676
|
const historyVersion = {
|
@@ -660,21 +717,21 @@ const historyVersion = {
|
|
660
717
|
}
|
661
718
|
}
|
662
719
|
};
|
663
|
-
const getFeature = () => {
|
720
|
+
const getFeature$1 = () => {
|
664
721
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
665
722
|
return {
|
666
723
|
register({ strapi: strapi2 }) {
|
667
724
|
strapi2.get("models").add(historyVersion);
|
668
725
|
},
|
669
726
|
bootstrap({ strapi: strapi2 }) {
|
670
|
-
getService(strapi2, "lifecycles").bootstrap();
|
727
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
671
728
|
},
|
672
729
|
destroy({ strapi: strapi2 }) {
|
673
|
-
getService(strapi2, "lifecycles").destroy();
|
730
|
+
getService$1(strapi2, "lifecycles").destroy();
|
674
731
|
},
|
675
|
-
controllers: controllers$
|
676
|
-
services: services$
|
677
|
-
routes: routes$
|
732
|
+
controllers: controllers$2,
|
733
|
+
services: services$2,
|
734
|
+
routes: routes$2
|
678
735
|
};
|
679
736
|
}
|
680
737
|
return {
|
@@ -683,9 +740,201 @@ const getFeature = () => {
|
|
683
740
|
}
|
684
741
|
};
|
685
742
|
};
|
686
|
-
const history = getFeature();
|
743
|
+
const history = getFeature$1();
|
744
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
745
|
+
const previewRouter = {
|
746
|
+
type: "admin",
|
747
|
+
routes: [
|
748
|
+
{
|
749
|
+
method: "GET",
|
750
|
+
info,
|
751
|
+
path: "/preview/url/:contentType",
|
752
|
+
handler: "preview.getPreviewUrl",
|
753
|
+
config: {
|
754
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
755
|
+
}
|
756
|
+
}
|
757
|
+
]
|
758
|
+
};
|
759
|
+
const routes$1 = {
|
760
|
+
preview: previewRouter
|
761
|
+
};
|
762
|
+
function getService(strapi2, name) {
|
763
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
764
|
+
}
|
765
|
+
const getPreviewUrlSchema = yup__namespace.object().shape({
|
766
|
+
// Will be undefined for single types
|
767
|
+
documentId: yup__namespace.string(),
|
768
|
+
locale: yup__namespace.string().nullable(),
|
769
|
+
status: yup__namespace.string()
|
770
|
+
}).required();
|
771
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
772
|
+
await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
|
773
|
+
const newParams = fp.pick(["documentId", "locale", "status"], params);
|
774
|
+
const model = strapi2.getModel(uid2);
|
775
|
+
if (!model || model.modelType !== "contentType") {
|
776
|
+
throw new strapiUtils.errors.ValidationError("Invalid content type");
|
777
|
+
}
|
778
|
+
const isSingleType = model?.kind === "singleType";
|
779
|
+
if (!isSingleType && !params.documentId) {
|
780
|
+
throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
|
781
|
+
}
|
782
|
+
if (isSingleType) {
|
783
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
784
|
+
if (!doc) {
|
785
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
786
|
+
}
|
787
|
+
newParams.documentId = doc?.documentId;
|
788
|
+
}
|
789
|
+
if (!newParams.status) {
|
790
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
791
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
792
|
+
}
|
793
|
+
return newParams;
|
794
|
+
};
|
795
|
+
const createPreviewController = () => {
|
796
|
+
return {
|
797
|
+
/**
|
798
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
799
|
+
* in the Content Manager.
|
800
|
+
*/
|
801
|
+
async getPreviewUrl(ctx) {
|
802
|
+
const uid2 = ctx.params.contentType;
|
803
|
+
const query = ctx.request.query;
|
804
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
805
|
+
const previewService = getService(strapi, "preview");
|
806
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
807
|
+
if (!url) {
|
808
|
+
ctx.status = 204;
|
809
|
+
}
|
810
|
+
return {
|
811
|
+
data: { url }
|
812
|
+
};
|
813
|
+
}
|
814
|
+
};
|
815
|
+
};
|
816
|
+
const controllers$1 = {
|
817
|
+
preview: createPreviewController
|
818
|
+
/**
|
819
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
820
|
+
* passing a controller factory as the value, instead of a controller object directly
|
821
|
+
*/
|
822
|
+
};
|
823
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
824
|
+
const config = getService(strapi2, "preview-config");
|
825
|
+
return {
|
826
|
+
async getPreviewUrl(uid2, params) {
|
827
|
+
const handler = config.getPreviewHandler();
|
828
|
+
try {
|
829
|
+
return handler(uid2, params);
|
830
|
+
} catch (error) {
|
831
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
832
|
+
throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
|
833
|
+
}
|
834
|
+
return;
|
835
|
+
}
|
836
|
+
};
|
837
|
+
};
|
838
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
839
|
+
const middlewares = strapi.config.get("middlewares");
|
840
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
841
|
+
if (currentMiddleware === middleware.name) {
|
842
|
+
return middleware;
|
843
|
+
}
|
844
|
+
if (currentMiddleware.name === middleware.name) {
|
845
|
+
return fp.mergeWith(
|
846
|
+
(objValue, srcValue) => {
|
847
|
+
if (Array.isArray(objValue)) {
|
848
|
+
return objValue.concat(srcValue);
|
849
|
+
}
|
850
|
+
return void 0;
|
851
|
+
},
|
852
|
+
currentMiddleware,
|
853
|
+
middleware
|
854
|
+
);
|
855
|
+
}
|
856
|
+
return currentMiddleware;
|
857
|
+
});
|
858
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
859
|
+
};
|
860
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
861
|
+
return {
|
862
|
+
register() {
|
863
|
+
if (!this.isEnabled()) {
|
864
|
+
return;
|
865
|
+
}
|
866
|
+
const config = strapi2.config.get("admin.preview");
|
867
|
+
if (config.config?.allowedOrigins) {
|
868
|
+
extendMiddlewareConfiguration({
|
869
|
+
name: "strapi::security",
|
870
|
+
config: {
|
871
|
+
contentSecurityPolicy: {
|
872
|
+
directives: {
|
873
|
+
"frame-src": config.config.allowedOrigins
|
874
|
+
}
|
875
|
+
}
|
876
|
+
}
|
877
|
+
});
|
878
|
+
}
|
879
|
+
},
|
880
|
+
isEnabled() {
|
881
|
+
const config = strapi2.config.get("admin.preview");
|
882
|
+
if (!config) {
|
883
|
+
return false;
|
884
|
+
}
|
885
|
+
return config?.enabled ?? true;
|
886
|
+
},
|
887
|
+
/**
|
888
|
+
* Validate if the configuration is valid
|
889
|
+
*/
|
890
|
+
validate() {
|
891
|
+
if (!this.isEnabled()) {
|
892
|
+
return;
|
893
|
+
}
|
894
|
+
const handler = this.getPreviewHandler();
|
895
|
+
if (typeof handler !== "function") {
|
896
|
+
throw new strapiUtils.errors.ValidationError(
|
897
|
+
"Preview configuration is invalid. Handler must be a function"
|
898
|
+
);
|
899
|
+
}
|
900
|
+
},
|
901
|
+
/**
|
902
|
+
* Utility to get the preview handler from the configuration
|
903
|
+
*/
|
904
|
+
getPreviewHandler() {
|
905
|
+
const config = strapi2.config.get("admin.preview");
|
906
|
+
const emptyHandler = () => {
|
907
|
+
return void 0;
|
908
|
+
};
|
909
|
+
if (!this.isEnabled()) {
|
910
|
+
return emptyHandler;
|
911
|
+
}
|
912
|
+
return config?.config?.handler || emptyHandler;
|
913
|
+
}
|
914
|
+
};
|
915
|
+
};
|
916
|
+
const services$1 = {
|
917
|
+
preview: createPreviewService,
|
918
|
+
"preview-config": createPreviewConfigService
|
919
|
+
};
|
920
|
+
const getFeature = () => {
|
921
|
+
return {
|
922
|
+
register() {
|
923
|
+
const config = getService(strapi, "preview-config");
|
924
|
+
config.validate();
|
925
|
+
config.register();
|
926
|
+
},
|
927
|
+
bootstrap() {
|
928
|
+
},
|
929
|
+
routes: routes$1,
|
930
|
+
controllers: controllers$1,
|
931
|
+
services: services$1
|
932
|
+
};
|
933
|
+
};
|
934
|
+
const preview = getFeature();
|
687
935
|
const register = async ({ strapi: strapi2 }) => {
|
688
936
|
await history.register?.({ strapi: strapi2 });
|
937
|
+
await preview.register?.({ strapi: strapi2 });
|
689
938
|
};
|
690
939
|
const ALLOWED_WEBHOOK_EVENTS = {
|
691
940
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -695,11 +944,12 @@ const bootstrap = async () => {
|
|
695
944
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
696
945
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
697
946
|
});
|
698
|
-
getService$
|
699
|
-
await getService$
|
700
|
-
await getService$
|
701
|
-
await getService$
|
947
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
948
|
+
await getService$2("components").syncConfigurations();
|
949
|
+
await getService$2("content-types").syncConfigurations();
|
950
|
+
await getService$2("permission").registerPermissions();
|
702
951
|
await history.bootstrap?.({ strapi });
|
952
|
+
await preview.bootstrap?.({ strapi });
|
703
953
|
};
|
704
954
|
const destroy = async ({ strapi: strapi2 }) => {
|
705
955
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1189,7 +1439,8 @@ const admin = {
|
|
1189
1439
|
};
|
1190
1440
|
const routes = {
|
1191
1441
|
admin,
|
1192
|
-
...history.routes ? history.routes : {}
|
1442
|
+
...history.routes ? history.routes : {},
|
1443
|
+
...preview.routes ? preview.routes : {}
|
1193
1444
|
};
|
1194
1445
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1195
1446
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1200,6 +1451,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1200
1451
|
const hasPermissions = createPolicy({
|
1201
1452
|
name: "plugin::content-manager.hasPermissions",
|
1202
1453
|
validator: validateHasPermissionsInput,
|
1454
|
+
/**
|
1455
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1456
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1457
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1458
|
+
*/
|
1203
1459
|
handler(ctx, config = {}) {
|
1204
1460
|
const { actions = [], hasAtLeastOne = false } = config;
|
1205
1461
|
const { userAbility } = ctx.state;
|
@@ -1247,8 +1503,7 @@ const isSortable = (schema, name) => {
|
|
1247
1503
|
if (!___default.default.has(schema.attributes, name)) {
|
1248
1504
|
return false;
|
1249
1505
|
}
|
1250
|
-
if (schema.modelType === "component" && name === "id")
|
1251
|
-
return false;
|
1506
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1252
1507
|
const attribute = schema.attributes[name];
|
1253
1508
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1254
1509
|
return false;
|
@@ -1393,8 +1648,7 @@ const createDefaultSettings = async (schema) => {
|
|
1393
1648
|
};
|
1394
1649
|
};
|
1395
1650
|
const syncSettings = async (configuration, schema) => {
|
1396
|
-
if (fp.isEmpty(configuration.settings))
|
1397
|
-
return createDefaultSettings(schema);
|
1651
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1398
1652
|
const defaultField = getDefaultMainField(schema);
|
1399
1653
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1400
1654
|
return {
|
@@ -1441,7 +1695,7 @@ const createMetadasSchema = (schema) => {
|
|
1441
1695
|
if (!value) {
|
1442
1696
|
return strapiUtils.yup.string();
|
1443
1697
|
}
|
1444
|
-
const targetSchema = getService$
|
1698
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1445
1699
|
schema.attributes[key].targetModel
|
1446
1700
|
);
|
1447
1701
|
if (!targetSchema) {
|
@@ -1570,8 +1824,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1570
1824
|
}
|
1571
1825
|
switch (attribute.type) {
|
1572
1826
|
case "relation": {
|
1573
|
-
if (canCreate(attributePath))
|
1574
|
-
return body2;
|
1827
|
+
if (canCreate(attributePath)) return body2;
|
1575
1828
|
return fp.set(attributePath, { set: [] }, body2);
|
1576
1829
|
}
|
1577
1830
|
case "component": {
|
@@ -1581,8 +1834,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1581
1834
|
]);
|
1582
1835
|
}
|
1583
1836
|
default: {
|
1584
|
-
if (canCreate(attributePath))
|
1585
|
-
return body2;
|
1837
|
+
if (canCreate(attributePath)) return body2;
|
1586
1838
|
return fp.set(attributePath, null, body2);
|
1587
1839
|
}
|
1588
1840
|
}
|
@@ -1593,9 +1845,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
|
|
1593
1845
|
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1594
1846
|
);
|
1595
1847
|
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1596
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1848
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1597
1849
|
const { allowMultipleLocales } = opts;
|
1598
|
-
const { locale, status, ...rest } = request || {};
|
1850
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1851
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1852
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1599
1853
|
const schema = strapiUtils.yup.object().shape({
|
1600
1854
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1601
1855
|
status: statusSchema
|
@@ -1608,7 +1862,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1608
1862
|
}
|
1609
1863
|
};
|
1610
1864
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1611
|
-
const documentMetadata2 = getService$
|
1865
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1612
1866
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1613
1867
|
let {
|
1614
1868
|
meta: { availableLocales, availableStatus }
|
@@ -1634,8 +1888,8 @@ const createDocument = async (ctx, opts) => {
|
|
1634
1888
|
const { userAbility, user } = ctx.state;
|
1635
1889
|
const { model } = ctx.params;
|
1636
1890
|
const { body } = ctx.request;
|
1637
|
-
const documentManager2 = getService$
|
1638
|
-
const permissionChecker2 = getService$
|
1891
|
+
const documentManager2 = getService$2("document-manager");
|
1892
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1639
1893
|
if (permissionChecker2.cannot.create()) {
|
1640
1894
|
throw new strapiUtils.errors.ForbiddenError();
|
1641
1895
|
}
|
@@ -1643,7 +1897,7 @@ const createDocument = async (ctx, opts) => {
|
|
1643
1897
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1644
1898
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1645
1899
|
const sanitizedBody = await sanitizeFn(body);
|
1646
|
-
const { locale, status
|
1900
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1647
1901
|
return documentManager2.create(model, {
|
1648
1902
|
data: sanitizedBody,
|
1649
1903
|
locale,
|
@@ -1655,14 +1909,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1655
1909
|
const { userAbility, user } = ctx.state;
|
1656
1910
|
const { id, model } = ctx.params;
|
1657
1911
|
const { body } = ctx.request;
|
1658
|
-
const documentManager2 = getService$
|
1659
|
-
const permissionChecker2 = getService$
|
1912
|
+
const documentManager2 = getService$2("document-manager");
|
1913
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1660
1914
|
if (permissionChecker2.cannot.update()) {
|
1661
1915
|
throw new strapiUtils.errors.ForbiddenError();
|
1662
1916
|
}
|
1663
1917
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1664
|
-
const populate = await getService$
|
1665
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1918
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1919
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1666
1920
|
const [documentVersion, documentExists] = await Promise.all([
|
1667
1921
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1668
1922
|
documentManager2.exists(model, id)
|
@@ -1678,7 +1932,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1678
1932
|
throw new strapiUtils.errors.ForbiddenError();
|
1679
1933
|
}
|
1680
1934
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1681
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1935
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1682
1936
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1683
1937
|
const sanitizedBody = await sanitizeFn(body);
|
1684
1938
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1692,15 +1946,15 @@ const collectionTypes = {
|
|
1692
1946
|
const { userAbility } = ctx.state;
|
1693
1947
|
const { model } = ctx.params;
|
1694
1948
|
const { query } = ctx.request;
|
1695
|
-
const documentMetadata2 = getService$
|
1696
|
-
const documentManager2 = getService$
|
1697
|
-
const permissionChecker2 = getService$
|
1949
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1950
|
+
const documentManager2 = getService$2("document-manager");
|
1951
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1698
1952
|
if (permissionChecker2.cannot.read()) {
|
1699
1953
|
return ctx.forbidden();
|
1700
1954
|
}
|
1701
1955
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1702
|
-
const populate = await getService$
|
1703
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1956
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1957
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1704
1958
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1705
1959
|
{ ...permissionQuery, populate, locale, status },
|
1706
1960
|
model
|
@@ -1728,14 +1982,14 @@ const collectionTypes = {
|
|
1728
1982
|
async findOne(ctx) {
|
1729
1983
|
const { userAbility } = ctx.state;
|
1730
1984
|
const { model, id } = ctx.params;
|
1731
|
-
const documentManager2 = getService$
|
1732
|
-
const permissionChecker2 = getService$
|
1985
|
+
const documentManager2 = getService$2("document-manager");
|
1986
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1733
1987
|
if (permissionChecker2.cannot.read()) {
|
1734
1988
|
return ctx.forbidden();
|
1735
1989
|
}
|
1736
1990
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1737
|
-
const populate = await getService$
|
1738
|
-
const { locale, status
|
1991
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1992
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1739
1993
|
const version = await documentManager2.findOne(id, model, {
|
1740
1994
|
populate,
|
1741
1995
|
locale,
|
@@ -1750,7 +2004,7 @@ const collectionTypes = {
|
|
1750
2004
|
permissionChecker2,
|
1751
2005
|
model,
|
1752
2006
|
// @ts-expect-error TODO: fix
|
1753
|
-
{ id, locale, publishedAt: null },
|
2007
|
+
{ documentId: id, locale, publishedAt: null },
|
1754
2008
|
{ availableLocales: true, availableStatus: false }
|
1755
2009
|
);
|
1756
2010
|
ctx.body = { data: {}, meta };
|
@@ -1765,7 +2019,7 @@ const collectionTypes = {
|
|
1765
2019
|
async create(ctx) {
|
1766
2020
|
const { userAbility } = ctx.state;
|
1767
2021
|
const { model } = ctx.params;
|
1768
|
-
const permissionChecker2 = getService$
|
2022
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1769
2023
|
const [totalEntries, document] = await Promise.all([
|
1770
2024
|
strapi.db.query(model).count(),
|
1771
2025
|
createDocument(ctx)
|
@@ -1786,7 +2040,7 @@ const collectionTypes = {
|
|
1786
2040
|
async update(ctx) {
|
1787
2041
|
const { userAbility } = ctx.state;
|
1788
2042
|
const { model } = ctx.params;
|
1789
|
-
const permissionChecker2 = getService$
|
2043
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1790
2044
|
const updatedVersion = await updateDocument(ctx);
|
1791
2045
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1792
2046
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1795,14 +2049,14 @@ const collectionTypes = {
|
|
1795
2049
|
const { userAbility, user } = ctx.state;
|
1796
2050
|
const { model, sourceId: id } = ctx.params;
|
1797
2051
|
const { body } = ctx.request;
|
1798
|
-
const documentManager2 = getService$
|
1799
|
-
const permissionChecker2 = getService$
|
2052
|
+
const documentManager2 = getService$2("document-manager");
|
2053
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1800
2054
|
if (permissionChecker2.cannot.create()) {
|
1801
2055
|
return ctx.forbidden();
|
1802
2056
|
}
|
1803
2057
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1804
|
-
const populate = await getService$
|
1805
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2058
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2059
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1806
2060
|
const document = await documentManager2.findOne(id, model, {
|
1807
2061
|
populate,
|
1808
2062
|
locale,
|
@@ -1840,14 +2094,14 @@ const collectionTypes = {
|
|
1840
2094
|
async delete(ctx) {
|
1841
2095
|
const { userAbility } = ctx.state;
|
1842
2096
|
const { id, model } = ctx.params;
|
1843
|
-
const documentManager2 = getService$
|
1844
|
-
const permissionChecker2 = getService$
|
2097
|
+
const documentManager2 = getService$2("document-manager");
|
2098
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1845
2099
|
if (permissionChecker2.cannot.delete()) {
|
1846
2100
|
return ctx.forbidden();
|
1847
2101
|
}
|
1848
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1849
|
-
const populate = await getService$
|
1850
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
2103
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2104
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1851
2105
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1852
2106
|
if (documentLocales.length === 0) {
|
1853
2107
|
return ctx.notFound();
|
@@ -1868,19 +2122,42 @@ const collectionTypes = {
|
|
1868
2122
|
const { userAbility } = ctx.state;
|
1869
2123
|
const { id, model } = ctx.params;
|
1870
2124
|
const { body } = ctx.request;
|
1871
|
-
const documentManager2 = getService$
|
1872
|
-
const permissionChecker2 = getService$
|
2125
|
+
const documentManager2 = getService$2("document-manager");
|
2126
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1873
2127
|
if (permissionChecker2.cannot.publish()) {
|
1874
2128
|
return ctx.forbidden();
|
1875
2129
|
}
|
1876
2130
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1877
2131
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1878
|
-
const populate = await getService$
|
1879
|
-
|
2132
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2133
|
+
let document;
|
2134
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2135
|
+
const isCreate = fp.isNil(id);
|
2136
|
+
if (isCreate) {
|
2137
|
+
if (permissionChecker2.cannot.create()) {
|
2138
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2139
|
+
}
|
2140
|
+
document = await createDocument(ctx, { populate });
|
2141
|
+
}
|
2142
|
+
const isUpdate = !isCreate;
|
2143
|
+
if (isUpdate) {
|
2144
|
+
const documentExists = documentManager2.exists(model, id);
|
2145
|
+
if (!documentExists) {
|
2146
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
2147
|
+
}
|
2148
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2149
|
+
if (!document) {
|
2150
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2151
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2152
|
+
}
|
2153
|
+
document = await updateDocument(ctx);
|
2154
|
+
} else if (permissionChecker2.can.update(document)) {
|
2155
|
+
await updateDocument(ctx);
|
2156
|
+
}
|
2157
|
+
}
|
1880
2158
|
if (permissionChecker2.cannot.publish(document)) {
|
1881
2159
|
throw new strapiUtils.errors.ForbiddenError();
|
1882
2160
|
}
|
1883
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1884
2161
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1885
2162
|
locale
|
1886
2163
|
// TODO: Allow setting creator fields on publish
|
@@ -1900,14 +2177,16 @@ const collectionTypes = {
|
|
1900
2177
|
const { body } = ctx.request;
|
1901
2178
|
const { documentIds } = body;
|
1902
2179
|
await validateBulkActionInput(body);
|
1903
|
-
const documentManager2 = getService$
|
1904
|
-
const permissionChecker2 = getService$
|
2180
|
+
const documentManager2 = getService$2("document-manager");
|
2181
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1905
2182
|
if (permissionChecker2.cannot.publish()) {
|
1906
2183
|
return ctx.forbidden();
|
1907
2184
|
}
|
1908
2185
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1909
|
-
const populate = await getService$
|
1910
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
2186
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2187
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2188
|
+
allowMultipleLocales: true
|
2189
|
+
});
|
1911
2190
|
const entityPromises = documentIds.map(
|
1912
2191
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1913
2192
|
);
|
@@ -1929,12 +2208,14 @@ const collectionTypes = {
|
|
1929
2208
|
const { body } = ctx.request;
|
1930
2209
|
const { documentIds } = body;
|
1931
2210
|
await validateBulkActionInput(body);
|
1932
|
-
const documentManager2 = getService$
|
1933
|
-
const permissionChecker2 = getService$
|
2211
|
+
const documentManager2 = getService$2("document-manager");
|
2212
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1934
2213
|
if (permissionChecker2.cannot.unpublish()) {
|
1935
2214
|
return ctx.forbidden();
|
1936
2215
|
}
|
1937
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2216
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2217
|
+
allowMultipleLocales: true
|
2218
|
+
});
|
1938
2219
|
const entityPromises = documentIds.map(
|
1939
2220
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1940
2221
|
);
|
@@ -1957,8 +2238,8 @@ const collectionTypes = {
|
|
1957
2238
|
const {
|
1958
2239
|
body: { discardDraft, ...body }
|
1959
2240
|
} = ctx.request;
|
1960
|
-
const documentManager2 = getService$
|
1961
|
-
const permissionChecker2 = getService$
|
2241
|
+
const documentManager2 = getService$2("document-manager");
|
2242
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1962
2243
|
if (permissionChecker2.cannot.unpublish()) {
|
1963
2244
|
return ctx.forbidden();
|
1964
2245
|
}
|
@@ -1966,8 +2247,8 @@ const collectionTypes = {
|
|
1966
2247
|
return ctx.forbidden();
|
1967
2248
|
}
|
1968
2249
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1969
|
-
const populate = await getService$
|
1970
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2250
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2251
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1971
2252
|
const document = await documentManager2.findOne(id, model, {
|
1972
2253
|
populate,
|
1973
2254
|
locale,
|
@@ -1997,14 +2278,14 @@ const collectionTypes = {
|
|
1997
2278
|
const { userAbility } = ctx.state;
|
1998
2279
|
const { id, model } = ctx.params;
|
1999
2280
|
const { body } = ctx.request;
|
2000
|
-
const documentManager2 = getService$
|
2001
|
-
const permissionChecker2 = getService$
|
2281
|
+
const documentManager2 = getService$2("document-manager");
|
2282
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2002
2283
|
if (permissionChecker2.cannot.discard()) {
|
2003
2284
|
return ctx.forbidden();
|
2004
2285
|
}
|
2005
2286
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2006
|
-
const populate = await getService$
|
2007
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2287
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2288
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2008
2289
|
const document = await documentManager2.findOne(id, model, {
|
2009
2290
|
populate,
|
2010
2291
|
locale,
|
@@ -2028,14 +2309,14 @@ const collectionTypes = {
|
|
2028
2309
|
const { query, body } = ctx.request;
|
2029
2310
|
const { documentIds } = body;
|
2030
2311
|
await validateBulkActionInput(body);
|
2031
|
-
const documentManager2 = getService$
|
2032
|
-
const permissionChecker2 = getService$
|
2312
|
+
const documentManager2 = getService$2("document-manager");
|
2313
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2033
2314
|
if (permissionChecker2.cannot.delete()) {
|
2034
2315
|
return ctx.forbidden();
|
2035
2316
|
}
|
2036
2317
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2037
|
-
const populate = await getService$
|
2038
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2318
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2319
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2039
2320
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2040
2321
|
populate,
|
2041
2322
|
locale
|
@@ -2055,14 +2336,14 @@ const collectionTypes = {
|
|
2055
2336
|
async countDraftRelations(ctx) {
|
2056
2337
|
const { userAbility } = ctx.state;
|
2057
2338
|
const { model, id } = ctx.params;
|
2058
|
-
const documentManager2 = getService$
|
2059
|
-
const permissionChecker2 = getService$
|
2339
|
+
const documentManager2 = getService$2("document-manager");
|
2340
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2060
2341
|
if (permissionChecker2.cannot.read()) {
|
2061
2342
|
return ctx.forbidden();
|
2062
2343
|
}
|
2063
2344
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2064
|
-
const populate = await getService$
|
2065
|
-
const { locale, status
|
2345
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2346
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2066
2347
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2067
2348
|
if (!entity) {
|
2068
2349
|
return ctx.notFound();
|
@@ -2080,12 +2361,12 @@ const collectionTypes = {
|
|
2080
2361
|
const ids = ctx.request.query.documentIds;
|
2081
2362
|
const locale = ctx.request.query.locale;
|
2082
2363
|
const { model } = ctx.params;
|
2083
|
-
const documentManager2 = getService$
|
2084
|
-
const permissionChecker2 = getService$
|
2364
|
+
const documentManager2 = getService$2("document-manager");
|
2365
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2085
2366
|
if (permissionChecker2.cannot.read()) {
|
2086
2367
|
return ctx.forbidden();
|
2087
2368
|
}
|
2088
|
-
const
|
2369
|
+
const documents = await documentManager2.findMany(
|
2089
2370
|
{
|
2090
2371
|
filters: {
|
2091
2372
|
documentId: ids
|
@@ -2094,7 +2375,7 @@ const collectionTypes = {
|
|
2094
2375
|
},
|
2095
2376
|
model
|
2096
2377
|
);
|
2097
|
-
if (!
|
2378
|
+
if (!documents) {
|
2098
2379
|
return ctx.notFound();
|
2099
2380
|
}
|
2100
2381
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2105,13 +2386,13 @@ const collectionTypes = {
|
|
2105
2386
|
};
|
2106
2387
|
const components$1 = {
|
2107
2388
|
findComponents(ctx) {
|
2108
|
-
const components2 = getService$
|
2109
|
-
const { toDto } = getService$
|
2389
|
+
const components2 = getService$2("components").findAllComponents();
|
2390
|
+
const { toDto } = getService$2("data-mapper");
|
2110
2391
|
ctx.body = { data: components2.map(toDto) };
|
2111
2392
|
},
|
2112
2393
|
async findComponentConfiguration(ctx) {
|
2113
2394
|
const { uid: uid2 } = ctx.params;
|
2114
|
-
const componentService = getService$
|
2395
|
+
const componentService = getService$2("components");
|
2115
2396
|
const component = componentService.findComponent(uid2);
|
2116
2397
|
if (!component) {
|
2117
2398
|
return ctx.notFound("component.notFound");
|
@@ -2128,7 +2409,7 @@ const components$1 = {
|
|
2128
2409
|
async updateComponentConfiguration(ctx) {
|
2129
2410
|
const { uid: uid2 } = ctx.params;
|
2130
2411
|
const { body } = ctx.request;
|
2131
|
-
const componentService = getService$
|
2412
|
+
const componentService = getService$2("components");
|
2132
2413
|
const component = componentService.findComponent(uid2);
|
2133
2414
|
if (!component) {
|
2134
2415
|
return ctx.notFound("component.notFound");
|
@@ -2162,12 +2443,12 @@ const contentTypes = {
|
|
2162
2443
|
} catch (error) {
|
2163
2444
|
return ctx.send({ error }, 400);
|
2164
2445
|
}
|
2165
|
-
const contentTypes2 = getService$
|
2166
|
-
const { toDto } = getService$
|
2446
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2447
|
+
const { toDto } = getService$2("data-mapper");
|
2167
2448
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2168
2449
|
},
|
2169
2450
|
async findContentTypesSettings(ctx) {
|
2170
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2451
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2171
2452
|
const contentTypes2 = await findAllContentTypes();
|
2172
2453
|
const configurations = await Promise.all(
|
2173
2454
|
contentTypes2.map(async (contentType) => {
|
@@ -2181,7 +2462,7 @@ const contentTypes = {
|
|
2181
2462
|
},
|
2182
2463
|
async findContentTypeConfiguration(ctx) {
|
2183
2464
|
const { uid: uid2 } = ctx.params;
|
2184
|
-
const contentTypeService = getService$
|
2465
|
+
const contentTypeService = getService$2("content-types");
|
2185
2466
|
const contentType = await contentTypeService.findContentType(uid2);
|
2186
2467
|
if (!contentType) {
|
2187
2468
|
return ctx.notFound("contentType.notFound");
|
@@ -2203,13 +2484,13 @@ const contentTypes = {
|
|
2203
2484
|
const { userAbility } = ctx.state;
|
2204
2485
|
const { uid: uid2 } = ctx.params;
|
2205
2486
|
const { body } = ctx.request;
|
2206
|
-
const contentTypeService = getService$
|
2207
|
-
const metricsService = getService$
|
2487
|
+
const contentTypeService = getService$2("content-types");
|
2488
|
+
const metricsService = getService$2("metrics");
|
2208
2489
|
const contentType = await contentTypeService.findContentType(uid2);
|
2209
2490
|
if (!contentType) {
|
2210
2491
|
return ctx.notFound("contentType.notFound");
|
2211
2492
|
}
|
2212
|
-
if (!getService$
|
2493
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2213
2494
|
return ctx.forbidden();
|
2214
2495
|
}
|
2215
2496
|
let input;
|
@@ -2242,10 +2523,10 @@ const contentTypes = {
|
|
2242
2523
|
};
|
2243
2524
|
const init = {
|
2244
2525
|
getInitData(ctx) {
|
2245
|
-
const { toDto } = getService$
|
2246
|
-
const { findAllComponents } = getService$
|
2247
|
-
const { getAllFieldSizes } = getService$
|
2248
|
-
const { findAllContentTypes } = getService$
|
2526
|
+
const { toDto } = getService$2("data-mapper");
|
2527
|
+
const { findAllComponents } = getService$2("components");
|
2528
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2529
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2249
2530
|
ctx.body = {
|
2250
2531
|
data: {
|
2251
2532
|
fieldSizes: getAllFieldSizes(),
|
@@ -2281,36 +2562,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2281
2562
|
params.filters.$and.push(filtersClause);
|
2282
2563
|
};
|
2283
2564
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2284
|
-
const permissionChecker2 = getService$
|
2565
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2285
2566
|
userAbility,
|
2286
2567
|
model: model.uid
|
2287
2568
|
});
|
2288
|
-
|
2569
|
+
const isMainFieldListable = isListable(model, mainField);
|
2570
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2571
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2289
2572
|
return "id";
|
2290
2573
|
}
|
2291
|
-
if (
|
2292
|
-
|
2293
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2294
|
-
userAbility,
|
2295
|
-
model: "plugin::users-permissions.user"
|
2296
|
-
});
|
2297
|
-
if (userPermissionChecker.can.read()) {
|
2298
|
-
return "name";
|
2299
|
-
}
|
2300
|
-
}
|
2301
|
-
return "id";
|
2574
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2575
|
+
return "name";
|
2302
2576
|
}
|
2303
2577
|
return mainField;
|
2304
2578
|
};
|
2305
|
-
const addStatusToRelations = async (
|
2306
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2579
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2580
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2581
|
+
return relations2;
|
2582
|
+
}
|
2583
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2584
|
+
if (!relations2.length) {
|
2307
2585
|
return relations2;
|
2308
2586
|
}
|
2309
|
-
const
|
2310
|
-
const
|
2587
|
+
const firstRelation = relations2[0];
|
2588
|
+
const filters = {
|
2589
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2590
|
+
// NOTE: find the "opposite" status
|
2591
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2592
|
+
};
|
2593
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2594
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2595
|
+
filters
|
2596
|
+
});
|
2311
2597
|
return relations2.map((relation) => {
|
2312
|
-
const availableStatuses =
|
2313
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2598
|
+
const availableStatuses = availableStatus.filter(
|
2599
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2314
2600
|
);
|
2315
2601
|
return {
|
2316
2602
|
...relation,
|
@@ -2331,11 +2617,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2331
2617
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2332
2618
|
const isSourceLocalized = isLocalized(sourceModel);
|
2333
2619
|
const isTargetLocalized = isLocalized(targetModel);
|
2334
|
-
let validatedLocale = locale;
|
2335
|
-
if (!targetModel || !isTargetLocalized)
|
2336
|
-
validatedLocale = void 0;
|
2337
2620
|
return {
|
2338
|
-
locale
|
2621
|
+
locale,
|
2339
2622
|
isSourceLocalized,
|
2340
2623
|
isTargetLocalized
|
2341
2624
|
};
|
@@ -2344,8 +2627,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2344
2627
|
const sourceModel = strapi.getModel(sourceUid);
|
2345
2628
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2346
2629
|
const isSourceDP = isDP(sourceModel);
|
2347
|
-
if (!isSourceDP)
|
2348
|
-
return { status: void 0 };
|
2630
|
+
if (!isSourceDP) return { status: void 0 };
|
2349
2631
|
switch (status) {
|
2350
2632
|
case "published":
|
2351
2633
|
return { status: "published" };
|
@@ -2375,7 +2657,7 @@ const relations = {
|
|
2375
2657
|
ctx.request?.query?.locale
|
2376
2658
|
);
|
2377
2659
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2378
|
-
const permissionChecker2 = getService$
|
2660
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2379
2661
|
userAbility,
|
2380
2662
|
model
|
2381
2663
|
});
|
@@ -2400,7 +2682,7 @@ const relations = {
|
|
2400
2682
|
where.id = id;
|
2401
2683
|
}
|
2402
2684
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2403
|
-
const populate = await getService$
|
2685
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2404
2686
|
const currentEntity = await strapi.db.query(model).findOne({
|
2405
2687
|
where,
|
2406
2688
|
populate
|
@@ -2415,7 +2697,7 @@ const relations = {
|
|
2415
2697
|
}
|
2416
2698
|
entryId = currentEntity.id;
|
2417
2699
|
}
|
2418
|
-
const modelConfig = isComponent2 ? await getService$
|
2700
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2419
2701
|
const targetSchema = strapi.getModel(targetUid);
|
2420
2702
|
const mainField = fp.flow(
|
2421
2703
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2438,7 +2720,7 @@ const relations = {
|
|
2438
2720
|
attribute,
|
2439
2721
|
fieldsToSelect,
|
2440
2722
|
mainField,
|
2441
|
-
source: { schema: sourceSchema },
|
2723
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2442
2724
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2443
2725
|
sourceSchema,
|
2444
2726
|
targetSchema,
|
@@ -2460,7 +2742,8 @@ const relations = {
|
|
2460
2742
|
fieldsToSelect,
|
2461
2743
|
mainField,
|
2462
2744
|
source: {
|
2463
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2745
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2746
|
+
isLocalized: isSourceLocalized
|
2464
2747
|
},
|
2465
2748
|
target: {
|
2466
2749
|
schema: { uid: targetUid },
|
@@ -2468,7 +2751,7 @@ const relations = {
|
|
2468
2751
|
}
|
2469
2752
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2470
2753
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2471
|
-
const permissionChecker2 = getService$
|
2754
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2472
2755
|
userAbility: ctx.state.userAbility,
|
2473
2756
|
model: targetUid
|
2474
2757
|
});
|
@@ -2498,12 +2781,16 @@ const relations = {
|
|
2498
2781
|
} else {
|
2499
2782
|
where.id = id;
|
2500
2783
|
}
|
2501
|
-
|
2502
|
-
|
2784
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2785
|
+
if (!fp.isEmpty(publishedAt)) {
|
2786
|
+
where[`${alias}.published_at`] = publishedAt;
|
2503
2787
|
}
|
2504
|
-
if (
|
2788
|
+
if (isTargetLocalized && locale) {
|
2505
2789
|
where[`${alias}.locale`] = locale;
|
2506
2790
|
}
|
2791
|
+
if (isSourceLocalized && locale) {
|
2792
|
+
where.locale = locale;
|
2793
|
+
}
|
2507
2794
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2508
2795
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2509
2796
|
}
|
@@ -2521,7 +2808,8 @@ const relations = {
|
|
2521
2808
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2522
2809
|
});
|
2523
2810
|
}
|
2524
|
-
const
|
2811
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2812
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2525
2813
|
ctx.body = {
|
2526
2814
|
...res,
|
2527
2815
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2536,29 +2824,39 @@ const relations = {
|
|
2536
2824
|
attribute,
|
2537
2825
|
targetField,
|
2538
2826
|
fieldsToSelect,
|
2539
|
-
|
2540
|
-
|
2541
|
-
}
|
2542
|
-
target: {
|
2543
|
-
schema: { uid: targetUid }
|
2544
|
-
}
|
2827
|
+
status,
|
2828
|
+
source: { schema: sourceSchema },
|
2829
|
+
target: { schema: targetSchema }
|
2545
2830
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2546
|
-
const
|
2831
|
+
const { uid: sourceUid } = sourceSchema;
|
2832
|
+
const { uid: targetUid } = targetSchema;
|
2833
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2547
2834
|
const dbQuery = strapi.db.query(sourceUid);
|
2548
2835
|
const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2836
|
+
const filters = {};
|
2837
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2838
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2839
|
+
if (status === "published") {
|
2840
|
+
filters.publishedAt = { $notNull: true };
|
2841
|
+
} else {
|
2842
|
+
filters.publishedAt = { $null: true };
|
2843
|
+
}
|
2844
|
+
}
|
2845
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2846
|
+
filters.publishedAt = { $null: true };
|
2847
|
+
}
|
2549
2848
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2550
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2849
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2551
2850
|
ordering: "desc",
|
2552
2851
|
page: ctx.request.query.page,
|
2553
|
-
pageSize: ctx.request.query.pageSize
|
2852
|
+
pageSize: ctx.request.query.pageSize,
|
2853
|
+
filters
|
2554
2854
|
});
|
2555
2855
|
const loadedIds = res.results.map((item) => item.id);
|
2556
2856
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2557
2857
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2558
2858
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2559
|
-
ordering: "desc"
|
2560
|
-
page: ctx.request.query.page,
|
2561
|
-
pageSize: ctx.request.query.pageSize
|
2859
|
+
ordering: "desc"
|
2562
2860
|
});
|
2563
2861
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2564
2862
|
ctx.body = {
|
@@ -2573,10 +2871,10 @@ const relations = {
|
|
2573
2871
|
}
|
2574
2872
|
};
|
2575
2873
|
const buildPopulateFromQuery = async (query, model) => {
|
2576
|
-
return getService$
|
2874
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2577
2875
|
};
|
2578
2876
|
const findDocument = async (query, uid2, opts = {}) => {
|
2579
|
-
const documentManager2 = getService$
|
2877
|
+
const documentManager2 = getService$2("document-manager");
|
2580
2878
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2581
2879
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2582
2880
|
};
|
@@ -2584,13 +2882,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2584
2882
|
const { user, userAbility } = ctx.state;
|
2585
2883
|
const { model } = ctx.params;
|
2586
2884
|
const { body, query } = ctx.request;
|
2587
|
-
const documentManager2 = getService$
|
2588
|
-
const permissionChecker2 = getService$
|
2885
|
+
const documentManager2 = getService$2("document-manager");
|
2886
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2589
2887
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2590
2888
|
throw new strapiUtils.errors.ForbiddenError();
|
2591
2889
|
}
|
2592
2890
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2593
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2891
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2594
2892
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2595
2893
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2596
2894
|
// Find the first document to check if it exists
|
@@ -2626,12 +2924,12 @@ const singleTypes = {
|
|
2626
2924
|
const { userAbility } = ctx.state;
|
2627
2925
|
const { model } = ctx.params;
|
2628
2926
|
const { query = {} } = ctx.request;
|
2629
|
-
const permissionChecker2 = getService$
|
2927
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2630
2928
|
if (permissionChecker2.cannot.read()) {
|
2631
2929
|
return ctx.forbidden();
|
2632
2930
|
}
|
2633
2931
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2634
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2932
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2635
2933
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2636
2934
|
if (!version) {
|
2637
2935
|
if (permissionChecker2.cannot.create()) {
|
@@ -2645,7 +2943,7 @@ const singleTypes = {
|
|
2645
2943
|
permissionChecker2,
|
2646
2944
|
model,
|
2647
2945
|
// @ts-expect-error - fix types
|
2648
|
-
{
|
2946
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2649
2947
|
{ availableLocales: true, availableStatus: false }
|
2650
2948
|
);
|
2651
2949
|
ctx.body = { data: {}, meta };
|
@@ -2660,7 +2958,7 @@ const singleTypes = {
|
|
2660
2958
|
async createOrUpdate(ctx) {
|
2661
2959
|
const { userAbility } = ctx.state;
|
2662
2960
|
const { model } = ctx.params;
|
2663
|
-
const permissionChecker2 = getService$
|
2961
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2664
2962
|
const document = await createOrUpdateDocument(ctx);
|
2665
2963
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2666
2964
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2669,14 +2967,14 @@ const singleTypes = {
|
|
2669
2967
|
const { userAbility } = ctx.state;
|
2670
2968
|
const { model } = ctx.params;
|
2671
2969
|
const { query = {} } = ctx.request;
|
2672
|
-
const documentManager2 = getService$
|
2673
|
-
const permissionChecker2 = getService$
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2674
2972
|
if (permissionChecker2.cannot.delete()) {
|
2675
2973
|
return ctx.forbidden();
|
2676
2974
|
}
|
2677
2975
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2678
2976
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2679
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2977
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2680
2978
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2681
2979
|
populate,
|
2682
2980
|
locale
|
@@ -2698,8 +2996,8 @@ const singleTypes = {
|
|
2698
2996
|
const { userAbility } = ctx.state;
|
2699
2997
|
const { model } = ctx.params;
|
2700
2998
|
const { query = {} } = ctx.request;
|
2701
|
-
const documentManager2 = getService$
|
2702
|
-
const permissionChecker2 = getService$
|
2999
|
+
const documentManager2 = getService$2("document-manager");
|
3000
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2703
3001
|
if (permissionChecker2.cannot.publish()) {
|
2704
3002
|
return ctx.forbidden();
|
2705
3003
|
}
|
@@ -2713,7 +3011,7 @@ const singleTypes = {
|
|
2713
3011
|
if (permissionChecker2.cannot.publish(document)) {
|
2714
3012
|
throw new strapiUtils.errors.ForbiddenError();
|
2715
3013
|
}
|
2716
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
3014
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2717
3015
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2718
3016
|
return publishResult.at(0);
|
2719
3017
|
});
|
@@ -2727,8 +3025,8 @@ const singleTypes = {
|
|
2727
3025
|
body: { discardDraft, ...body },
|
2728
3026
|
query = {}
|
2729
3027
|
} = ctx.request;
|
2730
|
-
const documentManager2 = getService$
|
2731
|
-
const permissionChecker2 = getService$
|
3028
|
+
const documentManager2 = getService$2("document-manager");
|
3029
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2732
3030
|
if (permissionChecker2.cannot.unpublish()) {
|
2733
3031
|
return ctx.forbidden();
|
2734
3032
|
}
|
@@ -2736,7 +3034,7 @@ const singleTypes = {
|
|
2736
3034
|
return ctx.forbidden();
|
2737
3035
|
}
|
2738
3036
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2739
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3037
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2740
3038
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2741
3039
|
if (!document) {
|
2742
3040
|
return ctx.notFound();
|
@@ -2762,13 +3060,13 @@ const singleTypes = {
|
|
2762
3060
|
const { userAbility } = ctx.state;
|
2763
3061
|
const { model } = ctx.params;
|
2764
3062
|
const { body, query = {} } = ctx.request;
|
2765
|
-
const documentManager2 = getService$
|
2766
|
-
const permissionChecker2 = getService$
|
3063
|
+
const documentManager2 = getService$2("document-manager");
|
3064
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2767
3065
|
if (permissionChecker2.cannot.discard()) {
|
2768
3066
|
return ctx.forbidden();
|
2769
3067
|
}
|
2770
3068
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2771
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3069
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2772
3070
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2773
3071
|
if (!document) {
|
2774
3072
|
return ctx.notFound();
|
@@ -2786,9 +3084,9 @@ const singleTypes = {
|
|
2786
3084
|
const { userAbility } = ctx.state;
|
2787
3085
|
const { model } = ctx.params;
|
2788
3086
|
const { query } = ctx.request;
|
2789
|
-
const documentManager2 = getService$
|
2790
|
-
const permissionChecker2 = getService$
|
2791
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3087
|
+
const documentManager2 = getService$2("document-manager");
|
3088
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3089
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2792
3090
|
if (permissionChecker2.cannot.read()) {
|
2793
3091
|
return ctx.forbidden();
|
2794
3092
|
}
|
@@ -2809,9 +3107,9 @@ const uid$1 = {
|
|
2809
3107
|
async generateUID(ctx) {
|
2810
3108
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2811
3109
|
const { query = {} } = ctx.request;
|
2812
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3110
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2813
3111
|
await validateUIDField(contentTypeUID, field);
|
2814
|
-
const uidService = getService$
|
3112
|
+
const uidService = getService$2("uid");
|
2815
3113
|
ctx.body = {
|
2816
3114
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2817
3115
|
};
|
@@ -2821,9 +3119,9 @@ const uid$1 = {
|
|
2821
3119
|
ctx.request.body
|
2822
3120
|
);
|
2823
3121
|
const { query = {} } = ctx.request;
|
2824
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3122
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2825
3123
|
await validateUIDField(contentTypeUID, field);
|
2826
|
-
const uidService = getService$
|
3124
|
+
const uidService = getService$2("uid");
|
2827
3125
|
const isAvailable = await uidService.checkUIDAvailability({
|
2828
3126
|
contentTypeUID,
|
2829
3127
|
field,
|
@@ -2844,7 +3142,8 @@ const controllers = {
|
|
2844
3142
|
relations,
|
2845
3143
|
"single-types": singleTypes,
|
2846
3144
|
uid: uid$1,
|
2847
|
-
...history.controllers ? history.controllers : {}
|
3145
|
+
...history.controllers ? history.controllers : {},
|
3146
|
+
...preview.controllers ? preview.controllers : {}
|
2848
3147
|
};
|
2849
3148
|
const keys = {
|
2850
3149
|
CONFIGURATION: "configuration"
|
@@ -2973,18 +3272,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2973
3272
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2974
3273
|
___default.default.set(acc, [key], updatedMeta);
|
2975
3274
|
}
|
2976
|
-
if (!___default.default.has(edit, "mainField"))
|
2977
|
-
return acc;
|
3275
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2978
3276
|
if (!isRelation$1(attr)) {
|
2979
3277
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2980
3278
|
___default.default.set(acc, [key], updatedMeta);
|
2981
3279
|
return acc;
|
2982
3280
|
}
|
2983
|
-
if (edit.mainField === "id")
|
2984
|
-
return acc;
|
3281
|
+
if (edit.mainField === "id") return acc;
|
2985
3282
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2986
|
-
if (!targetSchema)
|
2987
|
-
return acc;
|
3283
|
+
if (!targetSchema) return acc;
|
2988
3284
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2989
3285
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2990
3286
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -2995,12 +3291,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2995
3291
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
2996
3292
|
}
|
2997
3293
|
const getTargetSchema = (targetModel) => {
|
2998
|
-
return getService$
|
3294
|
+
return getService$2("content-types").findContentType(targetModel);
|
2999
3295
|
};
|
3000
3296
|
const DEFAULT_LIST_LENGTH = 4;
|
3001
3297
|
const MAX_ROW_SIZE = 12;
|
3002
3298
|
const isAllowedFieldSize = (type, size) => {
|
3003
|
-
const { getFieldSize } = getService$
|
3299
|
+
const { getFieldSize } = getService$2("field-sizes");
|
3004
3300
|
const fieldSize = getFieldSize(type);
|
3005
3301
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
3006
3302
|
return false;
|
@@ -3008,7 +3304,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
3008
3304
|
return size <= MAX_ROW_SIZE;
|
3009
3305
|
};
|
3010
3306
|
const getDefaultFieldSize = (attribute) => {
|
3011
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3307
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
3012
3308
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
3013
3309
|
};
|
3014
3310
|
async function createDefaultLayouts(schema) {
|
@@ -3029,8 +3325,7 @@ function createDefaultEditLayout(schema) {
|
|
3029
3325
|
return appendToEditLayout([], keys2, schema);
|
3030
3326
|
}
|
3031
3327
|
function syncLayouts(configuration, schema) {
|
3032
|
-
if (___default.default.isEmpty(configuration.layouts))
|
3033
|
-
return createDefaultLayouts(schema);
|
3328
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3034
3329
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3035
3330
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3036
3331
|
const cleanEditRelations = editRelations.filter(
|
@@ -3041,9 +3336,8 @@ function syncLayouts(configuration, schema) {
|
|
3041
3336
|
for (const row of edit) {
|
3042
3337
|
const newRow = [];
|
3043
3338
|
for (const el of row) {
|
3044
|
-
if (!hasEditableAttribute(schema, el.name))
|
3045
|
-
|
3046
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3339
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3340
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3047
3341
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3048
3342
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3049
3343
|
elementsToReAppend.push(el.name);
|
@@ -3073,8 +3367,7 @@ function syncLayouts(configuration, schema) {
|
|
3073
3367
|
};
|
3074
3368
|
}
|
3075
3369
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3076
|
-
if (keysToAppend.length === 0)
|
3077
|
-
return layout;
|
3370
|
+
if (keysToAppend.length === 0) return layout;
|
3078
3371
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3079
3372
|
if (!layout[currentRowIndex]) {
|
3080
3373
|
layout[currentRowIndex] = [];
|
@@ -3183,17 +3476,17 @@ const configurationService$1 = createConfigurationService({
|
|
3183
3476
|
isComponent: true,
|
3184
3477
|
prefix: STORE_KEY_PREFIX,
|
3185
3478
|
getModels() {
|
3186
|
-
const { toContentManagerModel } = getService$
|
3479
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3187
3480
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3188
3481
|
}
|
3189
3482
|
});
|
3190
3483
|
const components = ({ strapi: strapi2 }) => ({
|
3191
3484
|
findAllComponents() {
|
3192
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3193
3486
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3194
3487
|
},
|
3195
3488
|
findComponent(uid2) {
|
3196
|
-
const { toContentManagerModel } = getService$
|
3489
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3197
3490
|
const component = strapi2.components[uid2];
|
3198
3491
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3199
3492
|
},
|
@@ -3244,17 +3537,17 @@ const configurationService = createConfigurationService({
|
|
3244
3537
|
storeUtils,
|
3245
3538
|
prefix: "content_types",
|
3246
3539
|
getModels() {
|
3247
|
-
const { toContentManagerModel } = getService$
|
3540
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3248
3541
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3249
3542
|
}
|
3250
3543
|
});
|
3251
3544
|
const service = ({ strapi: strapi2 }) => ({
|
3252
3545
|
findAllContentTypes() {
|
3253
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3254
3547
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3255
3548
|
},
|
3256
3549
|
findContentType(uid2) {
|
3257
|
-
const { toContentManagerModel } = getService$
|
3550
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3258
3551
|
const contentType = strapi2.contentTypes[uid2];
|
3259
3552
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3260
3553
|
},
|
@@ -3283,7 +3576,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3283
3576
|
return this.findConfiguration(contentType);
|
3284
3577
|
},
|
3285
3578
|
findComponentsConfigurations(contentType) {
|
3286
|
-
return getService$
|
3579
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3287
3580
|
},
|
3288
3581
|
syncConfigurations() {
|
3289
3582
|
return configurationService.syncConfigurations();
|
@@ -3464,12 +3757,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3464
3757
|
ability: userAbility,
|
3465
3758
|
model
|
3466
3759
|
});
|
3467
|
-
const
|
3760
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3761
|
+
const toSubject = (entity) => {
|
3762
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3763
|
+
};
|
3468
3764
|
const can = (action, entity, field) => {
|
3469
|
-
|
3765
|
+
const subject = toSubject(entity);
|
3766
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3767
|
+
return (
|
3768
|
+
// Test the original action to see if it passes
|
3769
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3770
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3771
|
+
);
|
3470
3772
|
};
|
3471
3773
|
const cannot = (action, entity, field) => {
|
3472
|
-
|
3774
|
+
const subject = toSubject(entity);
|
3775
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3776
|
+
return (
|
3777
|
+
// Test both the original action
|
3778
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3779
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3780
|
+
);
|
3473
3781
|
};
|
3474
3782
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3475
3783
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3540,7 +3848,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3540
3848
|
return userAbility.can(action);
|
3541
3849
|
},
|
3542
3850
|
async registerPermissions() {
|
3543
|
-
const displayedContentTypes = getService$
|
3851
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3544
3852
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3545
3853
|
const actions = [
|
3546
3854
|
{
|
@@ -3625,6 +3933,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3625
3933
|
if (initialPopulate) {
|
3626
3934
|
return initialPopulate;
|
3627
3935
|
}
|
3936
|
+
if (attributeName === "localizations") {
|
3937
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3938
|
+
return {
|
3939
|
+
populate: validationPopulate.populate
|
3940
|
+
};
|
3941
|
+
}
|
3628
3942
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3629
3943
|
return true;
|
3630
3944
|
}
|
@@ -3684,6 +3998,9 @@ const getDeepPopulate = (uid2, {
|
|
3684
3998
|
return {};
|
3685
3999
|
}
|
3686
4000
|
const model = strapi.getModel(uid2);
|
4001
|
+
if (!model) {
|
4002
|
+
return {};
|
4003
|
+
}
|
3687
4004
|
return Object.keys(model.attributes).reduce(
|
3688
4005
|
(populateAcc, attributeName) => fp.merge(
|
3689
4006
|
populateAcc,
|
@@ -3703,40 +4020,46 @@ const getDeepPopulate = (uid2, {
|
|
3703
4020
|
{}
|
3704
4021
|
);
|
3705
4022
|
};
|
3706
|
-
const
|
3707
|
-
|
3708
|
-
|
3709
|
-
countOne = false,
|
3710
|
-
maxLevel = Infinity
|
3711
|
-
} = {}, level = 1) => {
|
3712
|
-
if (level > maxLevel) {
|
4023
|
+
const getPopulateForValidation = (uid2) => {
|
4024
|
+
const model = strapi.getModel(uid2);
|
4025
|
+
if (!model) {
|
3713
4026
|
return {};
|
3714
4027
|
}
|
3715
|
-
const model = strapi.getModel(uid2);
|
3716
4028
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3717
|
-
if (
|
4029
|
+
if (isScalarAttribute(attribute)) {
|
4030
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4031
|
+
populateAcc.fields = populateAcc.fields || [];
|
4032
|
+
populateAcc.fields.push(attributeName);
|
4033
|
+
}
|
3718
4034
|
return populateAcc;
|
3719
4035
|
}
|
3720
|
-
if (
|
3721
|
-
|
3722
|
-
|
3723
|
-
|
4036
|
+
if (isComponent(attribute)) {
|
4037
|
+
const component = attribute.component;
|
4038
|
+
const componentResult = getPopulateForValidation(component);
|
4039
|
+
if (Object.keys(componentResult).length > 0) {
|
4040
|
+
populateAcc.populate = populateAcc.populate || {};
|
4041
|
+
populateAcc.populate[attributeName] = componentResult;
|
4042
|
+
}
|
4043
|
+
return populateAcc;
|
3724
4044
|
}
|
3725
|
-
|
3726
|
-
|
3727
|
-
|
3728
|
-
|
3729
|
-
|
3730
|
-
|
3731
|
-
|
3732
|
-
|
3733
|
-
|
3734
|
-
countOne,
|
3735
|
-
maxLevel
|
4045
|
+
if (isDynamicZone(attribute)) {
|
4046
|
+
const components2 = attribute.components;
|
4047
|
+
const componentsResult = (components2 || []).reduce(
|
4048
|
+
(acc, componentUID) => {
|
4049
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4050
|
+
if (Object.keys(componentResult).length > 0) {
|
4051
|
+
acc[componentUID] = componentResult;
|
4052
|
+
}
|
4053
|
+
return acc;
|
3736
4054
|
},
|
3737
|
-
|
3738
|
-
)
|
3739
|
-
|
4055
|
+
{}
|
4056
|
+
);
|
4057
|
+
if (Object.keys(componentsResult).length > 0) {
|
4058
|
+
populateAcc.populate = populateAcc.populate || {};
|
4059
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4060
|
+
}
|
4061
|
+
}
|
4062
|
+
return populateAcc;
|
3740
4063
|
}, {});
|
3741
4064
|
};
|
3742
4065
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3746,6 +4069,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3746
4069
|
const attribute = model.attributes[attributeName];
|
3747
4070
|
switch (attribute.type) {
|
3748
4071
|
case "relation": {
|
4072
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4073
|
+
if (isMorphRelation) {
|
4074
|
+
break;
|
4075
|
+
}
|
3749
4076
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3750
4077
|
populateAcc[attributeName] = {
|
3751
4078
|
count: true,
|
@@ -3812,7 +4139,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3812
4139
|
return populateQuery;
|
3813
4140
|
};
|
3814
4141
|
const buildDeepPopulate = (uid2) => {
|
3815
|
-
return getService$
|
4142
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3816
4143
|
};
|
3817
4144
|
const populateBuilder = (uid2) => {
|
3818
4145
|
let getInitialPopulate = async () => {
|
@@ -3974,7 +4301,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3974
4301
|
"locale",
|
3975
4302
|
"updatedAt",
|
3976
4303
|
"createdAt",
|
3977
|
-
"status",
|
3978
4304
|
"publishedAt",
|
3979
4305
|
"documentId"
|
3980
4306
|
];
|
@@ -3995,34 +4321,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3995
4321
|
/**
|
3996
4322
|
* Returns available locales of a document for the current status
|
3997
4323
|
*/
|
3998
|
-
async getAvailableLocales(uid2, version, allVersions
|
4324
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3999
4325
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
4000
|
-
|
4326
|
+
if (version.locale) {
|
4327
|
+
delete versionsByLocale[version.locale];
|
4328
|
+
}
|
4001
4329
|
const model = strapi2.getModel(uid2);
|
4002
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4003
|
-
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4004
|
-
({ key }, { remove }) => {
|
4005
|
-
if (keysToKeep.includes(key)) {
|
4006
|
-
return;
|
4007
|
-
}
|
4008
|
-
remove(key);
|
4009
|
-
},
|
4010
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4011
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4012
|
-
localeVersion
|
4013
|
-
);
|
4014
4330
|
const mappingResult = await strapiUtils.async.map(
|
4015
4331
|
Object.values(versionsByLocale),
|
4016
4332
|
async (localeVersions) => {
|
4017
|
-
const mappedLocaleVersions = await strapiUtils.async.map(
|
4018
|
-
localeVersions,
|
4019
|
-
traversalFunction
|
4020
|
-
);
|
4021
4333
|
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4022
|
-
return
|
4334
|
+
return localeVersions[0];
|
4023
4335
|
}
|
4024
|
-
const draftVersion =
|
4025
|
-
const otherVersions =
|
4336
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4337
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4026
4338
|
if (!draftVersion) {
|
4027
4339
|
return;
|
4028
4340
|
}
|
@@ -4044,8 +4356,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4044
4356
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4045
4357
|
return matchLocale && matchStatus;
|
4046
4358
|
});
|
4047
|
-
if (!availableStatus)
|
4048
|
-
return availableStatus;
|
4359
|
+
if (!availableStatus) return availableStatus;
|
4049
4360
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4050
4361
|
},
|
4051
4362
|
/**
|
@@ -4055,18 +4366,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4055
4366
|
* @returns
|
4056
4367
|
*/
|
4057
4368
|
async getManyAvailableStatus(uid2, documents) {
|
4058
|
-
if (!documents.length)
|
4059
|
-
return [];
|
4369
|
+
if (!documents.length) return [];
|
4060
4370
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4061
|
-
const
|
4062
|
-
const
|
4063
|
-
|
4064
|
-
|
4065
|
-
|
4066
|
-
|
4067
|
-
|
4068
|
-
|
4069
|
-
|
4371
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4372
|
+
const where = {
|
4373
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4374
|
+
publishedAt: { $null: status === "published" }
|
4375
|
+
};
|
4376
|
+
if (locales.length) {
|
4377
|
+
where.locale = { $in: locales };
|
4378
|
+
}
|
4379
|
+
return strapi2.query(uid2).findMany({
|
4380
|
+
where,
|
4381
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4070
4382
|
});
|
4071
4383
|
},
|
4072
4384
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4083,10 +4395,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4083
4395
|
} else if (otherVersion) {
|
4084
4396
|
draftVersion = otherVersion;
|
4085
4397
|
}
|
4086
|
-
if (!draftVersion)
|
4087
|
-
|
4088
|
-
if (!publishedVersion)
|
4089
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4398
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4399
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4090
4400
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4091
4401
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4092
4402
|
},
|
@@ -4094,11 +4404,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4094
4404
|
// We could refactor this so the locales are only loaded when they're
|
4095
4405
|
// needed. e.g. in the bulk locale action modal.
|
4096
4406
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4097
|
-
const populate =
|
4098
|
-
const
|
4099
|
-
where: { documentId: version.documentId },
|
4407
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4408
|
+
const params = {
|
4100
4409
|
populate: {
|
4101
|
-
// Populate only fields that require validation for bulk locale actions
|
4102
4410
|
...populate,
|
4103
4411
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4104
4412
|
createdBy: {
|
@@ -4107,9 +4415,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4107
4415
|
updatedBy: {
|
4108
4416
|
select: ["id", "firstname", "lastname", "email"]
|
4109
4417
|
}
|
4418
|
+
},
|
4419
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4420
|
+
filters: {
|
4421
|
+
documentId: version.documentId
|
4110
4422
|
}
|
4111
|
-
}
|
4112
|
-
const
|
4423
|
+
};
|
4424
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4425
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4426
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
4113
4427
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4114
4428
|
return {
|
4115
4429
|
availableLocales: availableLocalesResult,
|
@@ -4123,13 +4437,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4123
4437
|
*/
|
4124
4438
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4125
4439
|
if (!document) {
|
4126
|
-
return
|
4440
|
+
return {
|
4441
|
+
data: document,
|
4442
|
+
meta: {
|
4443
|
+
availableLocales: [],
|
4444
|
+
availableStatus: []
|
4445
|
+
}
|
4446
|
+
};
|
4127
4447
|
}
|
4128
4448
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4129
4449
|
if (!hasDraftAndPublish) {
|
4130
4450
|
opts.availableStatus = false;
|
4131
4451
|
}
|
4132
4452
|
const meta = await this.getMetadata(uid2, document, opts);
|
4453
|
+
if (document.localizations) {
|
4454
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4455
|
+
document.localizations = document.localizations.map((d) => {
|
4456
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4457
|
+
return {
|
4458
|
+
...d,
|
4459
|
+
status: this.getStatus(d, status ? [status] : [])
|
4460
|
+
};
|
4461
|
+
});
|
4462
|
+
}
|
4133
4463
|
return {
|
4134
4464
|
data: {
|
4135
4465
|
...document,
|
@@ -4231,10 +4561,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4231
4561
|
async clone(id, body, uid2) {
|
4232
4562
|
const populate = await buildDeepPopulate(uid2);
|
4233
4563
|
const params = {
|
4234
|
-
data:
|
4235
|
-
...omitIdField(body),
|
4236
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4237
|
-
},
|
4564
|
+
data: omitIdField(body),
|
4238
4565
|
populate
|
4239
4566
|
};
|
4240
4567
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4350,7 +4677,8 @@ const services = {
|
|
4350
4677
|
permission,
|
4351
4678
|
"populate-builder": populateBuilder$1,
|
4352
4679
|
uid,
|
4353
|
-
...history.services ? history.services : {}
|
4680
|
+
...history.services ? history.services : {},
|
4681
|
+
...preview.services ? preview.services : {}
|
4354
4682
|
};
|
4355
4683
|
const index = () => {
|
4356
4684
|
return {
|