@strapi/content-manager 0.0.0-experimental.826f263c58b6886b849d3f03b81f7a530bc51c91 → 0.0.0-experimental.8e52d29d243dccc7c24beb53412cf1c9c0b36d11
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/{ComponentConfigurationPage-DJcn1DrO.js → ComponentConfigurationPage--MCP7Aew.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js.map → ComponentConfigurationPage--MCP7Aew.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs → ComponentConfigurationPage-DT41asyM.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs.map → ComponentConfigurationPage-DT41asyM.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs → EditConfigurationPage-DznPxn9p.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs.map → EditConfigurationPage-DznPxn9p.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js → EditConfigurationPage-qgnNvv_u.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js.map → EditConfigurationPage-qgnNvv_u.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DvaV7U9b.mjs → EditViewPage-B_k7z288.mjs} +72 -50
- package/dist/_chunks/EditViewPage-B_k7z288.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CoQEnFlC.js → EditViewPage-Bb4S7p8c.js} +70 -48
- package/dist/_chunks/EditViewPage-Bb4S7p8c.js.map +1 -0
- package/dist/_chunks/{Field-ZdrmmQ4Y.js → Field-ByR1mllE.js} +582 -230
- package/dist/_chunks/Field-ByR1mllE.js.map +1 -0
- package/dist/_chunks/{Field-Cz_J9551.mjs → Field-DmwbE0TL.mjs} +580 -228
- package/dist/_chunks/Field-DmwbE0TL.mjs.map +1 -0
- package/dist/_chunks/{Form-Bpig5rch.js → Form-BpeyAyS1.js} +52 -34
- package/dist/_chunks/Form-BpeyAyS1.js.map +1 -0
- package/dist/_chunks/{Form-Dxmihyw8.mjs → Form-Dvt5eouJ.mjs} +54 -36
- package/dist/_chunks/Form-Dvt5eouJ.mjs.map +1 -0
- package/dist/_chunks/{History-BZP8n7KT.mjs → History-CAERKpYl.mjs} +171 -77
- package/dist/_chunks/History-CAERKpYl.mjs.map +1 -0
- package/dist/_chunks/{History-BfX6XmZK.js → History-d-IgDGPl.js} +170 -76
- package/dist/_chunks/History-d-IgDGPl.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DxKuVkKz.mjs → ListConfigurationPage-CVVT45M8.mjs} +59 -49
- package/dist/_chunks/ListConfigurationPage-CVVT45M8.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-B3CXj8PY.js → ListConfigurationPage-DSX98CYb.js} +58 -47
- package/dist/_chunks/ListConfigurationPage-DSX98CYb.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Bk9VO__I.js → ListViewPage-C9gPPp-V.js} +117 -105
- package/dist/_chunks/ListViewPage-C9gPPp-V.js.map +1 -0
- package/dist/_chunks/{ListViewPage-D5D3tVPq.mjs → ListViewPage-Q4g6kHDl.mjs} +115 -103
- package/dist/_chunks/ListViewPage-Q4g6kHDl.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs → NoContentTypePage-BY4YRGs0.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs.map → NoContentTypePage-BY4YRGs0.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js → NoContentTypePage-D09gppmy.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js.map → NoContentTypePage-D09gppmy.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js → NoPermissionsPage-32WgThJG.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js.map → NoPermissionsPage-32WgThJG.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs → NoPermissionsPage-CyM16RKL.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs.map → NoPermissionsPage-CyM16RKL.mjs.map} +1 -1
- package/dist/_chunks/Preview-C2WFq4S8.mjs +267 -0
- package/dist/_chunks/Preview-C2WFq4S8.mjs.map +1 -0
- package/dist/_chunks/Preview-PpV3g9wJ.js +286 -0
- package/dist/_chunks/Preview-PpV3g9wJ.js.map +1 -0
- package/dist/_chunks/{Relations-BOYZmuWy.mjs → Relations-B_Yn9xGB.mjs} +73 -37
- package/dist/_chunks/Relations-B_Yn9xGB.mjs.map +1 -0
- package/dist/_chunks/{Relations-B6B3A3mb.js → Relations-mWaebC5t.js} +72 -36
- package/dist/_chunks/Relations-mWaebC5t.js.map +1 -0
- package/dist/_chunks/{en-BN1bvFK7.js → en-CHOp_xJv.js} +30 -16
- package/dist/_chunks/{en-BN1bvFK7.js.map → en-CHOp_xJv.js.map} +1 -1
- package/dist/_chunks/{en-Dzv55oQw.mjs → en-D_BMf0hT.mjs} +30 -16
- package/dist/_chunks/{en-Dzv55oQw.mjs.map → en-D_BMf0hT.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-VHviNMeW.mjs → index-CbytGVdz.mjs} +1154 -887
- package/dist/_chunks/index-CbytGVdz.mjs.map +1 -0
- package/dist/_chunks/{index-DzN3kBgx.js → index-iun2i4xv.js} +1133 -865
- package/dist/_chunks/index-iun2i4xv.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-CPn1PM6x.mjs → layout-Btu_cMRF.mjs} +41 -23
- package/dist/_chunks/layout-Btu_cMRF.mjs.map +1 -0
- package/dist/_chunks/{layout-b91XRlD2.js → layout-CkaP4K5_.js} +39 -21
- package/dist/_chunks/layout-CkaP4K5_.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-BsqxS6tR.mjs → relations-Cn5re8ia.mjs} +6 -7
- package/dist/_chunks/relations-Cn5re8ia.mjs.map +1 -0
- package/dist/_chunks/{relations-CA7IYmcP.js → relations-O_v9g0v_.js} +6 -7
- package/dist/_chunks/relations-O_v9g0v_.js.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +8 -7
- package/dist/admin/src/exports.d.ts +1 -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 +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- 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/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/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 -17
- 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 +551 -263
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +552 -264
- 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 +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +15 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +30 -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 +18 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/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 +13 -13
- package/dist/_chunks/EditViewPage-CoQEnFlC.js.map +0 -1
- 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.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat,
|
2
|
+
import { pick, omit, difference, castArray, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -7,10 +7,10 @@ import isNil from "lodash/isNil";
|
|
7
7
|
import _, { intersection as intersection$1, difference as difference$1 } from "lodash";
|
8
8
|
import qs from "qs";
|
9
9
|
import slugify from "@sindresorhus/slugify";
|
10
|
-
const getService$
|
10
|
+
const getService$2 = (name) => {
|
11
11
|
return strapi.plugin("content-manager").service(name);
|
12
12
|
};
|
13
|
-
function getService(strapi2, name) {
|
13
|
+
function getService$1(strapi2, name) {
|
14
14
|
return strapi2.service(`plugin::content-manager.${name}`);
|
15
15
|
}
|
16
16
|
const historyRestoreVersionSchema = yup.object().shape({
|
@@ -46,7 +46,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
46
46
|
if (!isSingleType && (!contentTypeUid || !ctx.query.documentId)) {
|
47
47
|
throw new errors.ForbiddenError("contentType and documentId are required");
|
48
48
|
}
|
49
|
-
const permissionChecker2 = getService$
|
49
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
50
50
|
userAbility: ctx.state.userAbility,
|
51
51
|
model: ctx.query.contentType
|
52
52
|
});
|
@@ -54,7 +54,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
54
54
|
return ctx.forbidden();
|
55
55
|
}
|
56
56
|
const query = await permissionChecker2.sanitizeQuery(ctx.query);
|
57
|
-
const { results, pagination: pagination2 } = await getService(strapi2, "history").findVersionsPage({
|
57
|
+
const { results, pagination: pagination2 } = await getService$1(strapi2, "history").findVersionsPage({
|
58
58
|
query: {
|
59
59
|
...query,
|
60
60
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -79,14 +79,14 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
79
79
|
async restoreVersion(ctx) {
|
80
80
|
const request = ctx.request;
|
81
81
|
await validateRestoreVersion(request.body, "contentType is required");
|
82
|
-
const permissionChecker2 = getService$
|
82
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
83
83
|
userAbility: ctx.state.userAbility,
|
84
84
|
model: request.body.contentType
|
85
85
|
});
|
86
86
|
if (permissionChecker2.cannot.update()) {
|
87
87
|
throw new errors.ForbiddenError();
|
88
88
|
}
|
89
|
-
const restoredDocument = await getService(strapi2, "history").restoreVersion(
|
89
|
+
const restoredDocument = await getService$1(strapi2, "history").restoreVersion(
|
90
90
|
request.params.versionId
|
91
91
|
);
|
92
92
|
return {
|
@@ -95,7 +95,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
95
95
|
}
|
96
96
|
};
|
97
97
|
};
|
98
|
-
const controllers$
|
98
|
+
const controllers$2 = {
|
99
99
|
"history-version": createHistoryVersionController
|
100
100
|
/**
|
101
101
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -173,7 +173,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
173
173
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
174
174
|
};
|
175
175
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
176
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
176
177
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
178
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
177
179
|
const getLocaleDictionary = async () => {
|
178
180
|
if (!localesService)
|
179
181
|
return {};
|
@@ -200,31 +202,53 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
200
202
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
201
203
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
202
204
|
};
|
203
|
-
const
|
205
|
+
const getComponentFields = (componentUID) => {
|
206
|
+
return Object.entries(strapi2.getModel(componentUID).attributes).reduce(
|
207
|
+
(fieldsAcc, [key, attribute]) => {
|
208
|
+
if (!["relation", "media", "component", "dynamiczone"].includes(attribute.type)) {
|
209
|
+
fieldsAcc.push(key);
|
210
|
+
}
|
211
|
+
return fieldsAcc;
|
212
|
+
},
|
213
|
+
[]
|
214
|
+
);
|
215
|
+
};
|
216
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
204
217
|
const model = strapi2.getModel(uid2);
|
205
218
|
const attributes = Object.entries(model.attributes);
|
219
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
206
220
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
207
221
|
switch (attribute.type) {
|
208
222
|
case "relation": {
|
223
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
224
|
+
if (isMorphRelation) {
|
225
|
+
break;
|
226
|
+
}
|
209
227
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
210
228
|
if (isVisible2) {
|
211
|
-
acc[attributeName] = {
|
229
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
212
230
|
}
|
213
231
|
break;
|
214
232
|
}
|
215
233
|
case "media": {
|
216
|
-
acc[attributeName] = {
|
234
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
217
235
|
break;
|
218
236
|
}
|
219
237
|
case "component": {
|
220
238
|
const populate = getDeepPopulate2(attribute.component);
|
221
|
-
acc[attributeName] = {
|
239
|
+
acc[attributeName] = {
|
240
|
+
populate,
|
241
|
+
[fieldSelector]: getComponentFields(attribute.component)
|
242
|
+
};
|
222
243
|
break;
|
223
244
|
}
|
224
245
|
case "dynamiczone": {
|
225
246
|
const populatedComponents = (attribute.components || []).reduce(
|
226
247
|
(acc2, componentUID) => {
|
227
|
-
acc2[componentUID] = {
|
248
|
+
acc2[componentUID] = {
|
249
|
+
populate: getDeepPopulate2(componentUID),
|
250
|
+
[fieldSelector]: getComponentFields(componentUID)
|
251
|
+
};
|
228
252
|
return acc2;
|
229
253
|
},
|
230
254
|
{}
|
@@ -286,6 +310,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
286
310
|
getRelationRestoreValue,
|
287
311
|
getMediaRestoreValue,
|
288
312
|
getDefaultLocale,
|
313
|
+
isLocalizedContentType,
|
289
314
|
getLocaleDictionary,
|
290
315
|
getRetentionDays,
|
291
316
|
getVersionStatus,
|
@@ -308,7 +333,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
308
333
|
});
|
309
334
|
},
|
310
335
|
async findVersionsPage(params) {
|
311
|
-
const
|
336
|
+
const model = strapi2.getModel(params.query.contentType);
|
337
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
338
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
339
|
+
let locale = null;
|
340
|
+
if (isLocalizedContentType) {
|
341
|
+
locale = params.query.locale || defaultLocale;
|
342
|
+
}
|
312
343
|
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
313
344
|
query.findPage({
|
314
345
|
...params.query,
|
@@ -330,7 +361,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
330
361
|
const attributeValue = entry.data[attributeKey];
|
331
362
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
332
363
|
if (attributeSchema.type === "media") {
|
333
|
-
const permissionChecker2 = getService$
|
364
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
334
365
|
userAbility: params.state.userAbility,
|
335
366
|
model: "plugin::upload.file"
|
336
367
|
});
|
@@ -353,7 +384,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
353
384
|
if (userToPopulate == null) {
|
354
385
|
return null;
|
355
386
|
}
|
356
|
-
return strapi2.query("admin::user").findOne({
|
387
|
+
return strapi2.query("admin::user").findOne({
|
388
|
+
where: {
|
389
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
390
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
391
|
+
}
|
392
|
+
});
|
357
393
|
})
|
358
394
|
);
|
359
395
|
return {
|
@@ -366,7 +402,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
366
402
|
[attributeKey]: adminUsers
|
367
403
|
};
|
368
404
|
}
|
369
|
-
const permissionChecker2 = getService$
|
405
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
370
406
|
userAbility: params.state.userAbility,
|
371
407
|
model: attributeSchema.target
|
372
408
|
});
|
@@ -464,13 +500,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
464
500
|
}
|
465
501
|
};
|
466
502
|
};
|
503
|
+
const shouldCreateHistoryVersion = (context) => {
|
504
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
505
|
+
return false;
|
506
|
+
}
|
507
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
508
|
+
return false;
|
509
|
+
}
|
510
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
511
|
+
return false;
|
512
|
+
}
|
513
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
514
|
+
return false;
|
515
|
+
}
|
516
|
+
return true;
|
517
|
+
};
|
518
|
+
const getSchemas = (uid2) => {
|
519
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
520
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
521
|
+
(currentComponentSchemas, key) => {
|
522
|
+
const fieldSchema = attributesSchema[key];
|
523
|
+
if (fieldSchema.type === "component") {
|
524
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
525
|
+
return {
|
526
|
+
...currentComponentSchemas,
|
527
|
+
[fieldSchema.component]: componentSchema
|
528
|
+
};
|
529
|
+
}
|
530
|
+
return currentComponentSchemas;
|
531
|
+
},
|
532
|
+
{}
|
533
|
+
);
|
534
|
+
return {
|
535
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
536
|
+
componentsSchemas
|
537
|
+
};
|
538
|
+
};
|
467
539
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
540
|
const state = {
|
469
541
|
deleteExpiredJob: null,
|
470
542
|
isInitialized: false
|
471
543
|
};
|
472
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
473
|
-
const historyService = getService(strapi2, "history");
|
474
544
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
475
545
|
return {
|
476
546
|
async bootstrap() {
|
@@ -478,73 +548,62 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
478
548
|
return;
|
479
549
|
}
|
480
550
|
strapi2.documents.use(async (context, next) => {
|
481
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
482
|
-
return next();
|
483
|
-
}
|
484
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
485
|
-
return next();
|
486
|
-
}
|
487
|
-
const contentTypeUid = context.contentType.uid;
|
488
|
-
if (!contentTypeUid.startsWith("api::")) {
|
489
|
-
return next();
|
490
|
-
}
|
491
551
|
const result = await next();
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
552
|
+
if (!shouldCreateHistoryVersion(context)) {
|
553
|
+
return result;
|
554
|
+
}
|
555
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
496
556
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
497
|
-
const
|
498
|
-
if (
|
499
|
-
|
500
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
501
|
-
);
|
502
|
-
return next();
|
557
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
558
|
+
if (!locales.length) {
|
559
|
+
return result;
|
503
560
|
}
|
504
|
-
const
|
505
|
-
|
506
|
-
|
507
|
-
|
561
|
+
const uid2 = context.contentType.uid;
|
562
|
+
const schemas = getSchemas(uid2);
|
563
|
+
const model = strapi2.getModel(uid2);
|
564
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
565
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
566
|
+
where: {
|
567
|
+
documentId,
|
568
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
569
|
+
...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
570
|
+
},
|
571
|
+
populate: serviceUtils.getDeepPopulate(
|
572
|
+
uid2,
|
573
|
+
true
|
574
|
+
/* use database syntax */
|
575
|
+
)
|
508
576
|
});
|
509
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
510
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
511
|
-
const componentsSchemas = Object.keys(
|
512
|
-
attributesSchema
|
513
|
-
).reduce((currentComponentSchemas, key) => {
|
514
|
-
const fieldSchema = attributesSchema[key];
|
515
|
-
if (fieldSchema.type === "component") {
|
516
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
517
|
-
return {
|
518
|
-
...currentComponentSchemas,
|
519
|
-
[fieldSchema.component]: componentSchema
|
520
|
-
};
|
521
|
-
}
|
522
|
-
return currentComponentSchemas;
|
523
|
-
}, {});
|
524
577
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
525
|
-
onCommit(() => {
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
578
|
+
onCommit(async () => {
|
579
|
+
for (const entry of localeEntries) {
|
580
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
581
|
+
await getService$1(strapi2, "history").createVersion({
|
582
|
+
contentType: uid2,
|
583
|
+
data: omit(FIELDS_TO_IGNORE, entry),
|
584
|
+
relatedDocumentId: documentId,
|
585
|
+
locale: entry.locale,
|
586
|
+
status,
|
587
|
+
...schemas
|
588
|
+
});
|
589
|
+
}
|
535
590
|
});
|
536
591
|
});
|
537
592
|
return result;
|
538
593
|
});
|
539
|
-
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
594
|
+
state.deleteExpiredJob = scheduleJob("historyDaily", "0 0 * * *", () => {
|
540
595
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
541
596
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
542
|
-
query.deleteMany({
|
597
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
543
598
|
where: {
|
544
599
|
created_at: {
|
545
|
-
$lt: expirationDate
|
600
|
+
$lt: expirationDate
|
546
601
|
}
|
547
602
|
}
|
603
|
+
}).catch((error) => {
|
604
|
+
if (error instanceof Error) {
|
605
|
+
strapi2.log.error("Error deleting expired history versions", error.message);
|
606
|
+
}
|
548
607
|
});
|
549
608
|
});
|
550
609
|
state.isInitialized = true;
|
@@ -556,17 +615,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
556
615
|
}
|
557
616
|
};
|
558
617
|
};
|
559
|
-
const services$
|
618
|
+
const services$2 = {
|
560
619
|
history: createHistoryService,
|
561
620
|
lifecycles: createLifecyclesService
|
562
621
|
};
|
563
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
622
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
564
623
|
const historyVersionRouter = {
|
565
624
|
type: "admin",
|
566
625
|
routes: [
|
567
626
|
{
|
568
627
|
method: "GET",
|
569
|
-
info,
|
628
|
+
info: info$1,
|
570
629
|
path: "/history-versions",
|
571
630
|
handler: "history-version.findMany",
|
572
631
|
config: {
|
@@ -575,7 +634,7 @@ const historyVersionRouter = {
|
|
575
634
|
},
|
576
635
|
{
|
577
636
|
method: "PUT",
|
578
|
-
info,
|
637
|
+
info: info$1,
|
579
638
|
path: "/history-versions/:versionId/restore",
|
580
639
|
handler: "history-version.restoreVersion",
|
581
640
|
config: {
|
@@ -584,7 +643,7 @@ const historyVersionRouter = {
|
|
584
643
|
}
|
585
644
|
]
|
586
645
|
};
|
587
|
-
const routes$
|
646
|
+
const routes$2 = {
|
588
647
|
"history-version": historyVersionRouter
|
589
648
|
};
|
590
649
|
const historyVersion = {
|
@@ -631,21 +690,21 @@ const historyVersion = {
|
|
631
690
|
}
|
632
691
|
}
|
633
692
|
};
|
634
|
-
const getFeature = () => {
|
693
|
+
const getFeature$1 = () => {
|
635
694
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
636
695
|
return {
|
637
696
|
register({ strapi: strapi2 }) {
|
638
697
|
strapi2.get("models").add(historyVersion);
|
639
698
|
},
|
640
699
|
bootstrap({ strapi: strapi2 }) {
|
641
|
-
getService(strapi2, "lifecycles").bootstrap();
|
700
|
+
getService$1(strapi2, "lifecycles").bootstrap();
|
642
701
|
},
|
643
702
|
destroy({ strapi: strapi2 }) {
|
644
|
-
getService(strapi2, "lifecycles").destroy();
|
703
|
+
getService$1(strapi2, "lifecycles").destroy();
|
645
704
|
},
|
646
|
-
controllers: controllers$
|
647
|
-
services: services$
|
648
|
-
routes: routes$
|
705
|
+
controllers: controllers$2,
|
706
|
+
services: services$2,
|
707
|
+
routes: routes$2
|
649
708
|
};
|
650
709
|
}
|
651
710
|
return {
|
@@ -654,7 +713,7 @@ const getFeature = () => {
|
|
654
713
|
}
|
655
714
|
};
|
656
715
|
};
|
657
|
-
const history = getFeature();
|
716
|
+
const history = getFeature$1();
|
658
717
|
const register = async ({ strapi: strapi2 }) => {
|
659
718
|
await history.register?.({ strapi: strapi2 });
|
660
719
|
};
|
@@ -662,15 +721,165 @@ const ALLOWED_WEBHOOK_EVENTS = {
|
|
662
721
|
ENTRY_PUBLISH: "entry.publish",
|
663
722
|
ENTRY_UNPUBLISH: "entry.unpublish"
|
664
723
|
};
|
724
|
+
const FEATURE_ID = "preview";
|
725
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
726
|
+
const previewRouter = {
|
727
|
+
type: "admin",
|
728
|
+
routes: [
|
729
|
+
{
|
730
|
+
method: "GET",
|
731
|
+
info,
|
732
|
+
path: "/preview/url/:contentType",
|
733
|
+
handler: "preview.getPreviewUrl",
|
734
|
+
config: {
|
735
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
736
|
+
}
|
737
|
+
}
|
738
|
+
]
|
739
|
+
};
|
740
|
+
const routes$1 = {
|
741
|
+
preview: previewRouter
|
742
|
+
};
|
743
|
+
function getService(strapi2, name) {
|
744
|
+
return strapi2.service(`plugin::content-manager.${name}`);
|
745
|
+
}
|
746
|
+
const getPreviewUrlSchema = yup.object().shape({
|
747
|
+
// Will be undefined for single types
|
748
|
+
documentId: yup.string(),
|
749
|
+
locale: yup.string().nullable(),
|
750
|
+
status: yup.string()
|
751
|
+
}).required();
|
752
|
+
const validatePreviewUrl = async (strapi2, uid2, params) => {
|
753
|
+
await validateYupSchema(getPreviewUrlSchema)(params);
|
754
|
+
const newParams = pick(["documentId", "locale", "status"], params);
|
755
|
+
const model = strapi2.getModel(uid2);
|
756
|
+
if (!model || model.modelType !== "contentType") {
|
757
|
+
throw new errors.ValidationError("Invalid content type");
|
758
|
+
}
|
759
|
+
const isSingleType = model?.kind === "singleType";
|
760
|
+
if (!isSingleType && !params.documentId) {
|
761
|
+
throw new errors.ValidationError("documentId is required for Collection Types");
|
762
|
+
}
|
763
|
+
if (isSingleType) {
|
764
|
+
const doc = await strapi2.documents(uid2).findFirst();
|
765
|
+
if (!doc) {
|
766
|
+
throw new errors.NotFoundError("Document not found");
|
767
|
+
}
|
768
|
+
newParams.documentId = doc?.documentId;
|
769
|
+
}
|
770
|
+
return newParams;
|
771
|
+
};
|
772
|
+
const createPreviewController = () => {
|
773
|
+
return {
|
774
|
+
/**
|
775
|
+
* Transforms an entry into a preview URL, so that it can be previewed
|
776
|
+
* in the Content Manager.
|
777
|
+
*/
|
778
|
+
async getPreviewUrl(ctx) {
|
779
|
+
const uid2 = ctx.params.contentType;
|
780
|
+
const query = ctx.request.query;
|
781
|
+
const params = await validatePreviewUrl(strapi, uid2, query);
|
782
|
+
const previewService = getService(strapi, "preview");
|
783
|
+
const url = await previewService.getPreviewUrl(uid2, params);
|
784
|
+
if (!url) {
|
785
|
+
ctx.status = 204;
|
786
|
+
}
|
787
|
+
return {
|
788
|
+
data: { url }
|
789
|
+
};
|
790
|
+
}
|
791
|
+
};
|
792
|
+
};
|
793
|
+
const controllers$1 = {
|
794
|
+
preview: createPreviewController
|
795
|
+
/**
|
796
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
797
|
+
* passing a controller factory as the value, instead of a controller object directly
|
798
|
+
*/
|
799
|
+
};
|
800
|
+
const createPreviewService = ({ strapi: strapi2 }) => {
|
801
|
+
const config = getService(strapi2, "preview-config");
|
802
|
+
return {
|
803
|
+
async getPreviewUrl(uid2, params) {
|
804
|
+
const handler = config.getPreviewHandler();
|
805
|
+
try {
|
806
|
+
return handler(uid2, params);
|
807
|
+
} catch (error) {
|
808
|
+
strapi2.log.error(`Failed to get preview URL: ${error}`);
|
809
|
+
throw new errors.ApplicationError("Failed to get preview URL");
|
810
|
+
}
|
811
|
+
return;
|
812
|
+
}
|
813
|
+
};
|
814
|
+
};
|
815
|
+
const createPreviewConfigService = ({ strapi: strapi2 }) => {
|
816
|
+
return {
|
817
|
+
isEnabled() {
|
818
|
+
const config = strapi2.config.get("admin.preview");
|
819
|
+
if (!config) {
|
820
|
+
return false;
|
821
|
+
}
|
822
|
+
return config?.enabled ?? true;
|
823
|
+
},
|
824
|
+
/**
|
825
|
+
* Validate if the configuration is valid
|
826
|
+
*/
|
827
|
+
validate() {
|
828
|
+
if (!this.isEnabled()) {
|
829
|
+
return;
|
830
|
+
}
|
831
|
+
const handler = this.getPreviewHandler();
|
832
|
+
if (typeof handler !== "function") {
|
833
|
+
throw new errors.ValidationError(
|
834
|
+
"Preview configuration is invalid. Handler must be a function"
|
835
|
+
);
|
836
|
+
}
|
837
|
+
},
|
838
|
+
/**
|
839
|
+
* Utility to get the preview handler from the configuration
|
840
|
+
*/
|
841
|
+
getPreviewHandler() {
|
842
|
+
const config = strapi2.config.get("admin.preview");
|
843
|
+
const emptyHandler = () => {
|
844
|
+
return void 0;
|
845
|
+
};
|
846
|
+
if (!this.isEnabled()) {
|
847
|
+
return emptyHandler;
|
848
|
+
}
|
849
|
+
return config?.config?.handler || emptyHandler;
|
850
|
+
}
|
851
|
+
};
|
852
|
+
};
|
853
|
+
const services$1 = {
|
854
|
+
preview: createPreviewService,
|
855
|
+
"preview-config": createPreviewConfigService
|
856
|
+
};
|
857
|
+
const getFeature = () => {
|
858
|
+
if (!strapi.features.future.isEnabled(FEATURE_ID)) {
|
859
|
+
return {};
|
860
|
+
}
|
861
|
+
return {
|
862
|
+
bootstrap() {
|
863
|
+
console.log("Bootstrapping preview server");
|
864
|
+
const config = getService(strapi, "preview-config");
|
865
|
+
config.validate();
|
866
|
+
},
|
867
|
+
routes: routes$1,
|
868
|
+
controllers: controllers$1,
|
869
|
+
services: services$1
|
870
|
+
};
|
871
|
+
};
|
872
|
+
const preview = getFeature();
|
665
873
|
const bootstrap = async () => {
|
666
874
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
667
875
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
668
876
|
});
|
669
|
-
getService$
|
670
|
-
await getService$
|
671
|
-
await getService$
|
672
|
-
await getService$
|
877
|
+
getService$2("field-sizes").setCustomFieldInputSizes();
|
878
|
+
await getService$2("components").syncConfigurations();
|
879
|
+
await getService$2("content-types").syncConfigurations();
|
880
|
+
await getService$2("permission").registerPermissions();
|
673
881
|
await history.bootstrap?.({ strapi });
|
882
|
+
await preview.bootstrap?.({ strapi });
|
674
883
|
};
|
675
884
|
const destroy = async ({ strapi: strapi2 }) => {
|
676
885
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1160,7 +1369,8 @@ const admin = {
|
|
1160
1369
|
};
|
1161
1370
|
const routes = {
|
1162
1371
|
admin,
|
1163
|
-
...history.routes ? history.routes : {}
|
1372
|
+
...history.routes ? history.routes : {},
|
1373
|
+
...preview.routes ? preview.routes : {}
|
1164
1374
|
};
|
1165
1375
|
const hasPermissionsSchema = yup$1.object({
|
1166
1376
|
actions: yup$1.array().of(yup$1.string()),
|
@@ -1171,6 +1381,11 @@ const { createPolicy } = policy;
|
|
1171
1381
|
const hasPermissions = createPolicy({
|
1172
1382
|
name: "plugin::content-manager.hasPermissions",
|
1173
1383
|
validator: validateHasPermissionsInput,
|
1384
|
+
/**
|
1385
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1386
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1387
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1388
|
+
*/
|
1174
1389
|
handler(ctx, config = {}) {
|
1175
1390
|
const { actions = [], hasAtLeastOne = false } = config;
|
1176
1391
|
const { userAbility } = ctx.state;
|
@@ -1412,7 +1627,7 @@ const createMetadasSchema = (schema) => {
|
|
1412
1627
|
if (!value) {
|
1413
1628
|
return yup$1.string();
|
1414
1629
|
}
|
1415
|
-
const targetSchema = getService$
|
1630
|
+
const targetSchema = getService$2("content-types").findContentType(
|
1416
1631
|
schema.attributes[key].targetModel
|
1417
1632
|
);
|
1418
1633
|
if (!targetSchema) {
|
@@ -1564,9 +1779,11 @@ const multipleLocaleSchema = yup$1.lazy(
|
|
1564
1779
|
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1565
1780
|
);
|
1566
1781
|
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1567
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1782
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1568
1783
|
const { allowMultipleLocales } = opts;
|
1569
|
-
const { locale, status, ...rest } = request || {};
|
1784
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1785
|
+
const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1786
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1570
1787
|
const schema = yup$1.object().shape({
|
1571
1788
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1572
1789
|
status: statusSchema
|
@@ -1579,7 +1796,7 @@ const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales
|
|
1579
1796
|
}
|
1580
1797
|
};
|
1581
1798
|
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1582
|
-
const documentMetadata2 = getService$
|
1799
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1583
1800
|
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1584
1801
|
let {
|
1585
1802
|
meta: { availableLocales, availableStatus }
|
@@ -1605,8 +1822,8 @@ const createDocument = async (ctx, opts) => {
|
|
1605
1822
|
const { userAbility, user } = ctx.state;
|
1606
1823
|
const { model } = ctx.params;
|
1607
1824
|
const { body } = ctx.request;
|
1608
|
-
const documentManager2 = getService$
|
1609
|
-
const permissionChecker2 = getService$
|
1825
|
+
const documentManager2 = getService$2("document-manager");
|
1826
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1610
1827
|
if (permissionChecker2.cannot.create()) {
|
1611
1828
|
throw new errors.ForbiddenError();
|
1612
1829
|
}
|
@@ -1614,7 +1831,7 @@ const createDocument = async (ctx, opts) => {
|
|
1614
1831
|
const setCreator = setCreatorFields({ user });
|
1615
1832
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1616
1833
|
const sanitizedBody = await sanitizeFn(body);
|
1617
|
-
const { locale, status
|
1834
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1618
1835
|
return documentManager2.create(model, {
|
1619
1836
|
data: sanitizedBody,
|
1620
1837
|
locale,
|
@@ -1626,14 +1843,14 @@ const updateDocument = async (ctx, opts) => {
|
|
1626
1843
|
const { userAbility, user } = ctx.state;
|
1627
1844
|
const { id, model } = ctx.params;
|
1628
1845
|
const { body } = ctx.request;
|
1629
|
-
const documentManager2 = getService$
|
1630
|
-
const permissionChecker2 = getService$
|
1846
|
+
const documentManager2 = getService$2("document-manager");
|
1847
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1631
1848
|
if (permissionChecker2.cannot.update()) {
|
1632
1849
|
throw new errors.ForbiddenError();
|
1633
1850
|
}
|
1634
1851
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1635
|
-
const populate = await getService$
|
1636
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1852
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1853
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1637
1854
|
const [documentVersion, documentExists] = await Promise.all([
|
1638
1855
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1639
1856
|
documentManager2.exists(model, id)
|
@@ -1649,7 +1866,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1649
1866
|
throw new errors.ForbiddenError();
|
1650
1867
|
}
|
1651
1868
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1652
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1869
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1653
1870
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1654
1871
|
const sanitizedBody = await sanitizeFn(body);
|
1655
1872
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1663,15 +1880,15 @@ const collectionTypes = {
|
|
1663
1880
|
const { userAbility } = ctx.state;
|
1664
1881
|
const { model } = ctx.params;
|
1665
1882
|
const { query } = ctx.request;
|
1666
|
-
const documentMetadata2 = getService$
|
1667
|
-
const documentManager2 = getService$
|
1668
|
-
const permissionChecker2 = getService$
|
1883
|
+
const documentMetadata2 = getService$2("document-metadata");
|
1884
|
+
const documentManager2 = getService$2("document-manager");
|
1885
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1669
1886
|
if (permissionChecker2.cannot.read()) {
|
1670
1887
|
return ctx.forbidden();
|
1671
1888
|
}
|
1672
1889
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1673
|
-
const populate = await getService$
|
1674
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1890
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1891
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1675
1892
|
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1676
1893
|
{ ...permissionQuery, populate, locale, status },
|
1677
1894
|
model
|
@@ -1699,14 +1916,14 @@ const collectionTypes = {
|
|
1699
1916
|
async findOne(ctx) {
|
1700
1917
|
const { userAbility } = ctx.state;
|
1701
1918
|
const { model, id } = ctx.params;
|
1702
|
-
const documentManager2 = getService$
|
1703
|
-
const permissionChecker2 = getService$
|
1919
|
+
const documentManager2 = getService$2("document-manager");
|
1920
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1704
1921
|
if (permissionChecker2.cannot.read()) {
|
1705
1922
|
return ctx.forbidden();
|
1706
1923
|
}
|
1707
1924
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1708
|
-
const populate = await getService$
|
1709
|
-
const { locale, status
|
1925
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1926
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1710
1927
|
const version = await documentManager2.findOne(id, model, {
|
1711
1928
|
populate,
|
1712
1929
|
locale,
|
@@ -1721,7 +1938,7 @@ const collectionTypes = {
|
|
1721
1938
|
permissionChecker2,
|
1722
1939
|
model,
|
1723
1940
|
// @ts-expect-error TODO: fix
|
1724
|
-
{ id, locale, publishedAt: null },
|
1941
|
+
{ documentId: id, locale, publishedAt: null },
|
1725
1942
|
{ availableLocales: true, availableStatus: false }
|
1726
1943
|
);
|
1727
1944
|
ctx.body = { data: {}, meta };
|
@@ -1736,7 +1953,7 @@ const collectionTypes = {
|
|
1736
1953
|
async create(ctx) {
|
1737
1954
|
const { userAbility } = ctx.state;
|
1738
1955
|
const { model } = ctx.params;
|
1739
|
-
const permissionChecker2 = getService$
|
1956
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1740
1957
|
const [totalEntries, document] = await Promise.all([
|
1741
1958
|
strapi.db.query(model).count(),
|
1742
1959
|
createDocument(ctx)
|
@@ -1757,7 +1974,7 @@ const collectionTypes = {
|
|
1757
1974
|
async update(ctx) {
|
1758
1975
|
const { userAbility } = ctx.state;
|
1759
1976
|
const { model } = ctx.params;
|
1760
|
-
const permissionChecker2 = getService$
|
1977
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1761
1978
|
const updatedVersion = await updateDocument(ctx);
|
1762
1979
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1763
1980
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
@@ -1766,14 +1983,14 @@ const collectionTypes = {
|
|
1766
1983
|
const { userAbility, user } = ctx.state;
|
1767
1984
|
const { model, sourceId: id } = ctx.params;
|
1768
1985
|
const { body } = ctx.request;
|
1769
|
-
const documentManager2 = getService$
|
1770
|
-
const permissionChecker2 = getService$
|
1986
|
+
const documentManager2 = getService$2("document-manager");
|
1987
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1771
1988
|
if (permissionChecker2.cannot.create()) {
|
1772
1989
|
return ctx.forbidden();
|
1773
1990
|
}
|
1774
1991
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1775
|
-
const populate = await getService$
|
1776
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1992
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1993
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1777
1994
|
const document = await documentManager2.findOne(id, model, {
|
1778
1995
|
populate,
|
1779
1996
|
locale,
|
@@ -1811,14 +2028,14 @@ const collectionTypes = {
|
|
1811
2028
|
async delete(ctx) {
|
1812
2029
|
const { userAbility } = ctx.state;
|
1813
2030
|
const { id, model } = ctx.params;
|
1814
|
-
const documentManager2 = getService$
|
1815
|
-
const permissionChecker2 = getService$
|
2031
|
+
const documentManager2 = getService$2("document-manager");
|
2032
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1816
2033
|
if (permissionChecker2.cannot.delete()) {
|
1817
2034
|
return ctx.forbidden();
|
1818
2035
|
}
|
1819
2036
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1820
|
-
const populate = await getService$
|
1821
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
2037
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2038
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1822
2039
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1823
2040
|
if (documentLocales.length === 0) {
|
1824
2041
|
return ctx.notFound();
|
@@ -1839,19 +2056,42 @@ const collectionTypes = {
|
|
1839
2056
|
const { userAbility } = ctx.state;
|
1840
2057
|
const { id, model } = ctx.params;
|
1841
2058
|
const { body } = ctx.request;
|
1842
|
-
const documentManager2 = getService$
|
1843
|
-
const permissionChecker2 = getService$
|
2059
|
+
const documentManager2 = getService$2("document-manager");
|
2060
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1844
2061
|
if (permissionChecker2.cannot.publish()) {
|
1845
2062
|
return ctx.forbidden();
|
1846
2063
|
}
|
1847
2064
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1848
2065
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1849
|
-
const populate = await getService$
|
1850
|
-
|
2066
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2067
|
+
let document;
|
2068
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2069
|
+
const isCreate = isNil$1(id);
|
2070
|
+
if (isCreate) {
|
2071
|
+
if (permissionChecker2.cannot.create()) {
|
2072
|
+
throw new errors.ForbiddenError();
|
2073
|
+
}
|
2074
|
+
document = await createDocument(ctx, { populate });
|
2075
|
+
}
|
2076
|
+
const isUpdate = !isCreate;
|
2077
|
+
if (isUpdate) {
|
2078
|
+
const documentExists = documentManager2.exists(model, id);
|
2079
|
+
if (!documentExists) {
|
2080
|
+
throw new errors.NotFoundError("Document not found");
|
2081
|
+
}
|
2082
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
2083
|
+
if (!document) {
|
2084
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
2085
|
+
throw new errors.ForbiddenError();
|
2086
|
+
}
|
2087
|
+
document = await updateDocument(ctx);
|
2088
|
+
} else if (permissionChecker2.can.update(document)) {
|
2089
|
+
await updateDocument(ctx);
|
2090
|
+
}
|
2091
|
+
}
|
1851
2092
|
if (permissionChecker2.cannot.publish(document)) {
|
1852
2093
|
throw new errors.ForbiddenError();
|
1853
2094
|
}
|
1854
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1855
2095
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1856
2096
|
locale
|
1857
2097
|
// TODO: Allow setting creator fields on publish
|
@@ -1871,14 +2111,16 @@ const collectionTypes = {
|
|
1871
2111
|
const { body } = ctx.request;
|
1872
2112
|
const { documentIds } = body;
|
1873
2113
|
await validateBulkActionInput(body);
|
1874
|
-
const documentManager2 = getService$
|
1875
|
-
const permissionChecker2 = getService$
|
2114
|
+
const documentManager2 = getService$2("document-manager");
|
2115
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1876
2116
|
if (permissionChecker2.cannot.publish()) {
|
1877
2117
|
return ctx.forbidden();
|
1878
2118
|
}
|
1879
2119
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1880
|
-
const populate = await getService$
|
1881
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
2120
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
2121
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2122
|
+
allowMultipleLocales: true
|
2123
|
+
});
|
1882
2124
|
const entityPromises = documentIds.map(
|
1883
2125
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1884
2126
|
);
|
@@ -1900,12 +2142,14 @@ const collectionTypes = {
|
|
1900
2142
|
const { body } = ctx.request;
|
1901
2143
|
const { documentIds } = body;
|
1902
2144
|
await validateBulkActionInput(body);
|
1903
|
-
const documentManager2 = getService$
|
1904
|
-
const permissionChecker2 = getService$
|
2145
|
+
const documentManager2 = getService$2("document-manager");
|
2146
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1905
2147
|
if (permissionChecker2.cannot.unpublish()) {
|
1906
2148
|
return ctx.forbidden();
|
1907
2149
|
}
|
1908
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2150
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2151
|
+
allowMultipleLocales: true
|
2152
|
+
});
|
1909
2153
|
const entityPromises = documentIds.map(
|
1910
2154
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1911
2155
|
);
|
@@ -1928,8 +2172,8 @@ const collectionTypes = {
|
|
1928
2172
|
const {
|
1929
2173
|
body: { discardDraft, ...body }
|
1930
2174
|
} = ctx.request;
|
1931
|
-
const documentManager2 = getService$
|
1932
|
-
const permissionChecker2 = getService$
|
2175
|
+
const documentManager2 = getService$2("document-manager");
|
2176
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1933
2177
|
if (permissionChecker2.cannot.unpublish()) {
|
1934
2178
|
return ctx.forbidden();
|
1935
2179
|
}
|
@@ -1937,8 +2181,8 @@ const collectionTypes = {
|
|
1937
2181
|
return ctx.forbidden();
|
1938
2182
|
}
|
1939
2183
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1940
|
-
const populate = await getService$
|
1941
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2184
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2185
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1942
2186
|
const document = await documentManager2.findOne(id, model, {
|
1943
2187
|
populate,
|
1944
2188
|
locale,
|
@@ -1968,14 +2212,14 @@ const collectionTypes = {
|
|
1968
2212
|
const { userAbility } = ctx.state;
|
1969
2213
|
const { id, model } = ctx.params;
|
1970
2214
|
const { body } = ctx.request;
|
1971
|
-
const documentManager2 = getService$
|
1972
|
-
const permissionChecker2 = getService$
|
2215
|
+
const documentManager2 = getService$2("document-manager");
|
2216
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
1973
2217
|
if (permissionChecker2.cannot.discard()) {
|
1974
2218
|
return ctx.forbidden();
|
1975
2219
|
}
|
1976
2220
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1977
|
-
const populate = await getService$
|
1978
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2221
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2222
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1979
2223
|
const document = await documentManager2.findOne(id, model, {
|
1980
2224
|
populate,
|
1981
2225
|
locale,
|
@@ -1999,14 +2243,14 @@ const collectionTypes = {
|
|
1999
2243
|
const { query, body } = ctx.request;
|
2000
2244
|
const { documentIds } = body;
|
2001
2245
|
await validateBulkActionInput(body);
|
2002
|
-
const documentManager2 = getService$
|
2003
|
-
const permissionChecker2 = getService$
|
2246
|
+
const documentManager2 = getService$2("document-manager");
|
2247
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2004
2248
|
if (permissionChecker2.cannot.delete()) {
|
2005
2249
|
return ctx.forbidden();
|
2006
2250
|
}
|
2007
2251
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2008
|
-
const populate = await getService$
|
2009
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2252
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2253
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2010
2254
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2011
2255
|
populate,
|
2012
2256
|
locale
|
@@ -2026,14 +2270,14 @@ const collectionTypes = {
|
|
2026
2270
|
async countDraftRelations(ctx) {
|
2027
2271
|
const { userAbility } = ctx.state;
|
2028
2272
|
const { model, id } = ctx.params;
|
2029
|
-
const documentManager2 = getService$
|
2030
|
-
const permissionChecker2 = getService$
|
2273
|
+
const documentManager2 = getService$2("document-manager");
|
2274
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2031
2275
|
if (permissionChecker2.cannot.read()) {
|
2032
2276
|
return ctx.forbidden();
|
2033
2277
|
}
|
2034
2278
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2035
|
-
const populate = await getService$
|
2036
|
-
const { locale, status
|
2279
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2280
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2037
2281
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2038
2282
|
if (!entity) {
|
2039
2283
|
return ctx.notFound();
|
@@ -2051,12 +2295,12 @@ const collectionTypes = {
|
|
2051
2295
|
const ids = ctx.request.query.documentIds;
|
2052
2296
|
const locale = ctx.request.query.locale;
|
2053
2297
|
const { model } = ctx.params;
|
2054
|
-
const documentManager2 = getService$
|
2055
|
-
const permissionChecker2 = getService$
|
2298
|
+
const documentManager2 = getService$2("document-manager");
|
2299
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2056
2300
|
if (permissionChecker2.cannot.read()) {
|
2057
2301
|
return ctx.forbidden();
|
2058
2302
|
}
|
2059
|
-
const
|
2303
|
+
const documents = await documentManager2.findMany(
|
2060
2304
|
{
|
2061
2305
|
filters: {
|
2062
2306
|
documentId: ids
|
@@ -2065,7 +2309,7 @@ const collectionTypes = {
|
|
2065
2309
|
},
|
2066
2310
|
model
|
2067
2311
|
);
|
2068
|
-
if (!
|
2312
|
+
if (!documents) {
|
2069
2313
|
return ctx.notFound();
|
2070
2314
|
}
|
2071
2315
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2076,13 +2320,13 @@ const collectionTypes = {
|
|
2076
2320
|
};
|
2077
2321
|
const components$1 = {
|
2078
2322
|
findComponents(ctx) {
|
2079
|
-
const components2 = getService$
|
2080
|
-
const { toDto } = getService$
|
2323
|
+
const components2 = getService$2("components").findAllComponents();
|
2324
|
+
const { toDto } = getService$2("data-mapper");
|
2081
2325
|
ctx.body = { data: components2.map(toDto) };
|
2082
2326
|
},
|
2083
2327
|
async findComponentConfiguration(ctx) {
|
2084
2328
|
const { uid: uid2 } = ctx.params;
|
2085
|
-
const componentService = getService$
|
2329
|
+
const componentService = getService$2("components");
|
2086
2330
|
const component = componentService.findComponent(uid2);
|
2087
2331
|
if (!component) {
|
2088
2332
|
return ctx.notFound("component.notFound");
|
@@ -2099,7 +2343,7 @@ const components$1 = {
|
|
2099
2343
|
async updateComponentConfiguration(ctx) {
|
2100
2344
|
const { uid: uid2 } = ctx.params;
|
2101
2345
|
const { body } = ctx.request;
|
2102
|
-
const componentService = getService$
|
2346
|
+
const componentService = getService$2("components");
|
2103
2347
|
const component = componentService.findComponent(uid2);
|
2104
2348
|
if (!component) {
|
2105
2349
|
return ctx.notFound("component.notFound");
|
@@ -2133,12 +2377,12 @@ const contentTypes = {
|
|
2133
2377
|
} catch (error) {
|
2134
2378
|
return ctx.send({ error }, 400);
|
2135
2379
|
}
|
2136
|
-
const contentTypes2 = getService$
|
2137
|
-
const { toDto } = getService$
|
2380
|
+
const contentTypes2 = getService$2("content-types").findContentTypesByKind(kind);
|
2381
|
+
const { toDto } = getService$2("data-mapper");
|
2138
2382
|
ctx.body = { data: contentTypes2.map(toDto) };
|
2139
2383
|
},
|
2140
2384
|
async findContentTypesSettings(ctx) {
|
2141
|
-
const { findAllContentTypes, findConfiguration } = getService$
|
2385
|
+
const { findAllContentTypes, findConfiguration } = getService$2("content-types");
|
2142
2386
|
const contentTypes2 = await findAllContentTypes();
|
2143
2387
|
const configurations = await Promise.all(
|
2144
2388
|
contentTypes2.map(async (contentType) => {
|
@@ -2152,7 +2396,7 @@ const contentTypes = {
|
|
2152
2396
|
},
|
2153
2397
|
async findContentTypeConfiguration(ctx) {
|
2154
2398
|
const { uid: uid2 } = ctx.params;
|
2155
|
-
const contentTypeService = getService$
|
2399
|
+
const contentTypeService = getService$2("content-types");
|
2156
2400
|
const contentType = await contentTypeService.findContentType(uid2);
|
2157
2401
|
if (!contentType) {
|
2158
2402
|
return ctx.notFound("contentType.notFound");
|
@@ -2174,13 +2418,13 @@ const contentTypes = {
|
|
2174
2418
|
const { userAbility } = ctx.state;
|
2175
2419
|
const { uid: uid2 } = ctx.params;
|
2176
2420
|
const { body } = ctx.request;
|
2177
|
-
const contentTypeService = getService$
|
2178
|
-
const metricsService = getService$
|
2421
|
+
const contentTypeService = getService$2("content-types");
|
2422
|
+
const metricsService = getService$2("metrics");
|
2179
2423
|
const contentType = await contentTypeService.findContentType(uid2);
|
2180
2424
|
if (!contentType) {
|
2181
2425
|
return ctx.notFound("contentType.notFound");
|
2182
2426
|
}
|
2183
|
-
if (!getService$
|
2427
|
+
if (!getService$2("permission").canConfigureContentType({ userAbility, contentType })) {
|
2184
2428
|
return ctx.forbidden();
|
2185
2429
|
}
|
2186
2430
|
let input;
|
@@ -2213,10 +2457,10 @@ const contentTypes = {
|
|
2213
2457
|
};
|
2214
2458
|
const init = {
|
2215
2459
|
getInitData(ctx) {
|
2216
|
-
const { toDto } = getService$
|
2217
|
-
const { findAllComponents } = getService$
|
2218
|
-
const { getAllFieldSizes } = getService$
|
2219
|
-
const { findAllContentTypes } = getService$
|
2460
|
+
const { toDto } = getService$2("data-mapper");
|
2461
|
+
const { findAllComponents } = getService$2("components");
|
2462
|
+
const { getAllFieldSizes } = getService$2("field-sizes");
|
2463
|
+
const { findAllContentTypes } = getService$2("content-types");
|
2220
2464
|
ctx.body = {
|
2221
2465
|
data: {
|
2222
2466
|
fieldSizes: getAllFieldSizes(),
|
@@ -2252,36 +2496,41 @@ const addFiltersClause = (params, filtersClause) => {
|
|
2252
2496
|
params.filters.$and.push(filtersClause);
|
2253
2497
|
};
|
2254
2498
|
const sanitizeMainField = (model, mainField, userAbility) => {
|
2255
|
-
const permissionChecker2 = getService$
|
2499
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2256
2500
|
userAbility,
|
2257
2501
|
model: model.uid
|
2258
2502
|
});
|
2259
|
-
|
2503
|
+
const isMainFieldListable = isListable(model, mainField);
|
2504
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2505
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2260
2506
|
return "id";
|
2261
2507
|
}
|
2262
|
-
if (
|
2263
|
-
|
2264
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2265
|
-
userAbility,
|
2266
|
-
model: "plugin::users-permissions.user"
|
2267
|
-
});
|
2268
|
-
if (userPermissionChecker.can.read()) {
|
2269
|
-
return "name";
|
2270
|
-
}
|
2271
|
-
}
|
2272
|
-
return "id";
|
2508
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2509
|
+
return "name";
|
2273
2510
|
}
|
2274
2511
|
return mainField;
|
2275
2512
|
};
|
2276
|
-
const addStatusToRelations = async (
|
2277
|
-
if (!contentTypes$1.hasDraftAndPublish(strapi.
|
2513
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2514
|
+
if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2278
2515
|
return relations2;
|
2279
2516
|
}
|
2280
|
-
const documentMetadata2 = getService$
|
2281
|
-
|
2517
|
+
const documentMetadata2 = getService$2("document-metadata");
|
2518
|
+
if (!relations2.length) {
|
2519
|
+
return relations2;
|
2520
|
+
}
|
2521
|
+
const firstRelation = relations2[0];
|
2522
|
+
const filters = {
|
2523
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2524
|
+
// NOTE: find the "opposite" status
|
2525
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2526
|
+
};
|
2527
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2528
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2529
|
+
filters
|
2530
|
+
});
|
2282
2531
|
return relations2.map((relation) => {
|
2283
|
-
const availableStatuses =
|
2284
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2532
|
+
const availableStatuses = availableStatus.filter(
|
2533
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2285
2534
|
);
|
2286
2535
|
return {
|
2287
2536
|
...relation,
|
@@ -2302,11 +2551,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2302
2551
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2303
2552
|
const isSourceLocalized = isLocalized(sourceModel);
|
2304
2553
|
const isTargetLocalized = isLocalized(targetModel);
|
2305
|
-
let validatedLocale = locale;
|
2306
|
-
if (!targetModel || !isTargetLocalized)
|
2307
|
-
validatedLocale = void 0;
|
2308
2554
|
return {
|
2309
|
-
locale
|
2555
|
+
locale,
|
2310
2556
|
isSourceLocalized,
|
2311
2557
|
isTargetLocalized
|
2312
2558
|
};
|
@@ -2346,7 +2592,7 @@ const relations = {
|
|
2346
2592
|
ctx.request?.query?.locale
|
2347
2593
|
);
|
2348
2594
|
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
2349
|
-
const permissionChecker2 = getService$
|
2595
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2350
2596
|
userAbility,
|
2351
2597
|
model
|
2352
2598
|
});
|
@@ -2371,7 +2617,7 @@ const relations = {
|
|
2371
2617
|
where.id = id;
|
2372
2618
|
}
|
2373
2619
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2374
|
-
const populate = await getService$
|
2620
|
+
const populate = await getService$2("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2375
2621
|
const currentEntity = await strapi.db.query(model).findOne({
|
2376
2622
|
where,
|
2377
2623
|
populate
|
@@ -2386,7 +2632,7 @@ const relations = {
|
|
2386
2632
|
}
|
2387
2633
|
entryId = currentEntity.id;
|
2388
2634
|
}
|
2389
|
-
const modelConfig = isComponent2 ? await getService$
|
2635
|
+
const modelConfig = isComponent2 ? await getService$2("components").findConfiguration(sourceSchema) : await getService$2("content-types").findConfiguration(sourceSchema);
|
2390
2636
|
const targetSchema = strapi.getModel(targetUid);
|
2391
2637
|
const mainField = flow(
|
2392
2638
|
prop(`metadatas.${targetField}.edit.mainField`),
|
@@ -2409,7 +2655,7 @@ const relations = {
|
|
2409
2655
|
attribute,
|
2410
2656
|
fieldsToSelect,
|
2411
2657
|
mainField,
|
2412
|
-
source: { schema: sourceSchema },
|
2658
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2413
2659
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2414
2660
|
sourceSchema,
|
2415
2661
|
targetSchema,
|
@@ -2431,7 +2677,8 @@ const relations = {
|
|
2431
2677
|
fieldsToSelect,
|
2432
2678
|
mainField,
|
2433
2679
|
source: {
|
2434
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2680
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2681
|
+
isLocalized: isSourceLocalized
|
2435
2682
|
},
|
2436
2683
|
target: {
|
2437
2684
|
schema: { uid: targetUid },
|
@@ -2439,7 +2686,7 @@ const relations = {
|
|
2439
2686
|
}
|
2440
2687
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2441
2688
|
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
2442
|
-
const permissionChecker2 = getService$
|
2689
|
+
const permissionChecker2 = getService$2("permission-checker").create({
|
2443
2690
|
userAbility: ctx.state.userAbility,
|
2444
2691
|
model: targetUid
|
2445
2692
|
});
|
@@ -2469,12 +2716,16 @@ const relations = {
|
|
2469
2716
|
} else {
|
2470
2717
|
where.id = id;
|
2471
2718
|
}
|
2472
|
-
|
2473
|
-
|
2719
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2720
|
+
if (!isEmpty(publishedAt)) {
|
2721
|
+
where[`${alias}.published_at`] = publishedAt;
|
2474
2722
|
}
|
2475
|
-
if (
|
2723
|
+
if (isTargetLocalized && locale) {
|
2476
2724
|
where[`${alias}.locale`] = locale;
|
2477
2725
|
}
|
2726
|
+
if (isSourceLocalized && locale) {
|
2727
|
+
where.locale = locale;
|
2728
|
+
}
|
2478
2729
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2479
2730
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2480
2731
|
}
|
@@ -2492,7 +2743,8 @@ const relations = {
|
|
2492
2743
|
id: { $notIn: uniq(idsToOmit) }
|
2493
2744
|
});
|
2494
2745
|
}
|
2495
|
-
const
|
2746
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2747
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2496
2748
|
ctx.body = {
|
2497
2749
|
...res,
|
2498
2750
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2507,29 +2759,39 @@ const relations = {
|
|
2507
2759
|
attribute,
|
2508
2760
|
targetField,
|
2509
2761
|
fieldsToSelect,
|
2510
|
-
|
2511
|
-
|
2512
|
-
}
|
2513
|
-
target: {
|
2514
|
-
schema: { uid: targetUid }
|
2515
|
-
}
|
2762
|
+
status,
|
2763
|
+
source: { schema: sourceSchema },
|
2764
|
+
target: { schema: targetSchema }
|
2516
2765
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2517
|
-
const
|
2766
|
+
const { uid: sourceUid } = sourceSchema;
|
2767
|
+
const { uid: targetUid } = targetSchema;
|
2768
|
+
const permissionQuery = await getService$2("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2518
2769
|
const dbQuery = strapi.db.query(sourceUid);
|
2519
2770
|
const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2771
|
+
const filters = {};
|
2772
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2773
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2774
|
+
if (status === "published") {
|
2775
|
+
filters.publishedAt = { $notNull: true };
|
2776
|
+
} else {
|
2777
|
+
filters.publishedAt = { $null: true };
|
2778
|
+
}
|
2779
|
+
}
|
2780
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2781
|
+
filters.publishedAt = { $null: true };
|
2782
|
+
}
|
2520
2783
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2521
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2784
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2522
2785
|
ordering: "desc",
|
2523
2786
|
page: ctx.request.query.page,
|
2524
|
-
pageSize: ctx.request.query.pageSize
|
2787
|
+
pageSize: ctx.request.query.pageSize,
|
2788
|
+
filters
|
2525
2789
|
});
|
2526
2790
|
const loadedIds = res.results.map((item) => item.id);
|
2527
2791
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2528
2792
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2529
2793
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2530
|
-
ordering: "desc"
|
2531
|
-
page: ctx.request.query.page,
|
2532
|
-
pageSize: ctx.request.query.pageSize
|
2794
|
+
ordering: "desc"
|
2533
2795
|
});
|
2534
2796
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2535
2797
|
ctx.body = {
|
@@ -2544,10 +2806,10 @@ const relations = {
|
|
2544
2806
|
}
|
2545
2807
|
};
|
2546
2808
|
const buildPopulateFromQuery = async (query, model) => {
|
2547
|
-
return getService$
|
2809
|
+
return getService$2("populate-builder")(model).populateFromQuery(query).populateDeep(Infinity).countRelations().build();
|
2548
2810
|
};
|
2549
2811
|
const findDocument = async (query, uid2, opts = {}) => {
|
2550
|
-
const documentManager2 = getService$
|
2812
|
+
const documentManager2 = getService$2("document-manager");
|
2551
2813
|
const populate = await buildPopulateFromQuery(query, uid2);
|
2552
2814
|
return documentManager2.findMany({ ...opts, populate }, uid2).then((documents) => documents[0]);
|
2553
2815
|
};
|
@@ -2555,13 +2817,13 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2555
2817
|
const { user, userAbility } = ctx.state;
|
2556
2818
|
const { model } = ctx.params;
|
2557
2819
|
const { body, query } = ctx.request;
|
2558
|
-
const documentManager2 = getService$
|
2559
|
-
const permissionChecker2 = getService$
|
2820
|
+
const documentManager2 = getService$2("document-manager");
|
2821
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2560
2822
|
if (permissionChecker2.cannot.create() && permissionChecker2.cannot.update()) {
|
2561
2823
|
throw new errors.ForbiddenError();
|
2562
2824
|
}
|
2563
2825
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2564
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2826
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2565
2827
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2566
2828
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2567
2829
|
// Find the first document to check if it exists
|
@@ -2597,12 +2859,12 @@ const singleTypes = {
|
|
2597
2859
|
const { userAbility } = ctx.state;
|
2598
2860
|
const { model } = ctx.params;
|
2599
2861
|
const { query = {} } = ctx.request;
|
2600
|
-
const permissionChecker2 = getService$
|
2862
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2601
2863
|
if (permissionChecker2.cannot.read()) {
|
2602
2864
|
return ctx.forbidden();
|
2603
2865
|
}
|
2604
2866
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2605
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2867
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2606
2868
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2607
2869
|
if (!version) {
|
2608
2870
|
if (permissionChecker2.cannot.create()) {
|
@@ -2616,7 +2878,7 @@ const singleTypes = {
|
|
2616
2878
|
permissionChecker2,
|
2617
2879
|
model,
|
2618
2880
|
// @ts-expect-error - fix types
|
2619
|
-
{
|
2881
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2620
2882
|
{ availableLocales: true, availableStatus: false }
|
2621
2883
|
);
|
2622
2884
|
ctx.body = { data: {}, meta };
|
@@ -2631,7 +2893,7 @@ const singleTypes = {
|
|
2631
2893
|
async createOrUpdate(ctx) {
|
2632
2894
|
const { userAbility } = ctx.state;
|
2633
2895
|
const { model } = ctx.params;
|
2634
|
-
const permissionChecker2 = getService$
|
2896
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2635
2897
|
const document = await createOrUpdateDocument(ctx);
|
2636
2898
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2637
2899
|
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
@@ -2640,14 +2902,14 @@ const singleTypes = {
|
|
2640
2902
|
const { userAbility } = ctx.state;
|
2641
2903
|
const { model } = ctx.params;
|
2642
2904
|
const { query = {} } = ctx.request;
|
2643
|
-
const documentManager2 = getService$
|
2644
|
-
const permissionChecker2 = getService$
|
2905
|
+
const documentManager2 = getService$2("document-manager");
|
2906
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2645
2907
|
if (permissionChecker2.cannot.delete()) {
|
2646
2908
|
return ctx.forbidden();
|
2647
2909
|
}
|
2648
2910
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2649
2911
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2650
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2912
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2651
2913
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2652
2914
|
populate,
|
2653
2915
|
locale
|
@@ -2669,8 +2931,8 @@ const singleTypes = {
|
|
2669
2931
|
const { userAbility } = ctx.state;
|
2670
2932
|
const { model } = ctx.params;
|
2671
2933
|
const { query = {} } = ctx.request;
|
2672
|
-
const documentManager2 = getService$
|
2673
|
-
const permissionChecker2 = getService$
|
2934
|
+
const documentManager2 = getService$2("document-manager");
|
2935
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2674
2936
|
if (permissionChecker2.cannot.publish()) {
|
2675
2937
|
return ctx.forbidden();
|
2676
2938
|
}
|
@@ -2684,7 +2946,7 @@ const singleTypes = {
|
|
2684
2946
|
if (permissionChecker2.cannot.publish(document)) {
|
2685
2947
|
throw new errors.ForbiddenError();
|
2686
2948
|
}
|
2687
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2949
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2688
2950
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2689
2951
|
return publishResult.at(0);
|
2690
2952
|
});
|
@@ -2698,8 +2960,8 @@ const singleTypes = {
|
|
2698
2960
|
body: { discardDraft, ...body },
|
2699
2961
|
query = {}
|
2700
2962
|
} = ctx.request;
|
2701
|
-
const documentManager2 = getService$
|
2702
|
-
const permissionChecker2 = getService$
|
2963
|
+
const documentManager2 = getService$2("document-manager");
|
2964
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2703
2965
|
if (permissionChecker2.cannot.unpublish()) {
|
2704
2966
|
return ctx.forbidden();
|
2705
2967
|
}
|
@@ -2707,7 +2969,7 @@ const singleTypes = {
|
|
2707
2969
|
return ctx.forbidden();
|
2708
2970
|
}
|
2709
2971
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2710
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2972
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2711
2973
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2712
2974
|
if (!document) {
|
2713
2975
|
return ctx.notFound();
|
@@ -2733,13 +2995,13 @@ const singleTypes = {
|
|
2733
2995
|
const { userAbility } = ctx.state;
|
2734
2996
|
const { model } = ctx.params;
|
2735
2997
|
const { body, query = {} } = ctx.request;
|
2736
|
-
const documentManager2 = getService$
|
2737
|
-
const permissionChecker2 = getService$
|
2998
|
+
const documentManager2 = getService$2("document-manager");
|
2999
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
2738
3000
|
if (permissionChecker2.cannot.discard()) {
|
2739
3001
|
return ctx.forbidden();
|
2740
3002
|
}
|
2741
3003
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2742
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
3004
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2743
3005
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2744
3006
|
if (!document) {
|
2745
3007
|
return ctx.notFound();
|
@@ -2757,9 +3019,9 @@ const singleTypes = {
|
|
2757
3019
|
const { userAbility } = ctx.state;
|
2758
3020
|
const { model } = ctx.params;
|
2759
3021
|
const { query } = ctx.request;
|
2760
|
-
const documentManager2 = getService$
|
2761
|
-
const permissionChecker2 = getService$
|
2762
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3022
|
+
const documentManager2 = getService$2("document-manager");
|
3023
|
+
const permissionChecker2 = getService$2("permission-checker").create({ userAbility, model });
|
3024
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2763
3025
|
if (permissionChecker2.cannot.read()) {
|
2764
3026
|
return ctx.forbidden();
|
2765
3027
|
}
|
@@ -2780,9 +3042,9 @@ const uid$1 = {
|
|
2780
3042
|
async generateUID(ctx) {
|
2781
3043
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2782
3044
|
const { query = {} } = ctx.request;
|
2783
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3045
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2784
3046
|
await validateUIDField(contentTypeUID, field);
|
2785
|
-
const uidService = getService$
|
3047
|
+
const uidService = getService$2("uid");
|
2786
3048
|
ctx.body = {
|
2787
3049
|
data: await uidService.generateUIDField({ contentTypeUID, field, data, locale })
|
2788
3050
|
};
|
@@ -2792,9 +3054,9 @@ const uid$1 = {
|
|
2792
3054
|
ctx.request.body
|
2793
3055
|
);
|
2794
3056
|
const { query = {} } = ctx.request;
|
2795
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
3057
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2796
3058
|
await validateUIDField(contentTypeUID, field);
|
2797
|
-
const uidService = getService$
|
3059
|
+
const uidService = getService$2("uid");
|
2798
3060
|
const isAvailable = await uidService.checkUIDAvailability({
|
2799
3061
|
contentTypeUID,
|
2800
3062
|
field,
|
@@ -2815,7 +3077,8 @@ const controllers = {
|
|
2815
3077
|
relations,
|
2816
3078
|
"single-types": singleTypes,
|
2817
3079
|
uid: uid$1,
|
2818
|
-
...history.controllers ? history.controllers : {}
|
3080
|
+
...history.controllers ? history.controllers : {},
|
3081
|
+
...preview.controllers ? preview.controllers : {}
|
2819
3082
|
};
|
2820
3083
|
const keys = {
|
2821
3084
|
CONFIGURATION: "configuration"
|
@@ -2966,12 +3229,12 @@ async function syncMetadatas(configuration, schema) {
|
|
2966
3229
|
return _.assign(metasWithDefaults, updatedMetas);
|
2967
3230
|
}
|
2968
3231
|
const getTargetSchema = (targetModel) => {
|
2969
|
-
return getService$
|
3232
|
+
return getService$2("content-types").findContentType(targetModel);
|
2970
3233
|
};
|
2971
3234
|
const DEFAULT_LIST_LENGTH = 4;
|
2972
3235
|
const MAX_ROW_SIZE = 12;
|
2973
3236
|
const isAllowedFieldSize = (type, size) => {
|
2974
|
-
const { getFieldSize } = getService$
|
3237
|
+
const { getFieldSize } = getService$2("field-sizes");
|
2975
3238
|
const fieldSize = getFieldSize(type);
|
2976
3239
|
if (!fieldSize.isResizable && size !== fieldSize.default) {
|
2977
3240
|
return false;
|
@@ -2979,7 +3242,7 @@ const isAllowedFieldSize = (type, size) => {
|
|
2979
3242
|
return size <= MAX_ROW_SIZE;
|
2980
3243
|
};
|
2981
3244
|
const getDefaultFieldSize = (attribute) => {
|
2982
|
-
const { hasFieldSize, getFieldSize } = getService$
|
3245
|
+
const { hasFieldSize, getFieldSize } = getService$2("field-sizes");
|
2983
3246
|
return getFieldSize(hasFieldSize(attribute.customField) ? attribute.customField : attribute.type).default;
|
2984
3247
|
};
|
2985
3248
|
async function createDefaultLayouts(schema) {
|
@@ -3014,7 +3277,7 @@ function syncLayouts(configuration, schema) {
|
|
3014
3277
|
for (const el of row) {
|
3015
3278
|
if (!hasEditableAttribute(schema, el.name))
|
3016
3279
|
continue;
|
3017
|
-
const { hasFieldSize } = getService$
|
3280
|
+
const { hasFieldSize } = getService$2("field-sizes");
|
3018
3281
|
const fieldType = hasFieldSize(schema.attributes[el.name].customField) ? schema.attributes[el.name].customField : schema.attributes[el.name].type;
|
3019
3282
|
if (!isAllowedFieldSize(fieldType, el.size)) {
|
3020
3283
|
elementsToReAppend.push(el.name);
|
@@ -3154,17 +3417,17 @@ const configurationService$1 = createConfigurationService({
|
|
3154
3417
|
isComponent: true,
|
3155
3418
|
prefix: STORE_KEY_PREFIX,
|
3156
3419
|
getModels() {
|
3157
|
-
const { toContentManagerModel } = getService$
|
3420
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3158
3421
|
return mapValues(toContentManagerModel, strapi.components);
|
3159
3422
|
}
|
3160
3423
|
});
|
3161
3424
|
const components = ({ strapi: strapi2 }) => ({
|
3162
3425
|
findAllComponents() {
|
3163
|
-
const { toContentManagerModel } = getService$
|
3426
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3164
3427
|
return Object.values(strapi2.components).map(toContentManagerModel);
|
3165
3428
|
},
|
3166
3429
|
findComponent(uid2) {
|
3167
|
-
const { toContentManagerModel } = getService$
|
3430
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3168
3431
|
const component = strapi2.components[uid2];
|
3169
3432
|
return isNil$1(component) ? component : toContentManagerModel(component);
|
3170
3433
|
},
|
@@ -3215,17 +3478,17 @@ const configurationService = createConfigurationService({
|
|
3215
3478
|
storeUtils,
|
3216
3479
|
prefix: "content_types",
|
3217
3480
|
getModels() {
|
3218
|
-
const { toContentManagerModel } = getService$
|
3481
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3219
3482
|
return mapValues(toContentManagerModel, strapi.contentTypes);
|
3220
3483
|
}
|
3221
3484
|
});
|
3222
3485
|
const service = ({ strapi: strapi2 }) => ({
|
3223
3486
|
findAllContentTypes() {
|
3224
|
-
const { toContentManagerModel } = getService$
|
3487
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3225
3488
|
return Object.values(strapi2.contentTypes).map(toContentManagerModel);
|
3226
3489
|
},
|
3227
3490
|
findContentType(uid2) {
|
3228
|
-
const { toContentManagerModel } = getService$
|
3491
|
+
const { toContentManagerModel } = getService$2("data-mapper");
|
3229
3492
|
const contentType = strapi2.contentTypes[uid2];
|
3230
3493
|
return isNil$1(contentType) ? contentType : toContentManagerModel(contentType);
|
3231
3494
|
},
|
@@ -3254,7 +3517,7 @@ const service = ({ strapi: strapi2 }) => ({
|
|
3254
3517
|
return this.findConfiguration(contentType);
|
3255
3518
|
},
|
3256
3519
|
findComponentsConfigurations(contentType) {
|
3257
|
-
return getService$
|
3520
|
+
return getService$2("components").findComponentsConfigurations(contentType);
|
3258
3521
|
},
|
3259
3522
|
syncConfigurations() {
|
3260
3523
|
return configurationService.syncConfigurations();
|
@@ -3435,12 +3698,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3435
3698
|
ability: userAbility,
|
3436
3699
|
model
|
3437
3700
|
});
|
3438
|
-
const
|
3701
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3702
|
+
const toSubject = (entity) => {
|
3703
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3704
|
+
};
|
3439
3705
|
const can = (action, entity, field) => {
|
3440
|
-
|
3706
|
+
const subject = toSubject(entity);
|
3707
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3708
|
+
return (
|
3709
|
+
// Test the original action to see if it passes
|
3710
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3711
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3712
|
+
);
|
3441
3713
|
};
|
3442
3714
|
const cannot = (action, entity, field) => {
|
3443
|
-
|
3715
|
+
const subject = toSubject(entity);
|
3716
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3717
|
+
return (
|
3718
|
+
// Test both the original action
|
3719
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3720
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3721
|
+
);
|
3444
3722
|
};
|
3445
3723
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3446
3724
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3511,7 +3789,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3511
3789
|
return userAbility.can(action);
|
3512
3790
|
},
|
3513
3791
|
async registerPermissions() {
|
3514
|
-
const displayedContentTypes = getService$
|
3792
|
+
const displayedContentTypes = getService$2("content-types").findDisplayedContentTypes();
|
3515
3793
|
const contentTypesUids = displayedContentTypes.map(prop("uid"));
|
3516
3794
|
const actions = [
|
3517
3795
|
{
|
@@ -3717,6 +3995,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3717
3995
|
const attribute = model.attributes[attributeName];
|
3718
3996
|
switch (attribute.type) {
|
3719
3997
|
case "relation": {
|
3998
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3999
|
+
if (isMorphRelation) {
|
4000
|
+
break;
|
4001
|
+
}
|
3720
4002
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3721
4003
|
populateAcc[attributeName] = {
|
3722
4004
|
count: true,
|
@@ -3783,7 +4065,7 @@ const getQueryPopulate = async (uid2, query) => {
|
|
3783
4065
|
return populateQuery;
|
3784
4066
|
};
|
3785
4067
|
const buildDeepPopulate = (uid2) => {
|
3786
|
-
return getService$
|
4068
|
+
return getService$2("populate-builder")(uid2).populateDeep(Infinity).countRelations().build();
|
3787
4069
|
};
|
3788
4070
|
const populateBuilder = (uid2) => {
|
3789
4071
|
let getInitialPopulate = async () => {
|
@@ -3968,7 +4250,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3968
4250
|
*/
|
3969
4251
|
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3970
4252
|
const versionsByLocale = groupBy("locale", allVersions);
|
3971
|
-
|
4253
|
+
if (version.locale) {
|
4254
|
+
delete versionsByLocale[version.locale];
|
4255
|
+
}
|
3972
4256
|
const model = strapi2.getModel(uid2);
|
3973
4257
|
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3974
4258
|
const traversalFunction = async (localeVersion) => traverseEntity(
|
@@ -4094,7 +4378,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4094
4378
|
*/
|
4095
4379
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4096
4380
|
if (!document) {
|
4097
|
-
return
|
4381
|
+
return {
|
4382
|
+
data: document,
|
4383
|
+
meta: {
|
4384
|
+
availableLocales: [],
|
4385
|
+
availableStatus: []
|
4386
|
+
}
|
4387
|
+
};
|
4098
4388
|
}
|
4099
4389
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
4100
4390
|
if (!hasDraftAndPublish) {
|
@@ -4202,10 +4492,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4202
4492
|
async clone(id, body, uid2) {
|
4203
4493
|
const populate = await buildDeepPopulate(uid2);
|
4204
4494
|
const params = {
|
4205
|
-
data:
|
4206
|
-
...omitIdField(body),
|
4207
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4208
|
-
},
|
4495
|
+
data: omitIdField(body),
|
4209
4496
|
populate
|
4210
4497
|
};
|
4211
4498
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4321,7 +4608,8 @@ const services = {
|
|
4321
4608
|
permission,
|
4322
4609
|
"populate-builder": populateBuilder$1,
|
4323
4610
|
uid,
|
4324
|
-
...history.services ? history.services : {}
|
4611
|
+
...history.services ? history.services : {},
|
4612
|
+
...preview.services ? preview.services : {}
|
4325
4613
|
};
|
4326
4614
|
const index = () => {
|
4327
4615
|
return {
|