@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.c3e9d4b26f9fd3d9eb530b5c11f9baa1d09b13ad
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs → ComponentConfigurationPage-BMajAl1u.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-BMajAl1u.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-y_7iLdmB.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-y_7iLdmB.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
- package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
- package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-CPVB8Uqc.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-CPVB8Uqc.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-CcOoD26O.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-CcOoD26O.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-CTTDHKkQ.js} +7 -9
- package/dist/_chunks/EditViewPage-CTTDHKkQ.js.map +1 -0
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-DWb0DE7R.mjs} +6 -6
- package/dist/_chunks/EditViewPage-DWb0DE7R.mjs.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-C5Z1Ivdv.js} +552 -661
- package/dist/_chunks/Field-C5Z1Ivdv.js.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-DnStdvQw.mjs} +500 -608
- package/dist/_chunks/Field-DnStdvQw.mjs.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-B81OtW-k.js} +21 -19
- package/dist/_chunks/Form-B81OtW-k.js.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-DqGgE55Q.mjs} +21 -18
- package/dist/_chunks/Form-DqGgE55Q.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-4NbOq2dX.js} +119 -49
- package/dist/_chunks/History-4NbOq2dX.js.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-DS6-HCYX.mjs} +119 -48
- package/dist/_chunks/History-DS6-HCYX.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-CpfstlYY.js} +17 -19
- package/dist/_chunks/ListConfigurationPage-CpfstlYY.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-DQJJltko.mjs} +14 -14
- package/dist/_chunks/ListConfigurationPage-DQJJltko.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-CA3I75m5.js} +43 -51
- package/dist/_chunks/ListViewPage-CA3I75m5.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-nQrOQuVo.mjs} +37 -45
- package/dist/_chunks/ListViewPage-nQrOQuVo.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-DbnHE22g.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-DbnHE22g.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-Dldu-_Mx.js} +5 -5
- package/dist/_chunks/NoContentTypePage-Dldu-_Mx.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-CO2MK200.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-CO2MK200.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-fOIkQM0v.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-fOIkQM0v.mjs.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-BDRl99Ux.mjs} +66 -56
- package/dist/_chunks/Relations-BDRl99Ux.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-DG2jnOcr.js} +70 -61
- package/dist/_chunks/Relations-DG2jnOcr.js.map +1 -0
- package/dist/_chunks/{en-MBPul9Su.mjs → en-Ux26r5pl.mjs} +7 -1
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Ux26r5pl.mjs.map} +1 -1
- package/dist/_chunks/{en-C-V1_90f.js → en-fbKQxLGn.js} +7 -1
- package/dist/_chunks/{en-C-V1_90f.js.map → en-fbKQxLGn.js.map} +1 -1
- package/dist/_chunks/{index-X_2tafck.js → index-BZoNZMXL.js} +1556 -795
- package/dist/_chunks/index-BZoNZMXL.js.map +1 -0
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-Drt2DN7v.mjs} +1569 -807
- package/dist/_chunks/index-Drt2DN7v.mjs.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-BzAbmoO6.mjs} +27 -22
- package/dist/_chunks/layout-BzAbmoO6.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-DEYBqgF1.js} +28 -25
- package/dist/_chunks/layout-DEYBqgF1.js.map +1 -0
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-D0eZ4VWw.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-D0eZ4VWw.js.map} +1 -1
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-D26zVRdi.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-D26zVRdi.mjs.map} +1 -1
- package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
- package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
- package/dist/_chunks/usePrev-DH6iah0A.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/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +3 -3
- package/dist/admin/src/exports.d.ts +1 -0
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +5 -8
- package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
- package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
- package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +3 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +67 -52
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- package/dist/admin/src/services/api.d.ts +2 -3
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +5 -5
- package/dist/admin/src/services/documents.d.ts +29 -17
- package/dist/admin/src/services/init.d.ts +2 -2
- package/dist/admin/src/services/relations.d.ts +3 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/api.d.ts +4 -18
- package/dist/admin/src/utils/validation.d.ts +1 -6
- package/dist/server/index.js +540 -414
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +548 -422
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/index.d.ts +1 -1
- package/dist/server/src/history/services/history.d.ts +2 -4
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/index.d.ts +6 -2
- package/dist/server/src/history/services/index.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts +9 -0
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
- package/dist/server/src/history/services/utils.d.ts +41 -9
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/history/utils.d.ts +6 -2
- package/dist/server/src/history/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +18 -39
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts +13 -12
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -29
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +18 -39
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +8 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +14 -6
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/relations.d.ts +2 -2
- package/dist/shared/contracts/relations.d.ts.map +1 -1
- package/package.json +13 -14
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
- package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
- package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
- package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
- package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
- package/dist/_chunks/History-C17LiyRg.js.map +0 -1
- package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
- package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
- package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
- package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
- package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
- package/dist/_chunks/index-X_2tafck.js.map +0 -1
- package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
- package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
- package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
package/dist/server/index.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1,
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set,
|
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, isNil as isNil$1, getOr, propEq, merge, groupBy, castArray } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -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 } = await getService(strapi2, "history").findVersionsPage({
|
57
|
+
const { results, pagination: pagination2 } = await getService(strapi2, "history").findVersionsPage({
|
58
58
|
query: {
|
59
59
|
...query,
|
60
60
|
...getValidPagination({ page: query.page, pageSize: query.pageSize })
|
@@ -73,7 +73,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
73
73
|
);
|
74
74
|
return {
|
75
75
|
data: sanitizedResults,
|
76
|
-
meta: { pagination }
|
76
|
+
meta: { pagination: pagination2 }
|
77
77
|
};
|
78
78
|
},
|
79
79
|
async restoreVersion(ctx) {
|
@@ -112,40 +112,65 @@ const FIELDS_TO_IGNORE = [
|
|
112
112
|
"strapi_stage",
|
113
113
|
"strapi_assignee"
|
114
114
|
];
|
115
|
-
const getSchemaAttributesDiff = (versionSchemaAttributes, contentTypeSchemaAttributes) => {
|
116
|
-
const sanitizedContentTypeSchemaAttributes = omit(FIELDS_TO_IGNORE, contentTypeSchemaAttributes);
|
117
|
-
const reduceDifferenceToAttributesObject = (diffKeys, source) => {
|
118
|
-
return diffKeys.reduce((previousAttributesObject, diffKey) => {
|
119
|
-
previousAttributesObject[diffKey] = source[diffKey];
|
120
|
-
return previousAttributesObject;
|
121
|
-
}, {});
|
122
|
-
};
|
123
|
-
const versionSchemaKeys = Object.keys(versionSchemaAttributes);
|
124
|
-
const contentTypeSchemaAttributesKeys = Object.keys(sanitizedContentTypeSchemaAttributes);
|
125
|
-
const uniqueToContentType = difference(contentTypeSchemaAttributesKeys, versionSchemaKeys);
|
126
|
-
const added = reduceDifferenceToAttributesObject(
|
127
|
-
uniqueToContentType,
|
128
|
-
sanitizedContentTypeSchemaAttributes
|
129
|
-
);
|
130
|
-
const uniqueToVersion = difference(versionSchemaKeys, contentTypeSchemaAttributesKeys);
|
131
|
-
const removed = reduceDifferenceToAttributesObject(uniqueToVersion, versionSchemaAttributes);
|
132
|
-
return { added, removed };
|
133
|
-
};
|
134
115
|
const DEFAULT_RETENTION_DAYS = 90;
|
135
|
-
const
|
136
|
-
const
|
137
|
-
|
138
|
-
|
116
|
+
const createServiceUtils = ({ strapi: strapi2 }) => {
|
117
|
+
const getSchemaAttributesDiff = (versionSchemaAttributes, contentTypeSchemaAttributes) => {
|
118
|
+
const sanitizedContentTypeSchemaAttributes = omit(
|
119
|
+
FIELDS_TO_IGNORE,
|
120
|
+
contentTypeSchemaAttributes
|
121
|
+
);
|
122
|
+
const reduceDifferenceToAttributesObject = (diffKeys, source) => {
|
123
|
+
return diffKeys.reduce(
|
124
|
+
(previousAttributesObject, diffKey) => {
|
125
|
+
previousAttributesObject[diffKey] = source[diffKey];
|
126
|
+
return previousAttributesObject;
|
127
|
+
},
|
128
|
+
{}
|
129
|
+
);
|
130
|
+
};
|
131
|
+
const versionSchemaKeys = Object.keys(versionSchemaAttributes);
|
132
|
+
const contentTypeSchemaAttributesKeys = Object.keys(sanitizedContentTypeSchemaAttributes);
|
133
|
+
const uniqueToContentType = difference(contentTypeSchemaAttributesKeys, versionSchemaKeys);
|
134
|
+
const added = reduceDifferenceToAttributesObject(
|
135
|
+
uniqueToContentType,
|
136
|
+
sanitizedContentTypeSchemaAttributes
|
137
|
+
);
|
138
|
+
const uniqueToVersion = difference(versionSchemaKeys, contentTypeSchemaAttributesKeys);
|
139
|
+
const removed = reduceDifferenceToAttributesObject(uniqueToVersion, versionSchemaAttributes);
|
140
|
+
return { added, removed };
|
139
141
|
};
|
140
|
-
const
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
142
|
+
const getRelationRestoreValue = async (versionRelationData, attribute) => {
|
143
|
+
if (Array.isArray(versionRelationData)) {
|
144
|
+
if (versionRelationData.length === 0)
|
145
|
+
return versionRelationData;
|
146
|
+
const existingAndMissingRelations = await Promise.all(
|
147
|
+
versionRelationData.map((relation) => {
|
148
|
+
return strapi2.documents(attribute.target).findOne({
|
149
|
+
documentId: relation.documentId,
|
150
|
+
locale: relation.locale || void 0
|
151
|
+
});
|
152
|
+
})
|
153
|
+
);
|
154
|
+
return existingAndMissingRelations.filter(
|
155
|
+
(relation) => relation !== null
|
156
|
+
);
|
147
157
|
}
|
148
|
-
return
|
158
|
+
return strapi2.documents(attribute.target).findOne({
|
159
|
+
documentId: versionRelationData.documentId,
|
160
|
+
locale: versionRelationData.locale || void 0
|
161
|
+
});
|
162
|
+
};
|
163
|
+
const getMediaRestoreValue = async (versionRelationData, attribute) => {
|
164
|
+
if (attribute.multiple) {
|
165
|
+
const existingAndMissingMedias = await Promise.all(
|
166
|
+
// @ts-expect-error Fix the type definitions so this isn't any
|
167
|
+
versionRelationData.map((media) => {
|
168
|
+
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
169
|
+
})
|
170
|
+
);
|
171
|
+
return existingAndMissingMedias.filter((media) => media != null);
|
172
|
+
}
|
173
|
+
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
149
174
|
};
|
150
175
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
151
176
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
@@ -161,6 +186,15 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
161
186
|
{}
|
162
187
|
);
|
163
188
|
};
|
189
|
+
const getRetentionDays = () => {
|
190
|
+
const featureConfig = strapi2.ee.features.get("cms-content-history");
|
191
|
+
const licenseRetentionDays = typeof featureConfig === "object" && featureConfig?.options.retentionDays;
|
192
|
+
const userRetentionDays = strapi2.config.get("admin.history.retentionDays");
|
193
|
+
if (userRetentionDays && userRetentionDays < licenseRetentionDays) {
|
194
|
+
return userRetentionDays;
|
195
|
+
}
|
196
|
+
return Math.min(licenseRetentionDays, DEFAULT_RETENTION_DAYS);
|
197
|
+
};
|
164
198
|
const getVersionStatus = async (contentTypeUid, document) => {
|
165
199
|
const documentMetadataService = strapi2.plugin("content-manager").service("document-metadata");
|
166
200
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
@@ -202,80 +236,68 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
202
236
|
return acc;
|
203
237
|
}, {});
|
204
238
|
};
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
212
|
-
return next();
|
239
|
+
const buildMediaResponse = async (values) => {
|
240
|
+
return values.slice(0, 25).reduce(
|
241
|
+
async (currentRelationDataPromise, entry) => {
|
242
|
+
const currentRelationData = await currentRelationDataPromise;
|
243
|
+
if (!entry) {
|
244
|
+
return currentRelationData;
|
213
245
|
}
|
214
|
-
|
215
|
-
|
246
|
+
const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
|
247
|
+
if (relatedEntry) {
|
248
|
+
currentRelationData.results.push(relatedEntry);
|
249
|
+
} else {
|
250
|
+
currentRelationData.meta.missingCount += 1;
|
216
251
|
}
|
217
|
-
|
218
|
-
|
219
|
-
|
252
|
+
return currentRelationData;
|
253
|
+
},
|
254
|
+
Promise.resolve({
|
255
|
+
results: [],
|
256
|
+
meta: { missingCount: 0 }
|
257
|
+
})
|
258
|
+
);
|
259
|
+
};
|
260
|
+
const buildRelationReponse = async (values, attributeSchema) => {
|
261
|
+
return values.slice(0, 25).reduce(
|
262
|
+
async (currentRelationDataPromise, entry) => {
|
263
|
+
const currentRelationData = await currentRelationDataPromise;
|
264
|
+
if (!entry) {
|
265
|
+
return currentRelationData;
|
220
266
|
}
|
221
|
-
const
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
documentId: documentContext.documentId,
|
227
|
-
locale,
|
228
|
-
populate: getDeepPopulate2(contentTypeUid)
|
229
|
-
});
|
230
|
-
const status = await getVersionStatus(contentTypeUid, document);
|
231
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
232
|
-
const componentsSchemas = Object.keys(
|
233
|
-
attributesSchema
|
234
|
-
).reduce((currentComponentSchemas, key) => {
|
235
|
-
const fieldSchema = attributesSchema[key];
|
236
|
-
if (fieldSchema.type === "component") {
|
237
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
238
|
-
return {
|
239
|
-
...currentComponentSchemas,
|
240
|
-
[fieldSchema.component]: componentSchema
|
241
|
-
};
|
242
|
-
}
|
243
|
-
return currentComponentSchemas;
|
244
|
-
}, {});
|
245
|
-
await strapi2.db.transaction(async ({ onCommit }) => {
|
246
|
-
onCommit(() => {
|
247
|
-
this.createVersion({
|
248
|
-
contentType: contentTypeUid,
|
249
|
-
data: omit(FIELDS_TO_IGNORE, document),
|
250
|
-
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
251
|
-
componentsSchemas,
|
252
|
-
relatedDocumentId: documentContext.documentId,
|
253
|
-
locale,
|
254
|
-
status
|
255
|
-
});
|
267
|
+
const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
|
268
|
+
if (relatedEntry) {
|
269
|
+
currentRelationData.results.push({
|
270
|
+
...relatedEntry,
|
271
|
+
status: await getVersionStatus(attributeSchema.target, relatedEntry)
|
256
272
|
});
|
257
|
-
}
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
273
|
+
} else {
|
274
|
+
currentRelationData.meta.missingCount += 1;
|
275
|
+
}
|
276
|
+
return currentRelationData;
|
277
|
+
},
|
278
|
+
Promise.resolve({
|
279
|
+
results: [],
|
280
|
+
meta: { missingCount: 0 }
|
281
|
+
})
|
282
|
+
);
|
283
|
+
};
|
284
|
+
return {
|
285
|
+
getSchemaAttributesDiff,
|
286
|
+
getRelationRestoreValue,
|
287
|
+
getMediaRestoreValue,
|
288
|
+
getDefaultLocale,
|
289
|
+
getLocaleDictionary,
|
290
|
+
getRetentionDays,
|
291
|
+
getVersionStatus,
|
292
|
+
getDeepPopulate: getDeepPopulate2,
|
293
|
+
buildMediaResponse,
|
294
|
+
buildRelationReponse
|
295
|
+
};
|
296
|
+
};
|
297
|
+
const createHistoryService = ({ strapi: strapi2 }) => {
|
298
|
+
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
299
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
300
|
+
return {
|
279
301
|
async createVersion(historyVersionData) {
|
280
302
|
await query.create({
|
281
303
|
data: {
|
@@ -286,8 +308,8 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
286
308
|
});
|
287
309
|
},
|
288
310
|
async findVersionsPage(params) {
|
289
|
-
const locale = params.query.locale || await getDefaultLocale();
|
290
|
-
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
311
|
+
const locale = params.query.locale || await serviceUtils.getDefaultLocale();
|
312
|
+
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
291
313
|
query.findPage({
|
292
314
|
...params.query,
|
293
315
|
where: {
|
@@ -300,78 +322,34 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
300
322
|
populate: ["createdBy"],
|
301
323
|
orderBy: [{ createdAt: "desc" }]
|
302
324
|
}),
|
303
|
-
getLocaleDictionary()
|
325
|
+
serviceUtils.getLocaleDictionary()
|
304
326
|
]);
|
305
|
-
const buildRelationReponse = async (values, attributeSchema) => {
|
306
|
-
return values.slice(0, 25).reduce(
|
307
|
-
async (currentRelationDataPromise, entry) => {
|
308
|
-
const currentRelationData = await currentRelationDataPromise;
|
309
|
-
if (!entry) {
|
310
|
-
return currentRelationData;
|
311
|
-
}
|
312
|
-
const relatedEntry = await strapi2.documents(attributeSchema.target).findOne({ documentId: entry.documentId, locale: entry.locale || void 0 });
|
313
|
-
const permissionChecker2 = getService$1("permission-checker").create({
|
314
|
-
userAbility: params.state.userAbility,
|
315
|
-
model: attributeSchema.target
|
316
|
-
});
|
317
|
-
const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
|
318
|
-
if (sanitizedEntry) {
|
319
|
-
currentRelationData.results.push({
|
320
|
-
...sanitizedEntry,
|
321
|
-
status: await getVersionStatus(attributeSchema.target, sanitizedEntry)
|
322
|
-
});
|
323
|
-
} else {
|
324
|
-
currentRelationData.meta.missingCount += 1;
|
325
|
-
}
|
326
|
-
return currentRelationData;
|
327
|
-
},
|
328
|
-
Promise.resolve({
|
329
|
-
results: [],
|
330
|
-
meta: { missingCount: 0 }
|
331
|
-
})
|
332
|
-
);
|
333
|
-
};
|
334
|
-
const buildMediaResponse = async (values) => {
|
335
|
-
return values.slice(0, 25).reduce(
|
336
|
-
async (currentRelationDataPromise, entry) => {
|
337
|
-
const currentRelationData = await currentRelationDataPromise;
|
338
|
-
if (!entry) {
|
339
|
-
return currentRelationData;
|
340
|
-
}
|
341
|
-
const permissionChecker2 = getService$1("permission-checker").create({
|
342
|
-
userAbility: params.state.userAbility,
|
343
|
-
model: "plugin::upload.file"
|
344
|
-
});
|
345
|
-
const relatedEntry = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: entry.id } });
|
346
|
-
const sanitizedEntry = await permissionChecker2.sanitizeOutput(relatedEntry);
|
347
|
-
if (sanitizedEntry) {
|
348
|
-
currentRelationData.results.push(sanitizedEntry);
|
349
|
-
} else {
|
350
|
-
currentRelationData.meta.missingCount += 1;
|
351
|
-
}
|
352
|
-
return currentRelationData;
|
353
|
-
},
|
354
|
-
Promise.resolve({
|
355
|
-
results: [],
|
356
|
-
meta: { missingCount: 0 }
|
357
|
-
})
|
358
|
-
);
|
359
|
-
};
|
360
327
|
const populateEntryRelations = async (entry) => {
|
361
328
|
const entryWithRelations = await Object.entries(entry.schema).reduce(
|
362
329
|
async (currentDataWithRelations, [attributeKey, attributeSchema]) => {
|
363
330
|
const attributeValue = entry.data[attributeKey];
|
364
331
|
const attributeValues = Array.isArray(attributeValue) ? attributeValue : [attributeValue];
|
365
332
|
if (attributeSchema.type === "media") {
|
333
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
334
|
+
userAbility: params.state.userAbility,
|
335
|
+
model: "plugin::upload.file"
|
336
|
+
});
|
337
|
+
const response = await serviceUtils.buildMediaResponse(attributeValues);
|
338
|
+
const sanitizedResults = await Promise.all(
|
339
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
340
|
+
);
|
366
341
|
return {
|
367
342
|
...await currentDataWithRelations,
|
368
|
-
[attributeKey]:
|
343
|
+
[attributeKey]: {
|
344
|
+
results: sanitizedResults,
|
345
|
+
meta: response.meta
|
346
|
+
}
|
369
347
|
};
|
370
348
|
}
|
371
349
|
if (attributeSchema.type === "relation" && attributeSchema.relation !== "morphToOne" && attributeSchema.relation !== "morphToMany") {
|
372
350
|
if (attributeSchema.target === "admin::user") {
|
373
351
|
const adminUsers = await Promise.all(
|
374
|
-
attributeValues.map(
|
352
|
+
attributeValues.map((userToPopulate) => {
|
375
353
|
if (userToPopulate == null) {
|
376
354
|
return null;
|
377
355
|
}
|
@@ -388,9 +366,23 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
388
366
|
[attributeKey]: adminUsers
|
389
367
|
};
|
390
368
|
}
|
369
|
+
const permissionChecker2 = getService$1("permission-checker").create({
|
370
|
+
userAbility: params.state.userAbility,
|
371
|
+
model: attributeSchema.target
|
372
|
+
});
|
373
|
+
const response = await serviceUtils.buildRelationReponse(
|
374
|
+
attributeValues,
|
375
|
+
attributeSchema
|
376
|
+
);
|
377
|
+
const sanitizedResults = await Promise.all(
|
378
|
+
response.results.map((media) => permissionChecker2.sanitizeOutput(media))
|
379
|
+
);
|
391
380
|
return {
|
392
381
|
...await currentDataWithRelations,
|
393
|
-
[attributeKey]:
|
382
|
+
[attributeKey]: {
|
383
|
+
results: sanitizedResults,
|
384
|
+
meta: response.meta
|
385
|
+
}
|
394
386
|
};
|
395
387
|
}
|
396
388
|
return currentDataWithRelations;
|
@@ -405,7 +397,7 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
405
397
|
...result,
|
406
398
|
data: await populateEntryRelations(result),
|
407
399
|
meta: {
|
408
|
-
unknownAttributes: getSchemaAttributesDiff(
|
400
|
+
unknownAttributes: serviceUtils.getSchemaAttributesDiff(
|
409
401
|
result.schema,
|
410
402
|
strapi2.getModel(params.query.contentType).attributes
|
411
403
|
)
|
@@ -416,13 +408,16 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
416
408
|
);
|
417
409
|
return {
|
418
410
|
results: formattedResults,
|
419
|
-
pagination
|
411
|
+
pagination: pagination2
|
420
412
|
};
|
421
413
|
},
|
422
414
|
async restoreVersion(versionId) {
|
423
415
|
const version = await query.findOne({ where: { id: versionId } });
|
424
416
|
const contentTypeSchemaAttributes = strapi2.getModel(version.contentType).attributes;
|
425
|
-
const schemaDiff = getSchemaAttributesDiff(
|
417
|
+
const schemaDiff = serviceUtils.getSchemaAttributesDiff(
|
418
|
+
version.schema,
|
419
|
+
contentTypeSchemaAttributes
|
420
|
+
);
|
426
421
|
const dataWithoutAddedAttributes = Object.keys(schemaDiff.added).reduce(
|
427
422
|
(currentData, addedKey) => {
|
428
423
|
currentData[addedKey] = null;
|
@@ -435,61 +430,26 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
435
430
|
FIELDS_TO_IGNORE,
|
436
431
|
contentTypeSchemaAttributes
|
437
432
|
);
|
438
|
-
const
|
439
|
-
|
440
|
-
|
441
|
-
const
|
442
|
-
if (
|
433
|
+
const reducer = async.reduce(Object.entries(sanitizedSchemaAttributes));
|
434
|
+
const dataWithoutMissingRelations = await reducer(
|
435
|
+
async (previousRelationAttributes, [name, attribute]) => {
|
436
|
+
const versionRelationData = version.data[name];
|
437
|
+
if (!versionRelationData) {
|
443
438
|
return previousRelationAttributes;
|
444
439
|
}
|
445
440
|
if (attribute.type === "relation" && // TODO: handle polymorphic relations
|
446
441
|
attribute.relation !== "morphToOne" && attribute.relation !== "morphToMany") {
|
447
|
-
|
448
|
-
|
449
|
-
return previousRelationAttributes;
|
450
|
-
const existingAndMissingRelations = await Promise.all(
|
451
|
-
relationData.map((relation) => {
|
452
|
-
return strapi2.documents(attribute.target).findOne({
|
453
|
-
documentId: relation.documentId,
|
454
|
-
locale: relation.locale || void 0
|
455
|
-
});
|
456
|
-
})
|
457
|
-
);
|
458
|
-
const existingRelations = existingAndMissingRelations.filter(
|
459
|
-
(relation) => relation !== null
|
460
|
-
);
|
461
|
-
previousRelationAttributes[name] = existingRelations;
|
462
|
-
} else {
|
463
|
-
const existingRelation = await strapi2.documents(attribute.target).findOne({
|
464
|
-
documentId: relationData.documentId,
|
465
|
-
locale: relationData.locale || void 0
|
466
|
-
});
|
467
|
-
if (!existingRelation) {
|
468
|
-
previousRelationAttributes[name] = null;
|
469
|
-
}
|
470
|
-
}
|
442
|
+
const data2 = await serviceUtils.getRelationRestoreValue(versionRelationData, attribute);
|
443
|
+
previousRelationAttributes[name] = data2;
|
471
444
|
}
|
472
445
|
if (attribute.type === "media") {
|
473
|
-
|
474
|
-
|
475
|
-
// @ts-expect-error Fix the type definitions so this isn't any
|
476
|
-
relationData.map((media) => {
|
477
|
-
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: media.id } });
|
478
|
-
})
|
479
|
-
);
|
480
|
-
const existingMedias = existingAndMissingMedias.filter((media) => media != null);
|
481
|
-
previousRelationAttributes[name] = existingMedias;
|
482
|
-
} else {
|
483
|
-
const existingMedia = await strapi2.db.query("plugin::upload.file").findOne({ where: { id: version.data[name].id } });
|
484
|
-
if (!existingMedia) {
|
485
|
-
previousRelationAttributes[name] = null;
|
486
|
-
}
|
487
|
-
}
|
446
|
+
const data2 = await serviceUtils.getMediaRestoreValue(versionRelationData, attribute);
|
447
|
+
previousRelationAttributes[name] = data2;
|
488
448
|
}
|
489
449
|
return previousRelationAttributes;
|
490
450
|
},
|
491
451
|
// Clone to avoid mutating the original version data
|
492
|
-
|
452
|
+
structuredClone(dataWithoutAddedAttributes)
|
493
453
|
);
|
494
454
|
const data = omit(["id", ...Object.keys(schemaDiff.removed)], dataWithoutMissingRelations);
|
495
455
|
const restoredDocument = await strapi2.documents(version.contentType).update({
|
@@ -504,8 +464,101 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
504
464
|
}
|
505
465
|
};
|
506
466
|
};
|
467
|
+
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
|
+
const state = {
|
469
|
+
deleteExpiredJob: null,
|
470
|
+
isInitialized: false
|
471
|
+
};
|
472
|
+
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
473
|
+
const historyService = getService(strapi2, "history");
|
474
|
+
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
475
|
+
return {
|
476
|
+
async bootstrap() {
|
477
|
+
if (state.isInitialized) {
|
478
|
+
return;
|
479
|
+
}
|
480
|
+
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
|
+
const result = await next();
|
492
|
+
const documentContext = {
|
493
|
+
documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
|
494
|
+
locale: context.params?.locale
|
495
|
+
};
|
496
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
497
|
+
const locale = documentContext.locale || defaultLocale;
|
498
|
+
if (Array.isArray(locale)) {
|
499
|
+
strapi2.log.warn(
|
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();
|
503
|
+
}
|
504
|
+
const document = await strapi2.documents(contentTypeUid).findOne({
|
505
|
+
documentId: documentContext.documentId,
|
506
|
+
locale,
|
507
|
+
populate: serviceUtils.getDeepPopulate(contentTypeUid)
|
508
|
+
});
|
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
|
+
await strapi2.db.transaction(async ({ onCommit }) => {
|
525
|
+
onCommit(() => {
|
526
|
+
historyService.createVersion({
|
527
|
+
contentType: contentTypeUid,
|
528
|
+
data: omit(FIELDS_TO_IGNORE, document),
|
529
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
530
|
+
componentsSchemas,
|
531
|
+
relatedDocumentId: documentContext.documentId,
|
532
|
+
locale,
|
533
|
+
status
|
534
|
+
});
|
535
|
+
});
|
536
|
+
});
|
537
|
+
return result;
|
538
|
+
});
|
539
|
+
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
540
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
541
|
+
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
542
|
+
query.deleteMany({
|
543
|
+
where: {
|
544
|
+
created_at: {
|
545
|
+
$lt: expirationDate.toISOString()
|
546
|
+
}
|
547
|
+
}
|
548
|
+
});
|
549
|
+
});
|
550
|
+
state.isInitialized = true;
|
551
|
+
},
|
552
|
+
async destroy() {
|
553
|
+
if (state.deleteExpiredJob) {
|
554
|
+
state.deleteExpiredJob.cancel();
|
555
|
+
}
|
556
|
+
}
|
557
|
+
};
|
558
|
+
};
|
507
559
|
const services$1 = {
|
508
|
-
history: createHistoryService
|
560
|
+
history: createHistoryService,
|
561
|
+
lifecycles: createLifecyclesService
|
509
562
|
};
|
510
563
|
const info = { pluginName: "content-manager", type: "admin" };
|
511
564
|
const historyVersionRouter = {
|
@@ -585,10 +638,10 @@ const getFeature = () => {
|
|
585
638
|
strapi2.get("models").add(historyVersion);
|
586
639
|
},
|
587
640
|
bootstrap({ strapi: strapi2 }) {
|
588
|
-
getService(strapi2, "
|
641
|
+
getService(strapi2, "lifecycles").bootstrap();
|
589
642
|
},
|
590
643
|
destroy({ strapi: strapi2 }) {
|
591
|
-
getService(strapi2, "
|
644
|
+
getService(strapi2, "lifecycles").destroy();
|
592
645
|
},
|
593
646
|
controllers: controllers$1,
|
594
647
|
services: services$1,
|
@@ -1407,7 +1460,7 @@ const { PaginationError, ValidationError } = errors;
|
|
1407
1460
|
const TYPES = ["singleType", "collectionType"];
|
1408
1461
|
const kindSchema = yup$1.string().oneOf(TYPES).nullable();
|
1409
1462
|
const bulkActionInputSchema = yup$1.object({
|
1410
|
-
|
1463
|
+
documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
|
1411
1464
|
}).required();
|
1412
1465
|
const generateUIDInputSchema = yup$1.object({
|
1413
1466
|
contentTypeUID: yup$1.string().required(),
|
@@ -1506,15 +1559,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1506
1559
|
}
|
1507
1560
|
}, body);
|
1508
1561
|
};
|
1509
|
-
const
|
1562
|
+
const singleLocaleSchema = yup$1.string().nullable();
|
1563
|
+
const multipleLocaleSchema = yup$1.lazy(
|
1564
|
+
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1565
|
+
);
|
1566
|
+
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1567
|
+
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1568
|
+
const { allowMultipleLocales } = opts;
|
1510
1569
|
const { locale, status, ...rest } = request || {};
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1570
|
+
const schema = yup$1.object().shape({
|
1571
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1572
|
+
status: statusSchema
|
1573
|
+
});
|
1574
|
+
try {
|
1575
|
+
await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1576
|
+
return { locale, status, ...rest };
|
1577
|
+
} catch (error) {
|
1578
|
+
throw new errors.ValidationError(`Validation error: ${error.message}`);
|
1516
1579
|
}
|
1517
|
-
|
1580
|
+
};
|
1581
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1582
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1583
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1584
|
+
let {
|
1585
|
+
meta: { availableLocales, availableStatus }
|
1586
|
+
} = serviceOutput;
|
1587
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1588
|
+
availableLocales = await async.map(
|
1589
|
+
availableLocales,
|
1590
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1591
|
+
);
|
1592
|
+
availableStatus = await async.map(
|
1593
|
+
availableStatus,
|
1594
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1595
|
+
);
|
1596
|
+
return {
|
1597
|
+
...serviceOutput,
|
1598
|
+
meta: {
|
1599
|
+
availableLocales,
|
1600
|
+
availableStatus
|
1601
|
+
}
|
1602
|
+
};
|
1518
1603
|
};
|
1519
1604
|
const createDocument = async (ctx, opts) => {
|
1520
1605
|
const { userAbility, user } = ctx.state;
|
@@ -1529,7 +1614,7 @@ const createDocument = async (ctx, opts) => {
|
|
1529
1614
|
const setCreator = setCreatorFields({ user });
|
1530
1615
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1531
1616
|
const sanitizedBody = await sanitizeFn(body);
|
1532
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
|
1617
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
|
1533
1618
|
return documentManager2.create(model, {
|
1534
1619
|
data: sanitizedBody,
|
1535
1620
|
locale,
|
@@ -1548,7 +1633,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1548
1633
|
}
|
1549
1634
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1550
1635
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1551
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1636
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1552
1637
|
const [documentVersion, documentExists] = await Promise.all([
|
1553
1638
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1554
1639
|
documentManager2.exists(model, id)
|
@@ -1586,8 +1671,8 @@ const collectionTypes = {
|
|
1586
1671
|
}
|
1587
1672
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1588
1673
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1589
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
1590
|
-
const { results: documents, pagination } = await documentManager2.findPage(
|
1674
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1675
|
+
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1591
1676
|
{ ...permissionQuery, populate, locale, status },
|
1592
1677
|
model
|
1593
1678
|
);
|
@@ -1608,21 +1693,20 @@ const collectionTypes = {
|
|
1608
1693
|
);
|
1609
1694
|
ctx.body = {
|
1610
1695
|
results,
|
1611
|
-
pagination
|
1696
|
+
pagination: pagination2
|
1612
1697
|
};
|
1613
1698
|
},
|
1614
1699
|
async findOne(ctx) {
|
1615
1700
|
const { userAbility } = ctx.state;
|
1616
1701
|
const { model, id } = ctx.params;
|
1617
1702
|
const documentManager2 = getService$1("document-manager");
|
1618
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1619
1703
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1620
1704
|
if (permissionChecker2.cannot.read()) {
|
1621
1705
|
return ctx.forbidden();
|
1622
1706
|
}
|
1623
1707
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1624
1708
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1625
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
1709
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1626
1710
|
const version = await documentManager2.findOne(id, model, {
|
1627
1711
|
populate,
|
1628
1712
|
locale,
|
@@ -1633,8 +1717,10 @@ const collectionTypes = {
|
|
1633
1717
|
if (!exists) {
|
1634
1718
|
return ctx.notFound();
|
1635
1719
|
}
|
1636
|
-
const { meta } = await
|
1720
|
+
const { meta } = await formatDocumentWithMetadata(
|
1721
|
+
permissionChecker2,
|
1637
1722
|
model,
|
1723
|
+
// @ts-expect-error TODO: fix
|
1638
1724
|
{ id, locale, publishedAt: null },
|
1639
1725
|
{ availableLocales: true, availableStatus: false }
|
1640
1726
|
);
|
@@ -1645,12 +1731,11 @@ const collectionTypes = {
|
|
1645
1731
|
return ctx.forbidden();
|
1646
1732
|
}
|
1647
1733
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1648
|
-
ctx.body = await
|
1734
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1649
1735
|
},
|
1650
1736
|
async create(ctx) {
|
1651
1737
|
const { userAbility } = ctx.state;
|
1652
1738
|
const { model } = ctx.params;
|
1653
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1654
1739
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1655
1740
|
const [totalEntries, document] = await Promise.all([
|
1656
1741
|
strapi.db.query(model).count(),
|
@@ -1658,7 +1743,7 @@ const collectionTypes = {
|
|
1658
1743
|
]);
|
1659
1744
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1660
1745
|
ctx.status = 201;
|
1661
|
-
ctx.body = await
|
1746
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1662
1747
|
// Empty metadata as it's not relevant for a new document
|
1663
1748
|
availableLocales: false,
|
1664
1749
|
availableStatus: false
|
@@ -1672,25 +1757,23 @@ const collectionTypes = {
|
|
1672
1757
|
async update(ctx) {
|
1673
1758
|
const { userAbility } = ctx.state;
|
1674
1759
|
const { model } = ctx.params;
|
1675
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1676
1760
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1677
1761
|
const updatedVersion = await updateDocument(ctx);
|
1678
1762
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1679
|
-
ctx.body = await
|
1763
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1680
1764
|
},
|
1681
1765
|
async clone(ctx) {
|
1682
1766
|
const { userAbility, user } = ctx.state;
|
1683
1767
|
const { model, sourceId: id } = ctx.params;
|
1684
1768
|
const { body } = ctx.request;
|
1685
1769
|
const documentManager2 = getService$1("document-manager");
|
1686
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1687
1770
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1688
1771
|
if (permissionChecker2.cannot.create()) {
|
1689
1772
|
return ctx.forbidden();
|
1690
1773
|
}
|
1691
1774
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1692
1775
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1693
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1776
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1694
1777
|
const document = await documentManager2.findOne(id, model, {
|
1695
1778
|
populate,
|
1696
1779
|
locale,
|
@@ -1706,7 +1789,7 @@ const collectionTypes = {
|
|
1706
1789
|
const sanitizedBody = await sanitizeFn(body);
|
1707
1790
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1708
1791
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1709
|
-
ctx.body = await
|
1792
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1710
1793
|
// Empty metadata as it's not relevant for a new document
|
1711
1794
|
availableLocales: false,
|
1712
1795
|
availableStatus: false
|
@@ -1735,7 +1818,7 @@ const collectionTypes = {
|
|
1735
1818
|
}
|
1736
1819
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1737
1820
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1738
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1821
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1739
1822
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1740
1823
|
if (documentLocales.length === 0) {
|
1741
1824
|
return ctx.notFound();
|
@@ -1757,7 +1840,6 @@ const collectionTypes = {
|
|
1757
1840
|
const { id, model } = ctx.params;
|
1758
1841
|
const { body } = ctx.request;
|
1759
1842
|
const documentManager2 = getService$1("document-manager");
|
1760
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1761
1843
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1762
1844
|
if (permissionChecker2.cannot.publish()) {
|
1763
1845
|
return ctx.forbidden();
|
@@ -1769,21 +1851,25 @@ const collectionTypes = {
|
|
1769
1851
|
if (permissionChecker2.cannot.publish(document)) {
|
1770
1852
|
throw new errors.ForbiddenError();
|
1771
1853
|
}
|
1772
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1773
|
-
|
1854
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1855
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1774
1856
|
locale
|
1775
1857
|
// TODO: Allow setting creator fields on publish
|
1776
1858
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1777
1859
|
});
|
1860
|
+
if (!publishResult || publishResult.length === 0) {
|
1861
|
+
throw new errors.NotFoundError("Document not found or already published.");
|
1862
|
+
}
|
1863
|
+
return publishResult[0];
|
1778
1864
|
});
|
1779
1865
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1780
|
-
ctx.body = await
|
1866
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1781
1867
|
},
|
1782
1868
|
async bulkPublish(ctx) {
|
1783
1869
|
const { userAbility } = ctx.state;
|
1784
1870
|
const { model } = ctx.params;
|
1785
1871
|
const { body } = ctx.request;
|
1786
|
-
const {
|
1872
|
+
const { documentIds } = body;
|
1787
1873
|
await validateBulkActionInput(body);
|
1788
1874
|
const documentManager2 = getService$1("document-manager");
|
1789
1875
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1792,8 +1878,11 @@ const collectionTypes = {
|
|
1792
1878
|
}
|
1793
1879
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1794
1880
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1795
|
-
const
|
1796
|
-
const
|
1881
|
+
const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
|
1882
|
+
const entityPromises = documentIds.map(
|
1883
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1884
|
+
);
|
1885
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1797
1886
|
for (const entity of entities) {
|
1798
1887
|
if (!entity) {
|
1799
1888
|
return ctx.notFound();
|
@@ -1802,24 +1891,25 @@ const collectionTypes = {
|
|
1802
1891
|
return ctx.forbidden();
|
1803
1892
|
}
|
1804
1893
|
}
|
1805
|
-
const
|
1894
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1806
1895
|
ctx.body = { count };
|
1807
1896
|
},
|
1808
1897
|
async bulkUnpublish(ctx) {
|
1809
1898
|
const { userAbility } = ctx.state;
|
1810
1899
|
const { model } = ctx.params;
|
1811
1900
|
const { body } = ctx.request;
|
1812
|
-
const {
|
1901
|
+
const { documentIds } = body;
|
1813
1902
|
await validateBulkActionInput(body);
|
1814
1903
|
const documentManager2 = getService$1("document-manager");
|
1815
1904
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1816
1905
|
if (permissionChecker2.cannot.unpublish()) {
|
1817
1906
|
return ctx.forbidden();
|
1818
1907
|
}
|
1819
|
-
const
|
1820
|
-
const
|
1821
|
-
|
1822
|
-
|
1908
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1909
|
+
const entityPromises = documentIds.map(
|
1910
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1911
|
+
);
|
1912
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1823
1913
|
for (const entity of entities) {
|
1824
1914
|
if (!entity) {
|
1825
1915
|
return ctx.notFound();
|
@@ -1828,7 +1918,8 @@ const collectionTypes = {
|
|
1828
1918
|
return ctx.forbidden();
|
1829
1919
|
}
|
1830
1920
|
}
|
1831
|
-
const
|
1921
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1922
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1832
1923
|
ctx.body = { count };
|
1833
1924
|
},
|
1834
1925
|
async unpublish(ctx) {
|
@@ -1838,7 +1929,6 @@ const collectionTypes = {
|
|
1838
1929
|
body: { discardDraft, ...body }
|
1839
1930
|
} = ctx.request;
|
1840
1931
|
const documentManager2 = getService$1("document-manager");
|
1841
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1842
1932
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1843
1933
|
if (permissionChecker2.cannot.unpublish()) {
|
1844
1934
|
return ctx.forbidden();
|
@@ -1848,7 +1938,7 @@ const collectionTypes = {
|
|
1848
1938
|
}
|
1849
1939
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1850
1940
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1851
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1941
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1852
1942
|
const document = await documentManager2.findOne(id, model, {
|
1853
1943
|
populate,
|
1854
1944
|
locale,
|
@@ -1870,7 +1960,7 @@ const collectionTypes = {
|
|
1870
1960
|
ctx.body = await async.pipe(
|
1871
1961
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1872
1962
|
permissionChecker2.sanitizeOutput,
|
1873
|
-
(document2) =>
|
1963
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1874
1964
|
)(document);
|
1875
1965
|
});
|
1876
1966
|
},
|
@@ -1879,14 +1969,13 @@ const collectionTypes = {
|
|
1879
1969
|
const { id, model } = ctx.params;
|
1880
1970
|
const { body } = ctx.request;
|
1881
1971
|
const documentManager2 = getService$1("document-manager");
|
1882
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1883
1972
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1884
1973
|
if (permissionChecker2.cannot.discard()) {
|
1885
1974
|
return ctx.forbidden();
|
1886
1975
|
}
|
1887
1976
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1888
1977
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1889
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1978
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1890
1979
|
const document = await documentManager2.findOne(id, model, {
|
1891
1980
|
populate,
|
1892
1981
|
locale,
|
@@ -1901,14 +1990,14 @@ const collectionTypes = {
|
|
1901
1990
|
ctx.body = await async.pipe(
|
1902
1991
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1903
1992
|
permissionChecker2.sanitizeOutput,
|
1904
|
-
(document2) =>
|
1993
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1905
1994
|
)(document);
|
1906
1995
|
},
|
1907
1996
|
async bulkDelete(ctx) {
|
1908
1997
|
const { userAbility } = ctx.state;
|
1909
1998
|
const { model } = ctx.params;
|
1910
1999
|
const { query, body } = ctx.request;
|
1911
|
-
const {
|
2000
|
+
const { documentIds } = body;
|
1912
2001
|
await validateBulkActionInput(body);
|
1913
2002
|
const documentManager2 = getService$1("document-manager");
|
1914
2003
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1916,14 +2005,22 @@ const collectionTypes = {
|
|
1916
2005
|
return ctx.forbidden();
|
1917
2006
|
}
|
1918
2007
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1919
|
-
const
|
1920
|
-
const
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
2008
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2009
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2010
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2011
|
+
populate,
|
2012
|
+
locale
|
2013
|
+
});
|
2014
|
+
if (documentLocales.length === 0) {
|
2015
|
+
return ctx.notFound();
|
2016
|
+
}
|
2017
|
+
for (const document of documentLocales) {
|
2018
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2019
|
+
return ctx.forbidden();
|
1924
2020
|
}
|
1925
|
-
}
|
1926
|
-
const
|
2021
|
+
}
|
2022
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2023
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1927
2024
|
ctx.body = { count };
|
1928
2025
|
},
|
1929
2026
|
async countDraftRelations(ctx) {
|
@@ -1936,7 +2033,7 @@ const collectionTypes = {
|
|
1936
2033
|
}
|
1937
2034
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1938
2035
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1939
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
2036
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1940
2037
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1941
2038
|
if (!entity) {
|
1942
2039
|
return ctx.notFound();
|
@@ -1951,7 +2048,7 @@ const collectionTypes = {
|
|
1951
2048
|
},
|
1952
2049
|
async countManyEntriesDraftRelations(ctx) {
|
1953
2050
|
const { userAbility } = ctx.state;
|
1954
|
-
const ids = ctx.request.query.
|
2051
|
+
const ids = ctx.request.query.documentIds;
|
1955
2052
|
const locale = ctx.request.query.locale;
|
1956
2053
|
const { model } = ctx.params;
|
1957
2054
|
const documentManager2 = getService$1("document-manager");
|
@@ -1962,7 +2059,7 @@ const collectionTypes = {
|
|
1962
2059
|
const entities = await documentManager2.findMany(
|
1963
2060
|
{
|
1964
2061
|
filters: {
|
1965
|
-
|
2062
|
+
documentId: ids
|
1966
2063
|
},
|
1967
2064
|
locale
|
1968
2065
|
},
|
@@ -2464,7 +2561,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2464
2561
|
throw new errors.ForbiddenError();
|
2465
2562
|
}
|
2466
2563
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2467
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2564
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2468
2565
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2469
2566
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2470
2567
|
// Find the first document to check if it exists
|
@@ -2501,12 +2598,11 @@ const singleTypes = {
|
|
2501
2598
|
const { model } = ctx.params;
|
2502
2599
|
const { query = {} } = ctx.request;
|
2503
2600
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2504
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2505
2601
|
if (permissionChecker2.cannot.read()) {
|
2506
2602
|
return ctx.forbidden();
|
2507
2603
|
}
|
2508
2604
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2509
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2605
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2510
2606
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2511
2607
|
if (!version) {
|
2512
2608
|
if (permissionChecker2.cannot.create()) {
|
@@ -2516,8 +2612,10 @@ const singleTypes = {
|
|
2516
2612
|
if (!document) {
|
2517
2613
|
return ctx.notFound();
|
2518
2614
|
}
|
2519
|
-
const { meta } = await
|
2615
|
+
const { meta } = await formatDocumentWithMetadata(
|
2616
|
+
permissionChecker2,
|
2520
2617
|
model,
|
2618
|
+
// @ts-expect-error - fix types
|
2521
2619
|
{ id: document.documentId, locale, publishedAt: null },
|
2522
2620
|
{ availableLocales: true, availableStatus: false }
|
2523
2621
|
);
|
@@ -2528,16 +2626,15 @@ const singleTypes = {
|
|
2528
2626
|
return ctx.forbidden();
|
2529
2627
|
}
|
2530
2628
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2531
|
-
ctx.body = await
|
2629
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2532
2630
|
},
|
2533
2631
|
async createOrUpdate(ctx) {
|
2534
2632
|
const { userAbility } = ctx.state;
|
2535
2633
|
const { model } = ctx.params;
|
2536
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2537
2634
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2538
2635
|
const document = await createOrUpdateDocument(ctx);
|
2539
2636
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2540
|
-
ctx.body = await
|
2637
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2541
2638
|
},
|
2542
2639
|
async delete(ctx) {
|
2543
2640
|
const { userAbility } = ctx.state;
|
@@ -2550,7 +2647,7 @@ const singleTypes = {
|
|
2550
2647
|
}
|
2551
2648
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2552
2649
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2553
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2650
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2554
2651
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2555
2652
|
populate,
|
2556
2653
|
locale
|
@@ -2573,7 +2670,6 @@ const singleTypes = {
|
|
2573
2670
|
const { model } = ctx.params;
|
2574
2671
|
const { query = {} } = ctx.request;
|
2575
2672
|
const documentManager2 = getService$1("document-manager");
|
2576
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2577
2673
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2578
2674
|
if (permissionChecker2.cannot.publish()) {
|
2579
2675
|
return ctx.forbidden();
|
@@ -2588,11 +2684,12 @@ const singleTypes = {
|
|
2588
2684
|
if (permissionChecker2.cannot.publish(document)) {
|
2589
2685
|
throw new errors.ForbiddenError();
|
2590
2686
|
}
|
2591
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2592
|
-
|
2687
|
+
const { locale } = await getDocumentLocaleAndStatus(document);
|
2688
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2689
|
+
return publishResult.at(0);
|
2593
2690
|
});
|
2594
2691
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2595
|
-
ctx.body = await
|
2692
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2596
2693
|
},
|
2597
2694
|
async unpublish(ctx) {
|
2598
2695
|
const { userAbility } = ctx.state;
|
@@ -2602,7 +2699,6 @@ const singleTypes = {
|
|
2602
2699
|
query = {}
|
2603
2700
|
} = ctx.request;
|
2604
2701
|
const documentManager2 = getService$1("document-manager");
|
2605
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2606
2702
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2607
2703
|
if (permissionChecker2.cannot.unpublish()) {
|
2608
2704
|
return ctx.forbidden();
|
@@ -2611,7 +2707,7 @@ const singleTypes = {
|
|
2611
2707
|
return ctx.forbidden();
|
2612
2708
|
}
|
2613
2709
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2614
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2710
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2615
2711
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2616
2712
|
if (!document) {
|
2617
2713
|
return ctx.notFound();
|
@@ -2629,7 +2725,7 @@ const singleTypes = {
|
|
2629
2725
|
ctx.body = await async.pipe(
|
2630
2726
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2631
2727
|
permissionChecker2.sanitizeOutput,
|
2632
|
-
(document2) =>
|
2728
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2633
2729
|
)(document);
|
2634
2730
|
});
|
2635
2731
|
},
|
@@ -2638,13 +2734,12 @@ const singleTypes = {
|
|
2638
2734
|
const { model } = ctx.params;
|
2639
2735
|
const { body, query = {} } = ctx.request;
|
2640
2736
|
const documentManager2 = getService$1("document-manager");
|
2641
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2642
2737
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2643
2738
|
if (permissionChecker2.cannot.discard()) {
|
2644
2739
|
return ctx.forbidden();
|
2645
2740
|
}
|
2646
2741
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2647
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2742
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2648
2743
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2649
2744
|
if (!document) {
|
2650
2745
|
return ctx.notFound();
|
@@ -2655,7 +2750,7 @@ const singleTypes = {
|
|
2655
2750
|
ctx.body = await async.pipe(
|
2656
2751
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2657
2752
|
permissionChecker2.sanitizeOutput,
|
2658
|
-
(document2) =>
|
2753
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2659
2754
|
)(document);
|
2660
2755
|
},
|
2661
2756
|
async countDraftRelations(ctx) {
|
@@ -2664,7 +2759,7 @@ const singleTypes = {
|
|
2664
2759
|
const { query } = ctx.request;
|
2665
2760
|
const documentManager2 = getService$1("document-manager");
|
2666
2761
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2667
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2762
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2668
2763
|
if (permissionChecker2.cannot.read()) {
|
2669
2764
|
return ctx.forbidden();
|
2670
2765
|
}
|
@@ -2685,7 +2780,7 @@ const uid$1 = {
|
|
2685
2780
|
async generateUID(ctx) {
|
2686
2781
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2687
2782
|
const { query = {} } = ctx.request;
|
2688
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2783
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2689
2784
|
await validateUIDField(contentTypeUID, field);
|
2690
2785
|
const uidService = getService$1("uid");
|
2691
2786
|
ctx.body = {
|
@@ -2697,7 +2792,7 @@ const uid$1 = {
|
|
2697
2792
|
ctx.request.body
|
2698
2793
|
);
|
2699
2794
|
const { query = {} } = ctx.request;
|
2700
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2795
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2701
2796
|
await validateUIDField(contentTypeUID, field);
|
2702
2797
|
const uidService = getService$1("uid");
|
2703
2798
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3488,7 +3583,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3488
3583
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3489
3584
|
}
|
3490
3585
|
});
|
3491
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
|
3586
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
|
3492
3587
|
const { isAnyToMany } = strapiUtils.relations;
|
3493
3588
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
|
3494
3589
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3579,6 +3674,42 @@ const getDeepPopulate = (uid2, {
|
|
3579
3674
|
{}
|
3580
3675
|
);
|
3581
3676
|
};
|
3677
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3678
|
+
initialPopulate = {},
|
3679
|
+
countMany = false,
|
3680
|
+
countOne = false,
|
3681
|
+
maxLevel = Infinity
|
3682
|
+
} = {}, level = 1) => {
|
3683
|
+
if (level > maxLevel) {
|
3684
|
+
return {};
|
3685
|
+
}
|
3686
|
+
const model = strapi.getModel(uid2);
|
3687
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3688
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3689
|
+
return populateAcc;
|
3690
|
+
}
|
3691
|
+
if (isScalarAttribute(attribute)) {
|
3692
|
+
return merge(populateAcc, {
|
3693
|
+
[attributeName]: true
|
3694
|
+
});
|
3695
|
+
}
|
3696
|
+
return merge(
|
3697
|
+
populateAcc,
|
3698
|
+
getPopulateFor(
|
3699
|
+
attributeName,
|
3700
|
+
model,
|
3701
|
+
{
|
3702
|
+
// @ts-expect-error - improve types
|
3703
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3704
|
+
countMany,
|
3705
|
+
countOne,
|
3706
|
+
maxLevel
|
3707
|
+
},
|
3708
|
+
level
|
3709
|
+
)
|
3710
|
+
);
|
3711
|
+
}, {});
|
3712
|
+
};
|
3582
3713
|
const getDeepPopulateDraftCount = (uid2) => {
|
3583
3714
|
const model = strapi.getModel(uid2);
|
3584
3715
|
let hasRelations = false;
|
@@ -3600,22 +3731,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3600
3731
|
attribute.component
|
3601
3732
|
);
|
3602
3733
|
if (childHasRelations) {
|
3603
|
-
populateAcc[attributeName] = {
|
3734
|
+
populateAcc[attributeName] = {
|
3735
|
+
populate: populate2
|
3736
|
+
};
|
3604
3737
|
hasRelations = true;
|
3605
3738
|
}
|
3606
3739
|
break;
|
3607
3740
|
}
|
3608
3741
|
case "dynamiczone": {
|
3609
|
-
const
|
3610
|
-
const { populate:
|
3611
|
-
if (
|
3742
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3743
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3744
|
+
if (componentHasRelations) {
|
3612
3745
|
hasRelations = true;
|
3613
|
-
return
|
3746
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3614
3747
|
}
|
3615
3748
|
return acc;
|
3616
3749
|
}, {});
|
3617
|
-
if (!isEmpty(
|
3618
|
-
populateAcc[attributeName] = {
|
3750
|
+
if (!isEmpty(dzPopulateFragment)) {
|
3751
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3619
3752
|
}
|
3620
3753
|
break;
|
3621
3754
|
}
|
@@ -3807,41 +3940,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3807
3940
|
"updatedBy",
|
3808
3941
|
"status"
|
3809
3942
|
];
|
3810
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
3943
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
3944
|
+
"id",
|
3945
|
+
"locale",
|
3946
|
+
"updatedAt",
|
3947
|
+
"createdAt",
|
3948
|
+
"status",
|
3949
|
+
"publishedAt",
|
3950
|
+
"documentId"
|
3951
|
+
];
|
3811
3952
|
const CONTENT_MANAGER_STATUS = {
|
3812
3953
|
PUBLISHED: "published",
|
3813
3954
|
DRAFT: "draft",
|
3814
3955
|
MODIFIED: "modified"
|
3815
3956
|
};
|
3816
|
-
const
|
3817
|
-
if (!
|
3957
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
3958
|
+
if (!version || !version.updatedAt) {
|
3818
3959
|
return false;
|
3819
3960
|
}
|
3820
|
-
const
|
3821
|
-
const
|
3822
|
-
|
3823
|
-
return difference2 <= threshold;
|
3961
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
3962
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
3963
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3824
3964
|
};
|
3825
3965
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3826
3966
|
/**
|
3827
3967
|
* Returns available locales of a document for the current status
|
3828
3968
|
*/
|
3829
|
-
getAvailableLocales(uid2, version, allVersions) {
|
3969
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3830
3970
|
const versionsByLocale = groupBy("locale", allVersions);
|
3831
3971
|
delete versionsByLocale[version.locale];
|
3832
|
-
|
3833
|
-
|
3834
|
-
|
3972
|
+
const model = strapi2.getModel(uid2);
|
3973
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3974
|
+
const traversalFunction = async (localeVersion) => traverseEntity(
|
3975
|
+
({ key }, { remove }) => {
|
3976
|
+
if (keysToKeep.includes(key)) {
|
3977
|
+
return;
|
3978
|
+
}
|
3979
|
+
remove(key);
|
3980
|
+
},
|
3981
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
3982
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
3983
|
+
localeVersion
|
3984
|
+
);
|
3985
|
+
const mappingResult = await async.map(
|
3986
|
+
Object.values(versionsByLocale),
|
3987
|
+
async (localeVersions) => {
|
3988
|
+
const mappedLocaleVersions = await async.map(
|
3989
|
+
localeVersions,
|
3990
|
+
traversalFunction
|
3991
|
+
);
|
3992
|
+
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
3993
|
+
return mappedLocaleVersions[0];
|
3994
|
+
}
|
3995
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
3996
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
3997
|
+
if (!draftVersion) {
|
3998
|
+
return;
|
3999
|
+
}
|
4000
|
+
return {
|
4001
|
+
...draftVersion,
|
4002
|
+
status: this.getStatus(draftVersion, otherVersions)
|
4003
|
+
};
|
3835
4004
|
}
|
3836
|
-
|
3837
|
-
|
3838
|
-
if (!draftVersion)
|
3839
|
-
return;
|
3840
|
-
return {
|
3841
|
-
...pick(AVAILABLE_LOCALES_FIELDS, draftVersion),
|
3842
|
-
status: this.getStatus(draftVersion, otherVersions)
|
3843
|
-
};
|
3844
|
-
}).filter(Boolean);
|
4005
|
+
);
|
4006
|
+
return mappingResult.filter(Boolean);
|
3845
4007
|
},
|
3846
4008
|
/**
|
3847
4009
|
* Returns available status of a document for the current locale
|
@@ -3879,26 +4041,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3879
4041
|
});
|
3880
4042
|
},
|
3881
4043
|
getStatus(version, otherDocumentStatuses) {
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
4044
|
+
let draftVersion;
|
4045
|
+
let publishedVersion;
|
4046
|
+
if (version.publishedAt) {
|
4047
|
+
publishedVersion = version;
|
4048
|
+
} else {
|
4049
|
+
draftVersion = version;
|
3885
4050
|
}
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
4051
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4052
|
+
if (otherVersion?.publishedAt) {
|
4053
|
+
publishedVersion = otherVersion;
|
4054
|
+
} else if (otherVersion) {
|
4055
|
+
draftVersion = otherVersion;
|
3891
4056
|
}
|
3892
|
-
if (
|
4057
|
+
if (!draftVersion)
|
3893
4058
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3894
|
-
|
3895
|
-
|
4059
|
+
if (!publishedVersion)
|
4060
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4061
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4062
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3896
4063
|
},
|
4064
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4065
|
+
// We could refactor this so the locales are only loaded when they're
|
4066
|
+
// needed. e.g. in the bulk locale action modal.
|
3897
4067
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4068
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3898
4069
|
const versions = await strapi2.db.query(uid2).findMany({
|
3899
4070
|
where: { documentId: version.documentId },
|
3900
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3901
4071
|
populate: {
|
4072
|
+
// Populate only fields that require validation for bulk locale actions
|
4073
|
+
...populate,
|
4074
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3902
4075
|
createdBy: {
|
3903
4076
|
select: ["id", "firstname", "lastname", "email"]
|
3904
4077
|
},
|
@@ -3907,7 +4080,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3907
4080
|
}
|
3908
4081
|
}
|
3909
4082
|
});
|
3910
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4083
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3911
4084
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3912
4085
|
return {
|
3913
4086
|
availableLocales: availableLocalesResult,
|
@@ -3920,8 +4093,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3920
4093
|
* - Available status of the document for the current locale
|
3921
4094
|
*/
|
3922
4095
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3923
|
-
if (!document)
|
4096
|
+
if (!document) {
|
3924
4097
|
return document;
|
4098
|
+
}
|
3925
4099
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
3926
4100
|
if (!hasDraftAndPublish) {
|
3927
4101
|
opts.availableStatus = false;
|
@@ -3971,26 +4145,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
3971
4145
|
}, 0);
|
3972
4146
|
};
|
3973
4147
|
const { ApplicationError } = errors;
|
3974
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
3975
4148
|
const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
|
3976
4149
|
const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
|
3977
4150
|
const omitIdField = omit("id");
|
3978
|
-
const emitEvent = async (uid2, event, document) => {
|
3979
|
-
const modelDef = strapi.getModel(uid2);
|
3980
|
-
const sanitizedDocument = await sanitize.sanitizers.defaultSanitizeOutput(
|
3981
|
-
{
|
3982
|
-
schema: modelDef,
|
3983
|
-
getModel(uid22) {
|
3984
|
-
return strapi.getModel(uid22);
|
3985
|
-
}
|
3986
|
-
},
|
3987
|
-
document
|
3988
|
-
);
|
3989
|
-
strapi.eventHub.emit(event, {
|
3990
|
-
model: modelDef.modelName,
|
3991
|
-
entry: sanitizedDocument
|
3992
|
-
});
|
3993
|
-
};
|
3994
4151
|
const documentManager = ({ strapi: strapi2 }) => {
|
3995
4152
|
return {
|
3996
4153
|
async findOne(id, uid2, opts = {}) {
|
@@ -4009,6 +4166,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4009
4166
|
} else if (opts.locale && opts.locale !== "*") {
|
4010
4167
|
where.locale = opts.locale;
|
4011
4168
|
}
|
4169
|
+
if (typeof opts.isPublished === "boolean") {
|
4170
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4171
|
+
}
|
4012
4172
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4013
4173
|
},
|
4014
4174
|
async findMany(opts, uid2) {
|
@@ -4016,20 +4176,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4016
4176
|
return strapi2.documents(uid2).findMany(params);
|
4017
4177
|
},
|
4018
4178
|
async findPage(opts, uid2) {
|
4019
|
-
const
|
4020
|
-
|
4179
|
+
const params = pagination.withDefaultPagination(opts || {}, {
|
4180
|
+
maxLimit: 1e3
|
4181
|
+
});
|
4021
4182
|
const [documents, total = 0] = await Promise.all([
|
4022
|
-
strapi2.documents(uid2).findMany(
|
4023
|
-
strapi2.documents(uid2).count(
|
4183
|
+
strapi2.documents(uid2).findMany(params),
|
4184
|
+
strapi2.documents(uid2).count(params)
|
4024
4185
|
]);
|
4025
4186
|
return {
|
4026
4187
|
results: documents,
|
4027
|
-
pagination:
|
4028
|
-
page,
|
4029
|
-
pageSize,
|
4030
|
-
pageCount: Math.ceil(total / pageSize),
|
4031
|
-
total
|
4032
|
-
}
|
4188
|
+
pagination: pagination.transformPagedPaginationInfo(params, total)
|
4033
4189
|
};
|
4034
4190
|
},
|
4035
4191
|
async create(uid2, opts = {}) {
|
@@ -4075,70 +4231,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4075
4231
|
return {};
|
4076
4232
|
},
|
4077
4233
|
// FIXME: handle relations
|
4078
|
-
async deleteMany(
|
4079
|
-
const
|
4080
|
-
|
4081
|
-
|
4082
|
-
}
|
4083
|
-
return { count: docs.length };
|
4234
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4235
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4236
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4237
|
+
});
|
4238
|
+
return { count: deletedEntries.length };
|
4084
4239
|
},
|
4085
4240
|
async publish(id, uid2, opts = {}) {
|
4086
4241
|
const populate = await buildDeepPopulate(uid2);
|
4087
4242
|
const params = { ...opts, populate };
|
4088
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4243
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4089
4244
|
},
|
4090
|
-
async publishMany(
|
4091
|
-
|
4092
|
-
|
4093
|
-
|
4094
|
-
|
4095
|
-
|
4096
|
-
|
4097
|
-
strapi2.getModel(uid2),
|
4098
|
-
document,
|
4099
|
-
void 0,
|
4100
|
-
// @ts-expect-error - FIXME: entity here is unnecessary
|
4101
|
-
document
|
4102
|
-
);
|
4103
|
-
})
|
4104
|
-
);
|
4105
|
-
const entitiesToPublish = entities.filter((doc) => !doc[PUBLISHED_AT_ATTRIBUTE]).map((doc) => doc.id);
|
4106
|
-
const filters = { id: { $in: entitiesToPublish } };
|
4107
|
-
const data = { [PUBLISHED_AT_ATTRIBUTE]: /* @__PURE__ */ new Date() };
|
4108
|
-
const populate = await buildDeepPopulate(uid2);
|
4109
|
-
const publishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4110
|
-
where: filters,
|
4111
|
-
data
|
4112
|
-
});
|
4113
|
-
const publishedEntities = await strapi2.db.query(uid2).findMany({
|
4114
|
-
where: filters,
|
4115
|
-
populate
|
4245
|
+
async publishMany(uid2, documentIds, locale) {
|
4246
|
+
return strapi2.db.transaction(async () => {
|
4247
|
+
const results = await Promise.all(
|
4248
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4249
|
+
);
|
4250
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4251
|
+
return publishedEntitiesCount;
|
4116
4252
|
});
|
4117
|
-
await Promise.all(
|
4118
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4119
|
-
);
|
4120
|
-
return publishedEntitiesCount;
|
4121
4253
|
},
|
4122
|
-
async unpublishMany(
|
4123
|
-
|
4124
|
-
return
|
4125
|
-
|
4126
|
-
|
4127
|
-
|
4128
|
-
|
4129
|
-
const populate = await buildDeepPopulate(uid2);
|
4130
|
-
const unpublishedEntitiesCount = await strapi2.db.query(uid2).updateMany({
|
4131
|
-
where: filters,
|
4132
|
-
data
|
4133
|
-
});
|
4134
|
-
const unpublishedEntities = await strapi2.db.query(uid2).findMany({
|
4135
|
-
where: filters,
|
4136
|
-
populate
|
4254
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4255
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4256
|
+
return Promise.all(
|
4257
|
+
documentIds.map(
|
4258
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4259
|
+
)
|
4260
|
+
);
|
4137
4261
|
});
|
4138
|
-
|
4139
|
-
|
4140
|
-
);
|
4141
|
-
return unpublishedEntitiesCount;
|
4262
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4263
|
+
return { count: unpublishedEntitiesCount };
|
4142
4264
|
},
|
4143
4265
|
async unpublish(id, uid2, opts = {}) {
|
4144
4266
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4163,16 +4285,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4163
4285
|
}
|
4164
4286
|
return sumDraftCounts(document, uid2);
|
4165
4287
|
},
|
4166
|
-
async countManyEntriesDraftRelations(
|
4288
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4167
4289
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4168
4290
|
if (!hasRelations) {
|
4169
4291
|
return 0;
|
4170
4292
|
}
|
4293
|
+
let localeFilter = {};
|
4294
|
+
if (locale) {
|
4295
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4296
|
+
}
|
4171
4297
|
const entities = await strapi2.db.query(uid2).findMany({
|
4172
4298
|
populate,
|
4173
4299
|
where: {
|
4174
|
-
|
4175
|
-
...
|
4300
|
+
documentId: { $in: documentIds },
|
4301
|
+
...localeFilter
|
4176
4302
|
}
|
4177
4303
|
});
|
4178
4304
|
const totalNumberDraftRelations = entities.reduce(
|