@strapi/content-manager 0.0.0-experimental.9df68962083938acba06546a7901c68a63266aec → 0.0.0-experimental.9f812af47f0e9db3d5531382c836c2ac0776afdf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-BSEZcJVB.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-BSEZcJVB.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-BiASGi7x.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-BiASGi7x.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-DjFJw56M.js → EditConfigurationPage-D2rtvneE.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-D2rtvneE.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-vN4zupij.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-vN4zupij.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BwisF04Q.js} +63 -13
- package/dist/_chunks/EditViewPage-BwisF04Q.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-_A31Cl4g.mjs} +63 -12
- package/dist/_chunks/EditViewPage-_A31Cl4g.mjs.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CvIunNOj.mjs} +405 -256
- package/dist/_chunks/Field-CvIunNOj.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dsu6-FrM.js} +409 -260
- package/dist/_chunks/Field-Dsu6-FrM.js.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DK0fG0Gj.mjs} +37 -18
- package/dist/_chunks/Form-DK0fG0Gj.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-DUwWcCmA.js} +39 -21
- package/dist/_chunks/Form-DUwWcCmA.js.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-CeCDhoJG.js} +81 -114
- package/dist/_chunks/History-CeCDhoJG.js.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-DP8gmXpm.mjs} +82 -114
- package/dist/_chunks/History-DP8gmXpm.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BCkO5iuN.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-BCkO5iuN.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-C-bAd44a.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-C-bAd44a.js.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-BKTZFhsM.js} +121 -81
- package/dist/_chunks/ListViewPage-BKTZFhsM.js.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-Cf_DgaFV.mjs} +118 -77
- package/dist/_chunks/ListViewPage-Cf_DgaFV.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-D3Cm3v3q.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-D3Cm3v3q.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-nHIyvJcB.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-nHIyvJcB.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-BALVSJ7x.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-BALVSJ7x.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-CChGWBj5.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-CChGWBj5.js.map} +1 -1
- package/dist/_chunks/Preview-C4NBzKUV.mjs +294 -0
- package/dist/_chunks/Preview-C4NBzKUV.mjs.map +1 -0
- package/dist/_chunks/Preview-CT28Ckpg.js +312 -0
- package/dist/_chunks/Preview-CT28Ckpg.js.map +1 -0
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-C8uC89cT.mjs} +76 -42
- package/dist/_chunks/Relations-C8uC89cT.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CvkPCng_.js} +76 -43
- package/dist/_chunks/Relations-CvkPCng_.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BK8Xyl5I.js} +32 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-Dtk_ot79.mjs} +32 -18
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-DVPWZkbS.js → index-CnX_j5h-.js} +1235 -746
- package/dist/_chunks/index-CnX_j5h-.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-Dh2aGTGJ.mjs} +1252 -763
- package/dist/_chunks/index-Dh2aGTGJ.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-B5qsPihj.mjs} +26 -13
- package/dist/_chunks/layout-B5qsPihj.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-B_qdWGny.js} +26 -14
- package/dist/_chunks/layout-B_qdWGny.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CKnpRgrN.js → relations-ChcieiF5.js} +6 -7
- package/dist/_chunks/relations-ChcieiF5.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-DMXpNY-e.mjs} +6 -7
- package/dist/_chunks/relations-DMXpNY-e.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/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 +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/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 +686 -360
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +687 -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-CPj61RMh.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
- package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
- package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
- package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
- package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
- package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
- package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
- package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
- package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
- package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
- package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
- package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
- package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
- package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
- package/dist/_chunks/relations-CKnpRgrN.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
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,31 +200,53 @@ 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": {
|
221
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
222
|
+
if (isMorphRelation) {
|
223
|
+
break;
|
224
|
+
}
|
209
225
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
210
226
|
if (isVisible2) {
|
211
|
-
acc[attributeName] = {
|
227
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
212
228
|
}
|
213
229
|
break;
|
214
230
|
}
|
215
231
|
case "media": {
|
216
|
-
acc[attributeName] = {
|
232
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
217
233
|
break;
|
218
234
|
}
|
219
235
|
case "component": {
|
220
236
|
const populate = getDeepPopulate2(attribute.component);
|
221
|
-
acc[attributeName] = {
|
237
|
+
acc[attributeName] = {
|
238
|
+
populate,
|
239
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
240
|
+
};
|
222
241
|
break;
|
223
242
|
}
|
224
243
|
case "dynamiczone": {
|
225
244
|
const populatedComponents = (attribute.components || []).reduce(
|
226
245
|
(acc2, componentUID) => {
|
227
|
-
acc2[componentUID] = {
|
246
|
+
acc2[componentUID] = {
|
247
|
+
populate: getDeepPopulate2(componentUID),
|
248
|
+
[fieldSelector]: getComponentFields(componentUID)
|
249
|
+
};
|
228
250
|
return acc2;
|
229
251
|
},
|
230
252
|
{}
|
@@ -286,6 +308,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
286
308
|
getRelationRestoreValue,
|
287
309
|
getMediaRestoreValue,
|
288
310
|
getDefaultLocale,
|
311
|
+
isLocalizedContentType,
|
289
312
|
getLocaleDictionary,
|
290
313
|
getRetentionDays,
|
291
314
|
getVersionStatus,
|
@@ -308,7 +331,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
308
331
|
});
|
309
332
|
},
|
310
333
|
async findVersionsPage(params) {
|
311
|
-
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
|
+
}
|
312
341
|
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
313
342
|
query.findPage({
|
314
343
|
...params.query,
|
@@ -330,7 +359,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
330
359
|
const attributeValue = entry.data[attributeKey];
|
331
360
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
332
361
|
if (attributeSchema.type === "media") {
|
333
|
-
const permissionChecker2 = getService$
|
362
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
334
363
|
userAbility: params.state.userAbility,
|
335
364
|
model: "plugin::upload.file"
|
336
365
|
});
|
@@ -353,7 +382,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
353
382
|
if (userToPopulate == null) {
|
354
383
|
return null;
|
355
384
|
}
|
356
|
-
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
|
+
});
|
357
391
|
})
|
358
392
|
);
|
359
393
|
return {
|
@@ -366,7 +400,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
366
400
|
[attributeKey]: adminUsers
|
367
401
|
};
|
368
402
|
}
|
369
|
-
const permissionChecker2 = getService$
|
403
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
370
404
|
userAbility: params.state.userAbility,
|
371
405
|
model: attributeSchema.target
|
372
406
|
});
|
@@ -464,6 +498,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
464
498
|
}
|
465
499
|
};
|
466
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
|
+
};
|
467
537
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
538
|
const state = {
|
469
539
|
deleteExpiredJob: null,
|
@@ -476,76 +546,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
476
546
|
return;
|
477
547
|
}
|
478
548
|
strapi2.documents.use(async (context, next) => {
|
479
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
480
|
-
return next();
|
481
|
-
}
|
482
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
483
|
-
return next();
|
484
|
-
}
|
485
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
486
|
-
return next();
|
487
|
-
}
|
488
|
-
const contentTypeUid = context.contentType.uid;
|
489
|
-
if (!contentTypeUid.startsWith("api::")) {
|
490
|
-
return next();
|
491
|
-
}
|
492
549
|
const result = await next();
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
550
|
+
if (!shouldCreateHistoryVersion(context)) {
|
551
|
+
return result;
|
552
|
+
}
|
553
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
497
554
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
498
|
-
const
|
499
|
-
if (
|
500
|
-
|
501
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
502
|
-
);
|
503
|
-
return next();
|
555
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
556
|
+
if (!locales.length) {
|
557
|
+
return result;
|
504
558
|
}
|
505
|
-
const
|
506
|
-
|
507
|
-
|
508
|
-
|
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
|
+
)
|
509
574
|
});
|
510
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
511
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
512
|
-
const componentsSchemas = Object.keys(
|
513
|
-
attributesSchema
|
514
|
-
).reduce((currentComponentSchemas, key) => {
|
515
|
-
const fieldSchema = attributesSchema[key];
|
516
|
-
if (fieldSchema.type === "component") {
|
517
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
518
|
-
return {
|
519
|
-
...currentComponentSchemas,
|
520
|
-
[fieldSchema.component]: componentSchema
|
521
|
-
};
|
522
|
-
}
|
523
|
-
return currentComponentSchemas;
|
524
|
-
}, {});
|
525
575
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
526
|
-
onCommit(() => {
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
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
|
+
}
|
536
588
|
});
|
537
589
|
});
|
538
590
|
return result;
|
539
591
|
});
|
540
|
-
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
592
|
+
state.deleteExpiredJob = scheduleJob("historyDaily", "0 0 * * *", () => {
|
541
593
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
542
594
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
543
595
|
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
544
596
|
where: {
|
545
597
|
created_at: {
|
546
|
-
$lt: expirationDate
|
598
|
+
$lt: expirationDate
|
547
599
|
}
|
548
600
|
}
|
601
|
+
}).catch((error) => {
|
602
|
+
if (error instanceof Error) {
|
603
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
604
|
+
}
|
549
605
|
});
|
550
606
|
});
|
551
607
|
state.isInitialized = true;
|
@@ -557,17 +613,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
557
613
|
}
|
558
614
|
};
|
559
615
|
};
|
560
|
-
const services$
|
616
|
+
const services$2 = {
|
561
617
|
history: createHistoryService,
|
562
618
|
lifecycles: createLifecyclesService
|
563
619
|
};
|
564
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
620
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
565
621
|
const historyVersionRouter = {
|
566
622
|
type: "admin",
|
567
623
|
routes: [
|
568
624
|
{
|
569
625
|
method: "GET",
|
570
|
-
info,
|
626
|
+
info: info$1,
|
571
627
|
path: "/history-versions",
|
572
628
|
handler: "history-version.findMany",
|
573
629
|
config: {
|
@@ -576,7 +632,7 @@ const historyVersionRouter = {
|
|
576
632
|
},
|
577
633
|
{
|
578
634
|
method: "PUT",
|
579
|
-
info,
|
635
|
+
info: info$1,
|
580
636
|
path: "/history-versions/:versionId/restore",
|
581
637
|
handler: "history-version.restoreVersion",
|
582
638
|
config: {
|
@@ -585,7 +641,7 @@ const historyVersionRouter = {
|
|
585
641
|
}
|
586
642
|
]
|
587
643
|
};
|
588
|
-
const routes$
|
644
|
+
const routes$2 = {
|
589
645
|
"history-version": historyVersionRouter
|
590
646
|
};
|
591
647
|
const historyVersion = {
|
@@ -632,21 +688,21 @@ const historyVersion = {
|
|
632
688
|
}
|
633
689
|
}
|
634
690
|
};
|
635
|
-
const getFeature = () => {
|
691
|
+
const getFeature$1 = () => {
|
636
692
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
637
693
|
return {
|
638
694
|
register({ strapi: strapi2 }) {
|
639
695
|
strapi2.get("models").add(historyVersion);
|
640
696
|
},
|
641
697
|
bootstrap({ strapi: strapi2 }) {
|
642
|
-
getService(strapi2, "lifecycles").bootstrap();
|
698
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
643
699
|
},
|
644
700
|
destroy({ strapi: strapi2 }) {
|
645
|
-
getService(strapi2, "lifecycles").destroy();
|
701
|
+
getService$1(strapi2, "lifecycles").destroy();
|
646
702
|
},
|
647
|
-
controllers: controllers$
|
648
|
-
services: services$
|
649
|
-
routes: routes$
|
703
|
+
controllers: controllers$2,
|
704
|
+
services: services$2,
|
705
|
+
routes: routes$2
|
650
706
|
};
|
651
707
|
}
|
652
708
|
return {
|
@@ -655,9 +711,201 @@ const getFeature = () => {
|
|
655
711
|
}
|
656
712
|
};
|
657
713
|
};
|
658
|
-
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();
|
659
906
|
const register = async ({ strapi: strapi2 }) => {
|
660
907
|
await history.register?.({ strapi: strapi2 });
|
908
|
+
await preview.register?.({ strapi: strapi2 });
|
661
909
|
};
|
662
910
|
const ALLOWED_WEBHOOK_EVENTS = {
|
663
911
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -667,11 +915,12 @@ const bootstrap = async () => {
|
|
667
915
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
668
916
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
669
917
|
});
|
670
|
-
getService$
|
671
|
-
await getService$
|
672
|
-
await getService$
|
673
|
-
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();
|
674
922
|
await history.bootstrap?.({ strapi });
|
923
|
+
await preview.bootstrap?.({ strapi });
|
675
924
|
};
|
676
925
|
const destroy = async ({ strapi: strapi2 }) => {
|
677
926
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1161,7 +1410,8 @@ const admin = {
|
|
1161
1410
|
};
|
1162
1411
|
const routes = {
|
1163
1412
|
admin,
|
1164
|
-
...history.routes ? history.routes : {}
|
1413
|
+
...history.routes ? history.routes : {},
|
1414
|
+
...preview.routes ? preview.routes : {}
|
1165
1415
|
};
|
1166
1416
|
const hasPermissionsSchema = yup$1.object({
|
1167
1417
|
actions: yup$1.array().of(yup$1.string()),
|
@@ -1172,6 +1422,11 @@ const { createPolicy } = policy;
|
|
1172
1422
|
const hasPermissions = createPolicy({
|
1173
1423
|
name: "plugin::content-manager.hasPermissions",
|
1174
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
|
+
*/
|
1175
1430
|
handler(ctx, config = {}) {
|
1176
1431
|
const { actions = [], hasAtLeastOne = false } = config;
|
1177
1432
|
const { userAbility } = ctx.state;
|
@@ -1219,8 +1474,7 @@ const isSortable = (schema, name) => {
|
|
1219
1474
|
if (!_.has(schema.attributes, name)) {
|
1220
1475
|
return false;
|
1221
1476
|
}
|
1222
|
-
if (schema.modelType === "component" && name === "id")
|
1223
|
-
return false;
|
1477
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1224
1478
|
const attribute = schema.attributes[name];
|
1225
1479
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1226
1480
|
return false;
|
@@ -1365,8 +1619,7 @@ const createDefaultSettings = async (schema) => {
|
|
1365
1619
|
};
|
1366
1620
|
};
|
1367
1621
|
const syncSettings = async (configuration, schema) => {
|
1368
|
-
if (isEmpty(configuration.settings))
|
1369
|
-
return createDefaultSettings(schema);
|
1622
|
+
if (isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1370
1623
|
const defaultField = getDefaultMainField(schema);
|
1371
1624
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1372
1625
|
return {
|
@@ -1413,7 +1666,7 @@ const createMetadasSchema = (schema) => {
|
|
1413
1666
|
if (!value) {
|
1414
1667
|
return yup$1.string();
|
1415
1668
|
}
|
1416
|
-
const targetSchema = getService$
|
1669
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1417
1670
|
schema.attributes[key].targetModel
|
1418
1671
|
);
|
1419
1672
|
if (!targetSchema) {
|
@@ -1542,8 +1795,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1542
1795
|
}
|
1543
1796
|
switch (attribute.type) {
|
1544
1797
|
case "relation": {
|
1545
|
-
if (canCreate(attributePath))
|
1546
|
-
return body2;
|
1798
|
+
if (canCreate(attributePath)) return body2;
|
1547
1799
|
return set(attributePath, { set: [] }, body2);
|
1548
1800
|
}
|
1549
1801
|
case "component": {
|
@@ -1553,8 +1805,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1553
1805
|
]);
|
1554
1806
|
}
|
1555
1807
|
default: {
|
1556
|
-
if (canCreate(attributePath))
|
1557
|
-
return body2;
|
1808
|
+
if (canCreate(attributePath)) return body2;
|
1558
1809
|
return set(attributePath, null, body2);
|
1559
1810
|
}
|
1560
1811
|
}
|
@@ -1565,9 +1816,11 @@ const multipleLocaleSchema = yup$1.lazy(
|
|
1565
1816
|
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1566
1817
|
);
|
1567
1818
|
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1568
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1819
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1569
1820
|
const { allowMultipleLocales } = opts;
|
1570
|
-
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;
|
1571
1824
|
const schema = yup$1.object().shape({
|
1572
1825
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1573
1826
|
status: statusSchema
|
@@ -1580,7 +1833,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1580
1833
|
}
|
1581
1834
|
};
|
1582
1835
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1583
|
-
const documentMetadata2 = getService$
|
1836
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1584
1837
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1585
1838
|
let {
|
1586
1839
|
meta: { availableLocales, availableStatus }
|
@@ -1606,8 +1859,8 @@ const createDocument = async (ctx, opts) => {
|
|
1606
1859
|
const { userAbility, user } = ctx.state;
|
1607
1860
|
const { model } = ctx.params;
|
1608
1861
|
const { body } = ctx.request;
|
1609
|
-
const documentManager2 = getService$
|
1610
|
-
const permissionChecker2 = getService$
|
1862
|
+
const documentManager2 = getService$2("document-manager");
|
1863
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1611
1864
|
if (permissionChecker2.cannot.create()) {
|
1612
1865
|
throw new errors.ForbiddenError();
|
1613
1866
|
}
|
@@ -1615,7 +1868,7 @@ const createDocument = async (ctx, opts) => {
|
|
1615
1868
|
const setCreator = setCreatorFields({ user });
|
1616
1869
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1617
1870
|
const sanitizedBody = await sanitizeFn(body);
|
1618
|
-
const { locale, status
|
1871
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1619
1872
|
return documentManager2.create(model, {
|
1620
1873
|
data: sanitizedBody,
|
1621
1874
|
locale,
|
@@ -1627,14 +1880,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1627
1880
|
const { userAbility, user } = ctx.state;
|
1628
1881
|
const { id, model } = ctx.params;
|
1629
1882
|
const { body } = ctx.request;
|
1630
|
-
const documentManager2 = getService$
|
1631
|
-
const permissionChecker2 = getService$
|
1883
|
+
const documentManager2 = getService$2("document-manager");
|
1884
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1632
1885
|
if (permissionChecker2.cannot.update()) {
|
1633
1886
|
throw new errors.ForbiddenError();
|
1634
1887
|
}
|
1635
1888
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1636
|
-
const populate = await getService$
|
1637
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1889
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1890
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1638
1891
|
const [documentVersion, documentExists] = await Promise.all([
|
1639
1892
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1640
1893
|
documentManager2.exists(model, id)
|
@@ -1650,7 +1903,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1650
1903
|
throw new errors.ForbiddenError();
|
1651
1904
|
}
|
1652
1905
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1653
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1906
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1654
1907
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1655
1908
|
const sanitizedBody = await sanitizeFn(body);
|
1656
1909
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1664,15 +1917,15 @@ const collectionTypes = {
|
|
1664
1917
|
const { userAbility } = ctx.state;
|
1665
1918
|
const { model } = ctx.params;
|
1666
1919
|
const { query } = ctx.request;
|
1667
|
-
const documentMetadata2 = getService$
|
1668
|
-
const documentManager2 = getService$
|
1669
|
-
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 });
|
1670
1923
|
if (permissionChecker2.cannot.read()) {
|
1671
1924
|
return ctx.forbidden();
|
1672
1925
|
}
|
1673
1926
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1674
|
-
const populate = await getService$
|
1675
|
-
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);
|
1676
1929
|
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1677
1930
|
{ ...permissionQuery, populate, locale, status },
|
1678
1931
|
model
|
@@ -1700,14 +1953,14 @@ const collectionTypes = {
|
|
1700
1953
|
async findOne(ctx) {
|
1701
1954
|
const { userAbility } = ctx.state;
|
1702
1955
|
const { model, id } = ctx.params;
|
1703
|
-
const documentManager2 = getService$
|
1704
|
-
const permissionChecker2 = getService$
|
1956
|
+
const documentManager2 = getService$2("document-manager");
|
1957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1705
1958
|
if (permissionChecker2.cannot.read()) {
|
1706
1959
|
return ctx.forbidden();
|
1707
1960
|
}
|
1708
1961
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1709
|
-
const populate = await getService$
|
1710
|
-
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);
|
1711
1964
|
const version = await documentManager2.findOne(id, model, {
|
1712
1965
|
populate,
|
1713
1966
|
locale,
|
@@ -1722,7 +1975,7 @@ const collectionTypes = {
|
|
1722
1975
|
permissionChecker2,
|
1723
1976
|
model,
|
1724
1977
|
// @ts-expect-error TODO: fix
|
1725
|
-
{ id, locale, publishedAt: null },
|
1978
|
+
{ documentId: id, locale, publishedAt: null },
|
1726
1979
|
{ availableLocales: true, availableStatus: false }
|
1727
1980
|
);
|
1728
1981
|
ctx.body = { data: {}, meta };
|
@@ -1737,7 +1990,7 @@ const collectionTypes = {
|
|
1737
1990
|
async create(ctx) {
|
1738
1991
|
const { userAbility } = ctx.state;
|
1739
1992
|
const { model } = ctx.params;
|
1740
|
-
const permissionChecker2 = getService$
|
1993
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1741
1994
|
const [totalEntries, document] = await Promise.all([
|
1742
1995
|
strapi.db.query(model).count(),
|
1743
1996
|
createDocument(ctx)
|
@@ -1758,7 +2011,7 @@ const collectionTypes = {
|
|
1758
2011
|
async update(ctx) {
|
1759
2012
|
const { userAbility } = ctx.state;
|
1760
2013
|
const { model } = ctx.params;
|
1761
|
-
const permissionChecker2 = getService$
|
2014
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1762
2015
|
const updatedVersion = await updateDocument(ctx);
|
1763
2016
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1764
2017
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1767,14 +2020,14 @@ const collectionTypes = {
|
|
1767
2020
|
const { userAbility, user } = ctx.state;
|
1768
2021
|
const { model, sourceId: id } = ctx.params;
|
1769
2022
|
const { body } = ctx.request;
|
1770
|
-
const documentManager2 = getService$
|
1771
|
-
const permissionChecker2 = getService$
|
2023
|
+
const documentManager2 = getService$2("document-manager");
|
2024
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1772
2025
|
if (permissionChecker2.cannot.create()) {
|
1773
2026
|
return ctx.forbidden();
|
1774
2027
|
}
|
1775
2028
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1776
|
-
const populate = await getService$
|
1777
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2029
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2030
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1778
2031
|
const document = await documentManager2.findOne(id, model, {
|
1779
2032
|
populate,
|
1780
2033
|
locale,
|
@@ -1812,14 +2065,14 @@ const collectionTypes = {
|
|
1812
2065
|
async delete(ctx) {
|
1813
2066
|
const { userAbility } = ctx.state;
|
1814
2067
|
const { id, model } = ctx.params;
|
1815
|
-
const documentManager2 = getService$
|
1816
|
-
const permissionChecker2 = getService$
|
2068
|
+
const documentManager2 = getService$2("document-manager");
|
2069
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1817
2070
|
if (permissionChecker2.cannot.delete()) {
|
1818
2071
|
return ctx.forbidden();
|
1819
2072
|
}
|
1820
2073
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1821
|
-
const populate = await getService$
|
1822
|
-
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);
|
1823
2076
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1824
2077
|
if (documentLocales.length === 0) {
|
1825
2078
|
return ctx.notFound();
|
@@ -1840,19 +2093,42 @@ const collectionTypes = {
|
|
1840
2093
|
const { userAbility } = ctx.state;
|
1841
2094
|
const { id, model } = ctx.params;
|
1842
2095
|
const { body } = ctx.request;
|
1843
|
-
const documentManager2 = getService$
|
1844
|
-
const permissionChecker2 = getService$
|
2096
|
+
const documentManager2 = getService$2("document-manager");
|
2097
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1845
2098
|
if (permissionChecker2.cannot.publish()) {
|
1846
2099
|
return ctx.forbidden();
|
1847
2100
|
}
|
1848
2101
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1849
2102
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1850
|
-
const populate = await getService$
|
1851
|
-
|
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
|
+
}
|
1852
2129
|
if (permissionChecker2.cannot.publish(document)) {
|
1853
2130
|
throw new errors.ForbiddenError();
|
1854
2131
|
}
|
1855
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1856
2132
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1857
2133
|
locale
|
1858
2134
|
// TODO: Allow setting creator fields on publish
|
@@ -1872,14 +2148,16 @@ const collectionTypes = {
|
|
1872
2148
|
const { body } = ctx.request;
|
1873
2149
|
const { documentIds } = body;
|
1874
2150
|
await validateBulkActionInput(body);
|
1875
|
-
const documentManager2 = getService$
|
1876
|
-
const permissionChecker2 = getService$
|
2151
|
+
const documentManager2 = getService$2("document-manager");
|
2152
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1877
2153
|
if (permissionChecker2.cannot.publish()) {
|
1878
2154
|
return ctx.forbidden();
|
1879
2155
|
}
|
1880
2156
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1881
|
-
const populate = await getService$
|
1882
|
-
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
|
+
});
|
1883
2161
|
const entityPromises = documentIds.map(
|
1884
2162
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1885
2163
|
);
|
@@ -1901,12 +2179,14 @@ const collectionTypes = {
|
|
1901
2179
|
const { body } = ctx.request;
|
1902
2180
|
const { documentIds } = body;
|
1903
2181
|
await validateBulkActionInput(body);
|
1904
|
-
const documentManager2 = getService$
|
1905
|
-
const permissionChecker2 = getService$
|
2182
|
+
const documentManager2 = getService$2("document-manager");
|
2183
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1906
2184
|
if (permissionChecker2.cannot.unpublish()) {
|
1907
2185
|
return ctx.forbidden();
|
1908
2186
|
}
|
1909
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2187
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2188
|
+
allowMultipleLocales: true
|
2189
|
+
});
|
1910
2190
|
const entityPromises = documentIds.map(
|
1911
2191
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1912
2192
|
);
|
@@ -1929,8 +2209,8 @@ const collectionTypes = {
|
|
1929
2209
|
const {
|
1930
2210
|
body: { discardDraft, ...body }
|
1931
2211
|
} = ctx.request;
|
1932
|
-
const documentManager2 = getService$
|
1933
|
-
const permissionChecker2 = getService$
|
2212
|
+
const documentManager2 = getService$2("document-manager");
|
2213
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1934
2214
|
if (permissionChecker2.cannot.unpublish()) {
|
1935
2215
|
return ctx.forbidden();
|
1936
2216
|
}
|
@@ -1938,8 +2218,8 @@ const collectionTypes = {
|
|
1938
2218
|
return ctx.forbidden();
|
1939
2219
|
}
|
1940
2220
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1941
|
-
const populate = await getService$
|
1942
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2221
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2222
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1943
2223
|
const document = await documentManager2.findOne(id, model, {
|
1944
2224
|
populate,
|
1945
2225
|
locale,
|
@@ -1969,14 +2249,14 @@ const collectionTypes = {
|
|
1969
2249
|
const { userAbility } = ctx.state;
|
1970
2250
|
const { id, model } = ctx.params;
|
1971
2251
|
const { body } = ctx.request;
|
1972
|
-
const documentManager2 = getService$
|
1973
|
-
const permissionChecker2 = getService$
|
2252
|
+
const documentManager2 = getService$2("document-manager");
|
2253
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1974
2254
|
if (permissionChecker2.cannot.discard()) {
|
1975
2255
|
return ctx.forbidden();
|
1976
2256
|
}
|
1977
2257
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1978
|
-
const populate = await getService$
|
1979
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2258
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2259
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1980
2260
|
const document = await documentManager2.findOne(id, model, {
|
1981
2261
|
populate,
|
1982
2262
|
locale,
|
@@ -2000,14 +2280,14 @@ const collectionTypes = {
|
|
2000
2280
|
const { query, body } = ctx.request;
|
2001
2281
|
const { documentIds } = body;
|
2002
2282
|
await validateBulkActionInput(body);
|
2003
|
-
const documentManager2 = getService$
|
2004
|
-
const permissionChecker2 = getService$
|
2283
|
+
const documentManager2 = getService$2("document-manager");
|
2284
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2005
2285
|
if (permissionChecker2.cannot.delete()) {
|
2006
2286
|
return ctx.forbidden();
|
2007
2287
|
}
|
2008
2288
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2009
|
-
const populate = await getService$
|
2010
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2289
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2290
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2011
2291
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2012
2292
|
populate,
|
2013
2293
|
locale
|
@@ -2027,14 +2307,14 @@ const collectionTypes = {
|
|
2027
2307
|
async countDraftRelations(ctx) {
|
2028
2308
|
const { userAbility } = ctx.state;
|
2029
2309
|
const { model, id } = ctx.params;
|
2030
|
-
const documentManager2 = getService$
|
2031
|
-
const permissionChecker2 = getService$
|
2310
|
+
const documentManager2 = getService$2("document-manager");
|
2311
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2032
2312
|
if (permissionChecker2.cannot.read()) {
|
2033
2313
|
return ctx.forbidden();
|
2034
2314
|
}
|
2035
2315
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2036
|
-
const populate = await getService$
|
2037
|
-
const { locale, status
|
2316
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2317
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2038
2318
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2039
2319
|
if (!entity) {
|
2040
2320
|
return ctx.notFound();
|
@@ -2052,8 +2332,8 @@ const collectionTypes = {
|
|
2052
2332
|
const ids = ctx.request.query.documentIds;
|
2053
2333
|
const locale = ctx.request.query.locale;
|
2054
2334
|
const { model } = ctx.params;
|
2055
|
-
const documentManager2 = getService$
|
2056
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2057
2337
|
if (permissionChecker2.cannot.read()) {
|
2058
2338
|
return ctx.forbidden();
|
2059
2339
|
}
|
@@ -2077,13 +2357,13 @@ const collectionTypes = {
|
|
2077
2357
|
};
|
2078
2358
|
const components$1 = {
|
2079
2359
|
findComponents(ctx) {
|
2080
|
-
const components2 = getService$
|
2081
|
-
const { toDto } = getService$
|
2360
|
+
const components2 = getService$2("components").findAllComponents();
|
2361
|
+
const { toDto } = getService$2("data-mapper");
|
2082
2362
|
ctx.body = { data: components2.map(toDto) };
|
2083
2363
|
},
|
2084
2364
|
async findComponentConfiguration(ctx) {
|
2085
2365
|
const { uid: uid2 } = ctx.params;
|
2086
|
-
const componentService = getService$
|
2366
|
+
const componentService = getService$2("components");
|
2087
2367
|
const component = componentService.findComponent(uid2);
|
2088
2368
|
if (!component) {
|
2089
2369
|
return ctx.notFound("component.notFound");
|
@@ -2100,7 +2380,7 @@ const components$1 = {
|
|
2100
2380
|
async updateComponentConfiguration(ctx) {
|
2101
2381
|
const { uid: uid2 } = ctx.params;
|
2102
2382
|
const { body } = ctx.request;
|
2103
|
-
const componentService = getService$
|
2383
|
+
const componentService = getService$2("components");
|
2104
2384
|
const component = componentService.findComponent(uid2);
|
2105
2385
|
if (!component) {
|
2106
2386
|
return ctx.notFound("component.notFound");
|
@@ -2134,12 +2414,12 @@ const contentTypes = {
|
|
2134
2414
|
} catch (error) {
|
2135
2415
|
return ctx.send({ error }, 400);
|
2136
2416
|
}
|
2137
|
-
const contentTypes2 = getService$
|
2138
|
-
const { toDto } = getService$
|
2417
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2418
|
+
const { toDto } = getService$2("data-mapper");
|
2139
2419
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2140
2420
|
},
|
2141
2421
|
async findContentTypesSettings(ctx) {
|
2142
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2422
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2143
2423
|
const contentTypes2 = await findAllContentTypes();
|
2144
2424
|
const configurations = await Promise.all(
|
2145
2425
|
contentTypes2.map(async (contentType) => {
|
@@ -2153,7 +2433,7 @@ const contentTypes = {
|
|
2153
2433
|
},
|
2154
2434
|
async findContentTypeConfiguration(ctx) {
|
2155
2435
|
const { uid: uid2 } = ctx.params;
|
2156
|
-
const contentTypeService = getService$
|
2436
|
+
const contentTypeService = getService$2("content-types");
|
2157
2437
|
const contentType = await contentTypeService.findContentType(uid2);
|
2158
2438
|
if (!contentType) {
|
2159
2439
|
return ctx.notFound("contentType.notFound");
|
@@ -2175,13 +2455,13 @@ const contentTypes = {
|
|
2175
2455
|
const { userAbility } = ctx.state;
|
2176
2456
|
const { uid: uid2 } = ctx.params;
|
2177
2457
|
const { body } = ctx.request;
|
2178
|
-
const contentTypeService = getService$
|
2179
|
-
const metricsService = getService$
|
2458
|
+
const contentTypeService = getService$2("content-types");
|
2459
|
+
const metricsService = getService$2("metrics");
|
2180
2460
|
const contentType = await contentTypeService.findContentType(uid2);
|
2181
2461
|
if (!contentType) {
|
2182
2462
|
return ctx.notFound("contentType.notFound");
|
2183
2463
|
}
|
2184
|
-
if (!getService$
|
2464
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2185
2465
|
return ctx.forbidden();
|
2186
2466
|
}
|
2187
2467
|
let input;
|
@@ -2214,10 +2494,10 @@ const contentTypes = {
|
|
2214
2494
|
};
|
2215
2495
|
const init = {
|
2216
2496
|
getInitData(ctx) {
|
2217
|
-
const { toDto } = getService$
|
2218
|
-
const { findAllComponents } = getService$
|
2219
|
-
const { getAllFieldSizes } = getService$
|
2220
|
-
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");
|
2221
2501
|
ctx.body = {
|
2222
2502
|
data: {
|
2223
2503
|
fieldSizes: getAllFieldSizes(),
|
@@ -2253,36 +2533,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2253
2533
|
params.filters.$and.push(filtersClause);
|
2254
2534
|
};
|
2255
2535
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2256
|
-
const permissionChecker2 = getService$
|
2536
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2257
2537
|
userAbility,
|
2258
2538
|
model: model.uid
|
2259
2539
|
});
|
2260
|
-
|
2540
|
+
const isMainFieldListable = isListable(model, mainField);
|
2541
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2542
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2261
2543
|
return "id";
|
2262
2544
|
}
|
2263
|
-
if (
|
2264
|
-
|
2265
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2266
|
-
userAbility,
|
2267
|
-
model: "plugin::users-permissions.user"
|
2268
|
-
});
|
2269
|
-
if (userPermissionChecker.can.read()) {
|
2270
|
-
return "name";
|
2271
|
-
}
|
2272
|
-
}
|
2273
|
-
return "id";
|
2545
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2546
|
+
return "name";
|
2274
2547
|
}
|
2275
2548
|
return mainField;
|
2276
2549
|
};
|
2277
|
-
const addStatusToRelations = async (
|
2278
|
-
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) {
|
2279
2556
|
return relations2;
|
2280
2557
|
}
|
2281
|
-
const
|
2282
|
-
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
|
+
});
|
2283
2568
|
return relations2.map((relation) => {
|
2284
|
-
const availableStatuses =
|
2285
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2569
|
+
const availableStatuses = availableStatus.filter(
|
2570
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2286
2571
|
);
|
2287
2572
|
return {
|
2288
2573
|
...relation,
|
@@ -2303,11 +2588,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2303
2588
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2304
2589
|
const isSourceLocalized = isLocalized(sourceModel);
|
2305
2590
|
const isTargetLocalized = isLocalized(targetModel);
|
2306
|
-
let validatedLocale = locale;
|
2307
|
-
if (!targetModel || !isTargetLocalized)
|
2308
|
-
validatedLocale = void 0;
|
2309
2591
|
return {
|
2310
|
-
locale
|
2592
|
+
locale,
|
2311
2593
|
isSourceLocalized,
|
2312
2594
|
isTargetLocalized
|
2313
2595
|
};
|
@@ -2316,8 +2598,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2316
2598
|
const sourceModel = strapi.getModel(sourceUid);
|
2317
2599
|
const isDP = contentTypes$1.hasDraftAndPublish;
|
2318
2600
|
const isSourceDP = isDP(sourceModel);
|
2319
|
-
if (!isSourceDP)
|
2320
|
-
return { status: void 0 };
|
2601
|
+
if (!isSourceDP) return { status: void 0 };
|
2321
2602
|
switch (status) {
|
2322
2603
|
case "published":
|
2323
2604
|
return { status: "published" };
|
@@ -2347,7 +2628,7 @@ const relations = {
|
|
2347
2628
|
ctx.request?.query?.locale
|
2348
2629
|
);
|
2349
2630
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2350
|
-
const permissionChecker2 = getService$
|
2631
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2351
2632
|
userAbility,
|
2352
2633
|
model
|
2353
2634
|
});
|
@@ -2372,7 +2653,7 @@ const relations = {
|
|
2372
2653
|
where.id = id;
|
2373
2654
|
}
|
2374
2655
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2375
|
-
const populate = await getService$
|
2656
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2376
2657
|
const currentEntity = await strapi.db.query(model).findOne({
|
2377
2658
|
where,
|
2378
2659
|
populate
|
@@ -2387,7 +2668,7 @@ const relations = {
|
|
2387
2668
|
}
|
2388
2669
|
entryId = currentEntity.id;
|
2389
2670
|
}
|
2390
|
-
const modelConfig = isComponent2 ? await getService$
|
2671
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2391
2672
|
const targetSchema = strapi.getModel(targetUid);
|
2392
2673
|
const mainField = flow(
|
2393
2674
|
prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2410,7 +2691,7 @@ const relations = {
|
|
2410
2691
|
attribute,
|
2411
2692
|
fieldsToSelect,
|
2412
2693
|
mainField,
|
2413
|
-
source: { schema: sourceSchema },
|
2694
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2414
2695
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2415
2696
|
sourceSchema,
|
2416
2697
|
targetSchema,
|
@@ -2432,7 +2713,8 @@ const relations = {
|
|
2432
2713
|
fieldsToSelect,
|
2433
2714
|
mainField,
|
2434
2715
|
source: {
|
2435
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2716
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2717
|
+
isLocalized: isSourceLocalized
|
2436
2718
|
},
|
2437
2719
|
target: {
|
2438
2720
|
schema: { uid: targetUid },
|
@@ -2440,7 +2722,7 @@ const relations = {
|
|
2440
2722
|
}
|
2441
2723
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2442
2724
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2443
|
-
const permissionChecker2 = getService$
|
2725
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2444
2726
|
userAbility: ctx.state.userAbility,
|
2445
2727
|
model: targetUid
|
2446
2728
|
});
|
@@ -2470,12 +2752,16 @@ const relations = {
|
|
2470
2752
|
} else {
|
2471
2753
|
where.id = id;
|
2472
2754
|
}
|
2473
|
-
|
2474
|
-
|
2755
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2756
|
+
if (!isEmpty(publishedAt)) {
|
2757
|
+
where[`${alias}.published_at`] = publishedAt;
|
2475
2758
|
}
|
2476
|
-
if (
|
2759
|
+
if (isTargetLocalized && locale) {
|
2477
2760
|
where[`${alias}.locale`] = locale;
|
2478
2761
|
}
|
2762
|
+
if (isSourceLocalized && locale) {
|
2763
|
+
where.locale = locale;
|
2764
|
+
}
|
2479
2765
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2480
2766
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2481
2767
|
}
|
@@ -2493,7 +2779,8 @@ const relations = {
|
|
2493
2779
|
id: { $notIn: uniq(idsToOmit) }
|
2494
2780
|
});
|
2495
2781
|
}
|
2496
|
-
const
|
2782
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2783
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2497
2784
|
ctx.body = {
|
2498
2785
|
...res,
|
2499
2786
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2508,29 +2795,39 @@ const relations = {
|
|
2508
2795
|
attribute,
|
2509
2796
|
targetField,
|
2510
2797
|
fieldsToSelect,
|
2511
|
-
|
2512
|
-
|
2513
|
-
}
|
2514
|
-
target: {
|
2515
|
-
schema: { uid: targetUid }
|
2516
|
-
}
|
2798
|
+
status,
|
2799
|
+
source: { schema: sourceSchema },
|
2800
|
+
target: { schema: targetSchema }
|
2517
2801
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2518
|
-
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 });
|
2519
2805
|
const dbQuery = strapi.db.query(sourceUid);
|
2520
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
|
+
}
|
2521
2819
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2522
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2820
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2523
2821
|
ordering: "desc",
|
2524
2822
|
page: ctx.request.query.page,
|
2525
|
-
pageSize: ctx.request.query.pageSize
|
2823
|
+
pageSize: ctx.request.query.pageSize,
|
2824
|
+
filters
|
2526
2825
|
});
|
2527
2826
|
const loadedIds = res.results.map((item) => item.id);
|
2528
2827
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2529
2828
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2530
2829
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2531
|
-
ordering: "desc"
|
2532
|
-
page: ctx.request.query.page,
|
2533
|
-
pageSize: ctx.request.query.pageSize
|
2830
|
+
ordering: "desc"
|
2534
2831
|
});
|
2535
2832
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2536
2833
|
ctx.body = {
|
@@ -2545,10 +2842,10 @@ const relations = {
|
|
2545
2842
|
}
|
2546
2843
|
};
|
2547
2844
|
const buildPopulateFromQuery = async (query, model) => {
|
2548
|
-
return getService$
|
2845
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2549
2846
|
};
|
2550
2847
|
const findDocument = async (query, uid2, opts = {}) => {
|
2551
|
-
const documentManager2 = getService$
|
2848
|
+
const documentManager2 = getService$2("document-manager");
|
2552
2849
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2553
2850
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2554
2851
|
};
|
@@ -2556,13 +2853,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2556
2853
|
const { user, userAbility } = ctx.state;
|
2557
2854
|
const { model } = ctx.params;
|
2558
2855
|
const { body, query } = ctx.request;
|
2559
|
-
const documentManager2 = getService$
|
2560
|
-
const permissionChecker2 = getService$
|
2856
|
+
const documentManager2 = getService$2("document-manager");
|
2857
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2561
2858
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2562
2859
|
throw new errors.ForbiddenError();
|
2563
2860
|
}
|
2564
2861
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2565
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2862
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2566
2863
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2567
2864
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2568
2865
|
// Find the first document to check if it exists
|
@@ -2598,12 +2895,12 @@ const singleTypes = {
|
|
2598
2895
|
const { userAbility } = ctx.state;
|
2599
2896
|
const { model } = ctx.params;
|
2600
2897
|
const { query = {} } = ctx.request;
|
2601
|
-
const permissionChecker2 = getService$
|
2898
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2602
2899
|
if (permissionChecker2.cannot.read()) {
|
2603
2900
|
return ctx.forbidden();
|
2604
2901
|
}
|
2605
2902
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2606
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2903
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2607
2904
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2608
2905
|
if (!version) {
|
2609
2906
|
if (permissionChecker2.cannot.create()) {
|
@@ -2617,7 +2914,7 @@ const singleTypes = {
|
|
2617
2914
|
permissionChecker2,
|
2618
2915
|
model,
|
2619
2916
|
// @ts-expect-error - fix types
|
2620
|
-
{
|
2917
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2621
2918
|
{ availableLocales: true, availableStatus: false }
|
2622
2919
|
);
|
2623
2920
|
ctx.body = { data: {}, meta };
|
@@ -2632,7 +2929,7 @@ const singleTypes = {
|
|
2632
2929
|
async createOrUpdate(ctx) {
|
2633
2930
|
const { userAbility } = ctx.state;
|
2634
2931
|
const { model } = ctx.params;
|
2635
|
-
const permissionChecker2 = getService$
|
2932
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2636
2933
|
const document = await createOrUpdateDocument(ctx);
|
2637
2934
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2638
2935
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2641,14 +2938,14 @@ const singleTypes = {
|
|
2641
2938
|
const { userAbility } = ctx.state;
|
2642
2939
|
const { model } = ctx.params;
|
2643
2940
|
const { query = {} } = ctx.request;
|
2644
|
-
const documentManager2 = getService$
|
2645
|
-
const permissionChecker2 = getService$
|
2941
|
+
const documentManager2 = getService$2("document-manager");
|
2942
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2646
2943
|
if (permissionChecker2.cannot.delete()) {
|
2647
2944
|
return ctx.forbidden();
|
2648
2945
|
}
|
2649
2946
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2650
2947
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2651
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2948
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2652
2949
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2653
2950
|
populate,
|
2654
2951
|
locale
|
@@ -2670,8 +2967,8 @@ const singleTypes = {
|
|
2670
2967
|
const { userAbility } = ctx.state;
|
2671
2968
|
const { model } = ctx.params;
|
2672
2969
|
const { query = {} } = ctx.request;
|
2673
|
-
const documentManager2 = getService$
|
2674
|
-
const permissionChecker2 = getService$
|
2970
|
+
const documentManager2 = getService$2("document-manager");
|
2971
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2675
2972
|
if (permissionChecker2.cannot.publish()) {
|
2676
2973
|
return ctx.forbidden();
|
2677
2974
|
}
|
@@ -2685,7 +2982,7 @@ const singleTypes = {
|
|
2685
2982
|
if (permissionChecker2.cannot.publish(document)) {
|
2686
2983
|
throw new errors.ForbiddenError();
|
2687
2984
|
}
|
2688
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2985
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2689
2986
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2690
2987
|
return publishResult.at(0);
|
2691
2988
|
});
|
@@ -2699,8 +2996,8 @@ const singleTypes = {
|
|
2699
2996
|
body: { discardDraft, ...body },
|
2700
2997
|
query = {}
|
2701
2998
|
} = ctx.request;
|
2702
|
-
const documentManager2 = getService$
|
2703
|
-
const permissionChecker2 = getService$
|
2999
|
+
const documentManager2 = getService$2("document-manager");
|
3000
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2704
3001
|
if (permissionChecker2.cannot.unpublish()) {
|
2705
3002
|
return ctx.forbidden();
|
2706
3003
|
}
|
@@ -2708,7 +3005,7 @@ const singleTypes = {
|
|
2708
3005
|
return ctx.forbidden();
|
2709
3006
|
}
|
2710
3007
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2711
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3008
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2712
3009
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2713
3010
|
if (!document) {
|
2714
3011
|
return ctx.notFound();
|
@@ -2734,13 +3031,13 @@ const singleTypes = {
|
|
2734
3031
|
const { userAbility } = ctx.state;
|
2735
3032
|
const { model } = ctx.params;
|
2736
3033
|
const { body, query = {} } = ctx.request;
|
2737
|
-
const documentManager2 = getService$
|
2738
|
-
const permissionChecker2 = getService$
|
3034
|
+
const documentManager2 = getService$2("document-manager");
|
3035
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2739
3036
|
if (permissionChecker2.cannot.discard()) {
|
2740
3037
|
return ctx.forbidden();
|
2741
3038
|
}
|
2742
3039
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2743
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3040
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2744
3041
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2745
3042
|
if (!document) {
|
2746
3043
|
return ctx.notFound();
|
@@ -2758,9 +3055,9 @@ const singleTypes = {
|
|
2758
3055
|
const { userAbility } = ctx.state;
|
2759
3056
|
const { model } = ctx.params;
|
2760
3057
|
const { query } = ctx.request;
|
2761
|
-
const documentManager2 = getService$
|
2762
|
-
const permissionChecker2 = getService$
|
2763
|
-
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);
|
2764
3061
|
if (permissionChecker2.cannot.read()) {
|
2765
3062
|
return ctx.forbidden();
|
2766
3063
|
}
|
@@ -2781,9 +3078,9 @@ const uid$1 = {
|
|
2781
3078
|
async generateUID(ctx) {
|
2782
3079
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2783
3080
|
const { query = {} } = ctx.request;
|
2784
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3081
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2785
3082
|
await validateUIDField(contentTypeUID, field);
|
2786
|
-
const uidService = getService$
|
3083
|
+
const uidService = getService$2("uid");
|
2787
3084
|
ctx.body = {
|
2788
3085
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2789
3086
|
};
|
@@ -2793,9 +3090,9 @@ const uid$1 = {
|
|
2793
3090
|
ctx.request.body
|
2794
3091
|
);
|
2795
3092
|
const { query = {} } = ctx.request;
|
2796
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3093
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2797
3094
|
await validateUIDField(contentTypeUID, field);
|
2798
|
-
const uidService = getService$
|
3095
|
+
const uidService = getService$2("uid");
|
2799
3096
|
const isAvailable = await uidService.checkUIDAvailability({
|
2800
3097
|
contentTypeUID,
|
2801
3098
|
field,
|
@@ -2816,7 +3113,8 @@ const controllers = {
|
|
2816
3113
|
relations,
|
2817
3114
|
"single-types": singleTypes,
|
2818
3115
|
uid: uid$1,
|
2819
|
-
...history.controllers ? history.controllers : {}
|
3116
|
+
...history.controllers ? history.controllers : {},
|
3117
|
+
...preview.controllers ? preview.controllers : {}
|
2820
3118
|
};
|
2821
3119
|
const keys = {
|
2822
3120
|
CONFIGURATION: "configuration"
|
@@ -2945,18 +3243,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2945
3243
|
_.set(updatedMeta, ["list", "searchable"], false);
|
2946
3244
|
_.set(acc, [key], updatedMeta);
|
2947
3245
|
}
|
2948
|
-
if (!_.has(edit, "mainField"))
|
2949
|
-
return acc;
|
3246
|
+
if (!_.has(edit, "mainField")) return acc;
|
2950
3247
|
if (!isRelation$1(attr)) {
|
2951
3248
|
_.set(updatedMeta, "edit", _.omit(edit, ["mainField"]));
|
2952
3249
|
_.set(acc, [key], updatedMeta);
|
2953
3250
|
return acc;
|
2954
3251
|
}
|
2955
|
-
if (edit.mainField === "id")
|
2956
|
-
return acc;
|
3252
|
+
if (edit.mainField === "id") return acc;
|
2957
3253
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2958
|
-
if (!targetSchema)
|
2959
|
-
return acc;
|
3254
|
+
if (!targetSchema) return acc;
|
2960
3255
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2961
3256
|
_.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2962
3257
|
_.set(acc, [key], updatedMeta);
|
@@ -2967,12 +3262,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2967
3262
|
return _.assign(metasWithDefaults, updatedMetas);
|
2968
3263
|
}
|
2969
3264
|
const getTargetSchema = (targetModel) => {
|
2970
|
-
return getService$
|
3265
|
+
return getService$2("content-types").findContentType(targetModel);
|
2971
3266
|
};
|
2972
3267
|
const DEFAULT_LIST_LENGTH = 4;
|
2973
3268
|
const MAX_ROW_SIZE = 12;
|
2974
3269
|
const isAllowedFieldSize = (type, size) => {
|
2975
|
-
const { getFieldSize } = getService$
|
3270
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2976
3271
|
const fieldSize = getFieldSize(type);
|
2977
3272
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2978
3273
|
return false;
|
@@ -2980,7 +3275,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2980
3275
|
return size <= MAX_ROW_SIZE;
|
2981
3276
|
};
|
2982
3277
|
const getDefaultFieldSize = (attribute) => {
|
2983
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3278
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2984
3279
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2985
3280
|
};
|
2986
3281
|
async function createDefaultLayouts(schema) {
|
@@ -3001,8 +3296,7 @@ function createDefaultEditLayout(schema) {
|
|
3001
3296
|
return appendToEditLayout([], keys2, schema);
|
3002
3297
|
}
|
3003
3298
|
function syncLayouts(configuration, schema) {
|
3004
|
-
if (_.isEmpty(configuration.layouts))
|
3005
|
-
return createDefaultLayouts(schema);
|
3299
|
+
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3006
3300
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3007
3301
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3008
3302
|
const cleanEditRelations = editRelations.filter(
|
@@ -3013,9 +3307,8 @@ function syncLayouts(configuration, schema) {
|
|
3013
3307
|
for (const row of edit) {
|
3014
3308
|
const newRow = [];
|
3015
3309
|
for (const el of row) {
|
3016
|
-
if (!hasEditableAttribute(schema, el.name))
|
3017
|
-
|
3018
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3310
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3311
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3019
3312
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3020
3313
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3021
3314
|
elementsToReAppend.push(el.name);
|
@@ -3045,8 +3338,7 @@ function syncLayouts(configuration, schema) {
|
|
3045
3338
|
};
|
3046
3339
|
}
|
3047
3340
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3048
|
-
if (keysToAppend.length === 0)
|
3049
|
-
return layout;
|
3341
|
+
if (keysToAppend.length === 0) return layout;
|
3050
3342
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3051
3343
|
if (!layout[currentRowIndex]) {
|
3052
3344
|
layout[currentRowIndex] = [];
|
@@ -3155,17 +3447,17 @@ const configurationService$1 = createConfigurationService({
|
|
3155
3447
|
isComponent: true,
|
3156
3448
|
prefix: STORE_KEY_PREFIX,
|
3157
3449
|
getModels() {
|
3158
|
-
const { toContentManagerModel } = getService$
|
3450
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3159
3451
|
return mapValues(toContentManagerModel, strapi.components);
|
3160
3452
|
}
|
3161
3453
|
});
|
3162
3454
|
const components = ({ strapi: strapi2 }) => ({
|
3163
3455
|
findAllComponents() {
|
3164
|
-
const { toContentManagerModel } = getService$
|
3456
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3165
3457
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3166
3458
|
},
|
3167
3459
|
findComponent(uid2) {
|
3168
|
-
const { toContentManagerModel } = getService$
|
3460
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3169
3461
|
const component = strapi2.components[uid2];
|
3170
3462
|
return isNil$1(component) ? component : toContentManagerModel(component);
|
3171
3463
|
},
|
@@ -3216,17 +3508,17 @@ const configurationService = createConfigurationService({
|
|
3216
3508
|
storeUtils,
|
3217
3509
|
prefix: "content_types",
|
3218
3510
|
getModels() {
|
3219
|
-
const { toContentManagerModel } = getService$
|
3511
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3220
3512
|
return mapValues(toContentManagerModel, strapi.contentTypes);
|
3221
3513
|
}
|
3222
3514
|
});
|
3223
3515
|
const service = ({ strapi: strapi2 }) => ({
|
3224
3516
|
findAllContentTypes() {
|
3225
|
-
const { toContentManagerModel } = getService$
|
3517
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3226
3518
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3227
3519
|
},
|
3228
3520
|
findContentType(uid2) {
|
3229
|
-
const { toContentManagerModel } = getService$
|
3521
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3230
3522
|
const contentType = strapi2.contentTypes[uid2];
|
3231
3523
|
return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
|
3232
3524
|
},
|
@@ -3255,7 +3547,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3255
3547
|
return this.findConfiguration(contentType);
|
3256
3548
|
},
|
3257
3549
|
findComponentsConfigurations(contentType) {
|
3258
|
-
return getService$
|
3550
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3259
3551
|
},
|
3260
3552
|
syncConfigurations() {
|
3261
3553
|
return configurationService.syncConfigurations();
|
@@ -3436,12 +3728,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3436
3728
|
ability: userAbility,
|
3437
3729
|
model
|
3438
3730
|
});
|
3439
|
-
const
|
3731
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3732
|
+
const toSubject = (entity) => {
|
3733
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3734
|
+
};
|
3440
3735
|
const can = (action, entity, field) => {
|
3441
|
-
|
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
|
+
);
|
3442
3743
|
};
|
3443
3744
|
const cannot = (action, entity, field) => {
|
3444
|
-
|
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
|
+
);
|
3445
3752
|
};
|
3446
3753
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3447
3754
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3512,7 +3819,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3512
3819
|
return userAbility.can(action);
|
3513
3820
|
},
|
3514
3821
|
async registerPermissions() {
|
3515
|
-
const displayedContentTypes = getService$
|
3822
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3516
3823
|
const contentTypesUids = displayedContentTypes.map(prop("uid"));
|
3517
3824
|
const actions = [
|
3518
3825
|
{
|
@@ -3597,6 +3904,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3597
3904
|
if (initialPopulate) {
|
3598
3905
|
return initialPopulate;
|
3599
3906
|
}
|
3907
|
+
if (attributeName === "localizations") {
|
3908
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3909
|
+
return {
|
3910
|
+
populate: validationPopulate.populate
|
3911
|
+
};
|
3912
|
+
}
|
3600
3913
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3601
3914
|
return true;
|
3602
3915
|
}
|
@@ -3656,6 +3969,9 @@ const getDeepPopulate = (uid2, {
|
|
3656
3969
|
return {};
|
3657
3970
|
}
|
3658
3971
|
const model = strapi.getModel(uid2);
|
3972
|
+
if (!model) {
|
3973
|
+
return {};
|
3974
|
+
}
|
3659
3975
|
return Object.keys(model.attributes).reduce(
|
3660
3976
|
(populateAcc, attributeName) => merge(
|
3661
3977
|
populateAcc,
|
@@ -3675,40 +3991,46 @@ const getDeepPopulate = (uid2, {
|
|
3675
3991
|
{}
|
3676
3992
|
);
|
3677
3993
|
};
|
3678
|
-
const
|
3679
|
-
|
3680
|
-
|
3681
|
-
countOne = false,
|
3682
|
-
maxLevel = Infinity
|
3683
|
-
} = {}, level = 1) => {
|
3684
|
-
if (level > maxLevel) {
|
3994
|
+
const getPopulateForValidation = (uid2) => {
|
3995
|
+
const model = strapi.getModel(uid2);
|
3996
|
+
if (!model) {
|
3685
3997
|
return {};
|
3686
3998
|
}
|
3687
|
-
const model = strapi.getModel(uid2);
|
3688
3999
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3689
|
-
if (
|
4000
|
+
if (isScalarAttribute(attribute)) {
|
4001
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4002
|
+
populateAcc.fields = populateAcc.fields || [];
|
4003
|
+
populateAcc.fields.push(attributeName);
|
4004
|
+
}
|
3690
4005
|
return populateAcc;
|
3691
4006
|
}
|
3692
|
-
if (
|
3693
|
-
|
3694
|
-
|
3695
|
-
|
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;
|
3696
4015
|
}
|
3697
|
-
|
3698
|
-
|
3699
|
-
|
3700
|
-
|
3701
|
-
|
3702
|
-
|
3703
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
countOne,
|
3707
|
-
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;
|
3708
4025
|
},
|
3709
|
-
|
3710
|
-
)
|
3711
|
-
|
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;
|
3712
4034
|
}, {});
|
3713
4035
|
};
|
3714
4036
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3718,6 +4040,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3718
4040
|
const attribute = model.attributes[attributeName];
|
3719
4041
|
switch (attribute.type) {
|
3720
4042
|
case "relation": {
|
4043
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4044
|
+
if (isMorphRelation) {
|
4045
|
+
break;
|
4046
|
+
}
|
3721
4047
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3722
4048
|
populateAcc[attributeName] = {
|
3723
4049
|
count: true,
|
@@ -3784,7 +4110,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3784
4110
|
return populateQuery;
|
3785
4111
|
};
|
3786
4112
|
const buildDeepPopulate = (uid2) => {
|
3787
|
-
return getService$
|
4113
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3788
4114
|
};
|
3789
4115
|
const populateBuilder = (uid2) => {
|
3790
4116
|
let getInitialPopulate = async () => {
|
@@ -3946,7 +4272,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3946
4272
|
"locale",
|
3947
4273
|
"updatedAt",
|
3948
4274
|
"createdAt",
|
3949
|
-
"status",
|
3950
4275
|
"publishedAt",
|
3951
4276
|
"documentId"
|
3952
4277
|
];
|
@@ -3967,34 +4292,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3967
4292
|
/**
|
3968
4293
|
* Returns available locales of a document for the current status
|
3969
4294
|
*/
|
3970
|
-
async getAvailableLocales(uid2, version, allVersions
|
4295
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3971
4296
|
const versionsByLocale = groupBy("locale", allVersions);
|
3972
|
-
|
4297
|
+
if (version.locale) {
|
4298
|
+
delete versionsByLocale[version.locale];
|
4299
|
+
}
|
3973
4300
|
const model = strapi2.getModel(uid2);
|
3974
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3975
|
-
const traversalFunction = async (localeVersion) => traverseEntity(
|
3976
|
-
({ key }, { remove }) => {
|
3977
|
-
if (keysToKeep.includes(key)) {
|
3978
|
-
return;
|
3979
|
-
}
|
3980
|
-
remove(key);
|
3981
|
-
},
|
3982
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
3983
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
3984
|
-
localeVersion
|
3985
|
-
);
|
3986
4301
|
const mappingResult = await async.map(
|
3987
4302
|
Object.values(versionsByLocale),
|
3988
4303
|
async (localeVersions) => {
|
3989
|
-
const mappedLocaleVersions = await async.map(
|
3990
|
-
localeVersions,
|
3991
|
-
traversalFunction
|
3992
|
-
);
|
3993
4304
|
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
3994
|
-
return
|
4305
|
+
return localeVersions[0];
|
3995
4306
|
}
|
3996
|
-
const draftVersion =
|
3997
|
-
const otherVersions =
|
4307
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4308
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
3998
4309
|
if (!draftVersion) {
|
3999
4310
|
return;
|
4000
4311
|
}
|
@@ -4016,8 +4327,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4016
4327
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4017
4328
|
return matchLocale && matchStatus;
|
4018
4329
|
});
|
4019
|
-
if (!availableStatus)
|
4020
|
-
return availableStatus;
|
4330
|
+
if (!availableStatus) return availableStatus;
|
4021
4331
|
return pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4022
4332
|
},
|
4023
4333
|
/**
|
@@ -4027,18 +4337,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4027
4337
|
* @returns
|
4028
4338
|
*/
|
4029
4339
|
async getManyAvailableStatus(uid2, documents) {
|
4030
|
-
if (!documents.length)
|
4031
|
-
return [];
|
4340
|
+
if (!documents.length) return [];
|
4032
4341
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4033
|
-
const
|
4034
|
-
const
|
4035
|
-
|
4036
|
-
|
4037
|
-
|
4038
|
-
|
4039
|
-
|
4040
|
-
|
4041
|
-
|
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"]
|
4042
4353
|
});
|
4043
4354
|
},
|
4044
4355
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4055,10 +4366,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4055
4366
|
} else if (otherVersion) {
|
4056
4367
|
draftVersion = otherVersion;
|
4057
4368
|
}
|
4058
|
-
if (!draftVersion)
|
4059
|
-
|
4060
|
-
if (!publishedVersion)
|
4061
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4369
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4370
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4062
4371
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4063
4372
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4064
4373
|
},
|
@@ -4066,11 +4375,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4066
4375
|
// We could refactor this so the locales are only loaded when they're
|
4067
4376
|
// needed. e.g. in the bulk locale action modal.
|
4068
4377
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4069
|
-
const populate =
|
4070
|
-
const
|
4071
|
-
where: { documentId: version.documentId },
|
4378
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4379
|
+
const params = {
|
4072
4380
|
populate: {
|
4073
|
-
// Populate only fields that require validation for bulk locale actions
|
4074
4381
|
...populate,
|
4075
4382
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4076
4383
|
createdBy: {
|
@@ -4079,9 +4386,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4079
4386
|
updatedBy: {
|
4080
4387
|
select: ["id", "firstname", "lastname", "email"]
|
4081
4388
|
}
|
4389
|
+
},
|
4390
|
+
fields: uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4391
|
+
filters: {
|
4392
|
+
documentId: version.documentId
|
4082
4393
|
}
|
4083
|
-
}
|
4084
|
-
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) : [];
|
4085
4398
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4086
4399
|
return {
|
4087
4400
|
availableLocales: availableLocalesResult,
|
@@ -4095,13 +4408,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4095
4408
|
*/
|
4096
4409
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4097
4410
|
if (!document) {
|
4098
|
-
return
|
4411
|
+
return {
|
4412
|
+
data: document,
|
4413
|
+
meta: {
|
4414
|
+
availableLocales: [],
|
4415
|
+
availableStatus: []
|
4416
|
+
}
|
4417
|
+
};
|
4099
4418
|
}
|
4100
4419
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
4101
4420
|
if (!hasDraftAndPublish) {
|
4102
4421
|
opts.availableStatus = false;
|
4103
4422
|
}
|
4104
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
|
+
}
|
4105
4434
|
return {
|
4106
4435
|
data: {
|
4107
4436
|
...document,
|
@@ -4203,10 +4532,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4203
4532
|
async clone(id, body, uid2) {
|
4204
4533
|
const populate = await buildDeepPopulate(uid2);
|
4205
4534
|
const params = {
|
4206
|
-
data:
|
4207
|
-
...omitIdField(body),
|
4208
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4209
|
-
},
|
4535
|
+
data: omitIdField(body),
|
4210
4536
|
populate
|
4211
4537
|
};
|
4212
4538
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4322,7 +4648,8 @@ const services = {
|
|
4322
4648
|
permission,
|
4323
4649
|
"populate-builder": populateBuilder$1,
|
4324
4650
|
uid,
|
4325
|
-
...history.services ? history.services : {}
|
4651
|
+
...history.services ? history.services : {},
|
4652
|
+
...preview.services ? preview.services : {}
|
4326
4653
|
};
|
4327
4654
|
const index = () => {
|
4328
4655
|
return {
|