@strapi/content-manager 0.0.0-experimental.32c4b04580cc12400710050c8198e46b3644cfd4 → 0.0.0-experimental.39bf1ab0d2e327b0a192d2f5adcb4182de865411
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs → ComponentConfigurationPage-CzVt9QCC.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs.map → ComponentConfigurationPage-CzVt9QCC.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js → ComponentConfigurationPage-DYq8aqos.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js.map → ComponentConfigurationPage-DYq8aqos.js.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-Xp7lun0f.js → EditConfigurationPage-C9IATpr0.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js.map → EditConfigurationPage-C9IATpr0.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs → EditConfigurationPage-CLDwrUv5.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs.map → EditConfigurationPage-CLDwrUv5.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-C-ukDOB7.js → EditViewPage-Ch-uBvbv.js} +63 -13
- package/dist/_chunks/EditViewPage-Ch-uBvbv.js.map +1 -0
- package/dist/_chunks/{EditViewPage-BLsjc5F-.mjs → EditViewPage-DtKM7Jgw.mjs} +63 -12
- package/dist/_chunks/EditViewPage-DtKM7Jgw.mjs.map +1 -0
- package/dist/_chunks/{Field-Bfph5SOd.js → Field-B9ADaInZ.js} +235 -164
- package/dist/_chunks/Field-B9ADaInZ.js.map +1 -0
- package/dist/_chunks/{Field-Cs7duwWd.mjs → Field-Bn1jgMeF.mjs} +232 -160
- package/dist/_chunks/Field-Bn1jgMeF.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-Dg_GS5TQ.mjs → Form-BB5i9Pxl.mjs} +37 -18
- package/dist/_chunks/Form-BB5i9Pxl.mjs.map +1 -0
- package/dist/_chunks/{Form-CPYqIWDG.js → Form-C3kjKrPw.js} +39 -21
- package/dist/_chunks/Form-C3kjKrPw.js.map +1 -0
- package/dist/_chunks/{History-DNQkXANT.js → History-AwrK0-SA.js} +42 -100
- package/dist/_chunks/History-AwrK0-SA.js.map +1 -0
- package/dist/_chunks/{History-wrnHqf09.mjs → History-Cw2Q7OQL.mjs} +43 -100
- package/dist/_chunks/History-Cw2Q7OQL.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DScmJVkW.mjs → ListConfigurationPage-B47JIu1e.mjs} +19 -8
- package/dist/_chunks/ListConfigurationPage-B47JIu1e.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-CUQxfpjT.js → ListConfigurationPage-CNTJ0DBm.js} +19 -9
- package/dist/_chunks/ListConfigurationPage-CNTJ0DBm.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BsLiH2-2.js → ListViewPage-Be_UEBar.js} +109 -78
- package/dist/_chunks/ListViewPage-Be_UEBar.js.map +1 -0
- package/dist/_chunks/{ListViewPage-C4IvrMgY.mjs → ListViewPage-DuvjX6ra.mjs} +106 -74
- package/dist/_chunks/ListViewPage-DuvjX6ra.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js → NoContentTypePage-B1J0KUCO.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js.map → NoContentTypePage-B1J0KUCO.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs → NoContentTypePage-C6M-Q0Tv.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs.map → NoContentTypePage-C6M-Q0Tv.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs → NoPermissionsPage-CAi3zCAD.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs.map → NoPermissionsPage-CAi3zCAD.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js → NoPermissionsPage-CN34TlEE.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js.map → NoPermissionsPage-CN34TlEE.js.map} +1 -1
- package/dist/_chunks/Preview-BrBRcL10.mjs +293 -0
- package/dist/_chunks/Preview-BrBRcL10.mjs.map +1 -0
- package/dist/_chunks/Preview-DOqm5jcJ.js +311 -0
- package/dist/_chunks/Preview-DOqm5jcJ.js.map +1 -0
- package/dist/_chunks/{Relations-BZr8tL0R.mjs → Relations-_K-HYOiM.mjs} +76 -42
- package/dist/_chunks/Relations-_K-HYOiM.mjs.map +1 -0
- package/dist/_chunks/{Relations-CtELXYIK.js → Relations-xtKZHtTN.js} +76 -43
- package/dist/_chunks/Relations-xtKZHtTN.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BK8Xyl5I.js} +28 -15
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-Dtk_ot79.mjs} +28 -15
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-OerGjbAN.js → index-BlX-OdHL.js} +1092 -758
- package/dist/_chunks/index-BlX-OdHL.js.map +1 -0
- package/dist/_chunks/{index-c_5DdJi-.mjs → index-tETMKK2G.mjs} +1110 -776
- package/dist/_chunks/index-tETMKK2G.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-oPBiO7RY.mjs → layout-BaQBaz56.mjs} +23 -10
- package/dist/_chunks/layout-BaQBaz56.mjs.map +1 -0
- package/dist/_chunks/{layout-Ci7qHlFb.js → layout-D8Sz3KxF.js} +23 -11
- package/dist/_chunks/layout-D8Sz3KxF.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-COBpStiF.js → relations-CAbbX8Sa.js} +6 -7
- package/dist/_chunks/relations-CAbbX8Sa.js.map +1 -0
- package/dist/_chunks/{relations-BIdWFjdq.mjs → relations-CsfmCqOU.mjs} +6 -7
- package/dist/_chunks/relations-CsfmCqOU.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- 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/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- 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/constants.d.ts +1 -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 +578 -271
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +578 -270
- 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/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- 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 +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- 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/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- 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 +15 -15
- package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +0 -1
- package/dist/_chunks/Field-Bfph5SOd.js.map +0 -1
- package/dist/_chunks/Field-Cs7duwWd.mjs.map +0 -1
- package/dist/_chunks/Form-CPYqIWDG.js.map +0 -1
- package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +0 -1
- package/dist/_chunks/History-DNQkXANT.js.map +0 -1
- package/dist/_chunks/History-wrnHqf09.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +0 -1
- package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +0 -1
- package/dist/_chunks/Relations-BZr8tL0R.mjs.map +0 -1
- package/dist/_chunks/Relations-CtELXYIK.js.map +0 -1
- package/dist/_chunks/index-OerGjbAN.js.map +0 -1
- package/dist/_chunks/index-c_5DdJi-.mjs.map +0 -1
- package/dist/_chunks/layout-Ci7qHlFb.js.map +0 -1
- package/dist/_chunks/layout-oPBiO7RY.mjs.map +0 -1
- package/dist/_chunks/relations-BIdWFjdq.mjs.map +0 -1
- package/dist/_chunks/relations-COBpStiF.js.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.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat,
|
2
|
+
import { pick, omit, difference, castArray, mergeWith, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -7,10 +7,10 @@ import isNil from "lodash/isNil";
|
|
7
7
|
import _, { intersection as intersection$1, difference as difference$1 } from "lodash";
|
8
8
|
import qs from "qs";
|
9
9
|
import slugify from "@sindresorhus/slugify";
|
10
|
-
const getService$
|
10
|
+
const getService$2 = (name) => {
|
11
11
|
return strapi.plugin("content-manager").service(name);
|
12
12
|
};
|
13
|
-
function getService(strapi2, name) {
|
13
|
+
function getService$1(strapi2, name) {
|
14
14
|
return strapi2.service(`plugin::content-manager.${name}`);
|
15
15
|
}
|
16
16
|
const historyRestoreVersionSchema = yup.object().shape({
|
@@ -46,7 +46,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
46
46
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
47
47
|
throw new errors.ForbiddenError("contentType and documentId are required");
|
48
48
|
}
|
49
|
-
const permissionChecker2 = getService$
|
49
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
50
50
|
userAbility: ctx.state.userAbility,
|
51
51
|
model: ctx.query.contentType
|
52
52
|
});
|
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
54
54
|
return ctx.forbidden();
|
55
55
|
}
|
56
56
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
57
|
-
const { results, pagination: pagination2 } = await getService(strapi2, "history").findVersionsPage({
|
57
|
+
const { results, pagination: pagination2 } = await getService$1(strapi2, "history").findVersionsPage({
|
58
58
|
query: {
|
59
59
|
...query,
|
60
60
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -79,14 +79,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
79
79
|
async restoreVersion(ctx) {
|
80
80
|
const request = ctx.request;
|
81
81
|
await validateRestoreVersion(request.body, "contentType is required");
|
82
|
-
const permissionChecker2 = getService$
|
82
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
83
83
|
userAbility: ctx.state.userAbility,
|
84
84
|
model: request.body.contentType
|
85
85
|
});
|
86
86
|
if (permissionChecker2.cannot.update()) {
|
87
87
|
throw new errors.ForbiddenError();
|
88
88
|
}
|
89
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
89
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
90
90
|
request.params.versionId
|
91
91
|
);
|
92
92
|
return {
|
@@ -95,7 +95,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
95
95
|
}
|
96
96
|
};
|
97
97
|
};
|
98
|
-
const controllers$
|
98
|
+
const controllers$2 = {
|
99
99
|
"history-version": createHistoryVersionController
|
100
100
|
/**
|
101
101
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -141,8 +141,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
141
141
|
};
|
142
142
|
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
143
143
|
if (Array.isArray(versionRelationData)) {
|
144
|
-
if (versionRelationData.length === 0)
|
145
|
-
return versionRelationData;
|
144
|
+
if (versionRelationData.length === 0) return versionRelationData;
|
146
145
|
const existingAndMissingRelations = await Promise.all(
|
147
146
|
versionRelationData.map((relation) => {
|
148
147
|
return strapi2.documents(attribute.target).findOne({
|
@@ -173,10 +172,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
173
172
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
174
173
|
};
|
175
174
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
175
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
176
176
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
177
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
177
178
|
const getLocaleDictionary = async () => {
|
178
|
-
if (!localesService)
|
179
|
-
return {};
|
179
|
+
if (!localesService) return {};
|
180
180
|
const locales = await localesService.find() || [];
|
181
181
|
return locales.reduce(
|
182
182
|
(acc, locale) => {
|
@@ -200,9 +200,21 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
200
200
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
201
201
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
202
202
|
};
|
203
|
-
const
|
203
|
+
const getComponentFields = (componentUID) => {
|
204
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
205
|
+
(fieldsAcc, [key, attribute]) => {
|
206
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
207
|
+
fieldsAcc.push(key);
|
208
|
+
}
|
209
|
+
return fieldsAcc;
|
210
|
+
},
|
211
|
+
[]
|
212
|
+
);
|
213
|
+
};
|
214
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
204
215
|
const model = strapi2.getModel(uid2);
|
205
216
|
const attributes = Object.entries(model.attributes);
|
217
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
206
218
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
207
219
|
switch (attribute.type) {
|
208
220
|
case "relation": {
|
@@ -212,23 +224,29 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
212
224
|
}
|
213
225
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
214
226
|
if (isVisible2) {
|
215
|
-
acc[attributeName] = {
|
227
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
216
228
|
}
|
217
229
|
break;
|
218
230
|
}
|
219
231
|
case "media": {
|
220
|
-
acc[attributeName] = {
|
232
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
221
233
|
break;
|
222
234
|
}
|
223
235
|
case "component": {
|
224
236
|
const populate = getDeepPopulate2(attribute.component);
|
225
|
-
acc[attributeName] = {
|
237
|
+
acc[attributeName] = {
|
238
|
+
populate,
|
239
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
240
|
+
};
|
226
241
|
break;
|
227
242
|
}
|
228
243
|
case "dynamiczone": {
|
229
244
|
const populatedComponents = (attribute.components || []).reduce(
|
230
245
|
(acc2, componentUID) => {
|
231
|
-
acc2[componentUID] = {
|
246
|
+
acc2[componentUID] = {
|
247
|
+
populate: getDeepPopulate2(componentUID),
|
248
|
+
[fieldSelector]: getComponentFields(componentUID)
|
249
|
+
};
|
232
250
|
return acc2;
|
233
251
|
},
|
234
252
|
{}
|
@@ -290,6 +308,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
290
308
|
getRelationRestoreValue,
|
291
309
|
getMediaRestoreValue,
|
292
310
|
getDefaultLocale,
|
311
|
+
isLocalizedContentType,
|
293
312
|
getLocaleDictionary,
|
294
313
|
getRetentionDays,
|
295
314
|
getVersionStatus,
|
@@ -312,7 +331,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
312
331
|
});
|
313
332
|
},
|
314
333
|
async findVersionsPage(params) {
|
315
|
-
const
|
334
|
+
const model = strapi2.getModel(params.query.contentType);
|
335
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
336
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
337
|
+
let locale = null;
|
338
|
+
if (isLocalizedContentType) {
|
339
|
+
locale = params.query.locale || defaultLocale;
|
340
|
+
}
|
316
341
|
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
317
342
|
query.findPage({
|
318
343
|
...params.query,
|
@@ -334,7 +359,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
359
|
const attributeValue = entry.data[attributeKey];
|
335
360
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
336
361
|
if (attributeSchema.type === "media") {
|
337
|
-
const permissionChecker2 = getService$
|
362
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
338
363
|
userAbility: params.state.userAbility,
|
339
364
|
model: "plugin::upload.file"
|
340
365
|
});
|
@@ -357,7 +382,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
357
382
|
if (userToPopulate == null) {
|
358
383
|
return null;
|
359
384
|
}
|
360
|
-
return strapi2.query("admin::user").findOne({
|
385
|
+
return strapi2.query("admin::user").findOne({
|
386
|
+
where: {
|
387
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
388
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
389
|
+
}
|
390
|
+
});
|
361
391
|
})
|
362
392
|
);
|
363
393
|
return {
|
@@ -370,7 +400,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
370
400
|
[attributeKey]: adminUsers
|
371
401
|
};
|
372
402
|
}
|
373
|
-
const permissionChecker2 = getService$
|
403
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
374
404
|
userAbility: params.state.userAbility,
|
375
405
|
model: attributeSchema.target
|
376
406
|
});
|
@@ -468,6 +498,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
468
498
|
}
|
469
499
|
};
|
470
500
|
};
|
501
|
+
const shouldCreateHistoryVersion = (context) => {
|
502
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
503
|
+
return false;
|
504
|
+
}
|
505
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
509
|
+
return false;
|
510
|
+
}
|
511
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
512
|
+
return false;
|
513
|
+
}
|
514
|
+
return true;
|
515
|
+
};
|
516
|
+
const getSchemas = (uid2) => {
|
517
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
518
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
519
|
+
(currentComponentSchemas, key) => {
|
520
|
+
const fieldSchema = attributesSchema[key];
|
521
|
+
if (fieldSchema.type === "component") {
|
522
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
523
|
+
return {
|
524
|
+
...currentComponentSchemas,
|
525
|
+
[fieldSchema.component]: componentSchema
|
526
|
+
};
|
527
|
+
}
|
528
|
+
return currentComponentSchemas;
|
529
|
+
},
|
530
|
+
{}
|
531
|
+
);
|
532
|
+
return {
|
533
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
534
|
+
componentsSchemas
|
535
|
+
};
|
536
|
+
};
|
471
537
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
472
538
|
const state = {
|
473
539
|
deleteExpiredJob: null,
|
@@ -480,76 +546,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
480
546
|
return;
|
481
547
|
}
|
482
548
|
strapi2.documents.use(async (context, next) => {
|
483
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
484
|
-
return next();
|
485
|
-
}
|
486
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
487
|
-
return next();
|
488
|
-
}
|
489
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
490
|
-
return next();
|
491
|
-
}
|
492
|
-
const contentTypeUid = context.contentType.uid;
|
493
|
-
if (!contentTypeUid.startsWith("api::")) {
|
494
|
-
return next();
|
495
|
-
}
|
496
549
|
const result = await next();
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
550
|
+
if (!shouldCreateHistoryVersion(context)) {
|
551
|
+
return result;
|
552
|
+
}
|
553
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
501
554
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
502
|
-
const
|
503
|
-
if (
|
504
|
-
|
505
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
506
|
-
);
|
507
|
-
return next();
|
555
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
556
|
+
if (!locales.length) {
|
557
|
+
return result;
|
508
558
|
}
|
509
|
-
const
|
510
|
-
|
511
|
-
|
512
|
-
|
559
|
+
const uid2 = context.contentType.uid;
|
560
|
+
const schemas = getSchemas(uid2);
|
561
|
+
const model = strapi2.getModel(uid2);
|
562
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
563
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
564
|
+
where: {
|
565
|
+
documentId,
|
566
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
567
|
+
...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
568
|
+
},
|
569
|
+
populate: serviceUtils.getDeepPopulate(
|
570
|
+
uid2,
|
571
|
+
true
|
572
|
+
/* use database syntax */
|
573
|
+
)
|
513
574
|
});
|
514
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
515
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
516
|
-
const componentsSchemas = Object.keys(
|
517
|
-
attributesSchema
|
518
|
-
).reduce((currentComponentSchemas, key) => {
|
519
|
-
const fieldSchema = attributesSchema[key];
|
520
|
-
if (fieldSchema.type === "component") {
|
521
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
522
|
-
return {
|
523
|
-
...currentComponentSchemas,
|
524
|
-
[fieldSchema.component]: componentSchema
|
525
|
-
};
|
526
|
-
}
|
527
|
-
return currentComponentSchemas;
|
528
|
-
}, {});
|
529
575
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
530
|
-
onCommit(() => {
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
576
|
+
onCommit(async () => {
|
577
|
+
for (const entry of localeEntries) {
|
578
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
579
|
+
await getService$1(strapi2, "history").createVersion({
|
580
|
+
contentType: uid2,
|
581
|
+
data: omit(FIELDS_TO_IGNORE, entry),
|
582
|
+
relatedDocumentId: documentId,
|
583
|
+
locale: entry.locale,
|
584
|
+
status,
|
585
|
+
...schemas
|
586
|
+
});
|
587
|
+
}
|
540
588
|
});
|
541
589
|
});
|
542
590
|
return result;
|
543
591
|
});
|
544
|
-
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
592
|
+
state.deleteExpiredJob = scheduleJob("historyDaily", "0 0 * * *", () => {
|
545
593
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
546
594
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
547
595
|
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
548
596
|
where: {
|
549
597
|
created_at: {
|
550
|
-
$lt: expirationDate
|
598
|
+
$lt: expirationDate
|
551
599
|
}
|
552
600
|
}
|
601
|
+
}).catch((error) => {
|
602
|
+
if (error instanceof Error) {
|
603
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
604
|
+
}
|
553
605
|
});
|
554
606
|
});
|
555
607
|
state.isInitialized = true;
|
@@ -561,17 +613,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
561
613
|
}
|
562
614
|
};
|
563
615
|
};
|
564
|
-
const services$
|
616
|
+
const services$2 = {
|
565
617
|
history: createHistoryService,
|
566
618
|
lifecycles: createLifecyclesService
|
567
619
|
};
|
568
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
620
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
569
621
|
const historyVersionRouter = {
|
570
622
|
type: "admin",
|
571
623
|
routes: [
|
572
624
|
{
|
573
625
|
method: "GET",
|
574
|
-
info,
|
626
|
+
info: info$1,
|
575
627
|
path: "/history-versions",
|
576
628
|
handler: "history-version.findMany",
|
577
629
|
config: {
|
@@ -580,7 +632,7 @@ const historyVersionRouter = {
|
|
580
632
|
},
|
581
633
|
{
|
582
634
|
method: "PUT",
|
583
|
-
info,
|
635
|
+
info: info$1,
|
584
636
|
path: "/history-versions/:versionId/restore",
|
585
637
|
handler: "history-version.restoreVersion",
|
586
638
|
config: {
|
@@ -589,7 +641,7 @@ const historyVersionRouter = {
|
|
589
641
|
}
|
590
642
|
]
|
591
643
|
};
|
592
|
-
const routes$
|
644
|
+
const routes$2 = {
|
593
645
|
"history-version": historyVersionRouter
|
594
646
|
};
|
595
647
|
const historyVersion = {
|
@@ -636,21 +688,21 @@ const historyVersion = {
|
|
636
688
|
}
|
637
689
|
}
|
638
690
|
};
|
639
|
-
const getFeature = () => {
|
691
|
+
const getFeature$1 = () => {
|
640
692
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
641
693
|
return {
|
642
694
|
register({ strapi: strapi2 }) {
|
643
695
|
strapi2.get("models").add(historyVersion);
|
644
696
|
},
|
645
697
|
bootstrap({ strapi: strapi2 }) {
|
646
|
-
getService(strapi2, "lifecycles").bootstrap();
|
698
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
647
699
|
},
|
648
700
|
destroy({ strapi: strapi2 }) {
|
649
|
-
getService(strapi2, "lifecycles").destroy();
|
701
|
+
getService$1(strapi2, "lifecycles").destroy();
|
650
702
|
},
|
651
|
-
controllers: controllers$
|
652
|
-
services: services$
|
653
|
-
routes: routes$
|
703
|
+
controllers: controllers$2,
|
704
|
+
services: services$2,
|
705
|
+
routes: routes$2
|
654
706
|
};
|
655
707
|
}
|
656
708
|
return {
|
@@ -659,9 +711,205 @@ const getFeature = () => {
|
|
659
711
|
}
|
660
712
|
};
|
661
713
|
};
|
662
|
-
const history = getFeature();
|
714
|
+
const history = getFeature$1();
|
715
|
+
const FEATURE_ID = "preview";
|
716
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
717
|
+
const previewRouter = {
|
718
|
+
type: "admin",
|
719
|
+
routes: [
|
720
|
+
{
|
721
|
+
method: "GET",
|
722
|
+
info,
|
723
|
+
path: "/preview/url/:contentType",
|
724
|
+
handler: "preview.getPreviewUrl",
|
725
|
+
config: {
|
726
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
727
|
+
}
|
728
|
+
}
|
729
|
+
]
|
730
|
+
};
|
731
|
+
const routes$1 = {
|
732
|
+
preview: previewRouter
|
733
|
+
};
|
734
|
+
function getService(strapi2, name) {
|
735
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
736
|
+
}
|
737
|
+
const getPreviewUrlSchema = yup.object().shape({
|
738
|
+
// Will be undefined for single types
|
739
|
+
documentId: yup.string(),
|
740
|
+
locale: yup.string().nullable(),
|
741
|
+
status: yup.string()
|
742
|
+
}).required();
|
743
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
744
|
+
await validateYupSchema(getPreviewUrlSchema)(params);
|
745
|
+
const newParams = pick(["documentId", "locale", "status"], params);
|
746
|
+
const model = strapi2.getModel(uid2);
|
747
|
+
if (!model || model.modelType !== "contentType") {
|
748
|
+
throw new errors.ValidationError("Invalid content type");
|
749
|
+
}
|
750
|
+
const isSingleType = model?.kind === "singleType";
|
751
|
+
if (!isSingleType && !params.documentId) {
|
752
|
+
throw new errors.ValidationError("documentId is required for Collection Types");
|
753
|
+
}
|
754
|
+
if (isSingleType) {
|
755
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
756
|
+
if (!doc) {
|
757
|
+
throw new errors.NotFoundError("Document not found");
|
758
|
+
}
|
759
|
+
newParams.documentId = doc?.documentId;
|
760
|
+
}
|
761
|
+
if (!newParams.status) {
|
762
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
763
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
764
|
+
}
|
765
|
+
return newParams;
|
766
|
+
};
|
767
|
+
const createPreviewController = () => {
|
768
|
+
return {
|
769
|
+
/**
|
770
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
771
|
+
* in the Content Manager.
|
772
|
+
*/
|
773
|
+
async getPreviewUrl(ctx) {
|
774
|
+
const uid2 = ctx.params.contentType;
|
775
|
+
const query = ctx.request.query;
|
776
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
777
|
+
const previewService = getService(strapi, "preview");
|
778
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
779
|
+
if (!url) {
|
780
|
+
ctx.status = 204;
|
781
|
+
}
|
782
|
+
return {
|
783
|
+
data: { url }
|
784
|
+
};
|
785
|
+
}
|
786
|
+
};
|
787
|
+
};
|
788
|
+
const controllers$1 = {
|
789
|
+
preview: createPreviewController
|
790
|
+
/**
|
791
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
792
|
+
* passing a controller factory as the value, instead of a controller object directly
|
793
|
+
*/
|
794
|
+
};
|
795
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
796
|
+
const config = getService(strapi2, "preview-config");
|
797
|
+
return {
|
798
|
+
async getPreviewUrl(uid2, params) {
|
799
|
+
const handler = config.getPreviewHandler();
|
800
|
+
try {
|
801
|
+
return handler(uid2, params);
|
802
|
+
} catch (error) {
|
803
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
804
|
+
throw new errors.ApplicationError("Failed to get preview URL");
|
805
|
+
}
|
806
|
+
return;
|
807
|
+
}
|
808
|
+
};
|
809
|
+
};
|
810
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
811
|
+
const middlewares = strapi.config.get("middlewares");
|
812
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
813
|
+
if (currentMiddleware === middleware.name) {
|
814
|
+
return middleware;
|
815
|
+
}
|
816
|
+
if (currentMiddleware.name === middleware.name) {
|
817
|
+
return mergeWith(
|
818
|
+
(objValue, srcValue) => {
|
819
|
+
if (Array.isArray(objValue)) {
|
820
|
+
return objValue.concat(srcValue);
|
821
|
+
}
|
822
|
+
return void 0;
|
823
|
+
},
|
824
|
+
currentMiddleware,
|
825
|
+
middleware
|
826
|
+
);
|
827
|
+
}
|
828
|
+
return currentMiddleware;
|
829
|
+
});
|
830
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
831
|
+
};
|
832
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
833
|
+
return {
|
834
|
+
register() {
|
835
|
+
if (!this.isEnabled()) {
|
836
|
+
return;
|
837
|
+
}
|
838
|
+
const config = strapi2.config.get("admin.preview");
|
839
|
+
if (config.config?.allowedOrigins) {
|
840
|
+
extendMiddlewareConfiguration({
|
841
|
+
name: "strapi::security",
|
842
|
+
config: {
|
843
|
+
contentSecurityPolicy: {
|
844
|
+
directives: {
|
845
|
+
"frame-src": config.config.allowedOrigins
|
846
|
+
}
|
847
|
+
}
|
848
|
+
}
|
849
|
+
});
|
850
|
+
}
|
851
|
+
},
|
852
|
+
isEnabled() {
|
853
|
+
const config = strapi2.config.get("admin.preview");
|
854
|
+
if (!config) {
|
855
|
+
return false;
|
856
|
+
}
|
857
|
+
return config?.enabled ?? true;
|
858
|
+
},
|
859
|
+
/**
|
860
|
+
* Validate if the configuration is valid
|
861
|
+
*/
|
862
|
+
validate() {
|
863
|
+
if (!this.isEnabled()) {
|
864
|
+
return;
|
865
|
+
}
|
866
|
+
const handler = this.getPreviewHandler();
|
867
|
+
if (typeof handler !== "function") {
|
868
|
+
throw new errors.ValidationError(
|
869
|
+
"Preview configuration is invalid. Handler must be a function"
|
870
|
+
);
|
871
|
+
}
|
872
|
+
},
|
873
|
+
/**
|
874
|
+
* Utility to get the preview handler from the configuration
|
875
|
+
*/
|
876
|
+
getPreviewHandler() {
|
877
|
+
const config = strapi2.config.get("admin.preview");
|
878
|
+
const emptyHandler = () => {
|
879
|
+
return void 0;
|
880
|
+
};
|
881
|
+
if (!this.isEnabled()) {
|
882
|
+
return emptyHandler;
|
883
|
+
}
|
884
|
+
return config?.config?.handler || emptyHandler;
|
885
|
+
}
|
886
|
+
};
|
887
|
+
};
|
888
|
+
const services$1 = {
|
889
|
+
preview: createPreviewService,
|
890
|
+
"preview-config": createPreviewConfigService
|
891
|
+
};
|
892
|
+
const getFeature = () => {
|
893
|
+
if (!strapi.features.future.isEnabled(FEATURE_ID)) {
|
894
|
+
return {};
|
895
|
+
}
|
896
|
+
return {
|
897
|
+
register() {
|
898
|
+
const config = getService(strapi, "preview-config");
|
899
|
+
config.validate();
|
900
|
+
config.register();
|
901
|
+
},
|
902
|
+
bootstrap() {
|
903
|
+
},
|
904
|
+
routes: routes$1,
|
905
|
+
controllers: controllers$1,
|
906
|
+
services: services$1
|
907
|
+
};
|
908
|
+
};
|
909
|
+
const preview = getFeature();
|
663
910
|
const register = async ({ strapi: strapi2 }) => {
|
664
911
|
await history.register?.({ strapi: strapi2 });
|
912
|
+
await preview.register?.({ strapi: strapi2 });
|
665
913
|
};
|
666
914
|
const ALLOWED_WEBHOOK_EVENTS = {
|
667
915
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -671,11 +919,12 @@ const bootstrap = async () => {
|
|
671
919
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
672
920
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
673
921
|
});
|
674
|
-
getService$
|
675
|
-
await getService$
|
676
|
-
await getService$
|
677
|
-
await getService$
|
922
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
923
|
+
await getService$2("components").syncConfigurations();
|
924
|
+
await getService$2("content-types").syncConfigurations();
|
925
|
+
await getService$2("permission").registerPermissions();
|
678
926
|
await history.bootstrap?.({ strapi });
|
927
|
+
await preview.bootstrap?.({ strapi });
|
679
928
|
};
|
680
929
|
const destroy = async ({ strapi: strapi2 }) => {
|
681
930
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1165,7 +1414,8 @@ const admin = {
|
|
1165
1414
|
};
|
1166
1415
|
const routes = {
|
1167
1416
|
admin,
|
1168
|
-
...history.routes ? history.routes : {}
|
1417
|
+
...history.routes ? history.routes : {},
|
1418
|
+
...preview.routes ? preview.routes : {}
|
1169
1419
|
};
|
1170
1420
|
const hasPermissionsSchema = yup$1.object({
|
1171
1421
|
actions: yup$1.array().of(yup$1.string()),
|
@@ -1176,6 +1426,11 @@ const { createPolicy } = policy;
|
|
1176
1426
|
const hasPermissions = createPolicy({
|
1177
1427
|
name: "plugin::content-manager.hasPermissions",
|
1178
1428
|
validator: validateHasPermissionsInput,
|
1429
|
+
/**
|
1430
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1431
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1432
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1433
|
+
*/
|
1179
1434
|
handler(ctx, config = {}) {
|
1180
1435
|
const { actions = [], hasAtLeastOne = false } = config;
|
1181
1436
|
const { userAbility } = ctx.state;
|
@@ -1223,8 +1478,7 @@ const isSortable = (schema, name) => {
|
|
1223
1478
|
if (!_.has(schema.attributes, name)) {
|
1224
1479
|
return false;
|
1225
1480
|
}
|
1226
|
-
if (schema.modelType === "component" && name === "id")
|
1227
|
-
return false;
|
1481
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1228
1482
|
const attribute = schema.attributes[name];
|
1229
1483
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1230
1484
|
return false;
|
@@ -1369,8 +1623,7 @@ const createDefaultSettings = async (schema) => {
|
|
1369
1623
|
};
|
1370
1624
|
};
|
1371
1625
|
const syncSettings = async (configuration, schema) => {
|
1372
|
-
if (isEmpty(configuration.settings))
|
1373
|
-
return createDefaultSettings(schema);
|
1626
|
+
if (isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1374
1627
|
const defaultField = getDefaultMainField(schema);
|
1375
1628
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1376
1629
|
return {
|
@@ -1417,7 +1670,7 @@ const createMetadasSchema = (schema) => {
|
|
1417
1670
|
if (!value) {
|
1418
1671
|
return yup$1.string();
|
1419
1672
|
}
|
1420
|
-
const targetSchema = getService$
|
1673
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1421
1674
|
schema.attributes[key].targetModel
|
1422
1675
|
);
|
1423
1676
|
if (!targetSchema) {
|
@@ -1546,8 +1799,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1546
1799
|
}
|
1547
1800
|
switch (attribute.type) {
|
1548
1801
|
case "relation": {
|
1549
|
-
if (canCreate(attributePath))
|
1550
|
-
return body2;
|
1802
|
+
if (canCreate(attributePath)) return body2;
|
1551
1803
|
return set(attributePath, { set: [] }, body2);
|
1552
1804
|
}
|
1553
1805
|
case "component": {
|
@@ -1557,8 +1809,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1557
1809
|
]);
|
1558
1810
|
}
|
1559
1811
|
default: {
|
1560
|
-
if (canCreate(attributePath))
|
1561
|
-
return body2;
|
1812
|
+
if (canCreate(attributePath)) return body2;
|
1562
1813
|
return set(attributePath, null, body2);
|
1563
1814
|
}
|
1564
1815
|
}
|
@@ -1586,7 +1837,7 @@ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultiple
|
|
1586
1837
|
}
|
1587
1838
|
};
|
1588
1839
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1589
|
-
const documentMetadata2 = getService$
|
1840
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1590
1841
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1591
1842
|
let {
|
1592
1843
|
meta: { availableLocales, availableStatus }
|
@@ -1612,8 +1863,8 @@ const createDocument = async (ctx, opts) => {
|
|
1612
1863
|
const { userAbility, user } = ctx.state;
|
1613
1864
|
const { model } = ctx.params;
|
1614
1865
|
const { body } = ctx.request;
|
1615
|
-
const documentManager2 = getService$
|
1616
|
-
const permissionChecker2 = getService$
|
1866
|
+
const documentManager2 = getService$2("document-manager");
|
1867
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1617
1868
|
if (permissionChecker2.cannot.create()) {
|
1618
1869
|
throw new errors.ForbiddenError();
|
1619
1870
|
}
|
@@ -1633,13 +1884,13 @@ const updateDocument = async (ctx, opts) => {
|
|
1633
1884
|
const { userAbility, user } = ctx.state;
|
1634
1885
|
const { id, model } = ctx.params;
|
1635
1886
|
const { body } = ctx.request;
|
1636
|
-
const documentManager2 = getService$
|
1637
|
-
const permissionChecker2 = getService$
|
1887
|
+
const documentManager2 = getService$2("document-manager");
|
1888
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1638
1889
|
if (permissionChecker2.cannot.update()) {
|
1639
1890
|
throw new errors.ForbiddenError();
|
1640
1891
|
}
|
1641
1892
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1642
|
-
const populate = await getService$
|
1893
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1643
1894
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1644
1895
|
const [documentVersion, documentExists] = await Promise.all([
|
1645
1896
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
@@ -1656,7 +1907,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1656
1907
|
throw new errors.ForbiddenError();
|
1657
1908
|
}
|
1658
1909
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1659
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1910
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1660
1911
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1661
1912
|
const sanitizedBody = await sanitizeFn(body);
|
1662
1913
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1670,14 +1921,14 @@ const collectionTypes = {
|
|
1670
1921
|
const { userAbility } = ctx.state;
|
1671
1922
|
const { model } = ctx.params;
|
1672
1923
|
const { query } = ctx.request;
|
1673
|
-
const documentMetadata2 = getService$
|
1674
|
-
const documentManager2 = getService$
|
1675
|
-
const permissionChecker2 = getService$
|
1924
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1925
|
+
const documentManager2 = getService$2("document-manager");
|
1926
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1676
1927
|
if (permissionChecker2.cannot.read()) {
|
1677
1928
|
return ctx.forbidden();
|
1678
1929
|
}
|
1679
1930
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1680
|
-
const populate = await getService$
|
1931
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1681
1932
|
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1682
1933
|
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1683
1934
|
{ ...permissionQuery, populate, locale, status },
|
@@ -1706,13 +1957,13 @@ const collectionTypes = {
|
|
1706
1957
|
async findOne(ctx) {
|
1707
1958
|
const { userAbility } = ctx.state;
|
1708
1959
|
const { model, id } = ctx.params;
|
1709
|
-
const documentManager2 = getService$
|
1710
|
-
const permissionChecker2 = getService$
|
1960
|
+
const documentManager2 = getService$2("document-manager");
|
1961
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1711
1962
|
if (permissionChecker2.cannot.read()) {
|
1712
1963
|
return ctx.forbidden();
|
1713
1964
|
}
|
1714
1965
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1715
|
-
const populate = await getService$
|
1966
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1716
1967
|
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1717
1968
|
const version = await documentManager2.findOne(id, model, {
|
1718
1969
|
populate,
|
@@ -1728,7 +1979,7 @@ const collectionTypes = {
|
|
1728
1979
|
permissionChecker2,
|
1729
1980
|
model,
|
1730
1981
|
// @ts-expect-error TODO: fix
|
1731
|
-
{ id, locale, publishedAt: null },
|
1982
|
+
{ documentId: id, locale, publishedAt: null },
|
1732
1983
|
{ availableLocales: true, availableStatus: false }
|
1733
1984
|
);
|
1734
1985
|
ctx.body = { data: {}, meta };
|
@@ -1743,7 +1994,7 @@ const collectionTypes = {
|
|
1743
1994
|
async create(ctx) {
|
1744
1995
|
const { userAbility } = ctx.state;
|
1745
1996
|
const { model } = ctx.params;
|
1746
|
-
const permissionChecker2 = getService$
|
1997
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1747
1998
|
const [totalEntries, document] = await Promise.all([
|
1748
1999
|
strapi.db.query(model).count(),
|
1749
2000
|
createDocument(ctx)
|
@@ -1764,7 +2015,7 @@ const collectionTypes = {
|
|
1764
2015
|
async update(ctx) {
|
1765
2016
|
const { userAbility } = ctx.state;
|
1766
2017
|
const { model } = ctx.params;
|
1767
|
-
const permissionChecker2 = getService$
|
2018
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1768
2019
|
const updatedVersion = await updateDocument(ctx);
|
1769
2020
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1770
2021
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1773,13 +2024,13 @@ const collectionTypes = {
|
|
1773
2024
|
const { userAbility, user } = ctx.state;
|
1774
2025
|
const { model, sourceId: id } = ctx.params;
|
1775
2026
|
const { body } = ctx.request;
|
1776
|
-
const documentManager2 = getService$
|
1777
|
-
const permissionChecker2 = getService$
|
2027
|
+
const documentManager2 = getService$2("document-manager");
|
2028
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1778
2029
|
if (permissionChecker2.cannot.create()) {
|
1779
2030
|
return ctx.forbidden();
|
1780
2031
|
}
|
1781
2032
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1782
|
-
const populate = await getService$
|
2033
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1783
2034
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1784
2035
|
const document = await documentManager2.findOne(id, model, {
|
1785
2036
|
populate,
|
@@ -1818,13 +2069,13 @@ const collectionTypes = {
|
|
1818
2069
|
async delete(ctx) {
|
1819
2070
|
const { userAbility } = ctx.state;
|
1820
2071
|
const { id, model } = ctx.params;
|
1821
|
-
const documentManager2 = getService$
|
1822
|
-
const permissionChecker2 = getService$
|
2072
|
+
const documentManager2 = getService$2("document-manager");
|
2073
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1823
2074
|
if (permissionChecker2.cannot.delete()) {
|
1824
2075
|
return ctx.forbidden();
|
1825
2076
|
}
|
1826
2077
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1827
|
-
const populate = await getService$
|
2078
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1828
2079
|
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1829
2080
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1830
2081
|
if (documentLocales.length === 0) {
|
@@ -1846,19 +2097,42 @@ const collectionTypes = {
|
|
1846
2097
|
const { userAbility } = ctx.state;
|
1847
2098
|
const { id, model } = ctx.params;
|
1848
2099
|
const { body } = ctx.request;
|
1849
|
-
const documentManager2 = getService$
|
1850
|
-
const permissionChecker2 = getService$
|
2100
|
+
const documentManager2 = getService$2("document-manager");
|
2101
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1851
2102
|
if (permissionChecker2.cannot.publish()) {
|
1852
2103
|
return ctx.forbidden();
|
1853
2104
|
}
|
1854
2105
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1855
2106
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1856
|
-
const populate = await getService$
|
1857
|
-
|
2107
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2108
|
+
let document;
|
2109
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2110
|
+
const isCreate = isNil$1(id);
|
2111
|
+
if (isCreate) {
|
2112
|
+
if (permissionChecker2.cannot.create()) {
|
2113
|
+
throw new errors.ForbiddenError();
|
2114
|
+
}
|
2115
|
+
document = await createDocument(ctx, { populate });
|
2116
|
+
}
|
2117
|
+
const isUpdate = !isCreate;
|
2118
|
+
if (isUpdate) {
|
2119
|
+
const documentExists = documentManager2.exists(model, id);
|
2120
|
+
if (!documentExists) {
|
2121
|
+
throw new errors.NotFoundError("Document not found");
|
2122
|
+
}
|
2123
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2124
|
+
if (!document) {
|
2125
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2126
|
+
throw new errors.ForbiddenError();
|
2127
|
+
}
|
2128
|
+
document = await updateDocument(ctx);
|
2129
|
+
} else if (permissionChecker2.can.update(document)) {
|
2130
|
+
await updateDocument(ctx);
|
2131
|
+
}
|
2132
|
+
}
|
1858
2133
|
if (permissionChecker2.cannot.publish(document)) {
|
1859
2134
|
throw new errors.ForbiddenError();
|
1860
2135
|
}
|
1861
|
-
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1862
2136
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1863
2137
|
locale
|
1864
2138
|
// TODO: Allow setting creator fields on publish
|
@@ -1878,13 +2152,13 @@ const collectionTypes = {
|
|
1878
2152
|
const { body } = ctx.request;
|
1879
2153
|
const { documentIds } = body;
|
1880
2154
|
await validateBulkActionInput(body);
|
1881
|
-
const documentManager2 = getService$
|
1882
|
-
const permissionChecker2 = getService$
|
2155
|
+
const documentManager2 = getService$2("document-manager");
|
2156
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1883
2157
|
if (permissionChecker2.cannot.publish()) {
|
1884
2158
|
return ctx.forbidden();
|
1885
2159
|
}
|
1886
2160
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1887
|
-
const populate = await getService$
|
2161
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1888
2162
|
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1889
2163
|
allowMultipleLocales: true
|
1890
2164
|
});
|
@@ -1909,12 +2183,14 @@ const collectionTypes = {
|
|
1909
2183
|
const { body } = ctx.request;
|
1910
2184
|
const { documentIds } = body;
|
1911
2185
|
await validateBulkActionInput(body);
|
1912
|
-
const documentManager2 = getService$
|
1913
|
-
const permissionChecker2 = getService$
|
2186
|
+
const documentManager2 = getService$2("document-manager");
|
2187
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1914
2188
|
if (permissionChecker2.cannot.unpublish()) {
|
1915
2189
|
return ctx.forbidden();
|
1916
2190
|
}
|
1917
|
-
const { locale } = await getDocumentLocaleAndStatus(body, model
|
2191
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2192
|
+
allowMultipleLocales: true
|
2193
|
+
});
|
1918
2194
|
const entityPromises = documentIds.map(
|
1919
2195
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1920
2196
|
);
|
@@ -1937,8 +2213,8 @@ const collectionTypes = {
|
|
1937
2213
|
const {
|
1938
2214
|
body: { discardDraft, ...body }
|
1939
2215
|
} = ctx.request;
|
1940
|
-
const documentManager2 = getService$
|
1941
|
-
const permissionChecker2 = getService$
|
2216
|
+
const documentManager2 = getService$2("document-manager");
|
2217
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1942
2218
|
if (permissionChecker2.cannot.unpublish()) {
|
1943
2219
|
return ctx.forbidden();
|
1944
2220
|
}
|
@@ -1946,7 +2222,7 @@ const collectionTypes = {
|
|
1946
2222
|
return ctx.forbidden();
|
1947
2223
|
}
|
1948
2224
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1949
|
-
const populate = await getService$
|
2225
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1950
2226
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1951
2227
|
const document = await documentManager2.findOne(id, model, {
|
1952
2228
|
populate,
|
@@ -1977,13 +2253,13 @@ const collectionTypes = {
|
|
1977
2253
|
const { userAbility } = ctx.state;
|
1978
2254
|
const { id, model } = ctx.params;
|
1979
2255
|
const { body } = ctx.request;
|
1980
|
-
const documentManager2 = getService$
|
1981
|
-
const permissionChecker2 = getService$
|
2256
|
+
const documentManager2 = getService$2("document-manager");
|
2257
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1982
2258
|
if (permissionChecker2.cannot.discard()) {
|
1983
2259
|
return ctx.forbidden();
|
1984
2260
|
}
|
1985
2261
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1986
|
-
const populate = await getService$
|
2262
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1987
2263
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1988
2264
|
const document = await documentManager2.findOne(id, model, {
|
1989
2265
|
populate,
|
@@ -2008,13 +2284,13 @@ const collectionTypes = {
|
|
2008
2284
|
const { query, body } = ctx.request;
|
2009
2285
|
const { documentIds } = body;
|
2010
2286
|
await validateBulkActionInput(body);
|
2011
|
-
const documentManager2 = getService$
|
2012
|
-
const permissionChecker2 = getService$
|
2287
|
+
const documentManager2 = getService$2("document-manager");
|
2288
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2013
2289
|
if (permissionChecker2.cannot.delete()) {
|
2014
2290
|
return ctx.forbidden();
|
2015
2291
|
}
|
2016
2292
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2017
|
-
const populate = await getService$
|
2293
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2018
2294
|
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2019
2295
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2020
2296
|
populate,
|
@@ -2035,13 +2311,13 @@ const collectionTypes = {
|
|
2035
2311
|
async countDraftRelations(ctx) {
|
2036
2312
|
const { userAbility } = ctx.state;
|
2037
2313
|
const { model, id } = ctx.params;
|
2038
|
-
const documentManager2 = getService$
|
2039
|
-
const permissionChecker2 = getService$
|
2314
|
+
const documentManager2 = getService$2("document-manager");
|
2315
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2040
2316
|
if (permissionChecker2.cannot.read()) {
|
2041
2317
|
return ctx.forbidden();
|
2042
2318
|
}
|
2043
2319
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2044
|
-
const populate = await getService$
|
2320
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2045
2321
|
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2046
2322
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2047
2323
|
if (!entity) {
|
@@ -2060,8 +2336,8 @@ const collectionTypes = {
|
|
2060
2336
|
const ids = ctx.request.query.documentIds;
|
2061
2337
|
const locale = ctx.request.query.locale;
|
2062
2338
|
const { model } = ctx.params;
|
2063
|
-
const documentManager2 = getService$
|
2064
|
-
const permissionChecker2 = getService$
|
2339
|
+
const documentManager2 = getService$2("document-manager");
|
2340
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2065
2341
|
if (permissionChecker2.cannot.read()) {
|
2066
2342
|
return ctx.forbidden();
|
2067
2343
|
}
|
@@ -2085,13 +2361,13 @@ const collectionTypes = {
|
|
2085
2361
|
};
|
2086
2362
|
const components$1 = {
|
2087
2363
|
findComponents(ctx) {
|
2088
|
-
const components2 = getService$
|
2089
|
-
const { toDto } = getService$
|
2364
|
+
const components2 = getService$2("components").findAllComponents();
|
2365
|
+
const { toDto } = getService$2("data-mapper");
|
2090
2366
|
ctx.body = { data: components2.map(toDto) };
|
2091
2367
|
},
|
2092
2368
|
async findComponentConfiguration(ctx) {
|
2093
2369
|
const { uid: uid2 } = ctx.params;
|
2094
|
-
const componentService = getService$
|
2370
|
+
const componentService = getService$2("components");
|
2095
2371
|
const component = componentService.findComponent(uid2);
|
2096
2372
|
if (!component) {
|
2097
2373
|
return ctx.notFound("component.notFound");
|
@@ -2108,7 +2384,7 @@ const components$1 = {
|
|
2108
2384
|
async updateComponentConfiguration(ctx) {
|
2109
2385
|
const { uid: uid2 } = ctx.params;
|
2110
2386
|
const { body } = ctx.request;
|
2111
|
-
const componentService = getService$
|
2387
|
+
const componentService = getService$2("components");
|
2112
2388
|
const component = componentService.findComponent(uid2);
|
2113
2389
|
if (!component) {
|
2114
2390
|
return ctx.notFound("component.notFound");
|
@@ -2142,12 +2418,12 @@ const contentTypes = {
|
|
2142
2418
|
} catch (error) {
|
2143
2419
|
return ctx.send({ error }, 400);
|
2144
2420
|
}
|
2145
|
-
const contentTypes2 = getService$
|
2146
|
-
const { toDto } = getService$
|
2421
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2422
|
+
const { toDto } = getService$2("data-mapper");
|
2147
2423
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2148
2424
|
},
|
2149
2425
|
async findContentTypesSettings(ctx) {
|
2150
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2426
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2151
2427
|
const contentTypes2 = await findAllContentTypes();
|
2152
2428
|
const configurations = await Promise.all(
|
2153
2429
|
contentTypes2.map(async (contentType) => {
|
@@ -2161,7 +2437,7 @@ const contentTypes = {
|
|
2161
2437
|
},
|
2162
2438
|
async findContentTypeConfiguration(ctx) {
|
2163
2439
|
const { uid: uid2 } = ctx.params;
|
2164
|
-
const contentTypeService = getService$
|
2440
|
+
const contentTypeService = getService$2("content-types");
|
2165
2441
|
const contentType = await contentTypeService.findContentType(uid2);
|
2166
2442
|
if (!contentType) {
|
2167
2443
|
return ctx.notFound("contentType.notFound");
|
@@ -2183,13 +2459,13 @@ const contentTypes = {
|
|
2183
2459
|
const { userAbility } = ctx.state;
|
2184
2460
|
const { uid: uid2 } = ctx.params;
|
2185
2461
|
const { body } = ctx.request;
|
2186
|
-
const contentTypeService = getService$
|
2187
|
-
const metricsService = getService$
|
2462
|
+
const contentTypeService = getService$2("content-types");
|
2463
|
+
const metricsService = getService$2("metrics");
|
2188
2464
|
const contentType = await contentTypeService.findContentType(uid2);
|
2189
2465
|
if (!contentType) {
|
2190
2466
|
return ctx.notFound("contentType.notFound");
|
2191
2467
|
}
|
2192
|
-
if (!getService$
|
2468
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2193
2469
|
return ctx.forbidden();
|
2194
2470
|
}
|
2195
2471
|
let input;
|
@@ -2222,10 +2498,10 @@ const contentTypes = {
|
|
2222
2498
|
};
|
2223
2499
|
const init = {
|
2224
2500
|
getInitData(ctx) {
|
2225
|
-
const { toDto } = getService$
|
2226
|
-
const { findAllComponents } = getService$
|
2227
|
-
const { getAllFieldSizes } = getService$
|
2228
|
-
const { findAllContentTypes } = getService$
|
2501
|
+
const { toDto } = getService$2("data-mapper");
|
2502
|
+
const { findAllComponents } = getService$2("components");
|
2503
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2504
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2229
2505
|
ctx.body = {
|
2230
2506
|
data: {
|
2231
2507
|
fieldSizes: getAllFieldSizes(),
|
@@ -2261,36 +2537,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2261
2537
|
params.filters.$and.push(filtersClause);
|
2262
2538
|
};
|
2263
2539
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2264
|
-
const permissionChecker2 = getService$
|
2540
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2265
2541
|
userAbility,
|
2266
2542
|
model: model.uid
|
2267
2543
|
});
|
2268
|
-
|
2544
|
+
const isMainFieldListable = isListable(model, mainField);
|
2545
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2546
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2269
2547
|
return "id";
|
2270
2548
|
}
|
2271
|
-
if (
|
2272
|
-
|
2273
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2274
|
-
userAbility,
|
2275
|
-
model: "plugin::users-permissions.user"
|
2276
|
-
});
|
2277
|
-
if (userPermissionChecker.can.read()) {
|
2278
|
-
return "name";
|
2279
|
-
}
|
2280
|
-
}
|
2281
|
-
return "id";
|
2549
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2550
|
+
return "name";
|
2282
2551
|
}
|
2283
2552
|
return mainField;
|
2284
2553
|
};
|
2285
|
-
const addStatusToRelations = async (
|
2286
|
-
if (!contentTypes$1.hasDraftAndPublish(strapi.
|
2554
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2555
|
+
if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2556
|
+
return relations2;
|
2557
|
+
}
|
2558
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2559
|
+
if (!relations2.length) {
|
2287
2560
|
return relations2;
|
2288
2561
|
}
|
2289
|
-
const
|
2290
|
-
const
|
2562
|
+
const firstRelation = relations2[0];
|
2563
|
+
const filters = {
|
2564
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2565
|
+
// NOTE: find the "opposite" status
|
2566
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2567
|
+
};
|
2568
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2569
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2570
|
+
filters
|
2571
|
+
});
|
2291
2572
|
return relations2.map((relation) => {
|
2292
|
-
const availableStatuses =
|
2293
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2573
|
+
const availableStatuses = availableStatus.filter(
|
2574
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2294
2575
|
);
|
2295
2576
|
return {
|
2296
2577
|
...relation,
|
@@ -2311,11 +2592,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2311
2592
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2312
2593
|
const isSourceLocalized = isLocalized(sourceModel);
|
2313
2594
|
const isTargetLocalized = isLocalized(targetModel);
|
2314
|
-
let validatedLocale = locale;
|
2315
|
-
if (!targetModel || !isTargetLocalized)
|
2316
|
-
validatedLocale = void 0;
|
2317
2595
|
return {
|
2318
|
-
locale
|
2596
|
+
locale,
|
2319
2597
|
isSourceLocalized,
|
2320
2598
|
isTargetLocalized
|
2321
2599
|
};
|
@@ -2324,8 +2602,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2324
2602
|
const sourceModel = strapi.getModel(sourceUid);
|
2325
2603
|
const isDP = contentTypes$1.hasDraftAndPublish;
|
2326
2604
|
const isSourceDP = isDP(sourceModel);
|
2327
|
-
if (!isSourceDP)
|
2328
|
-
return { status: void 0 };
|
2605
|
+
if (!isSourceDP) return { status: void 0 };
|
2329
2606
|
switch (status) {
|
2330
2607
|
case "published":
|
2331
2608
|
return { status: "published" };
|
@@ -2355,7 +2632,7 @@ const relations = {
|
|
2355
2632
|
ctx.request?.query?.locale
|
2356
2633
|
);
|
2357
2634
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2358
|
-
const permissionChecker2 = getService$
|
2635
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2359
2636
|
userAbility,
|
2360
2637
|
model
|
2361
2638
|
});
|
@@ -2380,7 +2657,7 @@ const relations = {
|
|
2380
2657
|
where.id = id;
|
2381
2658
|
}
|
2382
2659
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2383
|
-
const populate = await getService$
|
2660
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2384
2661
|
const currentEntity = await strapi.db.query(model).findOne({
|
2385
2662
|
where,
|
2386
2663
|
populate
|
@@ -2395,7 +2672,7 @@ const relations = {
|
|
2395
2672
|
}
|
2396
2673
|
entryId = currentEntity.id;
|
2397
2674
|
}
|
2398
|
-
const modelConfig = isComponent2 ? await getService$
|
2675
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2399
2676
|
const targetSchema = strapi.getModel(targetUid);
|
2400
2677
|
const mainField = flow(
|
2401
2678
|
prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2418,7 +2695,7 @@ const relations = {
|
|
2418
2695
|
attribute,
|
2419
2696
|
fieldsToSelect,
|
2420
2697
|
mainField,
|
2421
|
-
source: { schema: sourceSchema },
|
2698
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2422
2699
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2423
2700
|
sourceSchema,
|
2424
2701
|
targetSchema,
|
@@ -2440,7 +2717,8 @@ const relations = {
|
|
2440
2717
|
fieldsToSelect,
|
2441
2718
|
mainField,
|
2442
2719
|
source: {
|
2443
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2720
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2721
|
+
isLocalized: isSourceLocalized
|
2444
2722
|
},
|
2445
2723
|
target: {
|
2446
2724
|
schema: { uid: targetUid },
|
@@ -2448,7 +2726,7 @@ const relations = {
|
|
2448
2726
|
}
|
2449
2727
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2450
2728
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2451
|
-
const permissionChecker2 = getService$
|
2729
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2452
2730
|
userAbility: ctx.state.userAbility,
|
2453
2731
|
model: targetUid
|
2454
2732
|
});
|
@@ -2478,12 +2756,16 @@ const relations = {
|
|
2478
2756
|
} else {
|
2479
2757
|
where.id = id;
|
2480
2758
|
}
|
2481
|
-
|
2482
|
-
|
2759
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2760
|
+
if (!isEmpty(publishedAt)) {
|
2761
|
+
where[`${alias}.published_at`] = publishedAt;
|
2483
2762
|
}
|
2484
|
-
if (
|
2763
|
+
if (isTargetLocalized && locale) {
|
2485
2764
|
where[`${alias}.locale`] = locale;
|
2486
2765
|
}
|
2766
|
+
if (isSourceLocalized && locale) {
|
2767
|
+
where.locale = locale;
|
2768
|
+
}
|
2487
2769
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2488
2770
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2489
2771
|
}
|
@@ -2501,7 +2783,8 @@ const relations = {
|
|
2501
2783
|
id: { $notIn: uniq(idsToOmit) }
|
2502
2784
|
});
|
2503
2785
|
}
|
2504
|
-
const
|
2786
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2787
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2505
2788
|
ctx.body = {
|
2506
2789
|
...res,
|
2507
2790
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2516,29 +2799,39 @@ const relations = {
|
|
2516
2799
|
attribute,
|
2517
2800
|
targetField,
|
2518
2801
|
fieldsToSelect,
|
2519
|
-
|
2520
|
-
|
2521
|
-
}
|
2522
|
-
target: {
|
2523
|
-
schema: { uid: targetUid }
|
2524
|
-
}
|
2802
|
+
status,
|
2803
|
+
source: { schema: sourceSchema },
|
2804
|
+
target: { schema: targetSchema }
|
2525
2805
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2526
|
-
const
|
2806
|
+
const { uid: sourceUid } = sourceSchema;
|
2807
|
+
const { uid: targetUid } = targetSchema;
|
2808
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2527
2809
|
const dbQuery = strapi.db.query(sourceUid);
|
2528
2810
|
const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2811
|
+
const filters = {};
|
2812
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2813
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2814
|
+
if (status === "published") {
|
2815
|
+
filters.publishedAt = { $notNull: true };
|
2816
|
+
} else {
|
2817
|
+
filters.publishedAt = { $null: true };
|
2818
|
+
}
|
2819
|
+
}
|
2820
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2821
|
+
filters.publishedAt = { $null: true };
|
2822
|
+
}
|
2529
2823
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2530
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2824
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2531
2825
|
ordering: "desc",
|
2532
2826
|
page: ctx.request.query.page,
|
2533
|
-
pageSize: ctx.request.query.pageSize
|
2827
|
+
pageSize: ctx.request.query.pageSize,
|
2828
|
+
filters
|
2534
2829
|
});
|
2535
2830
|
const loadedIds = res.results.map((item) => item.id);
|
2536
2831
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2537
2832
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2538
2833
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2539
|
-
ordering: "desc"
|
2540
|
-
page: ctx.request.query.page,
|
2541
|
-
pageSize: ctx.request.query.pageSize
|
2834
|
+
ordering: "desc"
|
2542
2835
|
});
|
2543
2836
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2544
2837
|
ctx.body = {
|
@@ -2553,10 +2846,10 @@ const relations = {
|
|
2553
2846
|
}
|
2554
2847
|
};
|
2555
2848
|
const buildPopulateFromQuery = async (query, model) => {
|
2556
|
-
return getService$
|
2849
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2557
2850
|
};
|
2558
2851
|
const findDocument = async (query, uid2, opts = {}) => {
|
2559
|
-
const documentManager2 = getService$
|
2852
|
+
const documentManager2 = getService$2("document-manager");
|
2560
2853
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2561
2854
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2562
2855
|
};
|
@@ -2564,8 +2857,8 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2564
2857
|
const { user, userAbility } = ctx.state;
|
2565
2858
|
const { model } = ctx.params;
|
2566
2859
|
const { body, query } = ctx.request;
|
2567
|
-
const documentManager2 = getService$
|
2568
|
-
const permissionChecker2 = getService$
|
2860
|
+
const documentManager2 = getService$2("document-manager");
|
2861
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2569
2862
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2570
2863
|
throw new errors.ForbiddenError();
|
2571
2864
|
}
|
@@ -2606,7 +2899,7 @@ const singleTypes = {
|
|
2606
2899
|
const { userAbility } = ctx.state;
|
2607
2900
|
const { model } = ctx.params;
|
2608
2901
|
const { query = {} } = ctx.request;
|
2609
|
-
const permissionChecker2 = getService$
|
2902
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2610
2903
|
if (permissionChecker2.cannot.read()) {
|
2611
2904
|
return ctx.forbidden();
|
2612
2905
|
}
|
@@ -2625,7 +2918,7 @@ const singleTypes = {
|
|
2625
2918
|
permissionChecker2,
|
2626
2919
|
model,
|
2627
2920
|
// @ts-expect-error - fix types
|
2628
|
-
{
|
2921
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2629
2922
|
{ availableLocales: true, availableStatus: false }
|
2630
2923
|
);
|
2631
2924
|
ctx.body = { data: {}, meta };
|
@@ -2640,7 +2933,7 @@ const singleTypes = {
|
|
2640
2933
|
async createOrUpdate(ctx) {
|
2641
2934
|
const { userAbility } = ctx.state;
|
2642
2935
|
const { model } = ctx.params;
|
2643
|
-
const permissionChecker2 = getService$
|
2936
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2644
2937
|
const document = await createOrUpdateDocument(ctx);
|
2645
2938
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2646
2939
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2649,8 +2942,8 @@ const singleTypes = {
|
|
2649
2942
|
const { userAbility } = ctx.state;
|
2650
2943
|
const { model } = ctx.params;
|
2651
2944
|
const { query = {} } = ctx.request;
|
2652
|
-
const documentManager2 = getService$
|
2653
|
-
const permissionChecker2 = getService$
|
2945
|
+
const documentManager2 = getService$2("document-manager");
|
2946
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2654
2947
|
if (permissionChecker2.cannot.delete()) {
|
2655
2948
|
return ctx.forbidden();
|
2656
2949
|
}
|
@@ -2678,8 +2971,8 @@ const singleTypes = {
|
|
2678
2971
|
const { userAbility } = ctx.state;
|
2679
2972
|
const { model } = ctx.params;
|
2680
2973
|
const { query = {} } = ctx.request;
|
2681
|
-
const documentManager2 = getService$
|
2682
|
-
const permissionChecker2 = getService$
|
2974
|
+
const documentManager2 = getService$2("document-manager");
|
2975
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2683
2976
|
if (permissionChecker2.cannot.publish()) {
|
2684
2977
|
return ctx.forbidden();
|
2685
2978
|
}
|
@@ -2707,8 +3000,8 @@ const singleTypes = {
|
|
2707
3000
|
body: { discardDraft, ...body },
|
2708
3001
|
query = {}
|
2709
3002
|
} = ctx.request;
|
2710
|
-
const documentManager2 = getService$
|
2711
|
-
const permissionChecker2 = getService$
|
3003
|
+
const documentManager2 = getService$2("document-manager");
|
3004
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2712
3005
|
if (permissionChecker2.cannot.unpublish()) {
|
2713
3006
|
return ctx.forbidden();
|
2714
3007
|
}
|
@@ -2742,8 +3035,8 @@ const singleTypes = {
|
|
2742
3035
|
const { userAbility } = ctx.state;
|
2743
3036
|
const { model } = ctx.params;
|
2744
3037
|
const { body, query = {} } = ctx.request;
|
2745
|
-
const documentManager2 = getService$
|
2746
|
-
const permissionChecker2 = getService$
|
3038
|
+
const documentManager2 = getService$2("document-manager");
|
3039
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2747
3040
|
if (permissionChecker2.cannot.discard()) {
|
2748
3041
|
return ctx.forbidden();
|
2749
3042
|
}
|
@@ -2766,8 +3059,8 @@ const singleTypes = {
|
|
2766
3059
|
const { userAbility } = ctx.state;
|
2767
3060
|
const { model } = ctx.params;
|
2768
3061
|
const { query } = ctx.request;
|
2769
|
-
const documentManager2 = getService$
|
2770
|
-
const permissionChecker2 = getService$
|
3062
|
+
const documentManager2 = getService$2("document-manager");
|
3063
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2771
3064
|
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2772
3065
|
if (permissionChecker2.cannot.read()) {
|
2773
3066
|
return ctx.forbidden();
|
@@ -2791,7 +3084,7 @@ const uid$1 = {
|
|
2791
3084
|
const { query = {} } = ctx.request;
|
2792
3085
|
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2793
3086
|
await validateUIDField(contentTypeUID, field);
|
2794
|
-
const uidService = getService$
|
3087
|
+
const uidService = getService$2("uid");
|
2795
3088
|
ctx.body = {
|
2796
3089
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2797
3090
|
};
|
@@ -2803,7 +3096,7 @@ const uid$1 = {
|
|
2803
3096
|
const { query = {} } = ctx.request;
|
2804
3097
|
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2805
3098
|
await validateUIDField(contentTypeUID, field);
|
2806
|
-
const uidService = getService$
|
3099
|
+
const uidService = getService$2("uid");
|
2807
3100
|
const isAvailable = await uidService.checkUIDAvailability({
|
2808
3101
|
contentTypeUID,
|
2809
3102
|
field,
|
@@ -2824,7 +3117,8 @@ const controllers = {
|
|
2824
3117
|
relations,
|
2825
3118
|
"single-types": singleTypes,
|
2826
3119
|
uid: uid$1,
|
2827
|
-
...history.controllers ? history.controllers : {}
|
3120
|
+
...history.controllers ? history.controllers : {},
|
3121
|
+
...preview.controllers ? preview.controllers : {}
|
2828
3122
|
};
|
2829
3123
|
const keys = {
|
2830
3124
|
CONFIGURATION: "configuration"
|
@@ -2953,18 +3247,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2953
3247
|
_.set(updatedMeta, ["list", "searchable"], false);
|
2954
3248
|
_.set(acc, [key], updatedMeta);
|
2955
3249
|
}
|
2956
|
-
if (!_.has(edit, "mainField"))
|
2957
|
-
return acc;
|
3250
|
+
if (!_.has(edit, "mainField")) return acc;
|
2958
3251
|
if (!isRelation$1(attr)) {
|
2959
3252
|
_.set(updatedMeta, "edit", _.omit(edit, ["mainField"]));
|
2960
3253
|
_.set(acc, [key], updatedMeta);
|
2961
3254
|
return acc;
|
2962
3255
|
}
|
2963
|
-
if (edit.mainField === "id")
|
2964
|
-
return acc;
|
3256
|
+
if (edit.mainField === "id") return acc;
|
2965
3257
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2966
|
-
if (!targetSchema)
|
2967
|
-
return acc;
|
3258
|
+
if (!targetSchema) return acc;
|
2968
3259
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2969
3260
|
_.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2970
3261
|
_.set(acc, [key], updatedMeta);
|
@@ -2975,12 +3266,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2975
3266
|
return _.assign(metasWithDefaults, updatedMetas);
|
2976
3267
|
}
|
2977
3268
|
const getTargetSchema = (targetModel) => {
|
2978
|
-
return getService$
|
3269
|
+
return getService$2("content-types").findContentType(targetModel);
|
2979
3270
|
};
|
2980
3271
|
const DEFAULT_LIST_LENGTH = 4;
|
2981
3272
|
const MAX_ROW_SIZE = 12;
|
2982
3273
|
const isAllowedFieldSize = (type, size) => {
|
2983
|
-
const { getFieldSize } = getService$
|
3274
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2984
3275
|
const fieldSize = getFieldSize(type);
|
2985
3276
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2986
3277
|
return false;
|
@@ -2988,7 +3279,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2988
3279
|
return size <= MAX_ROW_SIZE;
|
2989
3280
|
};
|
2990
3281
|
const getDefaultFieldSize = (attribute) => {
|
2991
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3282
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2992
3283
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2993
3284
|
};
|
2994
3285
|
async function createDefaultLayouts(schema) {
|
@@ -3009,8 +3300,7 @@ function createDefaultEditLayout(schema) {
|
|
3009
3300
|
return appendToEditLayout([], keys2, schema);
|
3010
3301
|
}
|
3011
3302
|
function syncLayouts(configuration, schema) {
|
3012
|
-
if (_.isEmpty(configuration.layouts))
|
3013
|
-
return createDefaultLayouts(schema);
|
3303
|
+
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3014
3304
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3015
3305
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3016
3306
|
const cleanEditRelations = editRelations.filter(
|
@@ -3021,9 +3311,8 @@ function syncLayouts(configuration, schema) {
|
|
3021
3311
|
for (const row of edit) {
|
3022
3312
|
const newRow = [];
|
3023
3313
|
for (const el of row) {
|
3024
|
-
if (!hasEditableAttribute(schema, el.name))
|
3025
|
-
|
3026
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3314
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3315
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3027
3316
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3028
3317
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3029
3318
|
elementsToReAppend.push(el.name);
|
@@ -3053,8 +3342,7 @@ function syncLayouts(configuration, schema) {
|
|
3053
3342
|
};
|
3054
3343
|
}
|
3055
3344
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3056
|
-
if (keysToAppend.length === 0)
|
3057
|
-
return layout;
|
3345
|
+
if (keysToAppend.length === 0) return layout;
|
3058
3346
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3059
3347
|
if (!layout[currentRowIndex]) {
|
3060
3348
|
layout[currentRowIndex] = [];
|
@@ -3163,17 +3451,17 @@ const configurationService$1 = createConfigurationService({
|
|
3163
3451
|
isComponent: true,
|
3164
3452
|
prefix: STORE_KEY_PREFIX,
|
3165
3453
|
getModels() {
|
3166
|
-
const { toContentManagerModel } = getService$
|
3454
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3167
3455
|
return mapValues(toContentManagerModel, strapi.components);
|
3168
3456
|
}
|
3169
3457
|
});
|
3170
3458
|
const components = ({ strapi: strapi2 }) => ({
|
3171
3459
|
findAllComponents() {
|
3172
|
-
const { toContentManagerModel } = getService$
|
3460
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3173
3461
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3174
3462
|
},
|
3175
3463
|
findComponent(uid2) {
|
3176
|
-
const { toContentManagerModel } = getService$
|
3464
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3177
3465
|
const component = strapi2.components[uid2];
|
3178
3466
|
return isNil$1(component) ? component : toContentManagerModel(component);
|
3179
3467
|
},
|
@@ -3224,17 +3512,17 @@ const configurationService = createConfigurationService({
|
|
3224
3512
|
storeUtils,
|
3225
3513
|
prefix: "content_types",
|
3226
3514
|
getModels() {
|
3227
|
-
const { toContentManagerModel } = getService$
|
3515
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3228
3516
|
return mapValues(toContentManagerModel, strapi.contentTypes);
|
3229
3517
|
}
|
3230
3518
|
});
|
3231
3519
|
const service = ({ strapi: strapi2 }) => ({
|
3232
3520
|
findAllContentTypes() {
|
3233
|
-
const { toContentManagerModel } = getService$
|
3521
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3234
3522
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3235
3523
|
},
|
3236
3524
|
findContentType(uid2) {
|
3237
|
-
const { toContentManagerModel } = getService$
|
3525
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3238
3526
|
const contentType = strapi2.contentTypes[uid2];
|
3239
3527
|
return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
|
3240
3528
|
},
|
@@ -3263,7 +3551,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3263
3551
|
return this.findConfiguration(contentType);
|
3264
3552
|
},
|
3265
3553
|
findComponentsConfigurations(contentType) {
|
3266
|
-
return getService$
|
3554
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3267
3555
|
},
|
3268
3556
|
syncConfigurations() {
|
3269
3557
|
return configurationService.syncConfigurations();
|
@@ -3444,12 +3732,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3444
3732
|
ability: userAbility,
|
3445
3733
|
model
|
3446
3734
|
});
|
3447
|
-
const
|
3735
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3736
|
+
const toSubject = (entity) => {
|
3737
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3738
|
+
};
|
3448
3739
|
const can = (action, entity, field) => {
|
3449
|
-
|
3740
|
+
const subject = toSubject(entity);
|
3741
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3742
|
+
return (
|
3743
|
+
// Test the original action to see if it passes
|
3744
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3745
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3746
|
+
);
|
3450
3747
|
};
|
3451
3748
|
const cannot = (action, entity, field) => {
|
3452
|
-
|
3749
|
+
const subject = toSubject(entity);
|
3750
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3751
|
+
return (
|
3752
|
+
// Test both the original action
|
3753
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3754
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3755
|
+
);
|
3453
3756
|
};
|
3454
3757
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3455
3758
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3520,7 +3823,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3520
3823
|
return userAbility.can(action);
|
3521
3824
|
},
|
3522
3825
|
async registerPermissions() {
|
3523
|
-
const displayedContentTypes = getService$
|
3826
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3524
3827
|
const contentTypesUids = displayedContentTypes.map(prop("uid"));
|
3525
3828
|
const actions = [
|
3526
3829
|
{
|
@@ -3796,7 +4099,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3796
4099
|
return populateQuery;
|
3797
4100
|
};
|
3798
4101
|
const buildDeepPopulate = (uid2) => {
|
3799
|
-
return getService$
|
4102
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3800
4103
|
};
|
3801
4104
|
const populateBuilder = (uid2) => {
|
3802
4105
|
let getInitialPopulate = async () => {
|
@@ -3981,7 +4284,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3981
4284
|
*/
|
3982
4285
|
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3983
4286
|
const versionsByLocale = groupBy("locale", allVersions);
|
3984
|
-
|
4287
|
+
if (version.locale) {
|
4288
|
+
delete versionsByLocale[version.locale];
|
4289
|
+
}
|
3985
4290
|
const model = strapi2.getModel(uid2);
|
3986
4291
|
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3987
4292
|
const traversalFunction = async (localeVersion) => traverseEntity(
|
@@ -4028,8 +4333,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4028
4333
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4029
4334
|
return matchLocale && matchStatus;
|
4030
4335
|
});
|
4031
|
-
if (!availableStatus)
|
4032
|
-
return availableStatus;
|
4336
|
+
if (!availableStatus) return availableStatus;
|
4033
4337
|
return pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4034
4338
|
},
|
4035
4339
|
/**
|
@@ -4039,8 +4343,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4039
4343
|
* @returns
|
4040
4344
|
*/
|
4041
4345
|
async getManyAvailableStatus(uid2, documents) {
|
4042
|
-
if (!documents.length)
|
4043
|
-
return [];
|
4346
|
+
if (!documents.length) return [];
|
4044
4347
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4045
4348
|
const locale = documents[0]?.locale;
|
4046
4349
|
const otherStatus = status === "published" ? "draft" : "published";
|
@@ -4067,10 +4370,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4067
4370
|
} else if (otherVersion) {
|
4068
4371
|
draftVersion = otherVersion;
|
4069
4372
|
}
|
4070
|
-
if (!draftVersion)
|
4071
|
-
|
4072
|
-
if (!publishedVersion)
|
4073
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4373
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4374
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4074
4375
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4075
4376
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4076
4377
|
},
|
@@ -4107,7 +4408,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4107
4408
|
*/
|
4108
4409
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4109
4410
|
if (!document) {
|
4110
|
-
return
|
4411
|
+
return {
|
4412
|
+
data: document,
|
4413
|
+
meta: {
|
4414
|
+
availableLocales: [],
|
4415
|
+
availableStatus: []
|
4416
|
+
}
|
4417
|
+
};
|
4111
4418
|
}
|
4112
4419
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
4113
4420
|
if (!hasDraftAndPublish) {
|
@@ -4331,7 +4638,8 @@ const services = {
|
|
4331
4638
|
permission,
|
4332
4639
|
"populate-builder": populateBuilder$1,
|
4333
4640
|
uid,
|
4334
|
-
...history.services ? history.services : {}
|
4641
|
+
...history.services ? history.services : {},
|
4642
|
+
...preview.services ? preview.services : {}
|
4335
4643
|
};
|
4336
4644
|
const index = () => {
|
4337
4645
|
return {
|