@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.js
CHANGED
@@ -10,8 +10,7 @@ const qs = require("qs");
|
|
10
10
|
const slugify = require("@sindresorhus/slugify");
|
11
11
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
12
12
|
function _interopNamespace(e) {
|
13
|
-
if (e && e.__esModule)
|
14
|
-
return e;
|
13
|
+
if (e && e.__esModule) return e;
|
15
14
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
16
15
|
if (e) {
|
17
16
|
for (const k in e) {
|
@@ -33,10 +32,10 @@ const isNil__default = /* @__PURE__ */ _interopDefault(isNil);
|
|
33
32
|
const ___default = /* @__PURE__ */ _interopDefault(_);
|
34
33
|
const qs__default = /* @__PURE__ */ _interopDefault(qs);
|
35
34
|
const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
|
36
|
-
const getService$
|
35
|
+
const getService$2 = (name) => {
|
37
36
|
return strapi.plugin("content-manager").service(name);
|
38
37
|
};
|
39
|
-
function getService(strapi2, name) {
|
38
|
+
function getService$1(strapi2, name) {
|
40
39
|
return strapi2.service(`plugin::content-manager.${name}`);
|
41
40
|
}
|
42
41
|
const historyRestoreVersionSchema = yup__namespace.object().shape({
|
@@ -72,7 +71,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
72
71
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
73
72
|
throw new strapiUtils.errors.ForbiddenError("contentType and documentId are required");
|
74
73
|
}
|
75
|
-
const permissionChecker2 = getService$
|
74
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
76
75
|
userAbility: ctx.state.userAbility,
|
77
76
|
model: ctx.query.contentType
|
78
77
|
});
|
@@ -80,7 +79,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
80
79
|
return ctx.forbidden();
|
81
80
|
}
|
82
81
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
83
|
-
const { results, pagination } = await getService(strapi2, "history").findVersionsPage({
|
82
|
+
const { results, pagination } = await getService$1(strapi2, "history").findVersionsPage({
|
84
83
|
query: {
|
85
84
|
...query,
|
86
85
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -105,14 +104,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
105
104
|
async restoreVersion(ctx) {
|
106
105
|
const request = ctx.request;
|
107
106
|
await validateRestoreVersion(request.body, "contentType is required");
|
108
|
-
const permissionChecker2 = getService$
|
107
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
109
108
|
userAbility: ctx.state.userAbility,
|
110
109
|
model: request.body.contentType
|
111
110
|
});
|
112
111
|
if (permissionChecker2.cannot.update()) {
|
113
112
|
throw new strapiUtils.errors.ForbiddenError();
|
114
113
|
}
|
115
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
114
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
116
115
|
request.params.versionId
|
117
116
|
);
|
118
117
|
return {
|
@@ -121,7 +120,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
121
120
|
}
|
122
121
|
};
|
123
122
|
};
|
124
|
-
const controllers$
|
123
|
+
const controllers$2 = {
|
125
124
|
"history-version": createHistoryVersionController
|
126
125
|
/**
|
127
126
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -167,8 +166,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
167
166
|
};
|
168
167
|
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
169
168
|
if (Array.isArray(versionRelationData)) {
|
170
|
-
if (versionRelationData.length === 0)
|
171
|
-
return versionRelationData;
|
169
|
+
if (versionRelationData.length === 0) return versionRelationData;
|
172
170
|
const existingAndMissingRelations = await Promise.all(
|
173
171
|
versionRelationData.map((relation) => {
|
174
172
|
return strapi2.documents(attribute.target).findOne({
|
@@ -199,10 +197,11 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
199
197
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
200
198
|
};
|
201
199
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
200
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
202
201
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
202
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
203
203
|
const getLocaleDictionary = async () => {
|
204
|
-
if (!localesService)
|
205
|
-
return {};
|
204
|
+
if (!localesService) return {};
|
206
205
|
const locales = await localesService.find() || [];
|
207
206
|
return locales.reduce(
|
208
207
|
(acc, locale) => {
|
@@ -226,31 +225,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
225
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
226
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
227
|
};
|
229
|
-
const
|
228
|
+
const getComponentFields = (componentUID) => {
|
229
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
230
|
+
(fieldsAcc, [key, attribute]) => {
|
231
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
232
|
+
fieldsAcc.push(key);
|
233
|
+
}
|
234
|
+
return fieldsAcc;
|
235
|
+
},
|
236
|
+
[]
|
237
|
+
);
|
238
|
+
};
|
239
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
240
|
const model = strapi2.getModel(uid2);
|
231
241
|
const attributes = Object.entries(model.attributes);
|
242
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
243
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
244
|
switch (attribute.type) {
|
234
245
|
case "relation": {
|
246
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
247
|
+
if (isMorphRelation) {
|
248
|
+
break;
|
249
|
+
}
|
235
250
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
251
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
252
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
253
|
}
|
239
254
|
break;
|
240
255
|
}
|
241
256
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
257
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
258
|
break;
|
244
259
|
}
|
245
260
|
case "component": {
|
246
261
|
const populate = getDeepPopulate2(attribute.component);
|
247
|
-
acc[attributeName] = {
|
262
|
+
acc[attributeName] = {
|
263
|
+
populate,
|
264
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
265
|
+
};
|
248
266
|
break;
|
249
267
|
}
|
250
268
|
case "dynamiczone": {
|
251
269
|
const populatedComponents = (attribute.components || []).reduce(
|
252
270
|
(acc2, componentUID) => {
|
253
|
-
acc2[componentUID] = {
|
271
|
+
acc2[componentUID] = {
|
272
|
+
populate: getDeepPopulate2(componentUID),
|
273
|
+
[fieldSelector]: getComponentFields(componentUID)
|
274
|
+
};
|
254
275
|
return acc2;
|
255
276
|
},
|
256
277
|
{}
|
@@ -312,6 +333,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
312
333
|
getRelationRestoreValue,
|
313
334
|
getMediaRestoreValue,
|
314
335
|
getDefaultLocale,
|
336
|
+
isLocalizedContentType,
|
315
337
|
getLocaleDictionary,
|
316
338
|
getRetentionDays,
|
317
339
|
getVersionStatus,
|
@@ -334,7 +356,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
356
|
});
|
335
357
|
},
|
336
358
|
async findVersionsPage(params) {
|
337
|
-
const
|
359
|
+
const model = strapi2.getModel(params.query.contentType);
|
360
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
361
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
362
|
+
let locale = null;
|
363
|
+
if (isLocalizedContentType) {
|
364
|
+
locale = params.query.locale || defaultLocale;
|
365
|
+
}
|
338
366
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
339
367
|
query.findPage({
|
340
368
|
...params.query,
|
@@ -356,7 +384,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
356
384
|
const attributeValue = entry.data[attributeKey];
|
357
385
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
358
386
|
if (attributeSchema.type === "media") {
|
359
|
-
const permissionChecker2 = getService$
|
387
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
360
388
|
userAbility: params.state.userAbility,
|
361
389
|
model: "plugin::upload.file"
|
362
390
|
});
|
@@ -379,7 +407,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
379
407
|
if (userToPopulate == null) {
|
380
408
|
return null;
|
381
409
|
}
|
382
|
-
return strapi2.query("admin::user").findOne({
|
410
|
+
return strapi2.query("admin::user").findOne({
|
411
|
+
where: {
|
412
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
413
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
414
|
+
}
|
415
|
+
});
|
383
416
|
})
|
384
417
|
);
|
385
418
|
return {
|
@@ -392,7 +425,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
392
425
|
[attributeKey]: adminUsers
|
393
426
|
};
|
394
427
|
}
|
395
|
-
const permissionChecker2 = getService$
|
428
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
396
429
|
userAbility: params.state.userAbility,
|
397
430
|
model: attributeSchema.target
|
398
431
|
});
|
@@ -490,6 +523,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
523
|
}
|
491
524
|
};
|
492
525
|
};
|
526
|
+
const shouldCreateHistoryVersion = (context) => {
|
527
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
528
|
+
return false;
|
529
|
+
}
|
530
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
531
|
+
return false;
|
532
|
+
}
|
533
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
534
|
+
return false;
|
535
|
+
}
|
536
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
537
|
+
return false;
|
538
|
+
}
|
539
|
+
return true;
|
540
|
+
};
|
541
|
+
const getSchemas = (uid2) => {
|
542
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
543
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
544
|
+
(currentComponentSchemas, key) => {
|
545
|
+
const fieldSchema = attributesSchema[key];
|
546
|
+
if (fieldSchema.type === "component") {
|
547
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
548
|
+
return {
|
549
|
+
...currentComponentSchemas,
|
550
|
+
[fieldSchema.component]: componentSchema
|
551
|
+
};
|
552
|
+
}
|
553
|
+
return currentComponentSchemas;
|
554
|
+
},
|
555
|
+
{}
|
556
|
+
);
|
557
|
+
return {
|
558
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
559
|
+
componentsSchemas
|
560
|
+
};
|
561
|
+
};
|
493
562
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
563
|
const state = {
|
495
564
|
deleteExpiredJob: null,
|
@@ -502,76 +571,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
502
571
|
return;
|
503
572
|
}
|
504
573
|
strapi2.documents.use(async (context, next) => {
|
505
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
506
|
-
return next();
|
507
|
-
}
|
508
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
509
|
-
return next();
|
510
|
-
}
|
511
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
512
|
-
return next();
|
513
|
-
}
|
514
|
-
const contentTypeUid = context.contentType.uid;
|
515
|
-
if (!contentTypeUid.startsWith("api::")) {
|
516
|
-
return next();
|
517
|
-
}
|
518
574
|
const result = await next();
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
575
|
+
if (!shouldCreateHistoryVersion(context)) {
|
576
|
+
return result;
|
577
|
+
}
|
578
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
523
579
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
524
|
-
const
|
525
|
-
if (
|
526
|
-
|
527
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
528
|
-
);
|
529
|
-
return next();
|
580
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
581
|
+
if (!locales.length) {
|
582
|
+
return result;
|
530
583
|
}
|
531
|
-
const
|
532
|
-
|
533
|
-
|
534
|
-
|
584
|
+
const uid2 = context.contentType.uid;
|
585
|
+
const schemas = getSchemas(uid2);
|
586
|
+
const model = strapi2.getModel(uid2);
|
587
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
588
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
589
|
+
where: {
|
590
|
+
documentId,
|
591
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
592
|
+
...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
593
|
+
},
|
594
|
+
populate: serviceUtils.getDeepPopulate(
|
595
|
+
uid2,
|
596
|
+
true
|
597
|
+
/* use database syntax */
|
598
|
+
)
|
535
599
|
});
|
536
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
537
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
538
|
-
const componentsSchemas = Object.keys(
|
539
|
-
attributesSchema
|
540
|
-
).reduce((currentComponentSchemas, key) => {
|
541
|
-
const fieldSchema = attributesSchema[key];
|
542
|
-
if (fieldSchema.type === "component") {
|
543
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
544
|
-
return {
|
545
|
-
...currentComponentSchemas,
|
546
|
-
[fieldSchema.component]: componentSchema
|
547
|
-
};
|
548
|
-
}
|
549
|
-
return currentComponentSchemas;
|
550
|
-
}, {});
|
551
600
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
552
|
-
onCommit(() => {
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
601
|
+
onCommit(async () => {
|
602
|
+
for (const entry of localeEntries) {
|
603
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
604
|
+
await getService$1(strapi2, "history").createVersion({
|
605
|
+
contentType: uid2,
|
606
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
607
|
+
relatedDocumentId: documentId,
|
608
|
+
locale: entry.locale,
|
609
|
+
status,
|
610
|
+
...schemas
|
611
|
+
});
|
612
|
+
}
|
562
613
|
});
|
563
614
|
});
|
564
615
|
return result;
|
565
616
|
});
|
566
|
-
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
617
|
+
state.deleteExpiredJob = nodeSchedule.scheduleJob("historyDaily", "0 0 * * *", () => {
|
567
618
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
568
619
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
569
620
|
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
570
621
|
where: {
|
571
622
|
created_at: {
|
572
|
-
$lt: expirationDate
|
623
|
+
$lt: expirationDate
|
573
624
|
}
|
574
625
|
}
|
626
|
+
}).catch((error) => {
|
627
|
+
if (error instanceof Error) {
|
628
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
629
|
+
}
|
575
630
|
});
|
576
631
|
});
|
577
632
|
state.isInitialized = true;
|
@@ -583,17 +638,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
583
638
|
}
|
584
639
|
};
|
585
640
|
};
|
586
|
-
const services$
|
641
|
+
const services$2 = {
|
587
642
|
history: createHistoryService,
|
588
643
|
lifecycles: createLifecyclesService
|
589
644
|
};
|
590
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
645
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
591
646
|
const historyVersionRouter = {
|
592
647
|
type: "admin",
|
593
648
|
routes: [
|
594
649
|
{
|
595
650
|
method: "GET",
|
596
|
-
info,
|
651
|
+
info: info$1,
|
597
652
|
path: "/history-versions",
|
598
653
|
handler: "history-version.findMany",
|
599
654
|
config: {
|
@@ -602,7 +657,7 @@ const historyVersionRouter = {
|
|
602
657
|
},
|
603
658
|
{
|
604
659
|
method: "PUT",
|
605
|
-
info,
|
660
|
+
info: info$1,
|
606
661
|
path: "/history-versions/:versionId/restore",
|
607
662
|
handler: "history-version.restoreVersion",
|
608
663
|
config: {
|
@@ -611,7 +666,7 @@ const historyVersionRouter = {
|
|
611
666
|
}
|
612
667
|
]
|
613
668
|
};
|
614
|
-
const routes$
|
669
|
+
const routes$2 = {
|
615
670
|
"history-version": historyVersionRouter
|
616
671
|
};
|
617
672
|
const historyVersion = {
|
@@ -658,21 +713,21 @@ const historyVersion = {
|
|
658
713
|
}
|
659
714
|
}
|
660
715
|
};
|
661
|
-
const getFeature = () => {
|
716
|
+
const getFeature$1 = () => {
|
662
717
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
663
718
|
return {
|
664
719
|
register({ strapi: strapi2 }) {
|
665
720
|
strapi2.get("models").add(historyVersion);
|
666
721
|
},
|
667
722
|
bootstrap({ strapi: strapi2 }) {
|
668
|
-
getService(strapi2, "lifecycles").bootstrap();
|
723
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
669
724
|
},
|
670
725
|
destroy({ strapi: strapi2 }) {
|
671
|
-
getService(strapi2, "lifecycles").destroy();
|
726
|
+
getService$1(strapi2, "lifecycles").destroy();
|
672
727
|
},
|
673
|
-
controllers: controllers$
|
674
|
-
services: services$
|
675
|
-
routes: routes$
|
728
|
+
controllers: controllers$2,
|
729
|
+
services: services$2,
|
730
|
+
routes: routes$2
|
676
731
|
};
|
677
732
|
}
|
678
733
|
return {
|
@@ -681,9 +736,201 @@ const getFeature = () => {
|
|
681
736
|
}
|
682
737
|
};
|
683
738
|
};
|
684
|
-
const history = getFeature();
|
739
|
+
const history = getFeature$1();
|
740
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
741
|
+
const previewRouter = {
|
742
|
+
type: "admin",
|
743
|
+
routes: [
|
744
|
+
{
|
745
|
+
method: "GET",
|
746
|
+
info,
|
747
|
+
path: "/preview/url/:contentType",
|
748
|
+
handler: "preview.getPreviewUrl",
|
749
|
+
config: {
|
750
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
751
|
+
}
|
752
|
+
}
|
753
|
+
]
|
754
|
+
};
|
755
|
+
const routes$1 = {
|
756
|
+
preview: previewRouter
|
757
|
+
};
|
758
|
+
function getService(strapi2, name) {
|
759
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
760
|
+
}
|
761
|
+
const getPreviewUrlSchema = yup__namespace.object().shape({
|
762
|
+
// Will be undefined for single types
|
763
|
+
documentId: yup__namespace.string(),
|
764
|
+
locale: yup__namespace.string().nullable(),
|
765
|
+
status: yup__namespace.string()
|
766
|
+
}).required();
|
767
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
768
|
+
await strapiUtils.validateYupSchema(getPreviewUrlSchema)(params);
|
769
|
+
const newParams = fp.pick(["documentId", "locale", "status"], params);
|
770
|
+
const model = strapi2.getModel(uid2);
|
771
|
+
if (!model || model.modelType !== "contentType") {
|
772
|
+
throw new strapiUtils.errors.ValidationError("Invalid content type");
|
773
|
+
}
|
774
|
+
const isSingleType = model?.kind === "singleType";
|
775
|
+
if (!isSingleType && !params.documentId) {
|
776
|
+
throw new strapiUtils.errors.ValidationError("documentId is required for Collection Types");
|
777
|
+
}
|
778
|
+
if (isSingleType) {
|
779
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
780
|
+
if (!doc) {
|
781
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
782
|
+
}
|
783
|
+
newParams.documentId = doc?.documentId;
|
784
|
+
}
|
785
|
+
if (!newParams.status) {
|
786
|
+
const isDPEnabled = model?.options?.draftAndPublish;
|
787
|
+
newParams.status = isDPEnabled ? "draft" : "published";
|
788
|
+
}
|
789
|
+
return newParams;
|
790
|
+
};
|
791
|
+
const createPreviewController = () => {
|
792
|
+
return {
|
793
|
+
/**
|
794
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
795
|
+
* in the Content Manager.
|
796
|
+
*/
|
797
|
+
async getPreviewUrl(ctx) {
|
798
|
+
const uid2 = ctx.params.contentType;
|
799
|
+
const query = ctx.request.query;
|
800
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
801
|
+
const previewService = getService(strapi, "preview");
|
802
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
803
|
+
if (!url) {
|
804
|
+
ctx.status = 204;
|
805
|
+
}
|
806
|
+
return {
|
807
|
+
data: { url }
|
808
|
+
};
|
809
|
+
}
|
810
|
+
};
|
811
|
+
};
|
812
|
+
const controllers$1 = {
|
813
|
+
preview: createPreviewController
|
814
|
+
/**
|
815
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
816
|
+
* passing a controller factory as the value, instead of a controller object directly
|
817
|
+
*/
|
818
|
+
};
|
819
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
820
|
+
const config = getService(strapi2, "preview-config");
|
821
|
+
return {
|
822
|
+
async getPreviewUrl(uid2, params) {
|
823
|
+
const handler = config.getPreviewHandler();
|
824
|
+
try {
|
825
|
+
return handler(uid2, params);
|
826
|
+
} catch (error) {
|
827
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
828
|
+
throw new strapiUtils.errors.ApplicationError("Failed to get preview URL");
|
829
|
+
}
|
830
|
+
return;
|
831
|
+
}
|
832
|
+
};
|
833
|
+
};
|
834
|
+
const extendMiddlewareConfiguration = (middleware = { name: "", config: {} }) => {
|
835
|
+
const middlewares = strapi.config.get("middlewares");
|
836
|
+
const configuredMiddlewares = middlewares.map((currentMiddleware) => {
|
837
|
+
if (currentMiddleware === middleware.name) {
|
838
|
+
return middleware;
|
839
|
+
}
|
840
|
+
if (currentMiddleware.name === middleware.name) {
|
841
|
+
return fp.mergeWith(
|
842
|
+
(objValue, srcValue) => {
|
843
|
+
if (Array.isArray(objValue)) {
|
844
|
+
return objValue.concat(srcValue);
|
845
|
+
}
|
846
|
+
return void 0;
|
847
|
+
},
|
848
|
+
currentMiddleware,
|
849
|
+
middleware
|
850
|
+
);
|
851
|
+
}
|
852
|
+
return currentMiddleware;
|
853
|
+
});
|
854
|
+
strapi.config.set("middlewares", configuredMiddlewares);
|
855
|
+
};
|
856
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
857
|
+
return {
|
858
|
+
register() {
|
859
|
+
if (!this.isEnabled()) {
|
860
|
+
return;
|
861
|
+
}
|
862
|
+
const config = strapi2.config.get("admin.preview");
|
863
|
+
if (config.config?.allowedOrigins) {
|
864
|
+
extendMiddlewareConfiguration({
|
865
|
+
name: "strapi::security",
|
866
|
+
config: {
|
867
|
+
contentSecurityPolicy: {
|
868
|
+
directives: {
|
869
|
+
"frame-src": config.config.allowedOrigins
|
870
|
+
}
|
871
|
+
}
|
872
|
+
}
|
873
|
+
});
|
874
|
+
}
|
875
|
+
},
|
876
|
+
isEnabled() {
|
877
|
+
const config = strapi2.config.get("admin.preview");
|
878
|
+
if (!config) {
|
879
|
+
return false;
|
880
|
+
}
|
881
|
+
return config?.enabled ?? true;
|
882
|
+
},
|
883
|
+
/**
|
884
|
+
* Validate if the configuration is valid
|
885
|
+
*/
|
886
|
+
validate() {
|
887
|
+
if (!this.isEnabled()) {
|
888
|
+
return;
|
889
|
+
}
|
890
|
+
const handler = this.getPreviewHandler();
|
891
|
+
if (typeof handler !== "function") {
|
892
|
+
throw new strapiUtils.errors.ValidationError(
|
893
|
+
"Preview configuration is invalid. Handler must be a function"
|
894
|
+
);
|
895
|
+
}
|
896
|
+
},
|
897
|
+
/**
|
898
|
+
* Utility to get the preview handler from the configuration
|
899
|
+
*/
|
900
|
+
getPreviewHandler() {
|
901
|
+
const config = strapi2.config.get("admin.preview");
|
902
|
+
const emptyHandler = () => {
|
903
|
+
return void 0;
|
904
|
+
};
|
905
|
+
if (!this.isEnabled()) {
|
906
|
+
return emptyHandler;
|
907
|
+
}
|
908
|
+
return config?.config?.handler || emptyHandler;
|
909
|
+
}
|
910
|
+
};
|
911
|
+
};
|
912
|
+
const services$1 = {
|
913
|
+
preview: createPreviewService,
|
914
|
+
"preview-config": createPreviewConfigService
|
915
|
+
};
|
916
|
+
const getFeature = () => {
|
917
|
+
return {
|
918
|
+
register() {
|
919
|
+
const config = getService(strapi, "preview-config");
|
920
|
+
config.validate();
|
921
|
+
config.register();
|
922
|
+
},
|
923
|
+
bootstrap() {
|
924
|
+
},
|
925
|
+
routes: routes$1,
|
926
|
+
controllers: controllers$1,
|
927
|
+
services: services$1
|
928
|
+
};
|
929
|
+
};
|
930
|
+
const preview = getFeature();
|
685
931
|
const register = async ({ strapi: strapi2 }) => {
|
686
932
|
await history.register?.({ strapi: strapi2 });
|
933
|
+
await preview.register?.({ strapi: strapi2 });
|
687
934
|
};
|
688
935
|
const ALLOWED_WEBHOOK_EVENTS = {
|
689
936
|
ENTRY_PUBLISH: "entry.publish",
|
@@ -693,11 +940,12 @@ const bootstrap = async () => {
|
|
693
940
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
694
941
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
695
942
|
});
|
696
|
-
getService$
|
697
|
-
await getService$
|
698
|
-
await getService$
|
699
|
-
await getService$
|
943
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
944
|
+
await getService$2("components").syncConfigurations();
|
945
|
+
await getService$2("content-types").syncConfigurations();
|
946
|
+
await getService$2("permission").registerPermissions();
|
700
947
|
await history.bootstrap?.({ strapi });
|
948
|
+
await preview.bootstrap?.({ strapi });
|
701
949
|
};
|
702
950
|
const destroy = async ({ strapi: strapi2 }) => {
|
703
951
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1187,7 +1435,8 @@ const admin = {
|
|
1187
1435
|
};
|
1188
1436
|
const routes = {
|
1189
1437
|
admin,
|
1190
|
-
...history.routes ? history.routes : {}
|
1438
|
+
...history.routes ? history.routes : {},
|
1439
|
+
...preview.routes ? preview.routes : {}
|
1191
1440
|
};
|
1192
1441
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1193
1442
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1198,6 +1447,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1198
1447
|
const hasPermissions = createPolicy({
|
1199
1448
|
name: "plugin::content-manager.hasPermissions",
|
1200
1449
|
validator: validateHasPermissionsInput,
|
1450
|
+
/**
|
1451
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1452
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1453
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1454
|
+
*/
|
1201
1455
|
handler(ctx, config = {}) {
|
1202
1456
|
const { actions = [], hasAtLeastOne = false } = config;
|
1203
1457
|
const { userAbility } = ctx.state;
|
@@ -1245,8 +1499,7 @@ const isSortable = (schema, name) => {
|
|
1245
1499
|
if (!___default.default.has(schema.attributes, name)) {
|
1246
1500
|
return false;
|
1247
1501
|
}
|
1248
|
-
if (schema.modelType === "component" && name === "id")
|
1249
|
-
return false;
|
1502
|
+
if (schema.modelType === "component" && name === "id") return false;
|
1250
1503
|
const attribute = schema.attributes[name];
|
1251
1504
|
if (NON_SORTABLES.includes(attribute.type)) {
|
1252
1505
|
return false;
|
@@ -1391,8 +1644,7 @@ const createDefaultSettings = async (schema) => {
|
|
1391
1644
|
};
|
1392
1645
|
};
|
1393
1646
|
const syncSettings = async (configuration, schema) => {
|
1394
|
-
if (fp.isEmpty(configuration.settings))
|
1395
|
-
return createDefaultSettings(schema);
|
1647
|
+
if (fp.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
1396
1648
|
const defaultField = getDefaultMainField(schema);
|
1397
1649
|
const { mainField = defaultField, defaultSortBy = defaultField } = configuration.settings || {};
|
1398
1650
|
return {
|
@@ -1439,7 +1691,7 @@ const createMetadasSchema = (schema) => {
|
|
1439
1691
|
if (!value) {
|
1440
1692
|
return strapiUtils.yup.string();
|
1441
1693
|
}
|
1442
|
-
const targetSchema = getService$
|
1694
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1443
1695
|
schema.attributes[key].targetModel
|
1444
1696
|
);
|
1445
1697
|
if (!targetSchema) {
|
@@ -1568,8 +1820,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1568
1820
|
}
|
1569
1821
|
switch (attribute.type) {
|
1570
1822
|
case "relation": {
|
1571
|
-
if (canCreate(attributePath))
|
1572
|
-
return body2;
|
1823
|
+
if (canCreate(attributePath)) return body2;
|
1573
1824
|
return fp.set(attributePath, { set: [] }, body2);
|
1574
1825
|
}
|
1575
1826
|
case "component": {
|
@@ -1579,8 +1830,7 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1579
1830
|
]);
|
1580
1831
|
}
|
1581
1832
|
default: {
|
1582
|
-
if (canCreate(attributePath))
|
1583
|
-
return body2;
|
1833
|
+
if (canCreate(attributePath)) return body2;
|
1584
1834
|
return fp.set(attributePath, null, body2);
|
1585
1835
|
}
|
1586
1836
|
}
|
@@ -1591,9 +1841,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
|
|
1591
1841
|
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1592
1842
|
);
|
1593
1843
|
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1594
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1844
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1595
1845
|
const { allowMultipleLocales } = opts;
|
1596
|
-
const { locale, status, ...rest } = request || {};
|
1846
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1847
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1848
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1597
1849
|
const schema = strapiUtils.yup.object().shape({
|
1598
1850
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1599
1851
|
status: statusSchema
|
@@ -1606,7 +1858,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1606
1858
|
}
|
1607
1859
|
};
|
1608
1860
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1609
|
-
const documentMetadata2 = getService$
|
1861
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1610
1862
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1611
1863
|
let {
|
1612
1864
|
meta: { availableLocales, availableStatus }
|
@@ -1632,8 +1884,8 @@ const createDocument = async (ctx, opts) => {
|
|
1632
1884
|
const { userAbility, user } = ctx.state;
|
1633
1885
|
const { model } = ctx.params;
|
1634
1886
|
const { body } = ctx.request;
|
1635
|
-
const documentManager2 = getService$
|
1636
|
-
const permissionChecker2 = getService$
|
1887
|
+
const documentManager2 = getService$2("document-manager");
|
1888
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1637
1889
|
if (permissionChecker2.cannot.create()) {
|
1638
1890
|
throw new strapiUtils.errors.ForbiddenError();
|
1639
1891
|
}
|
@@ -1641,7 +1893,7 @@ const createDocument = async (ctx, opts) => {
|
|
1641
1893
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1642
1894
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1643
1895
|
const sanitizedBody = await sanitizeFn(body);
|
1644
|
-
const { locale, status
|
1896
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1645
1897
|
return documentManager2.create(model, {
|
1646
1898
|
data: sanitizedBody,
|
1647
1899
|
locale,
|
@@ -1653,14 +1905,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1653
1905
|
const { userAbility, user } = ctx.state;
|
1654
1906
|
const { id, model } = ctx.params;
|
1655
1907
|
const { body } = ctx.request;
|
1656
|
-
const documentManager2 = getService$
|
1657
|
-
const permissionChecker2 = getService$
|
1908
|
+
const documentManager2 = getService$2("document-manager");
|
1909
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1658
1910
|
if (permissionChecker2.cannot.update()) {
|
1659
1911
|
throw new strapiUtils.errors.ForbiddenError();
|
1660
1912
|
}
|
1661
1913
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1662
|
-
const populate = await getService$
|
1663
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1914
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1915
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1664
1916
|
const [documentVersion, documentExists] = await Promise.all([
|
1665
1917
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1666
1918
|
documentManager2.exists(model, id)
|
@@ -1676,7 +1928,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1676
1928
|
throw new strapiUtils.errors.ForbiddenError();
|
1677
1929
|
}
|
1678
1930
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1679
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1931
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1680
1932
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1681
1933
|
const sanitizedBody = await sanitizeFn(body);
|
1682
1934
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1690,15 +1942,15 @@ const collectionTypes = {
|
|
1690
1942
|
const { userAbility } = ctx.state;
|
1691
1943
|
const { model } = ctx.params;
|
1692
1944
|
const { query } = ctx.request;
|
1693
|
-
const documentMetadata2 = getService$
|
1694
|
-
const documentManager2 = getService$
|
1695
|
-
const permissionChecker2 = getService$
|
1945
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1946
|
+
const documentManager2 = getService$2("document-manager");
|
1947
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1696
1948
|
if (permissionChecker2.cannot.read()) {
|
1697
1949
|
return ctx.forbidden();
|
1698
1950
|
}
|
1699
1951
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1700
|
-
const populate = await getService$
|
1701
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1952
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1953
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1702
1954
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1703
1955
|
{ ...permissionQuery, populate, locale, status },
|
1704
1956
|
model
|
@@ -1726,14 +1978,14 @@ const collectionTypes = {
|
|
1726
1978
|
async findOne(ctx) {
|
1727
1979
|
const { userAbility } = ctx.state;
|
1728
1980
|
const { model, id } = ctx.params;
|
1729
|
-
const documentManager2 = getService$
|
1730
|
-
const permissionChecker2 = getService$
|
1981
|
+
const documentManager2 = getService$2("document-manager");
|
1982
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1731
1983
|
if (permissionChecker2.cannot.read()) {
|
1732
1984
|
return ctx.forbidden();
|
1733
1985
|
}
|
1734
1986
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1735
|
-
const populate = await getService$
|
1736
|
-
const { locale, status
|
1987
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1988
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1737
1989
|
const version = await documentManager2.findOne(id, model, {
|
1738
1990
|
populate,
|
1739
1991
|
locale,
|
@@ -1748,7 +2000,7 @@ const collectionTypes = {
|
|
1748
2000
|
permissionChecker2,
|
1749
2001
|
model,
|
1750
2002
|
// @ts-expect-error TODO: fix
|
1751
|
-
{ id, locale, publishedAt: null },
|
2003
|
+
{ documentId: id, locale, publishedAt: null },
|
1752
2004
|
{ availableLocales: true, availableStatus: false }
|
1753
2005
|
);
|
1754
2006
|
ctx.body = { data: {}, meta };
|
@@ -1763,7 +2015,7 @@ const collectionTypes = {
|
|
1763
2015
|
async create(ctx) {
|
1764
2016
|
const { userAbility } = ctx.state;
|
1765
2017
|
const { model } = ctx.params;
|
1766
|
-
const permissionChecker2 = getService$
|
2018
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1767
2019
|
const [totalEntries, document] = await Promise.all([
|
1768
2020
|
strapi.db.query(model).count(),
|
1769
2021
|
createDocument(ctx)
|
@@ -1784,7 +2036,7 @@ const collectionTypes = {
|
|
1784
2036
|
async update(ctx) {
|
1785
2037
|
const { userAbility } = ctx.state;
|
1786
2038
|
const { model } = ctx.params;
|
1787
|
-
const permissionChecker2 = getService$
|
2039
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1788
2040
|
const updatedVersion = await updateDocument(ctx);
|
1789
2041
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1790
2042
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1793,14 +2045,14 @@ const collectionTypes = {
|
|
1793
2045
|
const { userAbility, user } = ctx.state;
|
1794
2046
|
const { model, sourceId: id } = ctx.params;
|
1795
2047
|
const { body } = ctx.request;
|
1796
|
-
const documentManager2 = getService$
|
1797
|
-
const permissionChecker2 = getService$
|
2048
|
+
const documentManager2 = getService$2("document-manager");
|
2049
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1798
2050
|
if (permissionChecker2.cannot.create()) {
|
1799
2051
|
return ctx.forbidden();
|
1800
2052
|
}
|
1801
2053
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1802
|
-
const populate = await getService$
|
1803
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2054
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2055
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1804
2056
|
const document = await documentManager2.findOne(id, model, {
|
1805
2057
|
populate,
|
1806
2058
|
locale,
|
@@ -1838,14 +2090,14 @@ const collectionTypes = {
|
|
1838
2090
|
async delete(ctx) {
|
1839
2091
|
const { userAbility } = ctx.state;
|
1840
2092
|
const { id, model } = ctx.params;
|
1841
|
-
const documentManager2 = getService$
|
1842
|
-
const permissionChecker2 = getService$
|
2093
|
+
const documentManager2 = getService$2("document-manager");
|
2094
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1843
2095
|
if (permissionChecker2.cannot.delete()) {
|
1844
2096
|
return ctx.forbidden();
|
1845
2097
|
}
|
1846
2098
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1847
|
-
const populate = await getService$
|
1848
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
2099
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2100
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1849
2101
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1850
2102
|
if (documentLocales.length === 0) {
|
1851
2103
|
return ctx.notFound();
|
@@ -1866,19 +2118,42 @@ const collectionTypes = {
|
|
1866
2118
|
const { userAbility } = ctx.state;
|
1867
2119
|
const { id, model } = ctx.params;
|
1868
2120
|
const { body } = ctx.request;
|
1869
|
-
const documentManager2 = getService$
|
1870
|
-
const permissionChecker2 = getService$
|
2121
|
+
const documentManager2 = getService$2("document-manager");
|
2122
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1871
2123
|
if (permissionChecker2.cannot.publish()) {
|
1872
2124
|
return ctx.forbidden();
|
1873
2125
|
}
|
1874
2126
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1875
2127
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1876
|
-
const populate = await getService$
|
1877
|
-
|
2128
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2129
|
+
let document;
|
2130
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2131
|
+
const isCreate = fp.isNil(id);
|
2132
|
+
if (isCreate) {
|
2133
|
+
if (permissionChecker2.cannot.create()) {
|
2134
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2135
|
+
}
|
2136
|
+
document = await createDocument(ctx, { populate });
|
2137
|
+
}
|
2138
|
+
const isUpdate = !isCreate;
|
2139
|
+
if (isUpdate) {
|
2140
|
+
const documentExists = documentManager2.exists(model, id);
|
2141
|
+
if (!documentExists) {
|
2142
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
2143
|
+
}
|
2144
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2145
|
+
if (!document) {
|
2146
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2147
|
+
throw new strapiUtils.errors.ForbiddenError();
|
2148
|
+
}
|
2149
|
+
document = await updateDocument(ctx);
|
2150
|
+
} else if (permissionChecker2.can.update(document)) {
|
2151
|
+
await updateDocument(ctx);
|
2152
|
+
}
|
2153
|
+
}
|
1878
2154
|
if (permissionChecker2.cannot.publish(document)) {
|
1879
2155
|
throw new strapiUtils.errors.ForbiddenError();
|
1880
2156
|
}
|
1881
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1882
2157
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1883
2158
|
locale
|
1884
2159
|
// TODO: Allow setting creator fields on publish
|
@@ -1898,14 +2173,16 @@ const collectionTypes = {
|
|
1898
2173
|
const { body } = ctx.request;
|
1899
2174
|
const { documentIds } = body;
|
1900
2175
|
await validateBulkActionInput(body);
|
1901
|
-
const documentManager2 = getService$
|
1902
|
-
const permissionChecker2 = getService$
|
2176
|
+
const documentManager2 = getService$2("document-manager");
|
2177
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1903
2178
|
if (permissionChecker2.cannot.publish()) {
|
1904
2179
|
return ctx.forbidden();
|
1905
2180
|
}
|
1906
2181
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1907
|
-
const populate = await getService$
|
1908
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
2182
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2183
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2184
|
+
allowMultipleLocales: true
|
2185
|
+
});
|
1909
2186
|
const entityPromises = documentIds.map(
|
1910
2187
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1911
2188
|
);
|
@@ -1927,12 +2204,14 @@ const collectionTypes = {
|
|
1927
2204
|
const { body } = ctx.request;
|
1928
2205
|
const { documentIds } = body;
|
1929
2206
|
await validateBulkActionInput(body);
|
1930
|
-
const documentManager2 = getService$
|
1931
|
-
const permissionChecker2 = getService$
|
2207
|
+
const documentManager2 = getService$2("document-manager");
|
2208
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1932
2209
|
if (permissionChecker2.cannot.unpublish()) {
|
1933
2210
|
return ctx.forbidden();
|
1934
2211
|
}
|
1935
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2212
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2213
|
+
allowMultipleLocales: true
|
2214
|
+
});
|
1936
2215
|
const entityPromises = documentIds.map(
|
1937
2216
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1938
2217
|
);
|
@@ -1955,8 +2234,8 @@ const collectionTypes = {
|
|
1955
2234
|
const {
|
1956
2235
|
body: { discardDraft, ...body }
|
1957
2236
|
} = ctx.request;
|
1958
|
-
const documentManager2 = getService$
|
1959
|
-
const permissionChecker2 = getService$
|
2237
|
+
const documentManager2 = getService$2("document-manager");
|
2238
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1960
2239
|
if (permissionChecker2.cannot.unpublish()) {
|
1961
2240
|
return ctx.forbidden();
|
1962
2241
|
}
|
@@ -1964,8 +2243,8 @@ const collectionTypes = {
|
|
1964
2243
|
return ctx.forbidden();
|
1965
2244
|
}
|
1966
2245
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1967
|
-
const populate = await getService$
|
1968
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2246
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2247
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1969
2248
|
const document = await documentManager2.findOne(id, model, {
|
1970
2249
|
populate,
|
1971
2250
|
locale,
|
@@ -1995,14 +2274,14 @@ const collectionTypes = {
|
|
1995
2274
|
const { userAbility } = ctx.state;
|
1996
2275
|
const { id, model } = ctx.params;
|
1997
2276
|
const { body } = ctx.request;
|
1998
|
-
const documentManager2 = getService$
|
1999
|
-
const permissionChecker2 = getService$
|
2277
|
+
const documentManager2 = getService$2("document-manager");
|
2278
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2000
2279
|
if (permissionChecker2.cannot.discard()) {
|
2001
2280
|
return ctx.forbidden();
|
2002
2281
|
}
|
2003
2282
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2004
|
-
const populate = await getService$
|
2005
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2283
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2284
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2006
2285
|
const document = await documentManager2.findOne(id, model, {
|
2007
2286
|
populate,
|
2008
2287
|
locale,
|
@@ -2026,14 +2305,14 @@ const collectionTypes = {
|
|
2026
2305
|
const { query, body } = ctx.request;
|
2027
2306
|
const { documentIds } = body;
|
2028
2307
|
await validateBulkActionInput(body);
|
2029
|
-
const documentManager2 = getService$
|
2030
|
-
const permissionChecker2 = getService$
|
2308
|
+
const documentManager2 = getService$2("document-manager");
|
2309
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2031
2310
|
if (permissionChecker2.cannot.delete()) {
|
2032
2311
|
return ctx.forbidden();
|
2033
2312
|
}
|
2034
2313
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2035
|
-
const populate = await getService$
|
2036
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2314
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2315
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2037
2316
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2038
2317
|
populate,
|
2039
2318
|
locale
|
@@ -2053,14 +2332,14 @@ const collectionTypes = {
|
|
2053
2332
|
async countDraftRelations(ctx) {
|
2054
2333
|
const { userAbility } = ctx.state;
|
2055
2334
|
const { model, id } = ctx.params;
|
2056
|
-
const documentManager2 = getService$
|
2057
|
-
const permissionChecker2 = getService$
|
2335
|
+
const documentManager2 = getService$2("document-manager");
|
2336
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2058
2337
|
if (permissionChecker2.cannot.read()) {
|
2059
2338
|
return ctx.forbidden();
|
2060
2339
|
}
|
2061
2340
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2062
|
-
const populate = await getService$
|
2063
|
-
const { locale, status
|
2341
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2342
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2064
2343
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2065
2344
|
if (!entity) {
|
2066
2345
|
return ctx.notFound();
|
@@ -2078,8 +2357,8 @@ const collectionTypes = {
|
|
2078
2357
|
const ids = ctx.request.query.documentIds;
|
2079
2358
|
const locale = ctx.request.query.locale;
|
2080
2359
|
const { model } = ctx.params;
|
2081
|
-
const documentManager2 = getService$
|
2082
|
-
const permissionChecker2 = getService$
|
2360
|
+
const documentManager2 = getService$2("document-manager");
|
2361
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2083
2362
|
if (permissionChecker2.cannot.read()) {
|
2084
2363
|
return ctx.forbidden();
|
2085
2364
|
}
|
@@ -2103,13 +2382,13 @@ const collectionTypes = {
|
|
2103
2382
|
};
|
2104
2383
|
const components$1 = {
|
2105
2384
|
findComponents(ctx) {
|
2106
|
-
const components2 = getService$
|
2107
|
-
const { toDto } = getService$
|
2385
|
+
const components2 = getService$2("components").findAllComponents();
|
2386
|
+
const { toDto } = getService$2("data-mapper");
|
2108
2387
|
ctx.body = { data: components2.map(toDto) };
|
2109
2388
|
},
|
2110
2389
|
async findComponentConfiguration(ctx) {
|
2111
2390
|
const { uid: uid2 } = ctx.params;
|
2112
|
-
const componentService = getService$
|
2391
|
+
const componentService = getService$2("components");
|
2113
2392
|
const component = componentService.findComponent(uid2);
|
2114
2393
|
if (!component) {
|
2115
2394
|
return ctx.notFound("component.notFound");
|
@@ -2126,7 +2405,7 @@ const components$1 = {
|
|
2126
2405
|
async updateComponentConfiguration(ctx) {
|
2127
2406
|
const { uid: uid2 } = ctx.params;
|
2128
2407
|
const { body } = ctx.request;
|
2129
|
-
const componentService = getService$
|
2408
|
+
const componentService = getService$2("components");
|
2130
2409
|
const component = componentService.findComponent(uid2);
|
2131
2410
|
if (!component) {
|
2132
2411
|
return ctx.notFound("component.notFound");
|
@@ -2160,12 +2439,12 @@ const contentTypes = {
|
|
2160
2439
|
} catch (error) {
|
2161
2440
|
return ctx.send({ error }, 400);
|
2162
2441
|
}
|
2163
|
-
const contentTypes2 = getService$
|
2164
|
-
const { toDto } = getService$
|
2442
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2443
|
+
const { toDto } = getService$2("data-mapper");
|
2165
2444
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2166
2445
|
},
|
2167
2446
|
async findContentTypesSettings(ctx) {
|
2168
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2447
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2169
2448
|
const contentTypes2 = await findAllContentTypes();
|
2170
2449
|
const configurations = await Promise.all(
|
2171
2450
|
contentTypes2.map(async (contentType) => {
|
@@ -2179,7 +2458,7 @@ const contentTypes = {
|
|
2179
2458
|
},
|
2180
2459
|
async findContentTypeConfiguration(ctx) {
|
2181
2460
|
const { uid: uid2 } = ctx.params;
|
2182
|
-
const contentTypeService = getService$
|
2461
|
+
const contentTypeService = getService$2("content-types");
|
2183
2462
|
const contentType = await contentTypeService.findContentType(uid2);
|
2184
2463
|
if (!contentType) {
|
2185
2464
|
return ctx.notFound("contentType.notFound");
|
@@ -2201,13 +2480,13 @@ const contentTypes = {
|
|
2201
2480
|
const { userAbility } = ctx.state;
|
2202
2481
|
const { uid: uid2 } = ctx.params;
|
2203
2482
|
const { body } = ctx.request;
|
2204
|
-
const contentTypeService = getService$
|
2205
|
-
const metricsService = getService$
|
2483
|
+
const contentTypeService = getService$2("content-types");
|
2484
|
+
const metricsService = getService$2("metrics");
|
2206
2485
|
const contentType = await contentTypeService.findContentType(uid2);
|
2207
2486
|
if (!contentType) {
|
2208
2487
|
return ctx.notFound("contentType.notFound");
|
2209
2488
|
}
|
2210
|
-
if (!getService$
|
2489
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2211
2490
|
return ctx.forbidden();
|
2212
2491
|
}
|
2213
2492
|
let input;
|
@@ -2240,10 +2519,10 @@ const contentTypes = {
|
|
2240
2519
|
};
|
2241
2520
|
const init = {
|
2242
2521
|
getInitData(ctx) {
|
2243
|
-
const { toDto } = getService$
|
2244
|
-
const { findAllComponents } = getService$
|
2245
|
-
const { getAllFieldSizes } = getService$
|
2246
|
-
const { findAllContentTypes } = getService$
|
2522
|
+
const { toDto } = getService$2("data-mapper");
|
2523
|
+
const { findAllComponents } = getService$2("components");
|
2524
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2525
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2247
2526
|
ctx.body = {
|
2248
2527
|
data: {
|
2249
2528
|
fieldSizes: getAllFieldSizes(),
|
@@ -2279,36 +2558,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2279
2558
|
params.filters.$and.push(filtersClause);
|
2280
2559
|
};
|
2281
2560
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2282
|
-
const permissionChecker2 = getService$
|
2561
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2283
2562
|
userAbility,
|
2284
2563
|
model: model.uid
|
2285
2564
|
});
|
2286
|
-
|
2565
|
+
const isMainFieldListable = isListable(model, mainField);
|
2566
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2567
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2287
2568
|
return "id";
|
2288
2569
|
}
|
2289
|
-
if (
|
2290
|
-
|
2291
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2292
|
-
userAbility,
|
2293
|
-
model: "plugin::users-permissions.user"
|
2294
|
-
});
|
2295
|
-
if (userPermissionChecker.can.read()) {
|
2296
|
-
return "name";
|
2297
|
-
}
|
2298
|
-
}
|
2299
|
-
return "id";
|
2570
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2571
|
+
return "name";
|
2300
2572
|
}
|
2301
2573
|
return mainField;
|
2302
2574
|
};
|
2303
|
-
const addStatusToRelations = async (
|
2304
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2575
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2576
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2577
|
+
return relations2;
|
2578
|
+
}
|
2579
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2580
|
+
if (!relations2.length) {
|
2305
2581
|
return relations2;
|
2306
2582
|
}
|
2307
|
-
const
|
2308
|
-
const
|
2583
|
+
const firstRelation = relations2[0];
|
2584
|
+
const filters = {
|
2585
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2586
|
+
// NOTE: find the "opposite" status
|
2587
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2588
|
+
};
|
2589
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2590
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2591
|
+
filters
|
2592
|
+
});
|
2309
2593
|
return relations2.map((relation) => {
|
2310
|
-
const availableStatuses =
|
2311
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2594
|
+
const availableStatuses = availableStatus.filter(
|
2595
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2312
2596
|
);
|
2313
2597
|
return {
|
2314
2598
|
...relation,
|
@@ -2329,11 +2613,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2329
2613
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2330
2614
|
const isSourceLocalized = isLocalized(sourceModel);
|
2331
2615
|
const isTargetLocalized = isLocalized(targetModel);
|
2332
|
-
let validatedLocale = locale;
|
2333
|
-
if (!targetModel || !isTargetLocalized)
|
2334
|
-
validatedLocale = void 0;
|
2335
2616
|
return {
|
2336
|
-
locale
|
2617
|
+
locale,
|
2337
2618
|
isSourceLocalized,
|
2338
2619
|
isTargetLocalized
|
2339
2620
|
};
|
@@ -2342,8 +2623,7 @@ const validateStatus = (sourceUid, status) => {
|
|
2342
2623
|
const sourceModel = strapi.getModel(sourceUid);
|
2343
2624
|
const isDP = strapiUtils.contentTypes.hasDraftAndPublish;
|
2344
2625
|
const isSourceDP = isDP(sourceModel);
|
2345
|
-
if (!isSourceDP)
|
2346
|
-
return { status: void 0 };
|
2626
|
+
if (!isSourceDP) return { status: void 0 };
|
2347
2627
|
switch (status) {
|
2348
2628
|
case "published":
|
2349
2629
|
return { status: "published" };
|
@@ -2373,7 +2653,7 @@ const relations = {
|
|
2373
2653
|
ctx.request?.query?.locale
|
2374
2654
|
);
|
2375
2655
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2376
|
-
const permissionChecker2 = getService$
|
2656
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2377
2657
|
userAbility,
|
2378
2658
|
model
|
2379
2659
|
});
|
@@ -2398,7 +2678,7 @@ const relations = {
|
|
2398
2678
|
where.id = id;
|
2399
2679
|
}
|
2400
2680
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2401
|
-
const populate = await getService$
|
2681
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2402
2682
|
const currentEntity = await strapi.db.query(model).findOne({
|
2403
2683
|
where,
|
2404
2684
|
populate
|
@@ -2413,7 +2693,7 @@ const relations = {
|
|
2413
2693
|
}
|
2414
2694
|
entryId = currentEntity.id;
|
2415
2695
|
}
|
2416
|
-
const modelConfig = isComponent2 ? await getService$
|
2696
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2417
2697
|
const targetSchema = strapi.getModel(targetUid);
|
2418
2698
|
const mainField = fp.flow(
|
2419
2699
|
fp.prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2436,7 +2716,7 @@ const relations = {
|
|
2436
2716
|
attribute,
|
2437
2717
|
fieldsToSelect,
|
2438
2718
|
mainField,
|
2439
|
-
source: { schema: sourceSchema },
|
2719
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2440
2720
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2441
2721
|
sourceSchema,
|
2442
2722
|
targetSchema,
|
@@ -2458,7 +2738,8 @@ const relations = {
|
|
2458
2738
|
fieldsToSelect,
|
2459
2739
|
mainField,
|
2460
2740
|
source: {
|
2461
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2741
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2742
|
+
isLocalized: isSourceLocalized
|
2462
2743
|
},
|
2463
2744
|
target: {
|
2464
2745
|
schema: { uid: targetUid },
|
@@ -2466,7 +2747,7 @@ const relations = {
|
|
2466
2747
|
}
|
2467
2748
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2468
2749
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2469
|
-
const permissionChecker2 = getService$
|
2750
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2470
2751
|
userAbility: ctx.state.userAbility,
|
2471
2752
|
model: targetUid
|
2472
2753
|
});
|
@@ -2496,12 +2777,16 @@ const relations = {
|
|
2496
2777
|
} else {
|
2497
2778
|
where.id = id;
|
2498
2779
|
}
|
2499
|
-
|
2500
|
-
|
2780
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2781
|
+
if (!fp.isEmpty(publishedAt)) {
|
2782
|
+
where[`${alias}.published_at`] = publishedAt;
|
2501
2783
|
}
|
2502
|
-
if (
|
2784
|
+
if (isTargetLocalized && locale) {
|
2503
2785
|
where[`${alias}.locale`] = locale;
|
2504
2786
|
}
|
2787
|
+
if (isSourceLocalized && locale) {
|
2788
|
+
where.locale = locale;
|
2789
|
+
}
|
2505
2790
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2506
2791
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2507
2792
|
}
|
@@ -2519,7 +2804,8 @@ const relations = {
|
|
2519
2804
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2520
2805
|
});
|
2521
2806
|
}
|
2522
|
-
const
|
2807
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2808
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2523
2809
|
ctx.body = {
|
2524
2810
|
...res,
|
2525
2811
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2534,29 +2820,39 @@ const relations = {
|
|
2534
2820
|
attribute,
|
2535
2821
|
targetField,
|
2536
2822
|
fieldsToSelect,
|
2537
|
-
|
2538
|
-
|
2539
|
-
}
|
2540
|
-
target: {
|
2541
|
-
schema: { uid: targetUid }
|
2542
|
-
}
|
2823
|
+
status,
|
2824
|
+
source: { schema: sourceSchema },
|
2825
|
+
target: { schema: targetSchema }
|
2543
2826
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2544
|
-
const
|
2827
|
+
const { uid: sourceUid } = sourceSchema;
|
2828
|
+
const { uid: targetUid } = targetSchema;
|
2829
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2545
2830
|
const dbQuery = strapi.db.query(sourceUid);
|
2546
2831
|
const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2832
|
+
const filters = {};
|
2833
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2834
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2835
|
+
if (status === "published") {
|
2836
|
+
filters.publishedAt = { $notNull: true };
|
2837
|
+
} else {
|
2838
|
+
filters.publishedAt = { $null: true };
|
2839
|
+
}
|
2840
|
+
}
|
2841
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2842
|
+
filters.publishedAt = { $null: true };
|
2843
|
+
}
|
2547
2844
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2548
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2845
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2549
2846
|
ordering: "desc",
|
2550
2847
|
page: ctx.request.query.page,
|
2551
|
-
pageSize: ctx.request.query.pageSize
|
2848
|
+
pageSize: ctx.request.query.pageSize,
|
2849
|
+
filters
|
2552
2850
|
});
|
2553
2851
|
const loadedIds = res.results.map((item) => item.id);
|
2554
2852
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2555
2853
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2556
2854
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2557
|
-
ordering: "desc"
|
2558
|
-
page: ctx.request.query.page,
|
2559
|
-
pageSize: ctx.request.query.pageSize
|
2855
|
+
ordering: "desc"
|
2560
2856
|
});
|
2561
2857
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2562
2858
|
ctx.body = {
|
@@ -2571,10 +2867,10 @@ const relations = {
|
|
2571
2867
|
}
|
2572
2868
|
};
|
2573
2869
|
const buildPopulateFromQuery = async (query, model) => {
|
2574
|
-
return getService$
|
2870
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2575
2871
|
};
|
2576
2872
|
const findDocument = async (query, uid2, opts = {}) => {
|
2577
|
-
const documentManager2 = getService$
|
2873
|
+
const documentManager2 = getService$2("document-manager");
|
2578
2874
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2579
2875
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2580
2876
|
};
|
@@ -2582,13 +2878,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2582
2878
|
const { user, userAbility } = ctx.state;
|
2583
2879
|
const { model } = ctx.params;
|
2584
2880
|
const { body, query } = ctx.request;
|
2585
|
-
const documentManager2 = getService$
|
2586
|
-
const permissionChecker2 = getService$
|
2881
|
+
const documentManager2 = getService$2("document-manager");
|
2882
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2587
2883
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2588
2884
|
throw new strapiUtils.errors.ForbiddenError();
|
2589
2885
|
}
|
2590
2886
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2591
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2887
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2592
2888
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2593
2889
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2594
2890
|
// Find the first document to check if it exists
|
@@ -2624,12 +2920,12 @@ const singleTypes = {
|
|
2624
2920
|
const { userAbility } = ctx.state;
|
2625
2921
|
const { model } = ctx.params;
|
2626
2922
|
const { query = {} } = ctx.request;
|
2627
|
-
const permissionChecker2 = getService$
|
2923
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2628
2924
|
if (permissionChecker2.cannot.read()) {
|
2629
2925
|
return ctx.forbidden();
|
2630
2926
|
}
|
2631
2927
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2632
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2928
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2633
2929
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2634
2930
|
if (!version) {
|
2635
2931
|
if (permissionChecker2.cannot.create()) {
|
@@ -2643,7 +2939,7 @@ const singleTypes = {
|
|
2643
2939
|
permissionChecker2,
|
2644
2940
|
model,
|
2645
2941
|
// @ts-expect-error - fix types
|
2646
|
-
{
|
2942
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2647
2943
|
{ availableLocales: true, availableStatus: false }
|
2648
2944
|
);
|
2649
2945
|
ctx.body = { data: {}, meta };
|
@@ -2658,7 +2954,7 @@ const singleTypes = {
|
|
2658
2954
|
async createOrUpdate(ctx) {
|
2659
2955
|
const { userAbility } = ctx.state;
|
2660
2956
|
const { model } = ctx.params;
|
2661
|
-
const permissionChecker2 = getService$
|
2957
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2662
2958
|
const document = await createOrUpdateDocument(ctx);
|
2663
2959
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2664
2960
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2667,14 +2963,14 @@ const singleTypes = {
|
|
2667
2963
|
const { userAbility } = ctx.state;
|
2668
2964
|
const { model } = ctx.params;
|
2669
2965
|
const { query = {} } = ctx.request;
|
2670
|
-
const documentManager2 = getService$
|
2671
|
-
const permissionChecker2 = getService$
|
2966
|
+
const documentManager2 = getService$2("document-manager");
|
2967
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2672
2968
|
if (permissionChecker2.cannot.delete()) {
|
2673
2969
|
return ctx.forbidden();
|
2674
2970
|
}
|
2675
2971
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2676
2972
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2677
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2973
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2678
2974
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2679
2975
|
populate,
|
2680
2976
|
locale
|
@@ -2696,8 +2992,8 @@ const singleTypes = {
|
|
2696
2992
|
const { userAbility } = ctx.state;
|
2697
2993
|
const { model } = ctx.params;
|
2698
2994
|
const { query = {} } = ctx.request;
|
2699
|
-
const documentManager2 = getService$
|
2700
|
-
const permissionChecker2 = getService$
|
2995
|
+
const documentManager2 = getService$2("document-manager");
|
2996
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2701
2997
|
if (permissionChecker2.cannot.publish()) {
|
2702
2998
|
return ctx.forbidden();
|
2703
2999
|
}
|
@@ -2711,7 +3007,7 @@ const singleTypes = {
|
|
2711
3007
|
if (permissionChecker2.cannot.publish(document)) {
|
2712
3008
|
throw new strapiUtils.errors.ForbiddenError();
|
2713
3009
|
}
|
2714
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
3010
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2715
3011
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2716
3012
|
return publishResult.at(0);
|
2717
3013
|
});
|
@@ -2725,8 +3021,8 @@ const singleTypes = {
|
|
2725
3021
|
body: { discardDraft, ...body },
|
2726
3022
|
query = {}
|
2727
3023
|
} = ctx.request;
|
2728
|
-
const documentManager2 = getService$
|
2729
|
-
const permissionChecker2 = getService$
|
3024
|
+
const documentManager2 = getService$2("document-manager");
|
3025
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2730
3026
|
if (permissionChecker2.cannot.unpublish()) {
|
2731
3027
|
return ctx.forbidden();
|
2732
3028
|
}
|
@@ -2734,7 +3030,7 @@ const singleTypes = {
|
|
2734
3030
|
return ctx.forbidden();
|
2735
3031
|
}
|
2736
3032
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2737
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3033
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2738
3034
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2739
3035
|
if (!document) {
|
2740
3036
|
return ctx.notFound();
|
@@ -2760,13 +3056,13 @@ const singleTypes = {
|
|
2760
3056
|
const { userAbility } = ctx.state;
|
2761
3057
|
const { model } = ctx.params;
|
2762
3058
|
const { body, query = {} } = ctx.request;
|
2763
|
-
const documentManager2 = getService$
|
2764
|
-
const permissionChecker2 = getService$
|
3059
|
+
const documentManager2 = getService$2("document-manager");
|
3060
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2765
3061
|
if (permissionChecker2.cannot.discard()) {
|
2766
3062
|
return ctx.forbidden();
|
2767
3063
|
}
|
2768
3064
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2769
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3065
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2770
3066
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2771
3067
|
if (!document) {
|
2772
3068
|
return ctx.notFound();
|
@@ -2784,9 +3080,9 @@ const singleTypes = {
|
|
2784
3080
|
const { userAbility } = ctx.state;
|
2785
3081
|
const { model } = ctx.params;
|
2786
3082
|
const { query } = ctx.request;
|
2787
|
-
const documentManager2 = getService$
|
2788
|
-
const permissionChecker2 = getService$
|
2789
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3083
|
+
const documentManager2 = getService$2("document-manager");
|
3084
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3085
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2790
3086
|
if (permissionChecker2.cannot.read()) {
|
2791
3087
|
return ctx.forbidden();
|
2792
3088
|
}
|
@@ -2807,9 +3103,9 @@ const uid$1 = {
|
|
2807
3103
|
async generateUID(ctx) {
|
2808
3104
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2809
3105
|
const { query = {} } = ctx.request;
|
2810
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3106
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2811
3107
|
await validateUIDField(contentTypeUID, field);
|
2812
|
-
const uidService = getService$
|
3108
|
+
const uidService = getService$2("uid");
|
2813
3109
|
ctx.body = {
|
2814
3110
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2815
3111
|
};
|
@@ -2819,9 +3115,9 @@ const uid$1 = {
|
|
2819
3115
|
ctx.request.body
|
2820
3116
|
);
|
2821
3117
|
const { query = {} } = ctx.request;
|
2822
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3118
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2823
3119
|
await validateUIDField(contentTypeUID, field);
|
2824
|
-
const uidService = getService$
|
3120
|
+
const uidService = getService$2("uid");
|
2825
3121
|
const isAvailable = await uidService.checkUIDAvailability({
|
2826
3122
|
contentTypeUID,
|
2827
3123
|
field,
|
@@ -2842,7 +3138,8 @@ const controllers = {
|
|
2842
3138
|
relations,
|
2843
3139
|
"single-types": singleTypes,
|
2844
3140
|
uid: uid$1,
|
2845
|
-
...history.controllers ? history.controllers : {}
|
3141
|
+
...history.controllers ? history.controllers : {},
|
3142
|
+
...preview.controllers ? preview.controllers : {}
|
2846
3143
|
};
|
2847
3144
|
const keys = {
|
2848
3145
|
CONFIGURATION: "configuration"
|
@@ -2971,18 +3268,15 @@ async function syncMetadatas(configuration, schema) {
|
|
2971
3268
|
___default.default.set(updatedMeta, ["list", "searchable"], false);
|
2972
3269
|
___default.default.set(acc, [key], updatedMeta);
|
2973
3270
|
}
|
2974
|
-
if (!___default.default.has(edit, "mainField"))
|
2975
|
-
return acc;
|
3271
|
+
if (!___default.default.has(edit, "mainField")) return acc;
|
2976
3272
|
if (!isRelation$1(attr)) {
|
2977
3273
|
___default.default.set(updatedMeta, "edit", ___default.default.omit(edit, ["mainField"]));
|
2978
3274
|
___default.default.set(acc, [key], updatedMeta);
|
2979
3275
|
return acc;
|
2980
3276
|
}
|
2981
|
-
if (edit.mainField === "id")
|
2982
|
-
return acc;
|
3277
|
+
if (edit.mainField === "id") return acc;
|
2983
3278
|
const targetSchema = getTargetSchema(attr.targetModel);
|
2984
|
-
if (!targetSchema)
|
2985
|
-
return acc;
|
3279
|
+
if (!targetSchema) return acc;
|
2986
3280
|
if (!isSortable(targetSchema, edit.mainField) && !isListable(targetSchema, edit.mainField)) {
|
2987
3281
|
___default.default.set(updatedMeta, ["edit", "mainField"], getDefaultMainField(targetSchema));
|
2988
3282
|
___default.default.set(acc, [key], updatedMeta);
|
@@ -2993,12 +3287,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2993
3287
|
return ___default.default.assign(metasWithDefaults, updatedMetas);
|
2994
3288
|
}
|
2995
3289
|
const getTargetSchema = (targetModel) => {
|
2996
|
-
return getService$
|
3290
|
+
return getService$2("content-types").findContentType(targetModel);
|
2997
3291
|
};
|
2998
3292
|
const DEFAULT_LIST_LENGTH = 4;
|
2999
3293
|
const MAX_ROW_SIZE = 12;
|
3000
3294
|
const isAllowedFieldSize = (type, size) => {
|
3001
|
-
const { getFieldSize } = getService$
|
3295
|
+
const { getFieldSize } = getService$2("field-sizes");
|
3002
3296
|
const fieldSize = getFieldSize(type);
|
3003
3297
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
3004
3298
|
return false;
|
@@ -3006,7 +3300,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
3006
3300
|
return size <= MAX_ROW_SIZE;
|
3007
3301
|
};
|
3008
3302
|
const getDefaultFieldSize = (attribute) => {
|
3009
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3303
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
3010
3304
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
3011
3305
|
};
|
3012
3306
|
async function createDefaultLayouts(schema) {
|
@@ -3027,8 +3321,7 @@ function createDefaultEditLayout(schema) {
|
|
3027
3321
|
return appendToEditLayout([], keys2, schema);
|
3028
3322
|
}
|
3029
3323
|
function syncLayouts(configuration, schema) {
|
3030
|
-
if (___default.default.isEmpty(configuration.layouts))
|
3031
|
-
return createDefaultLayouts(schema);
|
3324
|
+
if (___default.default.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
3032
3325
|
const { list = [], editRelations = [], edit = [] } = configuration.layouts || {};
|
3033
3326
|
let cleanList = list.filter((attr) => isListable(schema, attr));
|
3034
3327
|
const cleanEditRelations = editRelations.filter(
|
@@ -3039,9 +3332,8 @@ function syncLayouts(configuration, schema) {
|
|
3039
3332
|
for (const row of edit) {
|
3040
3333
|
const newRow = [];
|
3041
3334
|
for (const el of row) {
|
3042
|
-
if (!hasEditableAttribute(schema, el.name))
|
3043
|
-
|
3044
|
-
const { hasFieldSize } = getService$1("field-sizes");
|
3335
|
+
if (!hasEditableAttribute(schema, el.name)) continue;
|
3336
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3045
3337
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3046
3338
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3047
3339
|
elementsToReAppend.push(el.name);
|
@@ -3071,8 +3363,7 @@ function syncLayouts(configuration, schema) {
|
|
3071
3363
|
};
|
3072
3364
|
}
|
3073
3365
|
const appendToEditLayout = (layout = [], keysToAppend, schema) => {
|
3074
|
-
if (keysToAppend.length === 0)
|
3075
|
-
return layout;
|
3366
|
+
if (keysToAppend.length === 0) return layout;
|
3076
3367
|
let currentRowIndex = Math.max(layout.length - 1, 0);
|
3077
3368
|
if (!layout[currentRowIndex]) {
|
3078
3369
|
layout[currentRowIndex] = [];
|
@@ -3181,17 +3472,17 @@ const configurationService$1 = createConfigurationService({
|
|
3181
3472
|
isComponent: true,
|
3182
3473
|
prefix: STORE_KEY_PREFIX,
|
3183
3474
|
getModels() {
|
3184
|
-
const { toContentManagerModel } = getService$
|
3475
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3185
3476
|
return fp.mapValues(toContentManagerModel, strapi.components);
|
3186
3477
|
}
|
3187
3478
|
});
|
3188
3479
|
const components = ({ strapi: strapi2 }) => ({
|
3189
3480
|
findAllComponents() {
|
3190
|
-
const { toContentManagerModel } = getService$
|
3481
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3191
3482
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3192
3483
|
},
|
3193
3484
|
findComponent(uid2) {
|
3194
|
-
const { toContentManagerModel } = getService$
|
3485
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3195
3486
|
const component = strapi2.components[uid2];
|
3196
3487
|
return fp.isNil(component) ? component : toContentManagerModel(component);
|
3197
3488
|
},
|
@@ -3242,17 +3533,17 @@ const configurationService = createConfigurationService({
|
|
3242
3533
|
storeUtils,
|
3243
3534
|
prefix: "content_types",
|
3244
3535
|
getModels() {
|
3245
|
-
const { toContentManagerModel } = getService$
|
3536
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3246
3537
|
return fp.mapValues(toContentManagerModel, strapi.contentTypes);
|
3247
3538
|
}
|
3248
3539
|
});
|
3249
3540
|
const service = ({ strapi: strapi2 }) => ({
|
3250
3541
|
findAllContentTypes() {
|
3251
|
-
const { toContentManagerModel } = getService$
|
3542
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3252
3543
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3253
3544
|
},
|
3254
3545
|
findContentType(uid2) {
|
3255
|
-
const { toContentManagerModel } = getService$
|
3546
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3256
3547
|
const contentType = strapi2.contentTypes[uid2];
|
3257
3548
|
return fp.isNil(contentType) ? contentType : toContentManagerModel(contentType);
|
3258
3549
|
},
|
@@ -3281,7 +3572,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3281
3572
|
return this.findConfiguration(contentType);
|
3282
3573
|
},
|
3283
3574
|
findComponentsConfigurations(contentType) {
|
3284
|
-
return getService$
|
3575
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3285
3576
|
},
|
3286
3577
|
syncConfigurations() {
|
3287
3578
|
return configurationService.syncConfigurations();
|
@@ -3462,12 +3753,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3462
3753
|
ability: userAbility,
|
3463
3754
|
model
|
3464
3755
|
});
|
3465
|
-
const
|
3756
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3757
|
+
const toSubject = (entity) => {
|
3758
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3759
|
+
};
|
3466
3760
|
const can = (action, entity, field) => {
|
3467
|
-
|
3761
|
+
const subject = toSubject(entity);
|
3762
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3763
|
+
return (
|
3764
|
+
// Test the original action to see if it passes
|
3765
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3766
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3767
|
+
);
|
3468
3768
|
};
|
3469
3769
|
const cannot = (action, entity, field) => {
|
3470
|
-
|
3770
|
+
const subject = toSubject(entity);
|
3771
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3772
|
+
return (
|
3773
|
+
// Test both the original action
|
3774
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3775
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3776
|
+
);
|
3471
3777
|
};
|
3472
3778
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3473
3779
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3538,7 +3844,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3538
3844
|
return userAbility.can(action);
|
3539
3845
|
},
|
3540
3846
|
async registerPermissions() {
|
3541
|
-
const displayedContentTypes = getService$
|
3847
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3542
3848
|
const contentTypesUids = displayedContentTypes.map(fp.prop("uid"));
|
3543
3849
|
const actions = [
|
3544
3850
|
{
|
@@ -3623,6 +3929,12 @@ function getPopulateForRelation(attribute, model, attributeName, { countMany, co
|
|
3623
3929
|
if (initialPopulate) {
|
3624
3930
|
return initialPopulate;
|
3625
3931
|
}
|
3932
|
+
if (attributeName === "localizations") {
|
3933
|
+
const validationPopulate = getPopulateForValidation(model.uid);
|
3934
|
+
return {
|
3935
|
+
populate: validationPopulate.populate
|
3936
|
+
};
|
3937
|
+
}
|
3626
3938
|
if (!isVisibleAttribute$1(model, attributeName)) {
|
3627
3939
|
return true;
|
3628
3940
|
}
|
@@ -3682,6 +3994,9 @@ const getDeepPopulate = (uid2, {
|
|
3682
3994
|
return {};
|
3683
3995
|
}
|
3684
3996
|
const model = strapi.getModel(uid2);
|
3997
|
+
if (!model) {
|
3998
|
+
return {};
|
3999
|
+
}
|
3685
4000
|
return Object.keys(model.attributes).reduce(
|
3686
4001
|
(populateAcc, attributeName) => fp.merge(
|
3687
4002
|
populateAcc,
|
@@ -3701,40 +4016,46 @@ const getDeepPopulate = (uid2, {
|
|
3701
4016
|
{}
|
3702
4017
|
);
|
3703
4018
|
};
|
3704
|
-
const
|
3705
|
-
|
3706
|
-
|
3707
|
-
countOne = false,
|
3708
|
-
maxLevel = Infinity
|
3709
|
-
} = {}, level = 1) => {
|
3710
|
-
if (level > maxLevel) {
|
4019
|
+
const getPopulateForValidation = (uid2) => {
|
4020
|
+
const model = strapi.getModel(uid2);
|
4021
|
+
if (!model) {
|
3711
4022
|
return {};
|
3712
4023
|
}
|
3713
|
-
const model = strapi.getModel(uid2);
|
3714
4024
|
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3715
|
-
if (
|
4025
|
+
if (isScalarAttribute(attribute)) {
|
4026
|
+
if (getDoesAttributeRequireValidation(attribute)) {
|
4027
|
+
populateAcc.fields = populateAcc.fields || [];
|
4028
|
+
populateAcc.fields.push(attributeName);
|
4029
|
+
}
|
3716
4030
|
return populateAcc;
|
3717
4031
|
}
|
3718
|
-
if (
|
3719
|
-
|
3720
|
-
|
3721
|
-
|
4032
|
+
if (isComponent(attribute)) {
|
4033
|
+
const component = attribute.component;
|
4034
|
+
const componentResult = getPopulateForValidation(component);
|
4035
|
+
if (Object.keys(componentResult).length > 0) {
|
4036
|
+
populateAcc.populate = populateAcc.populate || {};
|
4037
|
+
populateAcc.populate[attributeName] = componentResult;
|
4038
|
+
}
|
4039
|
+
return populateAcc;
|
3722
4040
|
}
|
3723
|
-
|
3724
|
-
|
3725
|
-
|
3726
|
-
|
3727
|
-
|
3728
|
-
|
3729
|
-
|
3730
|
-
|
3731
|
-
|
3732
|
-
countOne,
|
3733
|
-
maxLevel
|
4041
|
+
if (isDynamicZone(attribute)) {
|
4042
|
+
const components2 = attribute.components;
|
4043
|
+
const componentsResult = (components2 || []).reduce(
|
4044
|
+
(acc, componentUID) => {
|
4045
|
+
const componentResult = getPopulateForValidation(componentUID);
|
4046
|
+
if (Object.keys(componentResult).length > 0) {
|
4047
|
+
acc[componentUID] = componentResult;
|
4048
|
+
}
|
4049
|
+
return acc;
|
3734
4050
|
},
|
3735
|
-
|
3736
|
-
)
|
3737
|
-
|
4051
|
+
{}
|
4052
|
+
);
|
4053
|
+
if (Object.keys(componentsResult).length > 0) {
|
4054
|
+
populateAcc.populate = populateAcc.populate || {};
|
4055
|
+
populateAcc.populate[attributeName] = { on: componentsResult };
|
4056
|
+
}
|
4057
|
+
}
|
4058
|
+
return populateAcc;
|
3738
4059
|
}, {});
|
3739
4060
|
};
|
3740
4061
|
const getDeepPopulateDraftCount = (uid2) => {
|
@@ -3744,6 +4065,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3744
4065
|
const attribute = model.attributes[attributeName];
|
3745
4066
|
switch (attribute.type) {
|
3746
4067
|
case "relation": {
|
4068
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
4069
|
+
if (isMorphRelation) {
|
4070
|
+
break;
|
4071
|
+
}
|
3747
4072
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3748
4073
|
populateAcc[attributeName] = {
|
3749
4074
|
count: true,
|
@@ -3810,7 +4135,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3810
4135
|
return populateQuery;
|
3811
4136
|
};
|
3812
4137
|
const buildDeepPopulate = (uid2) => {
|
3813
|
-
return getService$
|
4138
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3814
4139
|
};
|
3815
4140
|
const populateBuilder = (uid2) => {
|
3816
4141
|
let getInitialPopulate = async () => {
|
@@ -3972,7 +4297,6 @@ const AVAILABLE_LOCALES_FIELDS = [
|
|
3972
4297
|
"locale",
|
3973
4298
|
"updatedAt",
|
3974
4299
|
"createdAt",
|
3975
|
-
"status",
|
3976
4300
|
"publishedAt",
|
3977
4301
|
"documentId"
|
3978
4302
|
];
|
@@ -3993,34 +4317,20 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3993
4317
|
/**
|
3994
4318
|
* Returns available locales of a document for the current status
|
3995
4319
|
*/
|
3996
|
-
async getAvailableLocales(uid2, version, allVersions
|
4320
|
+
async getAvailableLocales(uid2, version, allVersions) {
|
3997
4321
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3998
|
-
|
4322
|
+
if (version.locale) {
|
4323
|
+
delete versionsByLocale[version.locale];
|
4324
|
+
}
|
3999
4325
|
const model = strapi2.getModel(uid2);
|
4000
|
-
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4001
|
-
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
4002
|
-
({ key }, { remove }) => {
|
4003
|
-
if (keysToKeep.includes(key)) {
|
4004
|
-
return;
|
4005
|
-
}
|
4006
|
-
remove(key);
|
4007
|
-
},
|
4008
|
-
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
4009
|
-
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
4010
|
-
localeVersion
|
4011
|
-
);
|
4012
4326
|
const mappingResult = await strapiUtils.async.map(
|
4013
4327
|
Object.values(versionsByLocale),
|
4014
4328
|
async (localeVersions) => {
|
4015
|
-
const mappedLocaleVersions = await strapiUtils.async.map(
|
4016
|
-
localeVersions,
|
4017
|
-
traversalFunction
|
4018
|
-
);
|
4019
4329
|
if (!strapiUtils.contentTypes.hasDraftAndPublish(model)) {
|
4020
|
-
return
|
4330
|
+
return localeVersions[0];
|
4021
4331
|
}
|
4022
|
-
const draftVersion =
|
4023
|
-
const otherVersions =
|
4332
|
+
const draftVersion = localeVersions.find((v) => v.publishedAt === null);
|
4333
|
+
const otherVersions = localeVersions.filter((v) => v.id !== draftVersion?.id);
|
4024
4334
|
if (!draftVersion) {
|
4025
4335
|
return;
|
4026
4336
|
}
|
@@ -4042,8 +4352,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4042
4352
|
const matchStatus = status === "published" ? v.publishedAt !== null : v.publishedAt === null;
|
4043
4353
|
return matchLocale && matchStatus;
|
4044
4354
|
});
|
4045
|
-
if (!availableStatus)
|
4046
|
-
return availableStatus;
|
4355
|
+
if (!availableStatus) return availableStatus;
|
4047
4356
|
return fp.pick(AVAILABLE_STATUS_FIELDS, availableStatus);
|
4048
4357
|
},
|
4049
4358
|
/**
|
@@ -4053,18 +4362,19 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4053
4362
|
* @returns
|
4054
4363
|
*/
|
4055
4364
|
async getManyAvailableStatus(uid2, documents) {
|
4056
|
-
if (!documents.length)
|
4057
|
-
return [];
|
4365
|
+
if (!documents.length) return [];
|
4058
4366
|
const status = documents[0].publishedAt !== null ? "published" : "draft";
|
4059
|
-
const
|
4060
|
-
const
|
4061
|
-
|
4062
|
-
|
4063
|
-
|
4064
|
-
|
4065
|
-
|
4066
|
-
|
4067
|
-
|
4367
|
+
const locales = documents.map((d) => d.locale).filter(Boolean);
|
4368
|
+
const where = {
|
4369
|
+
documentId: { $in: documents.map((d) => d.documentId).filter(Boolean) },
|
4370
|
+
publishedAt: { $null: status === "published" }
|
4371
|
+
};
|
4372
|
+
if (locales.length) {
|
4373
|
+
where.locale = { $in: locales };
|
4374
|
+
}
|
4375
|
+
return strapi2.query(uid2).findMany({
|
4376
|
+
where,
|
4377
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"]
|
4068
4378
|
});
|
4069
4379
|
},
|
4070
4380
|
getStatus(version, otherDocumentStatuses) {
|
@@ -4081,10 +4391,8 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4081
4391
|
} else if (otherVersion) {
|
4082
4392
|
draftVersion = otherVersion;
|
4083
4393
|
}
|
4084
|
-
if (!draftVersion)
|
4085
|
-
|
4086
|
-
if (!publishedVersion)
|
4087
|
-
return CONTENT_MANAGER_STATUS.DRAFT;
|
4394
|
+
if (!draftVersion) return CONTENT_MANAGER_STATUS.PUBLISHED;
|
4395
|
+
if (!publishedVersion) return CONTENT_MANAGER_STATUS.DRAFT;
|
4088
4396
|
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4089
4397
|
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
4090
4398
|
},
|
@@ -4092,11 +4400,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4092
4400
|
// We could refactor this so the locales are only loaded when they're
|
4093
4401
|
// needed. e.g. in the bulk locale action modal.
|
4094
4402
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4095
|
-
const populate =
|
4096
|
-
const
|
4097
|
-
where: { documentId: version.documentId },
|
4403
|
+
const { populate = {}, fields = [] } = getPopulateForValidation(uid2);
|
4404
|
+
const params = {
|
4098
4405
|
populate: {
|
4099
|
-
// Populate only fields that require validation for bulk locale actions
|
4100
4406
|
...populate,
|
4101
4407
|
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
4102
4408
|
createdBy: {
|
@@ -4105,9 +4411,15 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4105
4411
|
updatedBy: {
|
4106
4412
|
select: ["id", "firstname", "lastname", "email"]
|
4107
4413
|
}
|
4414
|
+
},
|
4415
|
+
fields: fp.uniq([...AVAILABLE_LOCALES_FIELDS, ...fields]),
|
4416
|
+
filters: {
|
4417
|
+
documentId: version.documentId
|
4108
4418
|
}
|
4109
|
-
}
|
4110
|
-
const
|
4419
|
+
};
|
4420
|
+
const dbParams = strapi2.get("query-params").transform(uid2, params);
|
4421
|
+
const versions = await strapi2.db.query(uid2).findMany(dbParams);
|
4422
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions) : [];
|
4111
4423
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
4112
4424
|
return {
|
4113
4425
|
availableLocales: availableLocalesResult,
|
@@ -4121,13 +4433,29 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4121
4433
|
*/
|
4122
4434
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4123
4435
|
if (!document) {
|
4124
|
-
return
|
4436
|
+
return {
|
4437
|
+
data: document,
|
4438
|
+
meta: {
|
4439
|
+
availableLocales: [],
|
4440
|
+
availableStatus: []
|
4441
|
+
}
|
4442
|
+
};
|
4125
4443
|
}
|
4126
4444
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4127
4445
|
if (!hasDraftAndPublish) {
|
4128
4446
|
opts.availableStatus = false;
|
4129
4447
|
}
|
4130
4448
|
const meta = await this.getMetadata(uid2, document, opts);
|
4449
|
+
if (document.localizations) {
|
4450
|
+
const otherStatus = await this.getManyAvailableStatus(uid2, document.localizations);
|
4451
|
+
document.localizations = document.localizations.map((d) => {
|
4452
|
+
const status = otherStatus.find((s) => s.documentId === d.documentId);
|
4453
|
+
return {
|
4454
|
+
...d,
|
4455
|
+
status: this.getStatus(d, status ? [status] : [])
|
4456
|
+
};
|
4457
|
+
});
|
4458
|
+
}
|
4131
4459
|
return {
|
4132
4460
|
data: {
|
4133
4461
|
...document,
|
@@ -4229,10 +4557,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4229
4557
|
async clone(id, body, uid2) {
|
4230
4558
|
const populate = await buildDeepPopulate(uid2);
|
4231
4559
|
const params = {
|
4232
|
-
data:
|
4233
|
-
...omitIdField(body),
|
4234
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4235
|
-
},
|
4560
|
+
data: omitIdField(body),
|
4236
4561
|
populate
|
4237
4562
|
};
|
4238
4563
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4348,7 +4673,8 @@ const services = {
|
|
4348
4673
|
permission,
|
4349
4674
|
"populate-builder": populateBuilder$1,
|
4350
4675
|
uid,
|
4351
|
-
...history.services ? history.services : {}
|
4676
|
+
...history.services ? history.services : {},
|
4677
|
+
...preview.services ? preview.services : {}
|
4352
4678
|
};
|
4353
4679
|
const index = () => {
|
4354
4680
|
return {
|