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