@strapi/content-manager 0.0.0-experimental.4ddd402c7194d1a969a797313bf007c93148d59a → 0.0.0-experimental.5007ea441db2bdbc04f35e1169b3798c068f5d46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs → ComponentConfigurationPage-CIjXcRAB.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs.map → ComponentConfigurationPage-CIjXcRAB.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BZIaEffq.js → ComponentConfigurationPage-gsCd80MU.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BZIaEffq.js.map → ComponentConfigurationPage-gsCd80MU.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs → EditConfigurationPage-BglmD_BF.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs.map → EditConfigurationPage-BglmD_BF.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js → EditConfigurationPage-DHDQKBzw.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js.map → EditConfigurationPage-DHDQKBzw.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-CU7724gt.js → EditViewPage-C4iTxUPU.js} +68 -47
- package/dist/_chunks/EditViewPage-C4iTxUPU.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CzuJgWWp.mjs → EditViewPage-CiwVPMaK.mjs} +69 -48
- package/dist/_chunks/EditViewPage-CiwVPMaK.mjs.map +1 -0
- package/dist/_chunks/{Field-QtUSh5mU.mjs → Field-DIjL1b5d.mjs} +580 -228
- package/dist/_chunks/Field-DIjL1b5d.mjs.map +1 -0
- package/dist/_chunks/{Field-Dh1yZyqy.js → Field-DhXEK8y1.js} +582 -230
- package/dist/_chunks/Field-DhXEK8y1.js.map +1 -0
- package/dist/_chunks/{Form-COLpvlnv.mjs → Form-CmNesrvR.mjs} +54 -36
- package/dist/_chunks/Form-CmNesrvR.mjs.map +1 -0
- package/dist/_chunks/{Form-BOR8NOe1.js → Form-CwmJ4sWe.js} +52 -34
- package/dist/_chunks/Form-CwmJ4sWe.js.map +1 -0
- package/dist/_chunks/{History-CW2akQ6h.js → History-BLCCNgCt.js} +158 -41
- package/dist/_chunks/History-BLCCNgCt.js.map +1 -0
- package/dist/_chunks/{History-Bu53Yfw-.mjs → History-D-99Wh30.mjs} +159 -42
- package/dist/_chunks/History-D-99Wh30.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-jzdhEk_u.js → ListConfigurationPage-DxWpeZrO.js} +58 -47
- package/dist/_chunks/ListConfigurationPage-DxWpeZrO.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-TqrmwjPN.mjs → ListConfigurationPage-JPWZz7Kg.mjs} +59 -49
- package/dist/_chunks/ListConfigurationPage-JPWZz7Kg.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-B3bMOrMv.js → ListViewPage-CIQekSFz.js} +117 -105
- package/dist/_chunks/ListViewPage-CIQekSFz.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BO_mOXIl.mjs → ListViewPage-DSK3f0ST.mjs} +115 -103
- package/dist/_chunks/ListViewPage-DSK3f0ST.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-D77xsNHj.js → NoContentTypePage-C5cxKvC2.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-D77xsNHj.js.map → NoContentTypePage-C5cxKvC2.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs → NoContentTypePage-D99LU1YP.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs.map → NoContentTypePage-D99LU1YP.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs → NoPermissionsPage-DBrBw-0y.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs.map → NoPermissionsPage-DBrBw-0y.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js → NoPermissionsPage-Oy4tmUrW.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js.map → NoPermissionsPage-Oy4tmUrW.js.map} +1 -1
- package/dist/_chunks/{Relations-CJ4qdkRo.mjs → Relations-BBmhcWFV.mjs} +70 -37
- package/dist/_chunks/Relations-BBmhcWFV.mjs.map +1 -0
- package/dist/_chunks/{Relations-B6fb2POW.js → Relations-eG-9p_qS.js} +69 -36
- package/dist/_chunks/Relations-eG-9p_qS.js.map +1 -0
- package/dist/_chunks/{en-DZXjRiWA.js → en-Bm0D0IWz.js} +19 -15
- package/dist/_chunks/{en-DZXjRiWA.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-9GwRW_ku.mjs → en-DKV44jRb.mjs} +19 -15
- package/dist/_chunks/{en-9GwRW_ku.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-DcUu-_72.js → index-BIWDoFLK.js} +1042 -865
- package/dist/_chunks/index-BIWDoFLK.js.map +1 -0
- package/dist/_chunks/{index-Dahjdw4h.mjs → index-BrUzbQ30.mjs} +1051 -875
- package/dist/_chunks/index-BrUzbQ30.mjs.map +1 -0
- package/dist/_chunks/{layout-omucV6TV.mjs → layout-_5-cXs34.mjs} +27 -14
- package/dist/_chunks/layout-_5-cXs34.mjs.map +1 -0
- package/dist/_chunks/{layout-jcY4dyUG.js → layout-lMc9i1-Z.js} +25 -12
- package/dist/_chunks/layout-lMc9i1-Z.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-DGzD7ORa.js → relations-BRHithi8.js} +3 -7
- package/dist/_chunks/relations-BRHithi8.js.map +1 -0
- package/dist/_chunks/{relations-CN0-aw6p.mjs → relations-B_VLk-DD.mjs} +3 -7
- package/dist/_chunks/relations-B_VLk-DD.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -17
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +263 -136
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +264 -137
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +2 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/_chunks/EditViewPage-CU7724gt.js.map +0 -1
- package/dist/_chunks/EditViewPage-CzuJgWWp.mjs.map +0 -1
- package/dist/_chunks/Field-Dh1yZyqy.js.map +0 -1
- package/dist/_chunks/Field-QtUSh5mU.mjs.map +0 -1
- package/dist/_chunks/Form-BOR8NOe1.js.map +0 -1
- package/dist/_chunks/Form-COLpvlnv.mjs.map +0 -1
- package/dist/_chunks/History-Bu53Yfw-.mjs.map +0 -1
- package/dist/_chunks/History-CW2akQ6h.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-TqrmwjPN.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-jzdhEk_u.js.map +0 -1
- package/dist/_chunks/ListViewPage-B3bMOrMv.js.map +0 -1
- package/dist/_chunks/ListViewPage-BO_mOXIl.mjs.map +0 -1
- package/dist/_chunks/Relations-B6fb2POW.js.map +0 -1
- package/dist/_chunks/Relations-CJ4qdkRo.mjs.map +0 -1
- package/dist/_chunks/index-Dahjdw4h.mjs.map +0 -1
- package/dist/_chunks/index-DcUu-_72.js.map +0 -1
- package/dist/_chunks/layout-jcY4dyUG.js.map +0 -1
- package/dist/_chunks/layout-omucV6TV.mjs.map +0 -1
- package/dist/_chunks/relations-CN0-aw6p.mjs.map +0 -1
- package/dist/_chunks/relations-DGzD7ORa.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
|
2
|
-
import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat,
|
2
|
+
import { pick, omit, difference, castArray, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
|
3
3
|
import "@strapi/types";
|
4
4
|
import * as yup from "yup";
|
5
5
|
import { scheduleJob } from "node-schedule";
|
@@ -173,7 +173,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
173
173
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
174
174
|
};
|
175
175
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
176
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
176
177
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
178
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
177
179
|
const getLocaleDictionary = async () => {
|
178
180
|
if (!localesService)
|
179
181
|
return {};
|
@@ -200,20 +202,25 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
200
202
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
201
203
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
202
204
|
};
|
203
|
-
const getDeepPopulate2 = (uid2) => {
|
205
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
204
206
|
const model = strapi2.getModel(uid2);
|
205
207
|
const attributes = Object.entries(model.attributes);
|
208
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
206
209
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
207
210
|
switch (attribute.type) {
|
208
211
|
case "relation": {
|
212
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
213
|
+
if (isMorphRelation) {
|
214
|
+
break;
|
215
|
+
}
|
209
216
|
const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
|
210
217
|
if (isVisible2) {
|
211
|
-
acc[attributeName] = {
|
218
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
212
219
|
}
|
213
220
|
break;
|
214
221
|
}
|
215
222
|
case "media": {
|
216
|
-
acc[attributeName] = {
|
223
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
217
224
|
break;
|
218
225
|
}
|
219
226
|
case "component": {
|
@@ -286,6 +293,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
286
293
|
getRelationRestoreValue,
|
287
294
|
getMediaRestoreValue,
|
288
295
|
getDefaultLocale,
|
296
|
+
isLocalizedContentType,
|
289
297
|
getLocaleDictionary,
|
290
298
|
getRetentionDays,
|
291
299
|
getVersionStatus,
|
@@ -308,7 +316,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
308
316
|
});
|
309
317
|
},
|
310
318
|
async findVersionsPage(params) {
|
311
|
-
const
|
319
|
+
const model = strapi2.getModel(params.query.contentType);
|
320
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
321
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
322
|
+
let locale = null;
|
323
|
+
if (isLocalizedContentType) {
|
324
|
+
locale = params.query.locale || defaultLocale;
|
325
|
+
}
|
312
326
|
const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
|
313
327
|
query.findPage({
|
314
328
|
...params.query,
|
@@ -353,7 +367,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
353
367
|
if (userToPopulate == null) {
|
354
368
|
return null;
|
355
369
|
}
|
356
|
-
return strapi2.query("admin::user").findOne({
|
370
|
+
return strapi2.query("admin::user").findOne({
|
371
|
+
where: {
|
372
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
373
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
374
|
+
}
|
375
|
+
});
|
357
376
|
})
|
358
377
|
);
|
359
378
|
return {
|
@@ -464,13 +483,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
464
483
|
}
|
465
484
|
};
|
466
485
|
};
|
486
|
+
const shouldCreateHistoryVersion = (context) => {
|
487
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
488
|
+
return false;
|
489
|
+
}
|
490
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
491
|
+
return false;
|
492
|
+
}
|
493
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
494
|
+
return false;
|
495
|
+
}
|
496
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
497
|
+
return false;
|
498
|
+
}
|
499
|
+
return true;
|
500
|
+
};
|
501
|
+
const getSchemas = (uid2) => {
|
502
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
503
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
504
|
+
(currentComponentSchemas, key) => {
|
505
|
+
const fieldSchema = attributesSchema[key];
|
506
|
+
if (fieldSchema.type === "component") {
|
507
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
508
|
+
return {
|
509
|
+
...currentComponentSchemas,
|
510
|
+
[fieldSchema.component]: componentSchema
|
511
|
+
};
|
512
|
+
}
|
513
|
+
return currentComponentSchemas;
|
514
|
+
},
|
515
|
+
{}
|
516
|
+
);
|
517
|
+
return {
|
518
|
+
schema: omit(FIELDS_TO_IGNORE, attributesSchema),
|
519
|
+
componentsSchemas
|
520
|
+
};
|
521
|
+
};
|
467
522
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
468
523
|
const state = {
|
469
524
|
deleteExpiredJob: null,
|
470
525
|
isInitialized: false
|
471
526
|
};
|
472
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
473
|
-
const historyService = getService(strapi2, "history");
|
474
527
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
475
528
|
return {
|
476
529
|
async bootstrap() {
|
@@ -478,60 +531,45 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
478
531
|
return;
|
479
532
|
}
|
480
533
|
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
534
|
const result = await next();
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
535
|
+
if (!shouldCreateHistoryVersion(context)) {
|
536
|
+
return result;
|
537
|
+
}
|
538
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
496
539
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
497
|
-
const
|
498
|
-
if (
|
499
|
-
|
500
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
501
|
-
);
|
502
|
-
return next();
|
540
|
+
const locales = castArray(context.params?.locale || defaultLocale);
|
541
|
+
if (!locales.length) {
|
542
|
+
return result;
|
503
543
|
}
|
504
|
-
const
|
505
|
-
|
506
|
-
|
507
|
-
|
544
|
+
const uid2 = context.contentType.uid;
|
545
|
+
const schemas = getSchemas(uid2);
|
546
|
+
const model = strapi2.getModel(uid2);
|
547
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
548
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
549
|
+
where: {
|
550
|
+
documentId,
|
551
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
552
|
+
...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
553
|
+
},
|
554
|
+
populate: serviceUtils.getDeepPopulate(
|
555
|
+
uid2,
|
556
|
+
true
|
557
|
+
/* use database syntax */
|
558
|
+
)
|
508
559
|
});
|
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
560
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
525
|
-
onCommit(() => {
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
561
|
+
onCommit(async () => {
|
562
|
+
for (const entry of localeEntries) {
|
563
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
564
|
+
await getService(strapi2, "history").createVersion({
|
565
|
+
contentType: uid2,
|
566
|
+
data: omit(FIELDS_TO_IGNORE, entry),
|
567
|
+
relatedDocumentId: documentId,
|
568
|
+
locale: entry.locale,
|
569
|
+
status,
|
570
|
+
...schemas
|
571
|
+
});
|
572
|
+
}
|
535
573
|
});
|
536
574
|
});
|
537
575
|
return result;
|
@@ -539,7 +577,7 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
539
577
|
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
540
578
|
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
541
579
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
542
|
-
query.deleteMany({
|
580
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
543
581
|
where: {
|
544
582
|
created_at: {
|
545
583
|
$lt: expirationDate.toISOString()
|
@@ -631,7 +669,7 @@ const historyVersion = {
|
|
631
669
|
}
|
632
670
|
}
|
633
671
|
};
|
634
|
-
const getFeature = () => {
|
672
|
+
const getFeature$1 = () => {
|
635
673
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
636
674
|
return {
|
637
675
|
register({ strapi: strapi2 }) {
|
@@ -654,7 +692,7 @@ const getFeature = () => {
|
|
654
692
|
}
|
655
693
|
};
|
656
694
|
};
|
657
|
-
const history = getFeature();
|
695
|
+
const history = getFeature$1();
|
658
696
|
const register = async ({ strapi: strapi2 }) => {
|
659
697
|
await history.register?.({ strapi: strapi2 });
|
660
698
|
};
|
@@ -662,6 +700,18 @@ const ALLOWED_WEBHOOK_EVENTS = {
|
|
662
700
|
ENTRY_PUBLISH: "entry.publish",
|
663
701
|
ENTRY_UNPUBLISH: "entry.unpublish"
|
664
702
|
};
|
703
|
+
const FEATURE_ID = "preview";
|
704
|
+
const getFeature = () => {
|
705
|
+
if (!strapi.features.future.isEnabled(FEATURE_ID)) {
|
706
|
+
return {};
|
707
|
+
}
|
708
|
+
return {
|
709
|
+
bootstrap() {
|
710
|
+
console.log("Bootstrapping preview server");
|
711
|
+
}
|
712
|
+
};
|
713
|
+
};
|
714
|
+
const preview = getFeature();
|
665
715
|
const bootstrap = async () => {
|
666
716
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
667
717
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
@@ -671,6 +721,7 @@ const bootstrap = async () => {
|
|
671
721
|
await getService$1("content-types").syncConfigurations();
|
672
722
|
await getService$1("permission").registerPermissions();
|
673
723
|
await history.bootstrap?.({ strapi });
|
724
|
+
await preview.bootstrap?.({ strapi });
|
674
725
|
};
|
675
726
|
const destroy = async ({ strapi: strapi2 }) => {
|
676
727
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1171,6 +1222,11 @@ const { createPolicy } = policy;
|
|
1171
1222
|
const hasPermissions = createPolicy({
|
1172
1223
|
name: "plugin::content-manager.hasPermissions",
|
1173
1224
|
validator: validateHasPermissionsInput,
|
1225
|
+
/**
|
1226
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1227
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1228
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1229
|
+
*/
|
1174
1230
|
handler(ctx, config = {}) {
|
1175
1231
|
const { actions = [], hasAtLeastOne = false } = config;
|
1176
1232
|
const { userAbility } = ctx.state;
|
@@ -1564,9 +1620,11 @@ const multipleLocaleSchema = yup$1.lazy(
|
|
1564
1620
|
(value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1565
1621
|
);
|
1566
1622
|
const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
|
1567
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1623
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1568
1624
|
const { allowMultipleLocales } = opts;
|
1569
|
-
const { locale, status, ...rest } = request || {};
|
1625
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1626
|
+
const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1627
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1570
1628
|
const schema = yup$1.object().shape({
|
1571
1629
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1572
1630
|
status: statusSchema
|
@@ -1614,7 +1672,7 @@ const createDocument = async (ctx, opts) => {
|
|
1614
1672
|
const setCreator = setCreatorFields({ user });
|
1615
1673
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1616
1674
|
const sanitizedBody = await sanitizeFn(body);
|
1617
|
-
const { locale, status
|
1675
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1618
1676
|
return documentManager2.create(model, {
|
1619
1677
|
data: sanitizedBody,
|
1620
1678
|
locale,
|
@@ -1633,7 +1691,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1633
1691
|
}
|
1634
1692
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1635
1693
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1636
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1694
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1637
1695
|
const [documentVersion, documentExists] = await Promise.all([
|
1638
1696
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1639
1697
|
documentManager2.exists(model, id)
|
@@ -1649,7 +1707,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1649
1707
|
throw new errors.ForbiddenError();
|
1650
1708
|
}
|
1651
1709
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1652
|
-
const setCreator = setCreatorFields({ user, isEdition: true });
|
1710
|
+
const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
|
1653
1711
|
const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
|
1654
1712
|
const sanitizedBody = await sanitizeFn(body);
|
1655
1713
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1671,7 +1729,7 @@ const collectionTypes = {
|
|
1671
1729
|
}
|
1672
1730
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1673
1731
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1674
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1732
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1675
1733
|
const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
|
1676
1734
|
{ ...permissionQuery, populate, locale, status },
|
1677
1735
|
model
|
@@ -1706,7 +1764,7 @@ const collectionTypes = {
|
|
1706
1764
|
}
|
1707
1765
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1708
1766
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1709
|
-
const { locale, status
|
1767
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1710
1768
|
const version = await documentManager2.findOne(id, model, {
|
1711
1769
|
populate,
|
1712
1770
|
locale,
|
@@ -1721,7 +1779,7 @@ const collectionTypes = {
|
|
1721
1779
|
permissionChecker2,
|
1722
1780
|
model,
|
1723
1781
|
// @ts-expect-error TODO: fix
|
1724
|
-
{ id, locale, publishedAt: null },
|
1782
|
+
{ documentId: id, locale, publishedAt: null },
|
1725
1783
|
{ availableLocales: true, availableStatus: false }
|
1726
1784
|
);
|
1727
1785
|
ctx.body = { data: {}, meta };
|
@@ -1773,7 +1831,7 @@ const collectionTypes = {
|
|
1773
1831
|
}
|
1774
1832
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1775
1833
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1776
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1834
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1777
1835
|
const document = await documentManager2.findOne(id, model, {
|
1778
1836
|
populate,
|
1779
1837
|
locale,
|
@@ -1818,7 +1876,7 @@ const collectionTypes = {
|
|
1818
1876
|
}
|
1819
1877
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1820
1878
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1821
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1879
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1822
1880
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1823
1881
|
if (documentLocales.length === 0) {
|
1824
1882
|
return ctx.notFound();
|
@@ -1847,11 +1905,34 @@ const collectionTypes = {
|
|
1847
1905
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1848
1906
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1849
1907
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1850
|
-
|
1908
|
+
let document;
|
1909
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1910
|
+
const isCreate = isNil$1(id);
|
1911
|
+
if (isCreate) {
|
1912
|
+
if (permissionChecker2.cannot.create()) {
|
1913
|
+
throw new errors.ForbiddenError();
|
1914
|
+
}
|
1915
|
+
document = await createDocument(ctx, { populate });
|
1916
|
+
}
|
1917
|
+
const isUpdate = !isCreate;
|
1918
|
+
if (isUpdate) {
|
1919
|
+
const documentExists = documentManager2.exists(model, id);
|
1920
|
+
if (!documentExists) {
|
1921
|
+
throw new errors.NotFoundError("Document not found");
|
1922
|
+
}
|
1923
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
1924
|
+
if (!document) {
|
1925
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
1926
|
+
throw new errors.ForbiddenError();
|
1927
|
+
}
|
1928
|
+
document = await updateDocument(ctx);
|
1929
|
+
} else if (permissionChecker2.can.update(document)) {
|
1930
|
+
await updateDocument(ctx);
|
1931
|
+
}
|
1932
|
+
}
|
1851
1933
|
if (permissionChecker2.cannot.publish(document)) {
|
1852
1934
|
throw new errors.ForbiddenError();
|
1853
1935
|
}
|
1854
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1855
1936
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1856
1937
|
locale
|
1857
1938
|
// TODO: Allow setting creator fields on publish
|
@@ -1878,7 +1959,9 @@ const collectionTypes = {
|
|
1878
1959
|
}
|
1879
1960
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1880
1961
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1881
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
1962
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1963
|
+
allowMultipleLocales: true
|
1964
|
+
});
|
1882
1965
|
const entityPromises = documentIds.map(
|
1883
1966
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1884
1967
|
);
|
@@ -1905,7 +1988,9 @@ const collectionTypes = {
|
|
1905
1988
|
if (permissionChecker2.cannot.unpublish()) {
|
1906
1989
|
return ctx.forbidden();
|
1907
1990
|
}
|
1908
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
1991
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1992
|
+
allowMultipleLocales: true
|
1993
|
+
});
|
1909
1994
|
const entityPromises = documentIds.map(
|
1910
1995
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1911
1996
|
);
|
@@ -1938,7 +2023,7 @@ const collectionTypes = {
|
|
1938
2023
|
}
|
1939
2024
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1940
2025
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1941
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2026
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1942
2027
|
const document = await documentManager2.findOne(id, model, {
|
1943
2028
|
populate,
|
1944
2029
|
locale,
|
@@ -1975,7 +2060,7 @@ const collectionTypes = {
|
|
1975
2060
|
}
|
1976
2061
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
1977
2062
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1978
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2063
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1979
2064
|
const document = await documentManager2.findOne(id, model, {
|
1980
2065
|
populate,
|
1981
2066
|
locale,
|
@@ -2006,7 +2091,7 @@ const collectionTypes = {
|
|
2006
2091
|
}
|
2007
2092
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2008
2093
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2009
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2094
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2010
2095
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2011
2096
|
populate,
|
2012
2097
|
locale
|
@@ -2033,7 +2118,7 @@ const collectionTypes = {
|
|
2033
2118
|
}
|
2034
2119
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2035
2120
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2036
|
-
const { locale, status
|
2121
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2037
2122
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2038
2123
|
if (!entity) {
|
2039
2124
|
return ctx.notFound();
|
@@ -2056,7 +2141,7 @@ const collectionTypes = {
|
|
2056
2141
|
if (permissionChecker2.cannot.read()) {
|
2057
2142
|
return ctx.forbidden();
|
2058
2143
|
}
|
2059
|
-
const
|
2144
|
+
const documents = await documentManager2.findMany(
|
2060
2145
|
{
|
2061
2146
|
filters: {
|
2062
2147
|
documentId: ids
|
@@ -2065,7 +2150,7 @@ const collectionTypes = {
|
|
2065
2150
|
},
|
2066
2151
|
model
|
2067
2152
|
);
|
2068
|
-
if (!
|
2153
|
+
if (!documents) {
|
2069
2154
|
return ctx.notFound();
|
2070
2155
|
}
|
2071
2156
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2256,32 +2341,37 @@ const sanitizeMainField = (model, mainField, userAbility) => {
|
|
2256
2341
|
userAbility,
|
2257
2342
|
model: model.uid
|
2258
2343
|
});
|
2259
|
-
|
2344
|
+
const isMainFieldListable = isListable(model, mainField);
|
2345
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2346
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2260
2347
|
return "id";
|
2261
2348
|
}
|
2262
|
-
if (
|
2263
|
-
|
2264
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2265
|
-
userAbility,
|
2266
|
-
model: "plugin::users-permissions.user"
|
2267
|
-
});
|
2268
|
-
if (userPermissionChecker.can.read()) {
|
2269
|
-
return "name";
|
2270
|
-
}
|
2271
|
-
}
|
2272
|
-
return "id";
|
2349
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2350
|
+
return "name";
|
2273
2351
|
}
|
2274
2352
|
return mainField;
|
2275
2353
|
};
|
2276
|
-
const addStatusToRelations = async (
|
2277
|
-
if (!contentTypes$1.hasDraftAndPublish(strapi.
|
2354
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2355
|
+
if (!contentTypes$1.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2278
2356
|
return relations2;
|
2279
2357
|
}
|
2280
2358
|
const documentMetadata2 = getService$1("document-metadata");
|
2281
|
-
|
2359
|
+
if (!relations2.length) {
|
2360
|
+
return relations2;
|
2361
|
+
}
|
2362
|
+
const firstRelation = relations2[0];
|
2363
|
+
const filters = {
|
2364
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2365
|
+
// NOTE: find the "opposite" status
|
2366
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2367
|
+
};
|
2368
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2369
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2370
|
+
filters
|
2371
|
+
});
|
2282
2372
|
return relations2.map((relation) => {
|
2283
|
-
const availableStatuses =
|
2284
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2373
|
+
const availableStatuses = availableStatus.filter(
|
2374
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2285
2375
|
);
|
2286
2376
|
return {
|
2287
2377
|
...relation,
|
@@ -2302,11 +2392,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2302
2392
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2303
2393
|
const isSourceLocalized = isLocalized(sourceModel);
|
2304
2394
|
const isTargetLocalized = isLocalized(targetModel);
|
2305
|
-
let validatedLocale = locale;
|
2306
|
-
if (!targetModel || !isTargetLocalized)
|
2307
|
-
validatedLocale = void 0;
|
2308
2395
|
return {
|
2309
|
-
locale
|
2396
|
+
locale,
|
2310
2397
|
isSourceLocalized,
|
2311
2398
|
isTargetLocalized
|
2312
2399
|
};
|
@@ -2409,7 +2496,7 @@ const relations = {
|
|
2409
2496
|
attribute,
|
2410
2497
|
fieldsToSelect,
|
2411
2498
|
mainField,
|
2412
|
-
source: { schema: sourceSchema },
|
2499
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2413
2500
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2414
2501
|
sourceSchema,
|
2415
2502
|
targetSchema,
|
@@ -2431,7 +2518,8 @@ const relations = {
|
|
2431
2518
|
fieldsToSelect,
|
2432
2519
|
mainField,
|
2433
2520
|
source: {
|
2434
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2521
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2522
|
+
isLocalized: isSourceLocalized
|
2435
2523
|
},
|
2436
2524
|
target: {
|
2437
2525
|
schema: { uid: targetUid },
|
@@ -2469,12 +2557,16 @@ const relations = {
|
|
2469
2557
|
} else {
|
2470
2558
|
where.id = id;
|
2471
2559
|
}
|
2472
|
-
|
2473
|
-
|
2560
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2561
|
+
if (!isEmpty(publishedAt)) {
|
2562
|
+
where[`${alias}.published_at`] = publishedAt;
|
2474
2563
|
}
|
2475
|
-
if (
|
2564
|
+
if (isTargetLocalized && locale) {
|
2476
2565
|
where[`${alias}.locale`] = locale;
|
2477
2566
|
}
|
2567
|
+
if (isSourceLocalized && locale) {
|
2568
|
+
where.locale = locale;
|
2569
|
+
}
|
2478
2570
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2479
2571
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2480
2572
|
}
|
@@ -2492,7 +2584,8 @@ const relations = {
|
|
2492
2584
|
id: { $notIn: uniq(idsToOmit) }
|
2493
2585
|
});
|
2494
2586
|
}
|
2495
|
-
const
|
2587
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2588
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2496
2589
|
ctx.body = {
|
2497
2590
|
...res,
|
2498
2591
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2507,29 +2600,39 @@ const relations = {
|
|
2507
2600
|
attribute,
|
2508
2601
|
targetField,
|
2509
2602
|
fieldsToSelect,
|
2510
|
-
|
2511
|
-
|
2512
|
-
}
|
2513
|
-
target: {
|
2514
|
-
schema: { uid: targetUid }
|
2515
|
-
}
|
2603
|
+
status,
|
2604
|
+
source: { schema: sourceSchema },
|
2605
|
+
target: { schema: targetSchema }
|
2516
2606
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2607
|
+
const { uid: sourceUid } = sourceSchema;
|
2608
|
+
const { uid: targetUid } = targetSchema;
|
2517
2609
|
const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2518
2610
|
const dbQuery = strapi.db.query(sourceUid);
|
2519
2611
|
const loadRelations = relations$1.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2612
|
+
const filters = {};
|
2613
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2614
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2615
|
+
if (status === "published") {
|
2616
|
+
filters.publishedAt = { $notNull: true };
|
2617
|
+
} else {
|
2618
|
+
filters.publishedAt = { $null: true };
|
2619
|
+
}
|
2620
|
+
}
|
2621
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2622
|
+
filters.publishedAt = { $null: true };
|
2623
|
+
}
|
2520
2624
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2521
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2625
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2522
2626
|
ordering: "desc",
|
2523
2627
|
page: ctx.request.query.page,
|
2524
|
-
pageSize: ctx.request.query.pageSize
|
2628
|
+
pageSize: ctx.request.query.pageSize,
|
2629
|
+
filters
|
2525
2630
|
});
|
2526
2631
|
const loadedIds = res.results.map((item) => item.id);
|
2527
2632
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2528
2633
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2529
2634
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2530
|
-
ordering: "desc"
|
2531
|
-
page: ctx.request.query.page,
|
2532
|
-
pageSize: ctx.request.query.pageSize
|
2635
|
+
ordering: "desc"
|
2533
2636
|
});
|
2534
2637
|
const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
|
2535
2638
|
ctx.body = {
|
@@ -2561,7 +2664,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2561
2664
|
throw new errors.ForbiddenError();
|
2562
2665
|
}
|
2563
2666
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2564
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2667
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2565
2668
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2566
2669
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2567
2670
|
// Find the first document to check if it exists
|
@@ -2602,7 +2705,7 @@ const singleTypes = {
|
|
2602
2705
|
return ctx.forbidden();
|
2603
2706
|
}
|
2604
2707
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2605
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2708
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2606
2709
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2607
2710
|
if (!version) {
|
2608
2711
|
if (permissionChecker2.cannot.create()) {
|
@@ -2616,7 +2719,7 @@ const singleTypes = {
|
|
2616
2719
|
permissionChecker2,
|
2617
2720
|
model,
|
2618
2721
|
// @ts-expect-error - fix types
|
2619
|
-
{
|
2722
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2620
2723
|
{ availableLocales: true, availableStatus: false }
|
2621
2724
|
);
|
2622
2725
|
ctx.body = { data: {}, meta };
|
@@ -2647,7 +2750,7 @@ const singleTypes = {
|
|
2647
2750
|
}
|
2648
2751
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2649
2752
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2650
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2753
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2651
2754
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2652
2755
|
populate,
|
2653
2756
|
locale
|
@@ -2684,7 +2787,7 @@ const singleTypes = {
|
|
2684
2787
|
if (permissionChecker2.cannot.publish(document)) {
|
2685
2788
|
throw new errors.ForbiddenError();
|
2686
2789
|
}
|
2687
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2790
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2688
2791
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2689
2792
|
return publishResult.at(0);
|
2690
2793
|
});
|
@@ -2707,7 +2810,7 @@ const singleTypes = {
|
|
2707
2810
|
return ctx.forbidden();
|
2708
2811
|
}
|
2709
2812
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2710
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2813
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2711
2814
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2712
2815
|
if (!document) {
|
2713
2816
|
return ctx.notFound();
|
@@ -2739,7 +2842,7 @@ const singleTypes = {
|
|
2739
2842
|
return ctx.forbidden();
|
2740
2843
|
}
|
2741
2844
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2742
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2845
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2743
2846
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2744
2847
|
if (!document) {
|
2745
2848
|
return ctx.notFound();
|
@@ -2759,7 +2862,7 @@ const singleTypes = {
|
|
2759
2862
|
const { query } = ctx.request;
|
2760
2863
|
const documentManager2 = getService$1("document-manager");
|
2761
2864
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2762
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2865
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2763
2866
|
if (permissionChecker2.cannot.read()) {
|
2764
2867
|
return ctx.forbidden();
|
2765
2868
|
}
|
@@ -2780,7 +2883,7 @@ const uid$1 = {
|
|
2780
2883
|
async generateUID(ctx) {
|
2781
2884
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2782
2885
|
const { query = {} } = ctx.request;
|
2783
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2886
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2784
2887
|
await validateUIDField(contentTypeUID, field);
|
2785
2888
|
const uidService = getService$1("uid");
|
2786
2889
|
ctx.body = {
|
@@ -2792,7 +2895,7 @@ const uid$1 = {
|
|
2792
2895
|
ctx.request.body
|
2793
2896
|
);
|
2794
2897
|
const { query = {} } = ctx.request;
|
2795
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2898
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2796
2899
|
await validateUIDField(contentTypeUID, field);
|
2797
2900
|
const uidService = getService$1("uid");
|
2798
2901
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3435,12 +3538,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3435
3538
|
ability: userAbility,
|
3436
3539
|
model
|
3437
3540
|
});
|
3438
|
-
const
|
3541
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3542
|
+
const toSubject = (entity) => {
|
3543
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3544
|
+
};
|
3439
3545
|
const can = (action, entity, field) => {
|
3440
|
-
|
3546
|
+
const subject = toSubject(entity);
|
3547
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3548
|
+
return (
|
3549
|
+
// Test the original action to see if it passes
|
3550
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3551
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3552
|
+
);
|
3441
3553
|
};
|
3442
3554
|
const cannot = (action, entity, field) => {
|
3443
|
-
|
3555
|
+
const subject = toSubject(entity);
|
3556
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3557
|
+
return (
|
3558
|
+
// Test both the original action
|
3559
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3560
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3561
|
+
);
|
3444
3562
|
};
|
3445
3563
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3446
3564
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3717,6 +3835,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3717
3835
|
const attribute = model.attributes[attributeName];
|
3718
3836
|
switch (attribute.type) {
|
3719
3837
|
case "relation": {
|
3838
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3839
|
+
if (isMorphRelation) {
|
3840
|
+
break;
|
3841
|
+
}
|
3720
3842
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3721
3843
|
populateAcc[attributeName] = {
|
3722
3844
|
count: true,
|
@@ -3968,7 +4090,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3968
4090
|
*/
|
3969
4091
|
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3970
4092
|
const versionsByLocale = groupBy("locale", allVersions);
|
3971
|
-
|
4093
|
+
if (version.locale) {
|
4094
|
+
delete versionsByLocale[version.locale];
|
4095
|
+
}
|
3972
4096
|
const model = strapi2.getModel(uid2);
|
3973
4097
|
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
3974
4098
|
const traversalFunction = async (localeVersion) => traverseEntity(
|
@@ -4094,7 +4218,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4094
4218
|
*/
|
4095
4219
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4096
4220
|
if (!document) {
|
4097
|
-
return
|
4221
|
+
return {
|
4222
|
+
data: document,
|
4223
|
+
meta: {
|
4224
|
+
availableLocales: [],
|
4225
|
+
availableStatus: []
|
4226
|
+
}
|
4227
|
+
};
|
4098
4228
|
}
|
4099
4229
|
const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
|
4100
4230
|
if (!hasDraftAndPublish) {
|
@@ -4202,10 +4332,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4202
4332
|
async clone(id, body, uid2) {
|
4203
4333
|
const populate = await buildDeepPopulate(uid2);
|
4204
4334
|
const params = {
|
4205
|
-
data:
|
4206
|
-
...omitIdField(body),
|
4207
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4208
|
-
},
|
4335
|
+
data: omitIdField(body),
|
4209
4336
|
populate
|
4210
4337
|
};
|
4211
4338
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|