@strapi/content-manager 0.0.0-experimental.745741d19e90275ca6f7c928ca19f9bb0fd9d933 → 0.0.0-experimental.76d3543c13df7ef0095963ae2c20b792f179eef0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-CJPoOvy3.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-CJPoOvy3.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs → ComponentConfigurationPage-CcRDqD0e.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-CcRDqD0e.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-C1ddZ_zf.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-C1ddZ_zf.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-CF3lxOy2.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-CF3lxOy2.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-BPFcUbqi.mjs} +63 -12
- package/dist/_chunks/EditViewPage-BPFcUbqi.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-CDyTC6aU.js} +63 -13
- package/dist/_chunks/EditViewPage-CDyTC6aU.js.map +1 -0
- package/dist/_chunks/{Field-lsPFnAmH.js → Field-DuxAW9q2.js} +409 -260
- package/dist/_chunks/Field-DuxAW9q2.js.map +1 -0
- package/dist/_chunks/{Field-R5NbffTB.mjs → Field-fBnTwgU4.mjs} +405 -256
- package/dist/_chunks/Field-fBnTwgU4.mjs.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-BGl7PhlZ.mjs} +37 -18
- package/dist/_chunks/Form-BGl7PhlZ.mjs.map +1 -0
- package/dist/_chunks/{Form-CcGboku8.js → Form-DSGh_zkz.js} +39 -21
- package/dist/_chunks/Form-DSGh_zkz.js.map +1 -0
- package/dist/_chunks/{History-ByUPL3T3.mjs → History-DTYB9CSB.mjs} +66 -113
- package/dist/_chunks/History-DTYB9CSB.mjs.map +1 -0
- package/dist/_chunks/{History-Bsud8jwh.js → History-DrDJv698.js} +65 -113
- package/dist/_chunks/History-DrDJv698.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-qWx8r4D_.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-qWx8r4D_.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-zurIlUZ7.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-zurIlUZ7.js.map +1 -0
- package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-DTM2uO_S.js} +109 -78
- package/dist/_chunks/ListViewPage-DTM2uO_S.js.map +1 -0
- package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-GKpL5p8A.mjs} +106 -74
- package/dist/_chunks/ListViewPage-GKpL5p8A.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-B5Vc5Cal.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-B5Vc5Cal.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-BuZlNroO.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-BuZlNroO.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-BAZlWgJ4.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-BAZlWgJ4.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-DLzkS4Hy.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-DLzkS4Hy.js.map} +1 -1
- package/dist/_chunks/Preview-VOJ8RuQp.js +312 -0
- package/dist/_chunks/Preview-VOJ8RuQp.js.map +1 -0
- package/dist/_chunks/Preview-Zzjg2_K_.mjs +294 -0
- package/dist/_chunks/Preview-Zzjg2_K_.mjs.map +1 -0
- package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BVdRfDkW.mjs} +76 -42
- package/dist/_chunks/Relations-BVdRfDkW.mjs.map +1 -0
- package/dist/_chunks/{Relations-CghaPv2D.js → Relations-Dsj0boFJ.js} +76 -43
- package/dist/_chunks/Relations-Dsj0boFJ.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BzQmavmK.js} +37 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BzQmavmK.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-CSxLmrh1.mjs} +37 -18
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-CSxLmrh1.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-CaE6NG4a.mjs → index-Bu_-B7ZA.mjs} +1263 -772
- package/dist/_chunks/index-Bu_-B7ZA.mjs.map +1 -0
- package/dist/_chunks/{index-BOZx6IMg.js → index-Ct-GZ0iV.js} +1246 -755
- package/dist/_chunks/index-Ct-GZ0iV.js.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-Ciz224q5.js → layout-CDBEgRsM.js} +24 -12
- package/dist/_chunks/layout-CDBEgRsM.js.map +1 -0
- package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-COzAvgJh.mjs} +24 -11
- package/dist/_chunks/layout-COzAvgJh.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CP8sB2YZ.js → relations-BjiF1Aad.js} +6 -7
- package/dist/_chunks/relations-BjiF1Aad.js.map +1 -0
- package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-BtmMFBpM.mjs} +6 -7
- package/dist/_chunks/relations-BtmMFBpM.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +6 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +2 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +682 -360
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +683 -360
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -15
- package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +0 -1
- package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +0 -1
- package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
- package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
- package/dist/_chunks/Form-BHmXSfyy.mjs.map +0 -1
- package/dist/_chunks/Form-CcGboku8.js.map +0 -1
- package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
- package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
- package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +0 -1
- package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +0 -1
- package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
- package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
- package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
- package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
- package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
- package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
- package/dist/_chunks/relations-CP8sB2YZ.js.map +0 -1
- package/dist/_chunks/relations-Cxc1cEv3.mjs.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1,
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat,
|
1
|
+
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, pagination } from "@strapi/utils";
|
2
|
+
import { pick, omit, difference, castArray, mergeWith, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -7,10 +7,10 @@ import isNil from "lodash/isNil";
|
|
7
7
|
import _, { intersection as intersection$1, difference as difference$1 } from "lodash";
|
8
8
|
import qs from "qs";
|
9
9
|
import slugify from "@sindresorhus/slugify";
|
10
|
-
const getService$
|
10
|
+
const getService$2 = (name) => {
|
11
11
|
return strapi.plugin("content-manager").service(name);
|
12
12
|
};
|
13
|
-
function getService(strapi2, name) {
|
13
|
+
function getService$1(strapi2, name) {
|
14
14
|
return strapi2.service(`plugin::content-manager.${name}`);
|
15
15
|
}
|
16
16
|
const historyRestoreVersionSchema = yup.object().shape({
|
@@ -46,7 +46,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
46
46
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
47
47
|
throw new errors.ForbiddenError("contentType and documentId are required");
|
48
48
|
}
|
49
|
-
const permissionChecker2 = getService$
|
49
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
50
50
|
userAbility: ctx.state.userAbility,
|
51
51
|
model: ctx.query.contentType
|
52
52
|
});
|
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
54
54
|
return ctx.forbidden();
|
55
55
|
}
|
56
56
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
57
|
-
const { results, pagination: 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,201 @@ const getFeature = () => {
|
|
659
711
|
}
|
660
712
|
};
|
661
713
|
};
|
662
|
-
const history = getFeature();
|
714
|
+
const history = getFeature$1();
|
715
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
716
|
+
const previewRouter = {
|
717
|
+
type: "admin",
|
718
|
+
routes: [
|
719
|
+
{
|
720
|
+
method: "GET",
|
721
|
+
info,
|
722
|
+
path: "/preview/url/:contentType",
|
723
|
+
handler: "preview.getPreviewUrl",
|
724
|
+
config: {
|
725
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
726
|
+
}
|
727
|
+
}
|
728
|
+
]
|
729
|
+
};
|
730
|
+
const routes$1 = {
|
731
|
+
preview: previewRouter
|
732
|
+
};
|
733
|
+
function getService(strapi2, name) {
|
734
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
735
|
+
}
|
736
|
+
const getPreviewUrlSchema = yup.object().shape({
|
737
|
+
// Will be undefined for single types
|
738
|
+
documentId: yup.string(),
|
739
|
+
locale: yup.string().nullable(),
|
740
|
+
status: yup.string()
|
741
|
+
}).required();
|
742
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
743
|
+
await validateYupSchema(getPreviewUrlSchema)(params);
|
744
|
+
const newParams = pick(["documentId", "locale", "status"], params);
|
745
|
+
const model = strapi2.getModel(uid2);
|
746
|
+
if (!model || model.modelType !== "contentType") {
|
747
|
+
throw new errors.ValidationError("Invalid content type");
|
748
|
+
}
|
749
|
+
const isSingleType = model?.kind === "singleType";
|
750
|
+
if (!isSingleType && !params.documentId) {
|
751
|
+
throw new errors.ValidationError("documentId is required for Collection Types");
|
752
|
+
}
|
753
|
+
if (isSingleType) {
|
754
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
755
|
+
if (!doc) {
|
756
|
+
throw new errors.NotFoundError("Document not found");
|
757
|
+
}
|
758
|
+
newParams.documentId = doc?.documentId;
|
759
|
+
}
|
760
|
+
if (!newParams.status) {
|
761
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
762
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
763
|
+
}
|
764
|
+
return newParams;
|
765
|
+
};
|
766
|
+
const createPreviewController = () => {
|
767
|
+
return {
|
768
|
+
/**
|
769
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
770
|
+
* in the Content Manager.
|
771
|
+
*/
|
772
|
+
async getPreviewUrl(ctx) {
|
773
|
+
const uid2 = ctx.params.contentType;
|
774
|
+
const query = ctx.request.query;
|
775
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
776
|
+
const previewService = getService(strapi, "preview");
|
777
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
778
|
+
if (!url) {
|
779
|
+
ctx.status = 204;
|
780
|
+
}
|
781
|
+
return {
|
782
|
+
data: { url }
|
783
|
+
};
|
784
|
+
}
|
785
|
+
};
|
786
|
+
};
|
787
|
+
const controllers$1 = {
|
788
|
+
preview: createPreviewController
|
789
|
+
/**
|
790
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
791
|
+
* passing a controller factory as the value, instead of a controller object directly
|
792
|
+
*/
|
793
|
+
};
|
794
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
795
|
+
const config = getService(strapi2, "preview-config");
|
796
|
+
return {
|
797
|
+
async getPreviewUrl(uid2, params) {
|
798
|
+
const handler = config.getPreviewHandler();
|
799
|
+
try {
|
800
|
+
return handler(uid2, params);
|
801
|
+
} catch (error) {
|
802
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
803
|
+
throw new errors.ApplicationError("Failed to get preview URL");
|
804
|
+
}
|
805
|
+
return;
|
806
|
+
}
|
807
|
+
};
|
808
|
+
};
|
809
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
810
|
+
const middlewares = strapi.config.get("middlewares");
|
811
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
812
|
+
if (currentMiddleware === middleware.name) {
|
813
|
+
return middleware;
|
814
|
+
}
|
815
|
+
if (currentMiddleware.name === middleware.name) {
|
816
|
+
return mergeWith(
|
817
|
+
(objValue, srcValue) => {
|
818
|
+
if (Array.isArray(objValue)) {
|
819
|
+
return objValue.concat(srcValue);
|
820
|
+
}
|
821
|
+
return void 0;
|
822
|
+
},
|
823
|
+
currentMiddleware,
|
824
|
+
middleware
|
825
|
+
);
|
826
|
+
}
|
827
|
+
return currentMiddleware;
|
828
|
+
});
|
829
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
830
|
+
};
|
831
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
832
|
+
return {
|
833
|
+
register() {
|
834
|
+
if (!this.isEnabled()) {
|
835
|
+
return;
|
836
|
+
}
|
837
|
+
const config = strapi2.config.get("admin.preview");
|
838
|
+
if (config.config?.allowedOrigins) {
|
839
|
+
extendMiddlewareConfiguration({
|
840
|
+
name: "strapi::security",
|
841
|
+
config: {
|
842
|
+
contentSecurityPolicy: {
|
843
|
+
directives: {
|
844
|
+
"frame-src": config.config.allowedOrigins
|
845
|
+
}
|
846
|
+
}
|
847
|
+
}
|
848
|
+
});
|
849
|
+
}
|
850
|
+
},
|
851
|
+
isEnabled() {
|
852
|
+
const config = strapi2.config.get("admin.preview");
|
853
|
+
if (!config) {
|
854
|
+
return false;
|
855
|
+
}
|
856
|
+
return config?.enabled ?? true;
|
857
|
+
},
|
858
|
+
/**
|
859
|
+
* Validate if the configuration is valid
|
860
|
+
*/
|
861
|
+
validate() {
|
862
|
+
if (!this.isEnabled()) {
|
863
|
+
return;
|
864
|
+
}
|
865
|
+
const handler = this.getPreviewHandler();
|
866
|
+
if (typeof handler !== "function") {
|
867
|
+
throw new errors.ValidationError(
|
868
|
+
"Preview configuration is invalid. Handler must be a function"
|
869
|
+
);
|
870
|
+
}
|
871
|
+
},
|
872
|
+
/**
|
873
|
+
* Utility to get the preview handler from the configuration
|
874
|
+
*/
|
875
|
+
getPreviewHandler() {
|
876
|
+
const config = strapi2.config.get("admin.preview");
|
877
|
+
const emptyHandler = () => {
|
878
|
+
return void 0;
|
879
|
+
};
|
880
|
+
if (!this.isEnabled()) {
|
881
|
+
return emptyHandler;
|
882
|
+
}
|
883
|
+
return config?.config?.handler || emptyHandler;
|
884
|
+
}
|
885
|
+
};
|
886
|
+
};
|
887
|
+
const services$1 = {
|
888
|
+
preview: createPreviewService,
|
889
|
+
"preview-config": createPreviewConfigService
|
890
|
+
};
|
891
|
+
const getFeature = () => {
|
892
|
+
return {
|
893
|
+
register() {
|
894
|
+
const config = getService(strapi, "preview-config");
|
895
|
+
config.validate();
|
896
|
+
config.register();
|
897
|
+
},
|
898
|
+
bootstrap() {
|
899
|
+
},
|
900
|
+
routes: routes$1,
|
901
|
+
controllers: controllers$1,
|
902
|
+
services: services$1
|
903
|
+
};
|
904
|
+
};
|
905
|
+
const preview = getFeature();
|
663
906
|
const register = async ({ strapi: strapi2 }) => {
|
664
907
|
await history.register?.({ strapi: strapi2 });
|
908
|
+
await preview.register?.({ strapi: strapi2 });
|
665
909
|
};
|
666
910
|
const ALLOWED_WEBHOOK_EVENTS = {
|
667
911
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -671,11 +915,12 @@ const bootstrap = async () => {
|
|
671
915
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
672
916
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
673
917
|
});
|
674
|
-
getService$
|
675
|
-
await getService$
|
676
|
-
await getService$
|
677
|
-
await getService$
|
918
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
919
|
+
await getService$2("components").syncConfigurations();
|
920
|
+
await getService$2("content-types").syncConfigurations();
|
921
|
+
await getService$2("permission").registerPermissions();
|
678
922
|
await history.bootstrap?.({ strapi });
|
923
|
+
await preview.bootstrap?.({ strapi });
|
679
924
|
};
|
680
925
|
const destroy = async ({ strapi: strapi2 }) => {
|
681
926
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1165,7 +1410,8 @@ const admin = {
|
|
1165
1410
|
};
|
1166
1411
|
const routes = {
|
1167
1412
|
admin,
|
1168
|
-
...history.routes ? history.routes : {}
|
1413
|
+
...history.routes ? history.routes : {},
|
1414
|
+
...preview.routes ? preview.routes : {}
|
1169
1415
|
};
|
1170
1416
|
const hasPermissionsSchema = yup$1.object({
|
1171
1417
|
actions: yup$1.array().of(yup$1.string()),
|
@@ -1176,6 +1422,11 @@ const { createPolicy } = policy;
|
|
1176
1422
|
const hasPermissions = createPolicy({
|
1177
1423
|
name: "plugin::content-manager.hasPermissions",
|
1178
1424
|
validator: validateHasPermissionsInput,
|
1425
|
+
/**
|
1426
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1427
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1428
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1429
|
+
*/
|
1179
1430
|
handler(ctx, config = {}) {
|
1180
1431
|
const { actions = [], hasAtLeastOne = false } = config;
|
1181
1432
|
const { userAbility } = ctx.state;
|
@@ -1223,8 +1474,7 @@ const isSortable = (schema, name) => {
|
|
1223
1474
|
if (!_.has(schema.attributes, name)) {
|
1224
1475
|
return false;
|
1225
1476
|
}
|
1226
|
-
if (schema.modelType === "component" && name === "id")
|
1227
|
-
return false;
|
1477
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1228
1478
|
const attribute = schema.attributes[name];
|
1229
1479
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1230
1480
|
return false;
|
@@ -1369,8 +1619,7 @@ const createDefaultSettings = async (schema) => {
|
|
1369
1619
|
};
|
1370
1620
|
};
|
1371
1621
|
const syncSettings = async (configuration, schema) => {
|
1372
|
-
if (isEmpty(configuration.settings))
|
1373
|
-
return createDefaultSettings(schema);
|
1622
|
+
if (isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1374
1623
|
const defaultField = getDefaultMainField(schema);
|
1375
1624
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1376
1625
|
return {
|
@@ -1417,7 +1666,7 @@ const createMetadasSchema = (schema) => {
|
|
1417
1666
|
if (!value) {
|
1418
1667
|
return yup$1.string();
|
1419
1668
|
}
|
1420
|
-
const targetSchema = getService$
|
1669
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1421
1670
|
schema.attributes[key].targetModel
|
1422
1671
|
);
|
1423
1672
|
if (!targetSchema) {
|
@@ -1546,8 +1795,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1546
1795
|
}
|
1547
1796
|
switch (attribute.type) {
|
1548
1797
|
case "relation": {
|
1549
|
-
if (canCreate(attributePath))
|
1550
|
-
return body2;
|
1798
|
+
if (canCreate(attributePath)) return body2;
|
1551
1799
|
return set(attributePath, { set: [] }, body2);
|
1552
1800
|
}
|
1553
1801
|
case "component": {
|
@@ -1557,8 +1805,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1557
1805
|
]);
|
1558
1806
|
}
|
1559
1807
|
default: {
|
1560
|
-
if (canCreate(attributePath))
|
1561
|
-
return body2;
|
1808
|
+
if (canCreate(attributePath)) return body2;
|
1562
1809
|
return set(attributePath, null, body2);
|
1563
1810
|
}
|
1564
1811
|
}
|
@@ -1569,9 +1816,11 @@ const multipleLocaleSchema = yup$1.lazy(
|
|
1569
1816
|
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1570
1817
|
);
|
1571
1818
|
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1572
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1819
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1573
1820
|
const { allowMultipleLocales } = opts;
|
1574
|
-
const { locale, status, ...rest } = request || {};
|
1821
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1822
|
+
const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1823
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1575
1824
|
const schema = yup$1.object().shape({
|
1576
1825
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1577
1826
|
status: statusSchema
|
@@ -1584,7 +1833,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1584
1833
|
}
|
1585
1834
|
};
|
1586
1835
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1587
|
-
const documentMetadata2 = getService$
|
1836
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1588
1837
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1589
1838
|
let {
|
1590
1839
|
meta: { availableLocales, availableStatus }
|
@@ -1610,8 +1859,8 @@ const createDocument = async (ctx, opts) => {
|
|
1610
1859
|
const { userAbility, user } = ctx.state;
|
1611
1860
|
const { model } = ctx.params;
|
1612
1861
|
const { body } = ctx.request;
|
1613
|
-
const documentManager2 = getService$
|
1614
|
-
const permissionChecker2 = getService$
|
1862
|
+
const documentManager2 = getService$2("document-manager");
|
1863
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1615
1864
|
if (permissionChecker2.cannot.create()) {
|
1616
1865
|
throw new errors.ForbiddenError();
|
1617
1866
|
}
|
@@ -1619,7 +1868,7 @@ const createDocument = async (ctx, opts) => {
|
|
1619
1868
|
const setCreator = setCreatorFields({ user });
|
1620
1869
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1621
1870
|
const sanitizedBody = await sanitizeFn(body);
|
1622
|
-
const { locale, status
|
1871
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1623
1872
|
return documentManager2.create(model, {
|
1624
1873
|
data: sanitizedBody,
|
1625
1874
|
locale,
|
@@ -1631,14 +1880,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1631
1880
|
const { userAbility, user } = ctx.state;
|
1632
1881
|
const { id, model } = ctx.params;
|
1633
1882
|
const { body } = ctx.request;
|
1634
|
-
const documentManager2 = getService$
|
1635
|
-
const permissionChecker2 = getService$
|
1883
|
+
const documentManager2 = getService$2("document-manager");
|
1884
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1636
1885
|
if (permissionChecker2.cannot.update()) {
|
1637
1886
|
throw new errors.ForbiddenError();
|
1638
1887
|
}
|
1639
1888
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1640
|
-
const populate = await getService$
|
1641
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1889
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1890
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1642
1891
|
const [documentVersion, documentExists] = await Promise.all([
|
1643
1892
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1644
1893
|
documentManager2.exists(model, id)
|
@@ -1654,7 +1903,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1654
1903
|
throw new errors.ForbiddenError();
|
1655
1904
|
}
|
1656
1905
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1657
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1906
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1658
1907
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1659
1908
|
const sanitizedBody = await sanitizeFn(body);
|
1660
1909
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1668,15 +1917,15 @@ const collectionTypes = {
|
|
1668
1917
|
const { userAbility } = ctx.state;
|
1669
1918
|
const { model } = ctx.params;
|
1670
1919
|
const { query } = ctx.request;
|
1671
|
-
const documentMetadata2 = getService$
|
1672
|
-
const documentManager2 = getService$
|
1673
|
-
const permissionChecker2 = getService$
|
1920
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1921
|
+
const documentManager2 = getService$2("document-manager");
|
1922
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1674
1923
|
if (permissionChecker2.cannot.read()) {
|
1675
1924
|
return ctx.forbidden();
|
1676
1925
|
}
|
1677
1926
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1678
|
-
const populate = await getService$
|
1679
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1927
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1928
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1680
1929
|
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1681
1930
|
{ ...permissionQuery, populate, locale, status },
|
1682
1931
|
model
|
@@ -1704,14 +1953,14 @@ const collectionTypes = {
|
|
1704
1953
|
async findOne(ctx) {
|
1705
1954
|
const { userAbility } = ctx.state;
|
1706
1955
|
const { model, id } = ctx.params;
|
1707
|
-
const documentManager2 = getService$
|
1708
|
-
const permissionChecker2 = getService$
|
1956
|
+
const documentManager2 = getService$2("document-manager");
|
1957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1709
1958
|
if (permissionChecker2.cannot.read()) {
|
1710
1959
|
return ctx.forbidden();
|
1711
1960
|
}
|
1712
1961
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1713
|
-
const populate = await getService$
|
1714
|
-
const { locale, status
|
1962
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1963
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1715
1964
|
const version = await documentManager2.findOne(id, model, {
|
1716
1965
|
populate,
|
1717
1966
|
locale,
|
@@ -1726,7 +1975,7 @@ const collectionTypes = {
|
|
1726
1975
|
permissionChecker2,
|
1727
1976
|
model,
|
1728
1977
|
// @ts-expect-error TODO: fix
|
1729
|
-
{ id, locale, publishedAt: null },
|
1978
|
+
{ documentId: id, locale, publishedAt: null },
|
1730
1979
|
{ availableLocales: true, availableStatus: false }
|
1731
1980
|
);
|
1732
1981
|
ctx.body = { data: {}, meta };
|
@@ -1741,7 +1990,7 @@ const collectionTypes = {
|
|
1741
1990
|
async create(ctx) {
|
1742
1991
|
const { userAbility } = ctx.state;
|
1743
1992
|
const { model } = ctx.params;
|
1744
|
-
const permissionChecker2 = getService$
|
1993
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1745
1994
|
const [totalEntries, document] = await Promise.all([
|
1746
1995
|
strapi.db.query(model).count(),
|
1747
1996
|
createDocument(ctx)
|
@@ -1762,7 +2011,7 @@ const collectionTypes = {
|
|
1762
2011
|
async update(ctx) {
|
1763
2012
|
const { userAbility } = ctx.state;
|
1764
2013
|
const { model } = ctx.params;
|
1765
|
-
const permissionChecker2 = getService$
|
2014
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1766
2015
|
const updatedVersion = await updateDocument(ctx);
|
1767
2016
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1768
2017
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1771,14 +2020,14 @@ const collectionTypes = {
|
|
1771
2020
|
const { userAbility, user } = ctx.state;
|
1772
2021
|
const { model, sourceId: id } = ctx.params;
|
1773
2022
|
const { body } = ctx.request;
|
1774
|
-
const documentManager2 = getService$
|
1775
|
-
const permissionChecker2 = getService$
|
2023
|
+
const documentManager2 = getService$2("document-manager");
|
2024
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1776
2025
|
if (permissionChecker2.cannot.create()) {
|
1777
2026
|
return ctx.forbidden();
|
1778
2027
|
}
|
1779
2028
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1780
|
-
const populate = await getService$
|
1781
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2029
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2030
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1782
2031
|
const document = await documentManager2.findOne(id, model, {
|
1783
2032
|
populate,
|
1784
2033
|
locale,
|
@@ -1816,14 +2065,14 @@ const collectionTypes = {
|
|
1816
2065
|
async delete(ctx) {
|
1817
2066
|
const { userAbility } = ctx.state;
|
1818
2067
|
const { id, model } = ctx.params;
|
1819
|
-
const documentManager2 = getService$
|
1820
|
-
const permissionChecker2 = getService$
|
2068
|
+
const documentManager2 = getService$2("document-manager");
|
2069
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1821
2070
|
if (permissionChecker2.cannot.delete()) {
|
1822
2071
|
return ctx.forbidden();
|
1823
2072
|
}
|
1824
2073
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1825
|
-
const populate = await getService$
|
1826
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
2074
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2075
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1827
2076
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1828
2077
|
if (documentLocales.length === 0) {
|
1829
2078
|
return ctx.notFound();
|
@@ -1844,19 +2093,42 @@ const collectionTypes = {
|
|
1844
2093
|
const { userAbility } = ctx.state;
|
1845
2094
|
const { id, model } = ctx.params;
|
1846
2095
|
const { body } = ctx.request;
|
1847
|
-
const documentManager2 = getService$
|
1848
|
-
const permissionChecker2 = getService$
|
2096
|
+
const documentManager2 = getService$2("document-manager");
|
2097
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1849
2098
|
if (permissionChecker2.cannot.publish()) {
|
1850
2099
|
return ctx.forbidden();
|
1851
2100
|
}
|
1852
2101
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1853
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1854
|
-
const populate = await getService$
|
1855
|
-
|
2103
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2104
|
+
let document;
|
2105
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2106
|
+
const isCreate = isNil$1(id);
|
2107
|
+
if (isCreate) {
|
2108
|
+
if (permissionChecker2.cannot.create()) {
|
2109
|
+
throw new errors.ForbiddenError();
|
2110
|
+
}
|
2111
|
+
document = await createDocument(ctx, { populate });
|
2112
|
+
}
|
2113
|
+
const isUpdate = !isCreate;
|
2114
|
+
if (isUpdate) {
|
2115
|
+
const documentExists = documentManager2.exists(model, id);
|
2116
|
+
if (!documentExists) {
|
2117
|
+
throw new errors.NotFoundError("Document not found");
|
2118
|
+
}
|
2119
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2120
|
+
if (!document) {
|
2121
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2122
|
+
throw new errors.ForbiddenError();
|
2123
|
+
}
|
2124
|
+
document = await updateDocument(ctx);
|
2125
|
+
} else if (permissionChecker2.can.update(document)) {
|
2126
|
+
await updateDocument(ctx);
|
2127
|
+
}
|
2128
|
+
}
|
1856
2129
|
if (permissionChecker2.cannot.publish(document)) {
|
1857
2130
|
throw new errors.ForbiddenError();
|
1858
2131
|
}
|
1859
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1860
2132
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1861
2133
|
locale
|
1862
2134
|
// TODO: Allow setting creator fields on publish
|
@@ -1876,14 +2148,16 @@ const collectionTypes = {
|
|
1876
2148
|
const { body } = ctx.request;
|
1877
2149
|
const { documentIds } = body;
|
1878
2150
|
await validateBulkActionInput(body);
|
1879
|
-
const documentManager2 = getService$
|
1880
|
-
const permissionChecker2 = getService$
|
2151
|
+
const documentManager2 = getService$2("document-manager");
|
2152
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1881
2153
|
if (permissionChecker2.cannot.publish()) {
|
1882
2154
|
return ctx.forbidden();
|
1883
2155
|
}
|
1884
2156
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1885
|
-
const populate = await getService$
|
1886
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
2157
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2158
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2159
|
+
allowMultipleLocales: true
|
2160
|
+
});
|
1887
2161
|
const entityPromises = documentIds.map(
|
1888
2162
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1889
2163
|
);
|
@@ -1905,12 +2179,14 @@ const collectionTypes = {
|
|
1905
2179
|
const { body } = ctx.request;
|
1906
2180
|
const { documentIds } = body;
|
1907
2181
|
await validateBulkActionInput(body);
|
1908
|
-
const documentManager2 = getService$
|
1909
|
-
const permissionChecker2 = getService$
|
2182
|
+
const documentManager2 = getService$2("document-manager");
|
2183
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1910
2184
|
if (permissionChecker2.cannot.unpublish()) {
|
1911
2185
|
return ctx.forbidden();
|
1912
2186
|
}
|
1913
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2187
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2188
|
+
allowMultipleLocales: true
|
2189
|
+
});
|
1914
2190
|
const entityPromises = documentIds.map(
|
1915
2191
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1916
2192
|
);
|
@@ -1933,8 +2209,8 @@ const collectionTypes = {
|
|
1933
2209
|
const {
|
1934
2210
|
body: { discardDraft, ...body }
|
1935
2211
|
} = ctx.request;
|
1936
|
-
const documentManager2 = getService$
|
1937
|
-
const permissionChecker2 = getService$
|
2212
|
+
const documentManager2 = getService$2("document-manager");
|
2213
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1938
2214
|
if (permissionChecker2.cannot.unpublish()) {
|
1939
2215
|
return ctx.forbidden();
|
1940
2216
|
}
|
@@ -1942,8 +2218,8 @@ const collectionTypes = {
|
|
1942
2218
|
return ctx.forbidden();
|
1943
2219
|
}
|
1944
2220
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1945
|
-
const populate = await getService$
|
1946
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2221
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2222
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1947
2223
|
const document = await documentManager2.findOne(id, model, {
|
1948
2224
|
populate,
|
1949
2225
|
locale,
|
@@ -1973,14 +2249,14 @@ const collectionTypes = {
|
|
1973
2249
|
const { userAbility } = ctx.state;
|
1974
2250
|
const { id, model } = ctx.params;
|
1975
2251
|
const { body } = ctx.request;
|
1976
|
-
const documentManager2 = getService$
|
1977
|
-
const permissionChecker2 = getService$
|
2252
|
+
const documentManager2 = getService$2("document-manager");
|
2253
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1978
2254
|
if (permissionChecker2.cannot.discard()) {
|
1979
2255
|
return ctx.forbidden();
|
1980
2256
|
}
|
1981
2257
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1982
|
-
const populate = await getService$
|
1983
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2258
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2259
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1984
2260
|
const document = await documentManager2.findOne(id, model, {
|
1985
2261
|
populate,
|
1986
2262
|
locale,
|
@@ -2004,14 +2280,14 @@ const collectionTypes = {
|
|
2004
2280
|
const { query, body } = ctx.request;
|
2005
2281
|
const { documentIds } = body;
|
2006
2282
|
await validateBulkActionInput(body);
|
2007
|
-
const documentManager2 = getService$
|
2008
|
-
const permissionChecker2 = getService$
|
2283
|
+
const documentManager2 = getService$2("document-manager");
|
2284
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2009
2285
|
if (permissionChecker2.cannot.delete()) {
|
2010
2286
|
return ctx.forbidden();
|
2011
2287
|
}
|
2012
2288
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2013
|
-
const populate = await getService$
|
2014
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2289
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2290
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2015
2291
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2016
2292
|
populate,
|
2017
2293
|
locale
|
@@ -2031,14 +2307,14 @@ const collectionTypes = {
|
|
2031
2307
|
async countDraftRelations(ctx) {
|
2032
2308
|
const { userAbility } = ctx.state;
|
2033
2309
|
const { model, id } = ctx.params;
|
2034
|
-
const documentManager2 = getService$
|
2035
|
-
const permissionChecker2 = getService$
|
2310
|
+
const documentManager2 = getService$2("document-manager");
|
2311
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2036
2312
|
if (permissionChecker2.cannot.read()) {
|
2037
2313
|
return ctx.forbidden();
|
2038
2314
|
}
|
2039
2315
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2040
|
-
const populate = await getService$
|
2041
|
-
const { locale, status
|
2316
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2317
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2042
2318
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2043
2319
|
if (!entity) {
|
2044
2320
|
return ctx.notFound();
|
@@ -2056,8 +2332,8 @@ const collectionTypes = {
|
|
2056
2332
|
const ids = ctx.request.query.documentIds;
|
2057
2333
|
const locale = ctx.request.query.locale;
|
2058
2334
|
const { model } = ctx.params;
|
2059
|
-
const documentManager2 = getService$
|
2060
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2061
2337
|
if (permissionChecker2.cannot.read()) {
|
2062
2338
|
return ctx.forbidden();
|
2063
2339
|
}
|
@@ -2081,13 +2357,13 @@ const collectionTypes = {
|
|
2081
2357
|
};
|
2082
2358
|
const components$1 = {
|
2083
2359
|
findComponents(ctx) {
|
2084
|
-
const components2 = getService$
|
2085
|
-
const { toDto } = getService$
|
2360
|
+
const components2 = getService$2("components").findAllComponents();
|
2361
|
+
const { toDto } = getService$2("data-mapper");
|
2086
2362
|
ctx.body = { data: components2.map(toDto) };
|
2087
2363
|
},
|
2088
2364
|
async findComponentConfiguration(ctx) {
|
2089
2365
|
const { uid: uid2 } = ctx.params;
|
2090
|
-
const componentService = getService$
|
2366
|
+
const componentService = getService$2("components");
|
2091
2367
|
const component = componentService.findComponent(uid2);
|
2092
2368
|
if (!component) {
|
2093
2369
|
return ctx.notFound("component.notFound");
|
@@ -2104,7 +2380,7 @@ const components$1 = {
|
|
2104
2380
|
async updateComponentConfiguration(ctx) {
|
2105
2381
|
const { uid: uid2 } = ctx.params;
|
2106
2382
|
const { body } = ctx.request;
|
2107
|
-
const componentService = getService$
|
2383
|
+
const componentService = getService$2("components");
|
2108
2384
|
const component = componentService.findComponent(uid2);
|
2109
2385
|
if (!component) {
|
2110
2386
|
return ctx.notFound("component.notFound");
|
@@ -2138,12 +2414,12 @@ const contentTypes = {
|
|
2138
2414
|
} catch (error) {
|
2139
2415
|
return ctx.send({ error }, 400);
|
2140
2416
|
}
|
2141
|
-
const contentTypes2 = getService$
|
2142
|
-
const { toDto } = getService$
|
2417
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2418
|
+
const { toDto } = getService$2("data-mapper");
|
2143
2419
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2144
2420
|
},
|
2145
2421
|
async findContentTypesSettings(ctx) {
|
2146
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2422
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2147
2423
|
const contentTypes2 = await findAllContentTypes();
|
2148
2424
|
const configurations = await Promise.all(
|
2149
2425
|
contentTypes2.map(async (contentType) => {
|
@@ -2157,7 +2433,7 @@ const contentTypes = {
|
|
2157
2433
|
},
|
2158
2434
|
async findContentTypeConfiguration(ctx) {
|
2159
2435
|
const { uid: uid2 } = ctx.params;
|
2160
|
-
const contentTypeService = getService$
|
2436
|
+
const contentTypeService = getService$2("content-types");
|
2161
2437
|
const contentType = await contentTypeService.findContentType(uid2);
|
2162
2438
|
if (!contentType) {
|
2163
2439
|
return ctx.notFound("contentType.notFound");
|
@@ -2179,13 +2455,13 @@ const contentTypes = {
|
|
2179
2455
|
const { userAbility } = ctx.state;
|
2180
2456
|
const { uid: uid2 } = ctx.params;
|
2181
2457
|
const { body } = ctx.request;
|
2182
|
-
const contentTypeService = getService$
|
2183
|
-
const metricsService = getService$
|
2458
|
+
const contentTypeService = getService$2("content-types");
|
2459
|
+
const metricsService = getService$2("metrics");
|
2184
2460
|
const contentType = await contentTypeService.findContentType(uid2);
|
2185
2461
|
if (!contentType) {
|
2186
2462
|
return ctx.notFound("contentType.notFound");
|
2187
2463
|
}
|
2188
|
-
if (!getService$
|
2464
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2189
2465
|
return ctx.forbidden();
|
2190
2466
|
}
|
2191
2467
|
let input;
|
@@ -2218,10 +2494,10 @@ const contentTypes = {
|
|
2218
2494
|
};
|
2219
2495
|
const init = {
|
2220
2496
|
getInitData(ctx) {
|
2221
|
-
const { toDto } = getService$
|
2222
|
-
const { findAllComponents } = getService$
|
2223
|
-
const { getAllFieldSizes } = getService$
|
2224
|
-
const { findAllContentTypes } = getService$
|
2497
|
+
const { toDto } = getService$2("data-mapper");
|
2498
|
+
const { findAllComponents } = getService$2("components");
|
2499
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2500
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2225
2501
|
ctx.body = {
|
2226
2502
|
data: {
|
2227
2503
|
fieldSizes: getAllFieldSizes(),
|
@@ -2257,36 +2533,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2257
2533
|
params.filters.$and.push(filtersClause);
|
2258
2534
|
};
|
2259
2535
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2260
|
-
const permissionChecker2 = getService$
|
2536
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2261
2537
|
userAbility,
|
2262
2538
|
model: model.uid
|
2263
2539
|
});
|
2264
|
-
|
2540
|
+
const isMainFieldListable = isListable(model, mainField);
|
2541
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2542
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2265
2543
|
return "id";
|
2266
2544
|
}
|
2267
|
-
if (
|
2268
|
-
|
2269
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2270
|
-
userAbility,
|
2271
|
-
model: "plugin::users-permissions.user"
|
2272
|
-
});
|
2273
|
-
if (userPermissionChecker.can.read()) {
|
2274
|
-
return "name";
|
2275
|
-
}
|
2276
|
-
}
|
2277
|
-
return "id";
|
2545
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2546
|
+
return "name";
|
2278
2547
|
}
|
2279
2548
|
return mainField;
|
2280
2549
|
};
|
2281
|
-
const addStatusToRelations = async (
|
2282
|
-
if (!contentTypes$1.hasDraftAndPublish(strapi.
|
2550
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2551
|
+
if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2552
|
+
return relations2;
|
2553
|
+
}
|
2554
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2555
|
+
if (!relations2.length) {
|
2283
2556
|
return relations2;
|
2284
2557
|
}
|
2285
|
-
const
|
2286
|
-
const
|
2558
|
+
const firstRelation = relations2[0];
|
2559
|
+
const filters = {
|
2560
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2561
|
+
// NOTE: find the "opposite" status
|
2562
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2563
|
+
};
|
2564
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2565
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2566
|
+
filters
|
2567
|
+
});
|
2287
2568
|
return relations2.map((relation) => {
|
2288
|
-
const availableStatuses =
|
2289
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2569
|
+
const availableStatuses = availableStatus.filter(
|
2570
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2290
2571
|
);
|
2291
2572
|
return {
|
2292
2573
|
...relation,
|
@@ -2307,11 +2588,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2307
2588
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2308
2589
|
const isSourceLocalized = isLocalized(sourceModel);
|
2309
2590
|
const isTargetLocalized = isLocalized(targetModel);
|
2310
|
-
let validatedLocale = locale;
|
2311
|
-
if (!targetModel || !isTargetLocalized)
|
2312
|
-
validatedLocale = void 0;
|
2313
2591
|
return {
|
2314
|
-
locale
|
2592
|
+
locale,
|
2315
2593
|
isSourceLocalized,
|
2316
2594
|
isTargetLocalized
|
2317
2595
|
};
|
@@ -2320,8 +2598,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2320
2598
|
const sourceModel = strapi.getModel(sourceUid);
|
2321
2599
|
const isDP = contentTypes$1.hasDraftAndPublish;
|
2322
2600
|
const isSourceDP = isDP(sourceModel);
|
2323
|
-
if (!isSourceDP)
|
2324
|
-
return { status: void 0 };
|
2601
|
+
if (!isSourceDP) return { status: void 0 };
|
2325
2602
|
switch (status) {
|
2326
2603
|
case "published":
|
2327
2604
|
return { status: "published" };
|
@@ -2351,7 +2628,7 @@ const relations = {
|
|
2351
2628
|
ctx.request?.query?.locale
|
2352
2629
|
);
|
2353
2630
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2354
|
-
const permissionChecker2 = getService$
|
2631
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2355
2632
|
userAbility,
|
2356
2633
|
model
|
2357
2634
|
});
|
@@ -2376,7 +2653,7 @@ const relations = {
|
|
2376
2653
|
where.id = id;
|
2377
2654
|
}
|
2378
2655
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2379
|
-
const populate = await getService$
|
2656
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2380
2657
|
const currentEntity = await strapi.db.query(model).findOne({
|
2381
2658
|
where,
|
2382
2659
|
populate
|
@@ -2391,7 +2668,7 @@ const relations = {
|
|
2391
2668
|
}
|
2392
2669
|
entryId = currentEntity.id;
|
2393
2670
|
}
|
2394
|
-
const modelConfig = isComponent2 ? await getService$
|
2671
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2395
2672
|
const targetSchema = strapi.getModel(targetUid);
|
2396
2673
|
const mainField = flow(
|
2397
2674
|
prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2414,7 +2691,7 @@ const relations = {
|
|
2414
2691
|
attribute,
|
2415
2692
|
fieldsToSelect,
|
2416
2693
|
mainField,
|
2417
|
-
source: { schema: sourceSchema },
|
2694
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2418
2695
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2419
2696
|
sourceSchema,
|
2420
2697
|
targetSchema,
|
@@ -2436,7 +2713,8 @@ const relations = {
|
|
2436
2713
|
fieldsToSelect,
|
2437
2714
|
mainField,
|
2438
2715
|
source: {
|
2439
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2716
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2717
|
+
isLocalized: isSourceLocalized
|
2440
2718
|
},
|
2441
2719
|
target: {
|
2442
2720
|
schema: { uid: targetUid },
|
@@ -2444,7 +2722,7 @@ const relations = {
|
|
2444
2722
|
}
|
2445
2723
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2446
2724
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2447
|
-
const permissionChecker2 = getService$
|
2725
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2448
2726
|
userAbility: ctx.state.userAbility,
|
2449
2727
|
model: targetUid
|
2450
2728
|
});
|
@@ -2474,12 +2752,16 @@ const relations = {
|
|
2474
2752
|
} else {
|
2475
2753
|
where.id = id;
|
2476
2754
|
}
|
2477
|
-
|
2478
|
-
|
2755
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2756
|
+
if (!isEmpty(publishedAt)) {
|
2757
|
+
where[`${alias}.published_at`] = publishedAt;
|
2479
2758
|
}
|
2480
|
-
if (
|
2759
|
+
if (isTargetLocalized && locale) {
|
2481
2760
|
where[`${alias}.locale`] = locale;
|
2482
2761
|
}
|
2762
|
+
if (isSourceLocalized && locale) {
|
2763
|
+
where.locale = locale;
|
2764
|
+
}
|
2483
2765
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2484
2766
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2485
2767
|
}
|
@@ -2497,7 +2779,8 @@ const relations = {
|
|
2497
2779
|
id: { $notIn: uniq(idsToOmit) }
|
2498
2780
|
});
|
2499
2781
|
}
|
2500
|
-
const
|
2782
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2783
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2501
2784
|
ctx.body = {
|
2502
2785
|
...res,
|
2503
2786
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2512,29 +2795,39 @@ const relations = {
|
|
2512
2795
|
attribute,
|
2513
2796
|
targetField,
|
2514
2797
|
fieldsToSelect,
|
2515
|
-
|
2516
|
-
|
2517
|
-
}
|
2518
|
-
target: {
|
2519
|
-
schema: { uid: targetUid }
|
2520
|
-
}
|
2798
|
+
status,
|
2799
|
+
source: { schema: sourceSchema },
|
2800
|
+
target: { schema: targetSchema }
|
2521
2801
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2522
|
-
const
|
2802
|
+
const { uid: sourceUid } = sourceSchema;
|
2803
|
+
const { uid: targetUid } = targetSchema;
|
2804
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2523
2805
|
const dbQuery = strapi.db.query(sourceUid);
|
2524
2806
|
const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2807
|
+
const filters = {};
|
2808
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2809
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2810
|
+
if (status === "published") {
|
2811
|
+
filters.publishedAt = { $notNull: true };
|
2812
|
+
} else {
|
2813
|
+
filters.publishedAt = { $null: true };
|
2814
|
+
}
|
2815
|
+
}
|
2816
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2817
|
+
filters.publishedAt = { $null: true };
|
2818
|
+
}
|
2525
2819
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2526
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2820
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2527
2821
|
ordering: "desc",
|
2528
2822
|
page: ctx.request.query.page,
|
2529
|
-
pageSize: ctx.request.query.pageSize
|
2823
|
+
pageSize: ctx.request.query.pageSize,
|
2824
|
+
filters
|
2530
2825
|
});
|
2531
2826
|
const loadedIds = res.results.map((item) => item.id);
|
2532
2827
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2533
2828
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2534
2829
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2535
|
-
ordering: "desc"
|
2536
|
-
page: ctx.request.query.page,
|
2537
|
-
pageSize: ctx.request.query.pageSize
|
2830
|
+
ordering: "desc"
|
2538
2831
|
});
|
2539
2832
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2540
2833
|
ctx.body = {
|
@@ -2549,10 +2842,10 @@ const relations = {
|
|
2549
2842
|
}
|
2550
2843
|
};
|
2551
2844
|
const buildPopulateFromQuery = async (query, model) => {
|
2552
|
-
return getService$
|
2845
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2553
2846
|
};
|
2554
2847
|
const findDocument = async (query, uid2, opts = {}) => {
|
2555
|
-
const documentManager2 = getService$
|
2848
|
+
const documentManager2 = getService$2("document-manager");
|
2556
2849
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2557
2850
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2558
2851
|
};
|
@@ -2560,13 +2853,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2560
2853
|
const { user, userAbility } = ctx.state;
|
2561
2854
|
const { model } = ctx.params;
|
2562
2855
|
const { body, query } = ctx.request;
|
2563
|
-
const documentManager2 = getService$
|
2564
|
-
const permissionChecker2 = getService$
|
2856
|
+
const documentManager2 = getService$2("document-manager");
|
2857
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2565
2858
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2566
2859
|
throw new errors.ForbiddenError();
|
2567
2860
|
}
|
2568
2861
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2569
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2862
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2570
2863
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2571
2864
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2572
2865
|
// Find the first document to check if it exists
|
@@ -2602,12 +2895,12 @@ const singleTypes = {
|
|
2602
2895
|
const { userAbility } = ctx.state;
|
2603
2896
|
const { model } = ctx.params;
|
2604
2897
|
const { query = {} } = ctx.request;
|
2605
|
-
const permissionChecker2 = getService$
|
2898
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2606
2899
|
if (permissionChecker2.cannot.read()) {
|
2607
2900
|
return ctx.forbidden();
|
2608
2901
|
}
|
2609
2902
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2610
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2903
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2611
2904
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2612
2905
|
if (!version) {
|
2613
2906
|
if (permissionChecker2.cannot.create()) {
|
@@ -2621,7 +2914,7 @@ const singleTypes = {
|
|
2621
2914
|
permissionChecker2,
|
2622
2915
|
model,
|
2623
2916
|
// @ts-expect-error - fix types
|
2624
|
-
{
|
2917
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2625
2918
|
{ availableLocales: true, availableStatus: false }
|
2626
2919
|
);
|
2627
2920
|
ctx.body = { data: {}, meta };
|
@@ -2636,7 +2929,7 @@ const singleTypes = {
|
|
2636
2929
|
async createOrUpdate(ctx) {
|
2637
2930
|
const { userAbility } = ctx.state;
|
2638
2931
|
const { model } = ctx.params;
|
2639
|
-
const permissionChecker2 = getService$
|
2932
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2640
2933
|
const document = await createOrUpdateDocument(ctx);
|
2641
2934
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2642
2935
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2645,14 +2938,14 @@ const singleTypes = {
|
|
2645
2938
|
const { userAbility } = ctx.state;
|
2646
2939
|
const { model } = ctx.params;
|
2647
2940
|
const { query = {} } = ctx.request;
|
2648
|
-
const documentManager2 = getService$
|
2649
|
-
const permissionChecker2 = getService$
|
2941
|
+
const documentManager2 = getService$2("document-manager");
|
2942
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2650
2943
|
if (permissionChecker2.cannot.delete()) {
|
2651
2944
|
return ctx.forbidden();
|
2652
2945
|
}
|
2653
2946
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2654
2947
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2655
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2948
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2656
2949
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2657
2950
|
populate,
|
2658
2951
|
locale
|
@@ -2674,8 +2967,8 @@ const singleTypes = {
|
|
2674
2967
|
const { userAbility } = ctx.state;
|
2675
2968
|
const { model } = ctx.params;
|
2676
2969
|
const { query = {} } = ctx.request;
|
2677
|
-
const documentManager2 = getService$
|
2678
|
-
const permissionChecker2 = getService$
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2679
2972
|
if (permissionChecker2.cannot.publish()) {
|
2680
2973
|
return ctx.forbidden();
|
2681
2974
|
}
|
@@ -2689,7 +2982,7 @@ const singleTypes = {
|
|
2689
2982
|
if (permissionChecker2.cannot.publish(document)) {
|
2690
2983
|
throw new errors.ForbiddenError();
|
2691
2984
|
}
|
2692
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2985
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2693
2986
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2694
2987
|
return publishResult.at(0);
|
2695
2988
|
});
|
@@ -2703,8 +2996,8 @@ const singleTypes = {
|
|
2703
2996
|
body: { discardDraft, ...body },
|
2704
2997
|
query = {}
|
2705
2998
|
} = ctx.request;
|
2706
|
-
const documentManager2 = getService$
|
2707
|
-
const permissionChecker2 = getService$
|
2999
|
+
const documentManager2 = getService$2("document-manager");
|
3000
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2708
3001
|
if (permissionChecker2.cannot.unpublish()) {
|
2709
3002
|
return ctx.forbidden();
|
2710
3003
|
}
|
@@ -2712,7 +3005,7 @@ const singleTypes = {
|
|
2712
3005
|
return ctx.forbidden();
|
2713
3006
|
}
|
2714
3007
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2715
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3008
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2716
3009
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2717
3010
|
if (!document) {
|
2718
3011
|
return ctx.notFound();
|
@@ -2738,13 +3031,13 @@ const singleTypes = {
|
|
2738
3031
|
const { userAbility } = ctx.state;
|
2739
3032
|
const { model } = ctx.params;
|
2740
3033
|
const { body, query = {} } = ctx.request;
|
2741
|
-
const documentManager2 = getService$
|
2742
|
-
const permissionChecker2 = getService$
|
3034
|
+
const documentManager2 = getService$2("document-manager");
|
3035
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2743
3036
|
if (permissionChecker2.cannot.discard()) {
|
2744
3037
|
return ctx.forbidden();
|
2745
3038
|
}
|
2746
3039
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2747
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3040
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2748
3041
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2749
3042
|
if (!document) {
|
2750
3043
|
return ctx.notFound();
|
@@ -2762,9 +3055,9 @@ const singleTypes = {
|
|
2762
3055
|
const { userAbility } = ctx.state;
|
2763
3056
|
const { model } = ctx.params;
|
2764
3057
|
const { query } = ctx.request;
|
2765
|
-
const documentManager2 = getService$
|
2766
|
-
const permissionChecker2 = getService$
|
2767
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3058
|
+
const documentManager2 = getService$2("document-manager");
|
3059
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3060
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2768
3061
|
if (permissionChecker2.cannot.read()) {
|
2769
3062
|
return ctx.forbidden();
|
2770
3063
|
}
|
@@ -2785,9 +3078,9 @@ const uid$1 = {
|
|
2785
3078
|
async generateUID(ctx) {
|
2786
3079
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2787
3080
|
const { query = {} } = ctx.request;
|
2788
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3081
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2789
3082
|
await validateUIDField(contentTypeUID, field);
|
2790
|
-
const uidService = getService$
|
3083
|
+
const uidService = getService$2("uid");
|
2791
3084
|
ctx.body = {
|
2792
3085
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2793
3086
|
};
|
@@ -2797,9 +3090,9 @@ const uid$1 = {
|
|
2797
3090
|
ctx.request.body
|
2798
3091
|
);
|
2799
3092
|
const { query = {} } = ctx.request;
|
2800
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3093
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2801
3094
|
await validateUIDField(contentTypeUID, field);
|
2802
|
-
const uidService = getService$
|
3095
|
+
const uidService = getService$2("uid");
|
2803
3096
|
const isAvailable = await uidService.checkUIDAvailability({
|
2804
3097
|
contentTypeUID,
|
2805
3098
|
field,
|
@@ -2820,7 +3113,8 @@ const controllers = {
|
|
2820
3113
|
relations,
|
2821
3114
|
"single-types": singleTypes,
|
2822
3115
|
uid: uid$1,
|
2823
|
-
...history.controllers ? history.controllers : {}
|
3116
|
+
...history.controllers ? history.controllers : {},
|
3117
|
+
...preview.controllers ? preview.controllers : {}
|
2824
3118
|
};
|
2825
3119
|
const keys = {
|
2826
3120
|
CONFIGURATION: "configuration"
|
@@ -2949,18 +3243,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2949
3243
|
_.set(updatedMeta, ["list", "searchable"], false);
|
2950
3244
|
_.set(acc, [key], updatedMeta);
|
2951
3245
|
}
|
2952
|
-
if (!_.has(edit, "mainField"))
|
2953
|
-
return acc;
|
3246
|
+
if (!_.has(edit, "mainField")) return acc;
|
2954
3247
|
if (!isRelation$1(attr)) {
|
2955
3248
|
_.set(updatedMeta, "edit", _.omit(edit, ["mainField"]));
|
2956
3249
|
_.set(acc, [key], updatedMeta);
|
2957
3250
|
return acc;
|
2958
3251
|
}
|
2959
|
-
if (edit.mainField === "id")
|
2960
|
-
return acc;
|
3252
|
+
if (edit.mainField === "id") return acc;
|
2961
3253
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2962
|
-
if (!targetSchema)
|
2963
|
-
return acc;
|
3254
|
+
if (!targetSchema) return acc;
|
2964
3255
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2965
3256
|
_.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2966
3257
|
_.set(acc, [key], updatedMeta);
|
@@ -2971,12 +3262,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2971
3262
|
return _.assign(metasWithDefaults, updatedMetas);
|
2972
3263
|
}
|
2973
3264
|
const getTargetSchema = (targetModel) => {
|
2974
|
-
return getService$
|
3265
|
+
return getService$2("content-types").findContentType(targetModel);
|
2975
3266
|
};
|
2976
3267
|
const DEFAULT_LIST_LENGTH = 4;
|
2977
3268
|
const MAX_ROW_SIZE = 12;
|
2978
3269
|
const isAllowedFieldSize = (type, size) => {
|
2979
|
-
const { getFieldSize } = getService$
|
3270
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2980
3271
|
const fieldSize = getFieldSize(type);
|
2981
3272
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2982
3273
|
return false;
|
@@ -2984,7 +3275,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2984
3275
|
return size <= MAX_ROW_SIZE;
|
2985
3276
|
};
|
2986
3277
|
const getDefaultFieldSize = (attribute) => {
|
2987
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3278
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2988
3279
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2989
3280
|
};
|
2990
3281
|
async function createDefaultLayouts(schema) {
|
@@ -3005,8 +3296,7 @@ function createDefaultEditLayout(schema) {
|
|
3005
3296
|
return appendToEditLayout([], keys2, schema);
|
3006
3297
|
}
|
3007
3298
|
function syncLayouts(configuration, schema) {
|
3008
|
-
if (_.isEmpty(configuration.layouts))
|
3009
|
-
return createDefaultLayouts(schema);
|
3299
|
+
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3010
3300
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3011
3301
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3012
3302
|
const cleanEditRelations = editRelations.filter(
|
@@ -3017,9 +3307,8 @@ function syncLayouts(configuration, schema) {
|
|
3017
3307
|
for (const row of edit) {
|
3018
3308
|
const newRow = [];
|
3019
3309
|
for (const el of row) {
|
3020
|
-
if (!hasEditableAttribute(schema, el.name))
|
3021
|
-
|
3022
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3310
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3311
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3023
3312
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3024
3313
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3025
3314
|
elementsToReAppend.push(el.name);
|
@@ -3049,8 +3338,7 @@ function syncLayouts(configuration, schema) {
|
|
3049
3338
|
};
|
3050
3339
|
}
|
3051
3340
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3052
|
-
if (keysToAppend.length === 0)
|
3053
|
-
return layout;
|
3341
|
+
if (keysToAppend.length === 0) return layout;
|
3054
3342
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3055
3343
|
if (!layout[currentRowIndex]) {
|
3056
3344
|
layout[currentRowIndex] = [];
|
@@ -3159,17 +3447,17 @@ const configurationService$1 = createConfigurationService({
|
|
3159
3447
|
isComponent: true,
|
3160
3448
|
prefix: STORE_KEY_PREFIX,
|
3161
3449
|
getModels() {
|
3162
|
-
const { toContentManagerModel } = getService$
|
3450
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3163
3451
|
return mapValues(toContentManagerModel, strapi.components);
|
3164
3452
|
}
|
3165
3453
|
});
|
3166
3454
|
const components = ({ strapi: strapi2 }) => ({
|
3167
3455
|
findAllComponents() {
|
3168
|
-
const { toContentManagerModel } = getService$
|
3456
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3169
3457
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3170
3458
|
},
|
3171
3459
|
findComponent(uid2) {
|
3172
|
-
const { toContentManagerModel } = getService$
|
3460
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3173
3461
|
const component = strapi2.components[uid2];
|
3174
3462
|
return isNil$1(component) ? component : toContentManagerModel(component);
|
3175
3463
|
},
|
@@ -3220,17 +3508,17 @@ const configurationService = createConfigurationService({
|
|
3220
3508
|
storeUtils,
|
3221
3509
|
prefix: "content_types",
|
3222
3510
|
getModels() {
|
3223
|
-
const { toContentManagerModel } = getService$
|
3511
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3224
3512
|
return mapValues(toContentManagerModel, strapi.contentTypes);
|
3225
3513
|
}
|
3226
3514
|
});
|
3227
3515
|
const service = ({ strapi: strapi2 }) => ({
|
3228
3516
|
findAllContentTypes() {
|
3229
|
-
const { toContentManagerModel } = getService$
|
3517
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3230
3518
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3231
3519
|
},
|
3232
3520
|
findContentType(uid2) {
|
3233
|
-
const { toContentManagerModel } = getService$
|
3521
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3234
3522
|
const contentType = strapi2.contentTypes[uid2];
|
3235
3523
|
return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
|
3236
3524
|
},
|
@@ -3259,7 +3547,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3259
3547
|
return this.findConfiguration(contentType);
|
3260
3548
|
},
|
3261
3549
|
findComponentsConfigurations(contentType) {
|
3262
|
-
return getService$
|
3550
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3263
3551
|
},
|
3264
3552
|
syncConfigurations() {
|
3265
3553
|
return configurationService.syncConfigurations();
|
@@ -3440,12 +3728,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3440
3728
|
ability: userAbility,
|
3441
3729
|
model
|
3442
3730
|
});
|
3443
|
-
const
|
3731
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3732
|
+
const toSubject = (entity) => {
|
3733
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3734
|
+
};
|
3444
3735
|
const can = (action, entity, field) => {
|
3445
|
-
|
3736
|
+
const subject = toSubject(entity);
|
3737
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3738
|
+
return (
|
3739
|
+
// Test the original action to see if it passes
|
3740
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3741
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3742
|
+
);
|
3446
3743
|
};
|
3447
3744
|
const cannot = (action, entity, field) => {
|
3448
|
-
|
3745
|
+
const subject = toSubject(entity);
|
3746
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3747
|
+
return (
|
3748
|
+
// Test both the original action
|
3749
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3750
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3751
|
+
);
|
3449
3752
|
};
|
3450
3753
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3451
3754
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3516,7 +3819,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3516
3819
|
return userAbility.can(action);
|
3517
3820
|
},
|
3518
3821
|
async registerPermissions() {
|
3519
|
-
const displayedContentTypes = getService$
|
3822
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3520
3823
|
const contentTypesUids = displayedContentTypes.map(prop("uid"));
|
3521
3824
|
const actions = [
|
3522
3825
|
{
|
@@ -3601,6 +3904,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3601
3904
|
if (initialPopulate) {
|
3602
3905
|
return initialPopulate;
|
3603
3906
|
}
|
3907
|
+
if (attributeName === "localizations") {
|
3908
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3909
|
+
return {
|
3910
|
+
populate: validationPopulate.populate
|
3911
|
+
};
|
3912
|
+
}
|
3604
3913
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3605
3914
|
return true;
|
3606
3915
|
}
|
@@ -3660,6 +3969,9 @@ const getDeepPopulate = (uid2, {
|
|
3660
3969
|
return {};
|
3661
3970
|
}
|
3662
3971
|
const model = strapi.getModel(uid2);
|
3972
|
+
if (!model) {
|
3973
|
+
return {};
|
3974
|
+
}
|
3663
3975
|
return Object.keys(model.attributes).reduce(
|
3664
3976
|
(populateAcc, attributeName) => merge(
|
3665
3977
|
populateAcc,
|
@@ -3679,40 +3991,46 @@ const getDeepPopulate = (uid2, {
|
|
3679
3991
|
{}
|
3680
3992
|
);
|
3681
3993
|
};
|
3682
|
-
const
|
3683
|
-
|
3684
|
-
|
3685
|
-
countOne = false,
|
3686
|
-
maxLevel = Infinity
|
3687
|
-
} = {}, level = 1) => {
|
3688
|
-
if (level > maxLevel) {
|
3994
|
+
const getPopulateForValidation = (uid2) => {
|
3995
|
+
const model = strapi.getModel(uid2);
|
3996
|
+
if (!model) {
|
3689
3997
|
return {};
|
3690
3998
|
}
|
3691
|
-
const model = strapi.getModel(uid2);
|
3692
3999
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3693
|
-
if (
|
4000
|
+
if (isScalarAttribute(attribute)) {
|
4001
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4002
|
+
populateAcc.fields = populateAcc.fields || [];
|
4003
|
+
populateAcc.fields.push(attributeName);
|
4004
|
+
}
|
3694
4005
|
return populateAcc;
|
3695
4006
|
}
|
3696
|
-
if (
|
3697
|
-
|
3698
|
-
|
3699
|
-
|
4007
|
+
if (isComponent(attribute)) {
|
4008
|
+
const component = attribute.component;
|
4009
|
+
const componentResult = getPopulateForValidation(component);
|
4010
|
+
if (Object.keys(componentResult).length > 0) {
|
4011
|
+
populateAcc.populate = populateAcc.populate || {};
|
4012
|
+
populateAcc.populate[attributeName] = componentResult;
|
4013
|
+
}
|
4014
|
+
return populateAcc;
|
3700
4015
|
}
|
3701
|
-
|
3702
|
-
|
3703
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
|
3707
|
-
|
3708
|
-
|
3709
|
-
|
3710
|
-
countOne,
|
3711
|
-
maxLevel
|
4016
|
+
if (isDynamicZone(attribute)) {
|
4017
|
+
const components2 = attribute.components;
|
4018
|
+
const componentsResult = (components2 || []).reduce(
|
4019
|
+
(acc, componentUID) => {
|
4020
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4021
|
+
if (Object.keys(componentResult).length > 0) {
|
4022
|
+
acc[componentUID] = componentResult;
|
4023
|
+
}
|
4024
|
+
return acc;
|
3712
4025
|
},
|
3713
|
-
|
3714
|
-
)
|
3715
|
-
|
4026
|
+
{}
|
4027
|
+
);
|
4028
|
+
if (Object.keys(componentsResult).length > 0) {
|
4029
|
+
populateAcc.populate = populateAcc.populate || {};
|
4030
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4031
|
+
}
|
4032
|
+
}
|
4033
|
+
return populateAcc;
|
3716
4034
|
}, {});
|
3717
4035
|
};
|
3718
4036
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3722,6 +4040,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3722
4040
|
const attribute = model.attributes[attributeName];
|
3723
4041
|
switch (attribute.type) {
|
3724
4042
|
case "relation": {
|
4043
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4044
|
+
if (isMorphRelation) {
|
4045
|
+
break;
|
4046
|
+
}
|
3725
4047
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3726
4048
|
populateAcc[attributeName] = {
|
3727
4049
|
count: true,
|
@@ -3788,7 +4110,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3788
4110
|
return populateQuery;
|
3789
4111
|
};
|
3790
4112
|
const buildDeepPopulate = (uid2) => {
|
3791
|
-
return getService$
|
4113
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3792
4114
|
};
|
3793
4115
|
const populateBuilder = (uid2) => {
|
3794
4116
|
let getInitialPopulate = async () => {
|
@@ -3950,7 +4272,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3950
4272
|
"locale",
|
3951
4273
|
"updatedAt",
|
3952
4274
|
"createdAt",
|
3953
|
-
"status",
|
3954
4275
|
"publishedAt",
|
3955
4276
|
"documentId"
|
3956
4277
|
];
|
@@ -3971,34 +4292,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3971
4292
|
/**
|
3972
4293
|
* Returns available locales of a document for the current status
|
3973
4294
|
*/
|
3974
|
-
async getAvailableLocales(uid2, version, allVersions
|
4295
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3975
4296
|
const versionsByLocale = groupBy("locale", allVersions);
|
3976
|
-
|
4297
|
+
if (version.locale) {
|
4298
|
+
delete versionsByLocale[version.locale];
|
4299
|
+
}
|
3977
4300
|
const model = strapi2.getModel(uid2);
|
3978
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3979
|
-
const traversalFunction = async (localeVersion) => traverseEntity(
|
3980
|
-
({ key }, { remove }) => {
|
3981
|
-
if (keysToKeep.includes(key)) {
|
3982
|
-
return;
|
3983
|
-
}
|
3984
|
-
remove(key);
|
3985
|
-
},
|
3986
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
3987
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
3988
|
-
localeVersion
|
3989
|
-
);
|
3990
4301
|
const mappingResult = await async.map(
|
3991
4302
|
Object.values(versionsByLocale),
|
3992
4303
|
async (localeVersions) => {
|
3993
|
-
const mappedLocaleVersions = await async.map(
|
3994
|
-
localeVersions,
|
3995
|
-
traversalFunction
|
3996
|
-
);
|
3997
4304
|
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
3998
|
-
return
|
4305
|
+
return localeVersions[0];
|
3999
4306
|
}
|
4000
|
-
const draftVersion =
|
4001
|
-
const otherVersions =
|
4307
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4308
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4002
4309
|
if (!draftVersion) {
|
4003
4310
|
return;
|
4004
4311
|
}
|
@@ -4020,8 +4327,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4020
4327
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4021
4328
|
return matchLocale && matchStatus;
|
4022
4329
|
});
|
4023
|
-
if (!availableStatus)
|
4024
|
-
return availableStatus;
|
4330
|
+
if (!availableStatus) return availableStatus;
|
4025
4331
|
return pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4026
4332
|
},
|
4027
4333
|
/**
|
@@ -4031,18 +4337,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4031
4337
|
* @returns
|
4032
4338
|
*/
|
4033
4339
|
async getManyAvailableStatus(uid2, documents) {
|
4034
|
-
if (!documents.length)
|
4035
|
-
return [];
|
4340
|
+
if (!documents.length) return [];
|
4036
4341
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4037
|
-
const
|
4038
|
-
const
|
4039
|
-
|
4040
|
-
|
4041
|
-
|
4042
|
-
|
4043
|
-
|
4044
|
-
|
4045
|
-
|
4342
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4343
|
+
const where = {
|
4344
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4345
|
+
publishedAt: { $null: status === "published" }
|
4346
|
+
};
|
4347
|
+
if (locales.length) {
|
4348
|
+
where.locale = { $in: locales };
|
4349
|
+
}
|
4350
|
+
return strapi2.query(uid2).findMany({
|
4351
|
+
where,
|
4352
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4046
4353
|
});
|
4047
4354
|
},
|
4048
4355
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4059,10 +4366,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4059
4366
|
} else if (otherVersion) {
|
4060
4367
|
draftVersion = otherVersion;
|
4061
4368
|
}
|
4062
|
-
if (!draftVersion)
|
4063
|
-
|
4064
|
-
if (!publishedVersion)
|
4065
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4369
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4370
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4066
4371
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4067
4372
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4068
4373
|
},
|
@@ -4070,11 +4375,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4070
4375
|
// We could refactor this so the locales are only loaded when they're
|
4071
4376
|
// needed. e.g. in the bulk locale action modal.
|
4072
4377
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4073
|
-
const populate =
|
4074
|
-
const
|
4075
|
-
where: { documentId: version.documentId },
|
4378
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4379
|
+
const params = {
|
4076
4380
|
populate: {
|
4077
|
-
// Populate only fields that require validation for bulk locale actions
|
4078
4381
|
...populate,
|
4079
4382
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4080
4383
|
createdBy: {
|
@@ -4083,9 +4386,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4083
4386
|
updatedBy: {
|
4084
4387
|
select: ["id", "firstname", "lastname", "email"]
|
4085
4388
|
}
|
4389
|
+
},
|
4390
|
+
fields: uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4391
|
+
filters: {
|
4392
|
+
documentId: version.documentId
|
4086
4393
|
}
|
4087
|
-
}
|
4088
|
-
const
|
4394
|
+
};
|
4395
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4396
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4397
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
4089
4398
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4090
4399
|
return {
|
4091
4400
|
availableLocales: availableLocalesResult,
|
@@ -4099,13 +4408,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4099
4408
|
*/
|
4100
4409
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4101
4410
|
if (!document) {
|
4102
|
-
return
|
4411
|
+
return {
|
4412
|
+
data: document,
|
4413
|
+
meta: {
|
4414
|
+
availableLocales: [],
|
4415
|
+
availableStatus: []
|
4416
|
+
}
|
4417
|
+
};
|
4103
4418
|
}
|
4104
4419
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
4105
4420
|
if (!hasDraftAndPublish) {
|
4106
4421
|
opts.availableStatus = false;
|
4107
4422
|
}
|
4108
4423
|
const meta = await this.getMetadata(uid2, document, opts);
|
4424
|
+
if (document.localizations) {
|
4425
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4426
|
+
document.localizations = document.localizations.map((d) => {
|
4427
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4428
|
+
return {
|
4429
|
+
...d,
|
4430
|
+
status: this.getStatus(d, status ? [status] : [])
|
4431
|
+
};
|
4432
|
+
});
|
4433
|
+
}
|
4109
4434
|
return {
|
4110
4435
|
data: {
|
4111
4436
|
...document,
|
@@ -4207,10 +4532,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4207
4532
|
async clone(id, body, uid2) {
|
4208
4533
|
const populate = await buildDeepPopulate(uid2);
|
4209
4534
|
const params = {
|
4210
|
-
data:
|
4211
|
-
...omitIdField(body),
|
4212
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4213
|
-
},
|
4535
|
+
data: omitIdField(body),
|
4214
4536
|
populate
|
4215
4537
|
};
|
4216
4538
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4326,7 +4648,8 @@ const services = {
|
|
4326
4648
|
permission,
|
4327
4649
|
"populate-builder": populateBuilder$1,
|
4328
4650
|
uid,
|
4329
|
-
...history.services ? history.services : {}
|
4651
|
+
...history.services ? history.services : {},
|
4652
|
+
...preview.services ? preview.services : {}
|
4330
4653
|
};
|
4331
4654
|
const index = () => {
|
4332
4655
|
return {
|