@strapi/content-manager 5.0.0-beta.6 → 5.0.0-beta.8
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-CuWgXugY.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-CuWgXugY.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-by0e_kNd.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-by0e_kNd.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-CqBeCPGH.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-CqBeCPGH.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-DbI4KMyz.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-DbI4KMyz.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-ChgloMyO.js} +7 -9
- package/dist/_chunks/EditViewPage-ChgloMyO.js.map +1 -0
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-dFPBya9U.mjs} +6 -6
- package/dist/_chunks/EditViewPage-dFPBya9U.mjs.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-C1nUKcdS.mjs} +500 -608
- package/dist/_chunks/Field-C1nUKcdS.mjs.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-dLk-vgLL.js} +552 -661
- package/dist/_chunks/Field-dLk-vgLL.js.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-CbXtmHC_.js} +21 -19
- package/dist/_chunks/Form-CbXtmHC_.js.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-DOlpi7Js.mjs} +21 -18
- package/dist/_chunks/Form-DOlpi7Js.mjs.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-BFNUAiGc.mjs} +32 -43
- package/dist/_chunks/History-BFNUAiGc.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-BjDfohBr.js} +32 -44
- package/dist/_chunks/History-BjDfohBr.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-DDi0KqFm.mjs} +14 -14
- package/dist/_chunks/ListConfigurationPage-DDi0KqFm.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-IQBgWTaa.js} +17 -19
- package/dist/_chunks/ListConfigurationPage-IQBgWTaa.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-BPjljUsH.mjs} +25 -45
- package/dist/_chunks/ListViewPage-BPjljUsH.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-CZYGqlvF.js} +31 -51
- package/dist/_chunks/ListViewPage-CZYGqlvF.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-BOAI6VZ1.js} +5 -5
- package/dist/_chunks/NoContentTypePage-BOAI6VZ1.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-DaWw67K-.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-DaWw67K-.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-CZrJH00p.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-CZrJH00p.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-cYEtLc_e.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-cYEtLc_e.js.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-DTowyge2.mjs} +66 -56
- package/dist/_chunks/Relations-DTowyge2.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-DU6B7irU.js} +70 -61
- package/dist/_chunks/Relations-DU6B7irU.js.map +1 -0
- package/dist/_chunks/{en-C-V1_90f.js → en-DTULi5-d.js} +3 -1
- package/dist/_chunks/{en-C-V1_90f.js.map → en-DTULi5-d.js.map} +1 -1
- package/dist/_chunks/{en-MBPul9Su.mjs → en-GCOTL6jR.mjs} +3 -1
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-GCOTL6jR.mjs.map} +1 -1
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-BaGHmIir.mjs} +507 -202
- package/dist/_chunks/index-BaGHmIir.mjs.map +1 -0
- package/dist/_chunks/{index-X_2tafck.js → index-CCJeB7Rw.js} +502 -198
- package/dist/_chunks/index-CCJeB7Rw.js.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-BinjszSQ.mjs} +13 -13
- package/dist/_chunks/layout-BinjszSQ.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-ni_L9kT1.js} +14 -16
- package/dist/_chunks/layout-ni_L9kT1.js.map +1 -0
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-CeJAJc5I.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-CeJAJc5I.js.map} +1 -1
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-c91ji5eR.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-c91ji5eR.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 +5 -4
- 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/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/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 +529 -407
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +537 -415
- 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/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +0 -31
- 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,99 @@ 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 !== "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 = context.action === "create" ? { documentId: result.documentId, locale: context.params?.locale } : { documentId: context.params.documentId, locale: context.params?.locale };
|
493
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
494
|
+
const locale = documentContext.locale || defaultLocale;
|
495
|
+
if (Array.isArray(locale)) {
|
496
|
+
strapi2.log.warn(
|
497
|
+
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
498
|
+
);
|
499
|
+
return next();
|
500
|
+
}
|
501
|
+
const document = await strapi2.documents(contentTypeUid).findOne({
|
502
|
+
documentId: documentContext.documentId,
|
503
|
+
locale,
|
504
|
+
populate: serviceUtils.getDeepPopulate(contentTypeUid)
|
505
|
+
});
|
506
|
+
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
507
|
+
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
508
|
+
const componentsSchemas = Object.keys(
|
509
|
+
attributesSchema
|
510
|
+
).reduce((currentComponentSchemas, key) => {
|
511
|
+
const fieldSchema = attributesSchema[key];
|
512
|
+
if (fieldSchema.type === "component") {
|
513
|
+
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
514
|
+
return {
|
515
|
+
...currentComponentSchemas,
|
516
|
+
[fieldSchema.component]: componentSchema
|
517
|
+
};
|
518
|
+
}
|
519
|
+
return currentComponentSchemas;
|
520
|
+
}, {});
|
521
|
+
await strapi2.db.transaction(async ({ onCommit }) => {
|
522
|
+
onCommit(() => {
|
523
|
+
historyService.createVersion({
|
524
|
+
contentType: contentTypeUid,
|
525
|
+
data: omit(FIELDS_TO_IGNORE, document),
|
526
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
527
|
+
componentsSchemas,
|
528
|
+
relatedDocumentId: documentContext.documentId,
|
529
|
+
locale,
|
530
|
+
status
|
531
|
+
});
|
532
|
+
});
|
533
|
+
});
|
534
|
+
return result;
|
535
|
+
});
|
536
|
+
const retentionDays = serviceUtils.getRetentionDays();
|
537
|
+
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
538
|
+
const retentionDaysInMilliseconds = retentionDays * 24 * 60 * 60 * 1e3;
|
539
|
+
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
540
|
+
query.deleteMany({
|
541
|
+
where: {
|
542
|
+
created_at: {
|
543
|
+
$lt: expirationDate.toISOString()
|
544
|
+
}
|
545
|
+
}
|
546
|
+
});
|
547
|
+
});
|
548
|
+
state.isInitialized = true;
|
549
|
+
},
|
550
|
+
async destroy() {
|
551
|
+
if (state.deleteExpiredJob) {
|
552
|
+
state.deleteExpiredJob.cancel();
|
553
|
+
}
|
554
|
+
}
|
555
|
+
};
|
556
|
+
};
|
507
557
|
const services$1 = {
|
508
|
-
history: createHistoryService
|
558
|
+
history: createHistoryService,
|
559
|
+
lifecycles: createLifecyclesService
|
509
560
|
};
|
510
561
|
const info = { pluginName: "content-manager", type: "admin" };
|
511
562
|
const historyVersionRouter = {
|
@@ -585,10 +636,10 @@ const getFeature = () => {
|
|
585
636
|
strapi2.get("models").add(historyVersion);
|
586
637
|
},
|
587
638
|
bootstrap({ strapi: strapi2 }) {
|
588
|
-
getService(strapi2, "
|
639
|
+
getService(strapi2, "lifecycles").bootstrap();
|
589
640
|
},
|
590
641
|
destroy({ strapi: strapi2 }) {
|
591
|
-
getService(strapi2, "
|
642
|
+
getService(strapi2, "lifecycles").destroy();
|
592
643
|
},
|
593
644
|
controllers: controllers$1,
|
594
645
|
services: services$1,
|
@@ -1407,7 +1458,7 @@ const { PaginationError, ValidationError } = errors;
|
|
1407
1458
|
const TYPES = ["singleType", "collectionType"];
|
1408
1459
|
const kindSchema = yup$1.string().oneOf(TYPES).nullable();
|
1409
1460
|
const bulkActionInputSchema = yup$1.object({
|
1410
|
-
|
1461
|
+
documentIds: yup$1.array().of(yup$1.strapiID()).min(1).required()
|
1411
1462
|
}).required();
|
1412
1463
|
const generateUIDInputSchema = yup$1.object({
|
1413
1464
|
contentTypeUID: yup$1.string().required(),
|
@@ -1506,15 +1557,47 @@ const excludeNotCreatableFields = (uid2, permissionChecker2) => (body, path = []
|
|
1506
1557
|
}
|
1507
1558
|
}, body);
|
1508
1559
|
};
|
1509
|
-
const
|
1560
|
+
const singleLocaleSchema = yup$1.string().nullable();
|
1561
|
+
const multipleLocaleSchema = yup$1.lazy(
|
1562
|
+
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1563
|
+
);
|
1564
|
+
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1565
|
+
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1566
|
+
const { allowMultipleLocales } = opts;
|
1510
1567
|
const { locale, status, ...rest } = request || {};
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1568
|
+
const schema = yup$1.object().shape({
|
1569
|
+
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1570
|
+
status: statusSchema
|
1571
|
+
});
|
1572
|
+
try {
|
1573
|
+
await validateYupSchema(schema, { strict: true, abortEarly: false })(request);
|
1574
|
+
return { locale, status, ...rest };
|
1575
|
+
} catch (error) {
|
1576
|
+
throw new errors.ValidationError(`Validation error: ${error.message}`);
|
1516
1577
|
}
|
1517
|
-
|
1578
|
+
};
|
1579
|
+
const formatDocumentWithMetadata = async (permissionChecker2, uid2, document, opts = {}) => {
|
1580
|
+
const documentMetadata2 = getService$1("document-metadata");
|
1581
|
+
const serviceOutput = await documentMetadata2.formatDocumentWithMetadata(uid2, document, opts);
|
1582
|
+
let {
|
1583
|
+
meta: { availableLocales, availableStatus }
|
1584
|
+
} = serviceOutput;
|
1585
|
+
const metadataSanitizer = permissionChecker2.sanitizeOutput;
|
1586
|
+
availableLocales = await async.map(
|
1587
|
+
availableLocales,
|
1588
|
+
async (localeDocument) => metadataSanitizer(localeDocument)
|
1589
|
+
);
|
1590
|
+
availableStatus = await async.map(
|
1591
|
+
availableStatus,
|
1592
|
+
async (statusDocument) => metadataSanitizer(statusDocument)
|
1593
|
+
);
|
1594
|
+
return {
|
1595
|
+
...serviceOutput,
|
1596
|
+
meta: {
|
1597
|
+
availableLocales,
|
1598
|
+
availableStatus
|
1599
|
+
}
|
1600
|
+
};
|
1518
1601
|
};
|
1519
1602
|
const createDocument = async (ctx, opts) => {
|
1520
1603
|
const { userAbility, user } = ctx.state;
|
@@ -1529,7 +1612,7 @@ const createDocument = async (ctx, opts) => {
|
|
1529
1612
|
const setCreator = setCreatorFields({ user });
|
1530
1613
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1531
1614
|
const sanitizedBody = await sanitizeFn(body);
|
1532
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(body);
|
1615
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
|
1533
1616
|
return documentManager2.create(model, {
|
1534
1617
|
data: sanitizedBody,
|
1535
1618
|
locale,
|
@@ -1548,7 +1631,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1548
1631
|
}
|
1549
1632
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1550
1633
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1551
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1634
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1552
1635
|
const [documentVersion, documentExists] = await Promise.all([
|
1553
1636
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1554
1637
|
documentManager2.exists(model, id)
|
@@ -1586,8 +1669,8 @@ const collectionTypes = {
|
|
1586
1669
|
}
|
1587
1670
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1588
1671
|
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(
|
1672
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1673
|
+
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1591
1674
|
{ ...permissionQuery, populate, locale, status },
|
1592
1675
|
model
|
1593
1676
|
);
|
@@ -1608,21 +1691,20 @@ const collectionTypes = {
|
|
1608
1691
|
);
|
1609
1692
|
ctx.body = {
|
1610
1693
|
results,
|
1611
|
-
pagination
|
1694
|
+
pagination: pagination2
|
1612
1695
|
};
|
1613
1696
|
},
|
1614
1697
|
async findOne(ctx) {
|
1615
1698
|
const { userAbility } = ctx.state;
|
1616
1699
|
const { model, id } = ctx.params;
|
1617
1700
|
const documentManager2 = getService$1("document-manager");
|
1618
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1619
1701
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1620
1702
|
if (permissionChecker2.cannot.read()) {
|
1621
1703
|
return ctx.forbidden();
|
1622
1704
|
}
|
1623
1705
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1624
1706
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1625
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
1707
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1626
1708
|
const version = await documentManager2.findOne(id, model, {
|
1627
1709
|
populate,
|
1628
1710
|
locale,
|
@@ -1633,8 +1715,10 @@ const collectionTypes = {
|
|
1633
1715
|
if (!exists) {
|
1634
1716
|
return ctx.notFound();
|
1635
1717
|
}
|
1636
|
-
const { meta } = await
|
1718
|
+
const { meta } = await formatDocumentWithMetadata(
|
1719
|
+
permissionChecker2,
|
1637
1720
|
model,
|
1721
|
+
// @ts-expect-error TODO: fix
|
1638
1722
|
{ id, locale, publishedAt: null },
|
1639
1723
|
{ availableLocales: true, availableStatus: false }
|
1640
1724
|
);
|
@@ -1645,12 +1729,11 @@ const collectionTypes = {
|
|
1645
1729
|
return ctx.forbidden();
|
1646
1730
|
}
|
1647
1731
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
1648
|
-
ctx.body = await
|
1732
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1649
1733
|
},
|
1650
1734
|
async create(ctx) {
|
1651
1735
|
const { userAbility } = ctx.state;
|
1652
1736
|
const { model } = ctx.params;
|
1653
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1654
1737
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1655
1738
|
const [totalEntries, document] = await Promise.all([
|
1656
1739
|
strapi.db.query(model).count(),
|
@@ -1658,7 +1741,7 @@ const collectionTypes = {
|
|
1658
1741
|
]);
|
1659
1742
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
1660
1743
|
ctx.status = 201;
|
1661
|
-
ctx.body = await
|
1744
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1662
1745
|
// Empty metadata as it's not relevant for a new document
|
1663
1746
|
availableLocales: false,
|
1664
1747
|
availableStatus: false
|
@@ -1672,25 +1755,23 @@ const collectionTypes = {
|
|
1672
1755
|
async update(ctx) {
|
1673
1756
|
const { userAbility } = ctx.state;
|
1674
1757
|
const { model } = ctx.params;
|
1675
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1676
1758
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1677
1759
|
const updatedVersion = await updateDocument(ctx);
|
1678
1760
|
const sanitizedVersion = await permissionChecker2.sanitizeOutput(updatedVersion);
|
1679
|
-
ctx.body = await
|
1761
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedVersion);
|
1680
1762
|
},
|
1681
1763
|
async clone(ctx) {
|
1682
1764
|
const { userAbility, user } = ctx.state;
|
1683
1765
|
const { model, sourceId: id } = ctx.params;
|
1684
1766
|
const { body } = ctx.request;
|
1685
1767
|
const documentManager2 = getService$1("document-manager");
|
1686
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1687
1768
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1688
1769
|
if (permissionChecker2.cannot.create()) {
|
1689
1770
|
return ctx.forbidden();
|
1690
1771
|
}
|
1691
1772
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1692
1773
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1693
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1774
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1694
1775
|
const document = await documentManager2.findOne(id, model, {
|
1695
1776
|
populate,
|
1696
1777
|
locale,
|
@@ -1706,7 +1787,7 @@ const collectionTypes = {
|
|
1706
1787
|
const sanitizedBody = await sanitizeFn(body);
|
1707
1788
|
const clonedDocument = await documentManager2.clone(document.documentId, sanitizedBody, model);
|
1708
1789
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(clonedDocument);
|
1709
|
-
ctx.body = await
|
1790
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument, {
|
1710
1791
|
// Empty metadata as it's not relevant for a new document
|
1711
1792
|
availableLocales: false,
|
1712
1793
|
availableStatus: false
|
@@ -1735,7 +1816,7 @@ const collectionTypes = {
|
|
1735
1816
|
}
|
1736
1817
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1737
1818
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1738
|
-
const { locale } = getDocumentLocaleAndStatus(ctx.query);
|
1819
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1739
1820
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1740
1821
|
if (documentLocales.length === 0) {
|
1741
1822
|
return ctx.notFound();
|
@@ -1757,7 +1838,6 @@ const collectionTypes = {
|
|
1757
1838
|
const { id, model } = ctx.params;
|
1758
1839
|
const { body } = ctx.request;
|
1759
1840
|
const documentManager2 = getService$1("document-manager");
|
1760
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1761
1841
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1762
1842
|
if (permissionChecker2.cannot.publish()) {
|
1763
1843
|
return ctx.forbidden();
|
@@ -1769,21 +1849,25 @@ const collectionTypes = {
|
|
1769
1849
|
if (permissionChecker2.cannot.publish(document)) {
|
1770
1850
|
throw new errors.ForbiddenError();
|
1771
1851
|
}
|
1772
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1773
|
-
|
1852
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1853
|
+
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1774
1854
|
locale
|
1775
1855
|
// TODO: Allow setting creator fields on publish
|
1776
1856
|
// data: setCreatorFields({ user, isEdition: true })({}),
|
1777
1857
|
});
|
1858
|
+
if (!publishResult || publishResult.length === 0) {
|
1859
|
+
throw new errors.NotFoundError("Document not found or already published.");
|
1860
|
+
}
|
1861
|
+
return publishResult[0];
|
1778
1862
|
});
|
1779
1863
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
1780
|
-
ctx.body = await
|
1864
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
1781
1865
|
},
|
1782
1866
|
async bulkPublish(ctx) {
|
1783
1867
|
const { userAbility } = ctx.state;
|
1784
1868
|
const { model } = ctx.params;
|
1785
1869
|
const { body } = ctx.request;
|
1786
|
-
const {
|
1870
|
+
const { documentIds } = body;
|
1787
1871
|
await validateBulkActionInput(body);
|
1788
1872
|
const documentManager2 = getService$1("document-manager");
|
1789
1873
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1792,8 +1876,11 @@ const collectionTypes = {
|
|
1792
1876
|
}
|
1793
1877
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1794
1878
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1795
|
-
const
|
1796
|
-
const
|
1879
|
+
const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
|
1880
|
+
const entityPromises = documentIds.map(
|
1881
|
+
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1882
|
+
);
|
1883
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1797
1884
|
for (const entity of entities) {
|
1798
1885
|
if (!entity) {
|
1799
1886
|
return ctx.notFound();
|
@@ -1802,24 +1889,25 @@ const collectionTypes = {
|
|
1802
1889
|
return ctx.forbidden();
|
1803
1890
|
}
|
1804
1891
|
}
|
1805
|
-
const
|
1892
|
+
const count = await documentManager2.publishMany(model, documentIds, locale);
|
1806
1893
|
ctx.body = { count };
|
1807
1894
|
},
|
1808
1895
|
async bulkUnpublish(ctx) {
|
1809
1896
|
const { userAbility } = ctx.state;
|
1810
1897
|
const { model } = ctx.params;
|
1811
1898
|
const { body } = ctx.request;
|
1812
|
-
const {
|
1899
|
+
const { documentIds } = body;
|
1813
1900
|
await validateBulkActionInput(body);
|
1814
1901
|
const documentManager2 = getService$1("document-manager");
|
1815
1902
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1816
1903
|
if (permissionChecker2.cannot.unpublish()) {
|
1817
1904
|
return ctx.forbidden();
|
1818
1905
|
}
|
1819
|
-
const
|
1820
|
-
const
|
1821
|
-
|
1822
|
-
|
1906
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1907
|
+
const entityPromises = documentIds.map(
|
1908
|
+
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1909
|
+
);
|
1910
|
+
const entities = (await Promise.all(entityPromises)).flat();
|
1823
1911
|
for (const entity of entities) {
|
1824
1912
|
if (!entity) {
|
1825
1913
|
return ctx.notFound();
|
@@ -1828,7 +1916,8 @@ const collectionTypes = {
|
|
1828
1916
|
return ctx.forbidden();
|
1829
1917
|
}
|
1830
1918
|
}
|
1831
|
-
const
|
1919
|
+
const entitiesIds = entities.map((document) => document.documentId);
|
1920
|
+
const { count } = await documentManager2.unpublishMany(entitiesIds, model, { locale });
|
1832
1921
|
ctx.body = { count };
|
1833
1922
|
},
|
1834
1923
|
async unpublish(ctx) {
|
@@ -1838,7 +1927,6 @@ const collectionTypes = {
|
|
1838
1927
|
body: { discardDraft, ...body }
|
1839
1928
|
} = ctx.request;
|
1840
1929
|
const documentManager2 = getService$1("document-manager");
|
1841
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1842
1930
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1843
1931
|
if (permissionChecker2.cannot.unpublish()) {
|
1844
1932
|
return ctx.forbidden();
|
@@ -1848,7 +1936,7 @@ const collectionTypes = {
|
|
1848
1936
|
}
|
1849
1937
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1850
1938
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1851
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1939
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1852
1940
|
const document = await documentManager2.findOne(id, model, {
|
1853
1941
|
populate,
|
1854
1942
|
locale,
|
@@ -1870,7 +1958,7 @@ const collectionTypes = {
|
|
1870
1958
|
ctx.body = await async.pipe(
|
1871
1959
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
1872
1960
|
permissionChecker2.sanitizeOutput,
|
1873
|
-
(document2) =>
|
1961
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1874
1962
|
)(document);
|
1875
1963
|
});
|
1876
1964
|
},
|
@@ -1879,14 +1967,13 @@ const collectionTypes = {
|
|
1879
1967
|
const { id, model } = ctx.params;
|
1880
1968
|
const { body } = ctx.request;
|
1881
1969
|
const documentManager2 = getService$1("document-manager");
|
1882
|
-
const documentMetadata2 = getService$1("document-metadata");
|
1883
1970
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
1884
1971
|
if (permissionChecker2.cannot.discard()) {
|
1885
1972
|
return ctx.forbidden();
|
1886
1973
|
}
|
1887
1974
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1888
1975
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1889
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
1976
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
1890
1977
|
const document = await documentManager2.findOne(id, model, {
|
1891
1978
|
populate,
|
1892
1979
|
locale,
|
@@ -1901,14 +1988,14 @@ const collectionTypes = {
|
|
1901
1988
|
ctx.body = await async.pipe(
|
1902
1989
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
1903
1990
|
permissionChecker2.sanitizeOutput,
|
1904
|
-
(document2) =>
|
1991
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
1905
1992
|
)(document);
|
1906
1993
|
},
|
1907
1994
|
async bulkDelete(ctx) {
|
1908
1995
|
const { userAbility } = ctx.state;
|
1909
1996
|
const { model } = ctx.params;
|
1910
1997
|
const { query, body } = ctx.request;
|
1911
|
-
const {
|
1998
|
+
const { documentIds } = body;
|
1912
1999
|
await validateBulkActionInput(body);
|
1913
2000
|
const documentManager2 = getService$1("document-manager");
|
1914
2001
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
@@ -1916,14 +2003,22 @@ const collectionTypes = {
|
|
1916
2003
|
return ctx.forbidden();
|
1917
2004
|
}
|
1918
2005
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
1919
|
-
const
|
1920
|
-
const
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
2006
|
+
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2007
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2008
|
+
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2009
|
+
populate,
|
2010
|
+
locale
|
2011
|
+
});
|
2012
|
+
if (documentLocales.length === 0) {
|
2013
|
+
return ctx.notFound();
|
2014
|
+
}
|
2015
|
+
for (const document of documentLocales) {
|
2016
|
+
if (permissionChecker2.cannot.delete(document)) {
|
2017
|
+
return ctx.forbidden();
|
1924
2018
|
}
|
1925
|
-
}
|
1926
|
-
const
|
2019
|
+
}
|
2020
|
+
const localeDocumentsIds = documentLocales.map((document) => document.documentId);
|
2021
|
+
const { count } = await documentManager2.deleteMany(localeDocumentsIds, model, { locale });
|
1927
2022
|
ctx.body = { count };
|
1928
2023
|
},
|
1929
2024
|
async countDraftRelations(ctx) {
|
@@ -1936,7 +2031,7 @@ const collectionTypes = {
|
|
1936
2031
|
}
|
1937
2032
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1938
2033
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1939
|
-
const { locale, status = "draft" } = getDocumentLocaleAndStatus(ctx.query);
|
2034
|
+
const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
|
1940
2035
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
1941
2036
|
if (!entity) {
|
1942
2037
|
return ctx.notFound();
|
@@ -1951,7 +2046,7 @@ const collectionTypes = {
|
|
1951
2046
|
},
|
1952
2047
|
async countManyEntriesDraftRelations(ctx) {
|
1953
2048
|
const { userAbility } = ctx.state;
|
1954
|
-
const ids = ctx.request.query.
|
2049
|
+
const ids = ctx.request.query.documentIds;
|
1955
2050
|
const locale = ctx.request.query.locale;
|
1956
2051
|
const { model } = ctx.params;
|
1957
2052
|
const documentManager2 = getService$1("document-manager");
|
@@ -1962,7 +2057,7 @@ const collectionTypes = {
|
|
1962
2057
|
const entities = await documentManager2.findMany(
|
1963
2058
|
{
|
1964
2059
|
filters: {
|
1965
|
-
|
2060
|
+
documentId: ids
|
1966
2061
|
},
|
1967
2062
|
locale
|
1968
2063
|
},
|
@@ -2464,7 +2559,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2464
2559
|
throw new errors.ForbiddenError();
|
2465
2560
|
}
|
2466
2561
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2467
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2562
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2468
2563
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2469
2564
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2470
2565
|
// Find the first document to check if it exists
|
@@ -2501,12 +2596,11 @@ const singleTypes = {
|
|
2501
2596
|
const { model } = ctx.params;
|
2502
2597
|
const { query = {} } = ctx.request;
|
2503
2598
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2504
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2505
2599
|
if (permissionChecker2.cannot.read()) {
|
2506
2600
|
return ctx.forbidden();
|
2507
2601
|
}
|
2508
2602
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2509
|
-
const { locale, status } = getDocumentLocaleAndStatus(query);
|
2603
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2510
2604
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2511
2605
|
if (!version) {
|
2512
2606
|
if (permissionChecker2.cannot.create()) {
|
@@ -2516,8 +2610,10 @@ const singleTypes = {
|
|
2516
2610
|
if (!document) {
|
2517
2611
|
return ctx.notFound();
|
2518
2612
|
}
|
2519
|
-
const { meta } = await
|
2613
|
+
const { meta } = await formatDocumentWithMetadata(
|
2614
|
+
permissionChecker2,
|
2520
2615
|
model,
|
2616
|
+
// @ts-expect-error - fix types
|
2521
2617
|
{ id: document.documentId, locale, publishedAt: null },
|
2522
2618
|
{ availableLocales: true, availableStatus: false }
|
2523
2619
|
);
|
@@ -2528,16 +2624,15 @@ const singleTypes = {
|
|
2528
2624
|
return ctx.forbidden();
|
2529
2625
|
}
|
2530
2626
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(version);
|
2531
|
-
ctx.body = await
|
2627
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2532
2628
|
},
|
2533
2629
|
async createOrUpdate(ctx) {
|
2534
2630
|
const { userAbility } = ctx.state;
|
2535
2631
|
const { model } = ctx.params;
|
2536
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2537
2632
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2538
2633
|
const document = await createOrUpdateDocument(ctx);
|
2539
2634
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(document);
|
2540
|
-
ctx.body = await
|
2635
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2541
2636
|
},
|
2542
2637
|
async delete(ctx) {
|
2543
2638
|
const { userAbility } = ctx.state;
|
@@ -2550,7 +2645,7 @@ const singleTypes = {
|
|
2550
2645
|
}
|
2551
2646
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2552
2647
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2553
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2648
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2554
2649
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2555
2650
|
populate,
|
2556
2651
|
locale
|
@@ -2573,7 +2668,6 @@ const singleTypes = {
|
|
2573
2668
|
const { model } = ctx.params;
|
2574
2669
|
const { query = {} } = ctx.request;
|
2575
2670
|
const documentManager2 = getService$1("document-manager");
|
2576
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2577
2671
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2578
2672
|
if (permissionChecker2.cannot.publish()) {
|
2579
2673
|
return ctx.forbidden();
|
@@ -2588,11 +2682,12 @@ const singleTypes = {
|
|
2588
2682
|
if (permissionChecker2.cannot.publish(document)) {
|
2589
2683
|
throw new errors.ForbiddenError();
|
2590
2684
|
}
|
2591
|
-
const { locale } = getDocumentLocaleAndStatus(document);
|
2592
|
-
|
2685
|
+
const { locale } = await getDocumentLocaleAndStatus(document);
|
2686
|
+
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2687
|
+
return publishResult.at(0);
|
2593
2688
|
});
|
2594
2689
|
const sanitizedDocument = await permissionChecker2.sanitizeOutput(publishedDocument);
|
2595
|
-
ctx.body = await
|
2690
|
+
ctx.body = await formatDocumentWithMetadata(permissionChecker2, model, sanitizedDocument);
|
2596
2691
|
},
|
2597
2692
|
async unpublish(ctx) {
|
2598
2693
|
const { userAbility } = ctx.state;
|
@@ -2602,7 +2697,6 @@ const singleTypes = {
|
|
2602
2697
|
query = {}
|
2603
2698
|
} = ctx.request;
|
2604
2699
|
const documentManager2 = getService$1("document-manager");
|
2605
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2606
2700
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2607
2701
|
if (permissionChecker2.cannot.unpublish()) {
|
2608
2702
|
return ctx.forbidden();
|
@@ -2611,7 +2705,7 @@ const singleTypes = {
|
|
2611
2705
|
return ctx.forbidden();
|
2612
2706
|
}
|
2613
2707
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2614
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2708
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2615
2709
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2616
2710
|
if (!document) {
|
2617
2711
|
return ctx.notFound();
|
@@ -2629,7 +2723,7 @@ const singleTypes = {
|
|
2629
2723
|
ctx.body = await async.pipe(
|
2630
2724
|
(document2) => documentManager2.unpublish(document2.documentId, model, { locale }),
|
2631
2725
|
permissionChecker2.sanitizeOutput,
|
2632
|
-
(document2) =>
|
2726
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2633
2727
|
)(document);
|
2634
2728
|
});
|
2635
2729
|
},
|
@@ -2638,13 +2732,12 @@ const singleTypes = {
|
|
2638
2732
|
const { model } = ctx.params;
|
2639
2733
|
const { body, query = {} } = ctx.request;
|
2640
2734
|
const documentManager2 = getService$1("document-manager");
|
2641
|
-
const documentMetadata2 = getService$1("document-metadata");
|
2642
2735
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2643
2736
|
if (permissionChecker2.cannot.discard()) {
|
2644
2737
|
return ctx.forbidden();
|
2645
2738
|
}
|
2646
2739
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2647
|
-
const { locale } = getDocumentLocaleAndStatus(body);
|
2740
|
+
const { locale } = await getDocumentLocaleAndStatus(body);
|
2648
2741
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2649
2742
|
if (!document) {
|
2650
2743
|
return ctx.notFound();
|
@@ -2655,7 +2748,7 @@ const singleTypes = {
|
|
2655
2748
|
ctx.body = await async.pipe(
|
2656
2749
|
(document2) => documentManager2.discardDraft(document2.documentId, model, { locale }),
|
2657
2750
|
permissionChecker2.sanitizeOutput,
|
2658
|
-
(document2) =>
|
2751
|
+
(document2) => formatDocumentWithMetadata(permissionChecker2, model, document2)
|
2659
2752
|
)(document);
|
2660
2753
|
},
|
2661
2754
|
async countDraftRelations(ctx) {
|
@@ -2664,7 +2757,7 @@ const singleTypes = {
|
|
2664
2757
|
const { query } = ctx.request;
|
2665
2758
|
const documentManager2 = getService$1("document-manager");
|
2666
2759
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2667
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2760
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2668
2761
|
if (permissionChecker2.cannot.read()) {
|
2669
2762
|
return ctx.forbidden();
|
2670
2763
|
}
|
@@ -2685,7 +2778,7 @@ const uid$1 = {
|
|
2685
2778
|
async generateUID(ctx) {
|
2686
2779
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2687
2780
|
const { query = {} } = ctx.request;
|
2688
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2781
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2689
2782
|
await validateUIDField(contentTypeUID, field);
|
2690
2783
|
const uidService = getService$1("uid");
|
2691
2784
|
ctx.body = {
|
@@ -2697,7 +2790,7 @@ const uid$1 = {
|
|
2697
2790
|
ctx.request.body
|
2698
2791
|
);
|
2699
2792
|
const { query = {} } = ctx.request;
|
2700
|
-
const { locale } = getDocumentLocaleAndStatus(query);
|
2793
|
+
const { locale } = await getDocumentLocaleAndStatus(query);
|
2701
2794
|
await validateUIDField(contentTypeUID, field);
|
2702
2795
|
const uidService = getService$1("uid");
|
2703
2796
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3488,7 +3581,7 @@ const permission = ({ strapi: strapi2 }) => ({
|
|
3488
3581
|
await strapi2.service("admin::permission").actionProvider.registerMany(actions);
|
3489
3582
|
}
|
3490
3583
|
});
|
3491
|
-
const { isVisibleAttribute: isVisibleAttribute$1 } = strapiUtils.contentTypes;
|
3584
|
+
const { isVisibleAttribute: isVisibleAttribute$1, isScalarAttribute, getDoesAttributeRequireValidation } = strapiUtils.contentTypes;
|
3492
3585
|
const { isAnyToMany } = strapiUtils.relations;
|
3493
3586
|
const { PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1 } = strapiUtils.contentTypes.constants;
|
3494
3587
|
const isMorphToRelation = (attribute) => isRelation(attribute) && attribute.relation.includes("morphTo");
|
@@ -3579,6 +3672,42 @@ const getDeepPopulate = (uid2, {
|
|
3579
3672
|
{}
|
3580
3673
|
);
|
3581
3674
|
};
|
3675
|
+
const getValidatableFieldsPopulate = (uid2, {
|
3676
|
+
initialPopulate = {},
|
3677
|
+
countMany = false,
|
3678
|
+
countOne = false,
|
3679
|
+
maxLevel = Infinity
|
3680
|
+
} = {}, level = 1) => {
|
3681
|
+
if (level > maxLevel) {
|
3682
|
+
return {};
|
3683
|
+
}
|
3684
|
+
const model = strapi.getModel(uid2);
|
3685
|
+
return Object.entries(model.attributes).reduce((populateAcc, [attributeName, attribute]) => {
|
3686
|
+
if (!getDoesAttributeRequireValidation(attribute)) {
|
3687
|
+
return populateAcc;
|
3688
|
+
}
|
3689
|
+
if (isScalarAttribute(attribute)) {
|
3690
|
+
return merge(populateAcc, {
|
3691
|
+
[attributeName]: true
|
3692
|
+
});
|
3693
|
+
}
|
3694
|
+
return merge(
|
3695
|
+
populateAcc,
|
3696
|
+
getPopulateFor(
|
3697
|
+
attributeName,
|
3698
|
+
model,
|
3699
|
+
{
|
3700
|
+
// @ts-expect-error - improve types
|
3701
|
+
initialPopulate: initialPopulate?.[attributeName],
|
3702
|
+
countMany,
|
3703
|
+
countOne,
|
3704
|
+
maxLevel
|
3705
|
+
},
|
3706
|
+
level
|
3707
|
+
)
|
3708
|
+
);
|
3709
|
+
}, {});
|
3710
|
+
};
|
3582
3711
|
const getDeepPopulateDraftCount = (uid2) => {
|
3583
3712
|
const model = strapi.getModel(uid2);
|
3584
3713
|
let hasRelations = false;
|
@@ -3807,41 +3936,70 @@ const AVAILABLE_STATUS_FIELDS = [
|
|
3807
3936
|
"updatedBy",
|
3808
3937
|
"status"
|
3809
3938
|
];
|
3810
|
-
const AVAILABLE_LOCALES_FIELDS = [
|
3939
|
+
const AVAILABLE_LOCALES_FIELDS = [
|
3940
|
+
"id",
|
3941
|
+
"locale",
|
3942
|
+
"updatedAt",
|
3943
|
+
"createdAt",
|
3944
|
+
"status",
|
3945
|
+
"publishedAt",
|
3946
|
+
"documentId"
|
3947
|
+
];
|
3811
3948
|
const CONTENT_MANAGER_STATUS = {
|
3812
3949
|
PUBLISHED: "published",
|
3813
3950
|
DRAFT: "draft",
|
3814
3951
|
MODIFIED: "modified"
|
3815
3952
|
};
|
3816
|
-
const
|
3817
|
-
if (!
|
3953
|
+
const getIsVersionLatestModification = (version, otherVersion) => {
|
3954
|
+
if (!version || !version.updatedAt) {
|
3818
3955
|
return false;
|
3819
3956
|
}
|
3820
|
-
const
|
3821
|
-
const
|
3822
|
-
|
3823
|
-
return difference2 <= threshold;
|
3957
|
+
const versionUpdatedAt = version?.updatedAt ? new Date(version.updatedAt).getTime() : 0;
|
3958
|
+
const otherUpdatedAt = otherVersion?.updatedAt ? new Date(otherVersion.updatedAt).getTime() : 0;
|
3959
|
+
return versionUpdatedAt > otherUpdatedAt;
|
3824
3960
|
};
|
3825
3961
|
const documentMetadata = ({ strapi: strapi2 }) => ({
|
3826
3962
|
/**
|
3827
3963
|
* Returns available locales of a document for the current status
|
3828
3964
|
*/
|
3829
|
-
getAvailableLocales(uid2, version, allVersions) {
|
3965
|
+
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3830
3966
|
const versionsByLocale = groupBy("locale", allVersions);
|
3831
3967
|
delete versionsByLocale[version.locale];
|
3832
|
-
|
3833
|
-
|
3834
|
-
|
3968
|
+
const model = strapi2.getModel(uid2);
|
3969
|
+
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3970
|
+
const traversalFunction = async (localeVersion) => traverseEntity(
|
3971
|
+
({ key }, { remove }) => {
|
3972
|
+
if (keysToKeep.includes(key)) {
|
3973
|
+
return;
|
3974
|
+
}
|
3975
|
+
remove(key);
|
3976
|
+
},
|
3977
|
+
{ schema: model, getModel: strapi2.getModel.bind(strapi2) },
|
3978
|
+
// @ts-expect-error fix types DocumentVersion incompatible with Data
|
3979
|
+
localeVersion
|
3980
|
+
);
|
3981
|
+
const mappingResult = await async.map(
|
3982
|
+
Object.values(versionsByLocale),
|
3983
|
+
async (localeVersions) => {
|
3984
|
+
const mappedLocaleVersions = await async.map(
|
3985
|
+
localeVersions,
|
3986
|
+
traversalFunction
|
3987
|
+
);
|
3988
|
+
if (!contentTypes$1.hasDraftAndPublish(model)) {
|
3989
|
+
return mappedLocaleVersions[0];
|
3990
|
+
}
|
3991
|
+
const draftVersion = mappedLocaleVersions.find((v) => v.publishedAt === null);
|
3992
|
+
const otherVersions = mappedLocaleVersions.filter((v) => v.id !== draftVersion?.id);
|
3993
|
+
if (!draftVersion) {
|
3994
|
+
return;
|
3995
|
+
}
|
3996
|
+
return {
|
3997
|
+
...draftVersion,
|
3998
|
+
status: this.getStatus(draftVersion, otherVersions)
|
3999
|
+
};
|
3835
4000
|
}
|
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);
|
4001
|
+
);
|
4002
|
+
return mappingResult.filter(Boolean);
|
3845
4003
|
},
|
3846
4004
|
/**
|
3847
4005
|
* Returns available status of a document for the current locale
|
@@ -3879,26 +4037,37 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3879
4037
|
});
|
3880
4038
|
},
|
3881
4039
|
getStatus(version, otherDocumentStatuses) {
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
4040
|
+
let draftVersion;
|
4041
|
+
let publishedVersion;
|
4042
|
+
if (version.publishedAt) {
|
4043
|
+
publishedVersion = version;
|
4044
|
+
} else {
|
4045
|
+
draftVersion = version;
|
3885
4046
|
}
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
4047
|
+
const otherVersion = otherDocumentStatuses?.at(0);
|
4048
|
+
if (otherVersion?.publishedAt) {
|
4049
|
+
publishedVersion = otherVersion;
|
4050
|
+
} else if (otherVersion) {
|
4051
|
+
draftVersion = otherVersion;
|
3891
4052
|
}
|
3892
|
-
if (
|
4053
|
+
if (!draftVersion)
|
3893
4054
|
return CONTENT_MANAGER_STATUS.PUBLISHED;
|
3894
|
-
|
3895
|
-
|
4055
|
+
if (!publishedVersion)
|
4056
|
+
return CONTENT_MANAGER_STATUS.DRAFT;
|
4057
|
+
const isDraftModified = getIsVersionLatestModification(draftVersion, publishedVersion);
|
4058
|
+
return isDraftModified ? CONTENT_MANAGER_STATUS.MODIFIED : CONTENT_MANAGER_STATUS.PUBLISHED;
|
3896
4059
|
},
|
4060
|
+
// TODO is it necessary to return metadata on every page of the CM
|
4061
|
+
// We could refactor this so the locales are only loaded when they're
|
4062
|
+
// needed. e.g. in the bulk locale action modal.
|
3897
4063
|
async getMetadata(uid2, version, { availableLocales = true, availableStatus = true } = {}) {
|
4064
|
+
const populate = getValidatableFieldsPopulate(uid2);
|
3898
4065
|
const versions = await strapi2.db.query(uid2).findMany({
|
3899
4066
|
where: { documentId: version.documentId },
|
3900
|
-
select: ["createdAt", "updatedAt", "locale", "publishedAt", "documentId"],
|
3901
4067
|
populate: {
|
4068
|
+
// Populate only fields that require validation for bulk locale actions
|
4069
|
+
...populate,
|
4070
|
+
// NOTE: creator fields are selected in this way to avoid exposing sensitive data
|
3902
4071
|
createdBy: {
|
3903
4072
|
select: ["id", "firstname", "lastname", "email"]
|
3904
4073
|
},
|
@@ -3907,7 +4076,7 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3907
4076
|
}
|
3908
4077
|
}
|
3909
4078
|
});
|
3910
|
-
const availableLocalesResult = availableLocales ? this.getAvailableLocales(uid2, version, versions) : [];
|
4079
|
+
const availableLocalesResult = availableLocales ? await this.getAvailableLocales(uid2, version, versions, Object.keys(populate)) : [];
|
3911
4080
|
const availableStatusResult = availableStatus ? this.getAvailableStatus(version, versions) : null;
|
3912
4081
|
return {
|
3913
4082
|
availableLocales: availableLocalesResult,
|
@@ -3920,8 +4089,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3920
4089
|
* - Available status of the document for the current locale
|
3921
4090
|
*/
|
3922
4091
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
3923
|
-
if (!document)
|
4092
|
+
if (!document) {
|
3924
4093
|
return document;
|
4094
|
+
}
|
3925
4095
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
3926
4096
|
if (!hasDraftAndPublish) {
|
3927
4097
|
opts.availableStatus = false;
|
@@ -3971,26 +4141,9 @@ const sumDraftCounts = (entity, uid2) => {
|
|
3971
4141
|
}, 0);
|
3972
4142
|
};
|
3973
4143
|
const { ApplicationError } = errors;
|
3974
|
-
const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = ALLOWED_WEBHOOK_EVENTS;
|
3975
4144
|
const { PUBLISHED_AT_ATTRIBUTE } = contentTypes$1.constants;
|
3976
4145
|
const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
|
3977
4146
|
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
4147
|
const documentManager = ({ strapi: strapi2 }) => {
|
3995
4148
|
return {
|
3996
4149
|
async findOne(id, uid2, opts = {}) {
|
@@ -4009,6 +4162,9 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4009
4162
|
} else if (opts.locale && opts.locale !== "*") {
|
4010
4163
|
where.locale = opts.locale;
|
4011
4164
|
}
|
4165
|
+
if (typeof opts.isPublished === "boolean") {
|
4166
|
+
where.publishedAt = { $notNull: opts.isPublished };
|
4167
|
+
}
|
4012
4168
|
return strapi2.db.query(uid2).findMany({ populate: opts.populate, where });
|
4013
4169
|
},
|
4014
4170
|
async findMany(opts, uid2) {
|
@@ -4016,20 +4172,16 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4016
4172
|
return strapi2.documents(uid2).findMany(params);
|
4017
4173
|
},
|
4018
4174
|
async findPage(opts, uid2) {
|
4019
|
-
const
|
4020
|
-
|
4175
|
+
const params = pagination.withDefaultPagination(opts || {}, {
|
4176
|
+
maxLimit: 1e3
|
4177
|
+
});
|
4021
4178
|
const [documents, total = 0] = await Promise.all([
|
4022
|
-
strapi2.documents(uid2).findMany(
|
4023
|
-
strapi2.documents(uid2).count(
|
4179
|
+
strapi2.documents(uid2).findMany(params),
|
4180
|
+
strapi2.documents(uid2).count(params)
|
4024
4181
|
]);
|
4025
4182
|
return {
|
4026
4183
|
results: documents,
|
4027
|
-
pagination:
|
4028
|
-
page,
|
4029
|
-
pageSize,
|
4030
|
-
pageCount: Math.ceil(total / pageSize),
|
4031
|
-
total
|
4032
|
-
}
|
4184
|
+
pagination: pagination.transformPagedPaginationInfo(params, total)
|
4033
4185
|
};
|
4034
4186
|
},
|
4035
4187
|
async create(uid2, opts = {}) {
|
@@ -4075,70 +4227,36 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4075
4227
|
return {};
|
4076
4228
|
},
|
4077
4229
|
// FIXME: handle relations
|
4078
|
-
async deleteMany(
|
4079
|
-
const
|
4080
|
-
|
4081
|
-
|
4082
|
-
}
|
4083
|
-
return { count: docs.length };
|
4230
|
+
async deleteMany(documentIds, uid2, opts = {}) {
|
4231
|
+
const deletedEntries = await strapi2.db.transaction(async () => {
|
4232
|
+
return Promise.all(documentIds.map(async (id) => this.delete(id, uid2, opts)));
|
4233
|
+
});
|
4234
|
+
return { count: deletedEntries.length };
|
4084
4235
|
},
|
4085
4236
|
async publish(id, uid2, opts = {}) {
|
4086
4237
|
const populate = await buildDeepPopulate(uid2);
|
4087
4238
|
const params = { ...opts, populate };
|
4088
|
-
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries
|
4239
|
+
return strapi2.documents(uid2).publish({ ...params, documentId: id }).then((result) => result?.entries);
|
4089
4240
|
},
|
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
|
4241
|
+
async publishMany(uid2, documentIds, locale) {
|
4242
|
+
return strapi2.db.transaction(async () => {
|
4243
|
+
const results = await Promise.all(
|
4244
|
+
documentIds.map((documentId) => this.publish(documentId, uid2, { locale }))
|
4245
|
+
);
|
4246
|
+
const publishedEntitiesCount = results.flat().filter(Boolean).length;
|
4247
|
+
return publishedEntitiesCount;
|
4116
4248
|
});
|
4117
|
-
await Promise.all(
|
4118
|
-
publishedEntities.map((doc) => emitEvent(uid2, ENTRY_PUBLISH, doc))
|
4119
|
-
);
|
4120
|
-
return publishedEntitiesCount;
|
4121
4249
|
},
|
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
|
4250
|
+
async unpublishMany(documentIds, uid2, opts = {}) {
|
4251
|
+
const unpublishedEntries = await strapi2.db.transaction(async () => {
|
4252
|
+
return Promise.all(
|
4253
|
+
documentIds.map(
|
4254
|
+
(id) => strapi2.documents(uid2).unpublish({ ...opts, documentId: id }).then((result) => result?.entries)
|
4255
|
+
)
|
4256
|
+
);
|
4137
4257
|
});
|
4138
|
-
|
4139
|
-
|
4140
|
-
);
|
4141
|
-
return unpublishedEntitiesCount;
|
4258
|
+
const unpublishedEntitiesCount = unpublishedEntries.flat().filter(Boolean).length;
|
4259
|
+
return { count: unpublishedEntitiesCount };
|
4142
4260
|
},
|
4143
4261
|
async unpublish(id, uid2, opts = {}) {
|
4144
4262
|
const populate = await buildDeepPopulate(uid2);
|
@@ -4163,16 +4281,20 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4163
4281
|
}
|
4164
4282
|
return sumDraftCounts(document, uid2);
|
4165
4283
|
},
|
4166
|
-
async countManyEntriesDraftRelations(
|
4284
|
+
async countManyEntriesDraftRelations(documentIds, uid2, locale) {
|
4167
4285
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid2);
|
4168
4286
|
if (!hasRelations) {
|
4169
4287
|
return 0;
|
4170
4288
|
}
|
4289
|
+
let localeFilter = {};
|
4290
|
+
if (locale) {
|
4291
|
+
localeFilter = Array.isArray(locale) ? { locale: { $in: locale } } : { locale };
|
4292
|
+
}
|
4171
4293
|
const entities = await strapi2.db.query(uid2).findMany({
|
4172
4294
|
populate,
|
4173
4295
|
where: {
|
4174
|
-
|
4175
|
-
...
|
4296
|
+
documentId: { $in: documentIds },
|
4297
|
+
...localeFilter
|
4176
4298
|
}
|
4177
4299
|
});
|
4178
4300
|
const totalNumberDraftRelations = entities.reduce(
|