@strapi/content-manager 0.0.0-experimental.f75e3c6d67cc47c64ab37479efdbb7b43be50b78 → 0.0.0-experimental.f9cac24ba3b2f6acb12d0fb5669106e5a134174e
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-by0e_kNd.js → ComponentConfigurationPage-3feZ0gyp.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-by0e_kNd.js.map → ComponentConfigurationPage-3feZ0gyp.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs → ComponentConfigurationPage-DkUdgHD9.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs.map → ComponentConfigurationPage-DkUdgHD9.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js → EditConfigurationPage-B0KA-x9U.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js.map → EditConfigurationPage-B0KA-x9U.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs → EditConfigurationPage-Ox5wFgpq.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs.map → EditConfigurationPage-Ox5wFgpq.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-ChgloMyO.js → EditViewPage-OMv9CogC.js} +68 -47
- package/dist/_chunks/EditViewPage-OMv9CogC.js.map +1 -0
- package/dist/_chunks/{EditViewPage-dFPBya9U.mjs → EditViewPage-foKE8Al3.mjs} +69 -48
- package/dist/_chunks/EditViewPage-foKE8Al3.mjs.map +1 -0
- package/dist/_chunks/{Field-C1nUKcdS.mjs → Field-CLqZcnnc.mjs} +579 -227
- package/dist/_chunks/Field-CLqZcnnc.mjs.map +1 -0
- package/dist/_chunks/{Field-dLk-vgLL.js → Field-u09MCk3G.js} +581 -229
- package/dist/_chunks/Field-u09MCk3G.js.map +1 -0
- package/dist/_chunks/{Form-CbXtmHC_.js → Form-B9c_Ti0q.js} +52 -34
- package/dist/_chunks/Form-B9c_Ti0q.js.map +1 -0
- package/dist/_chunks/{Form-DOlpi7Js.mjs → Form-CU4hRyJf.mjs} +54 -36
- package/dist/_chunks/Form-CU4hRyJf.mjs.map +1 -0
- package/dist/_chunks/{History-BFNUAiGc.mjs → History-BFyFzpSS.mjs} +160 -42
- package/dist/_chunks/History-BFyFzpSS.mjs.map +1 -0
- package/dist/_chunks/{History-BjDfohBr.js → History-OlickLyX.js} +159 -41
- package/dist/_chunks/History-OlickLyX.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DDi0KqFm.mjs → ListConfigurationPage-Bu5Z_39o.mjs} +58 -48
- package/dist/_chunks/ListConfigurationPage-Bu5Z_39o.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-IQBgWTaa.js → ListConfigurationPage-D0AAi_cW.js} +57 -46
- package/dist/_chunks/ListConfigurationPage-D0AAi_cW.js.map +1 -0
- package/dist/_chunks/{ListViewPage-CZYGqlvF.js → ListViewPage--lV5p8Qi.js} +117 -104
- package/dist/_chunks/ListViewPage--lV5p8Qi.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BPjljUsH.mjs → ListViewPage-BAHxSPux.mjs} +116 -103
- package/dist/_chunks/ListViewPage-BAHxSPux.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs → NoContentTypePage-C6SMXW77.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs.map → NoContentTypePage-C6SMXW77.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js → NoContentTypePage-Dxl9oZqL.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js.map → NoContentTypePage-Dxl9oZqL.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js → NoPermissionsPage-BY1-rMng.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js.map → NoPermissionsPage-BY1-rMng.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs → NoPermissionsPage-o9BXzQeI.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs.map → NoPermissionsPage-o9BXzQeI.mjs.map} +1 -1
- package/dist/_chunks/{Relations-DTowyge2.mjs → Relations-BAK95JHc.mjs} +34 -25
- package/dist/_chunks/Relations-BAK95JHc.mjs.map +1 -0
- package/dist/_chunks/{Relations-DU6B7irU.js → Relations-CHfwGkBG.js} +34 -25
- package/dist/_chunks/Relations-CHfwGkBG.js.map +1 -0
- package/dist/_chunks/{en-DTULi5-d.js → en-Bm0D0IWz.js} +21 -15
- package/dist/_chunks/{en-DTULi5-d.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-GCOTL6jR.mjs → en-DKV44jRb.mjs} +21 -15
- package/dist/_chunks/{en-GCOTL6jR.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-BaGHmIir.mjs → index-CxlpxzA5.mjs} +1401 -779
- package/dist/_chunks/index-CxlpxzA5.mjs.map +1 -0
- package/dist/_chunks/{index-CCJeB7Rw.js → index-_Mlmsefd.js} +1368 -746
- package/dist/_chunks/index-_Mlmsefd.js.map +1 -0
- package/dist/_chunks/{layout-BinjszSQ.mjs → layout-Cr0H40au.mjs} +41 -23
- package/dist/_chunks/layout-Cr0H40au.mjs.map +1 -0
- package/dist/_chunks/{layout-ni_L9kT1.js → layout-vcHVgSr1.js} +39 -21
- package/dist/_chunks/layout-vcHVgSr1.js.map +1 -0
- package/dist/_chunks/{relations-c91ji5eR.mjs → relations-Dq60voyX.mjs} +2 -2
- package/dist/_chunks/{relations-c91ji5eR.mjs.map → relations-Dq60voyX.mjs.map} +1 -1
- package/dist/_chunks/{relations-CeJAJc5I.js → relations-hXUB80SH.js} +2 -2
- package/dist/_chunks/{relations-CeJAJc5I.js.map → relations-hXUB80SH.js.map} +1 -1
- 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 +7 -6
- 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/hooks/useDocumentActions.d.ts +1 -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/pages/ListView/components/BulkActions/PublishAction.d.ts +14 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/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 +233 -128
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +234 -129
- 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/single-types.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.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/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.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.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 +13 -13
- package/dist/_chunks/EditViewPage-ChgloMyO.js.map +0 -1
- package/dist/_chunks/EditViewPage-dFPBya9U.mjs.map +0 -1
- package/dist/_chunks/Field-C1nUKcdS.mjs.map +0 -1
- package/dist/_chunks/Field-dLk-vgLL.js.map +0 -1
- package/dist/_chunks/Form-CbXtmHC_.js.map +0 -1
- package/dist/_chunks/Form-DOlpi7Js.mjs.map +0 -1
- package/dist/_chunks/History-BFNUAiGc.mjs.map +0 -1
- package/dist/_chunks/History-BjDfohBr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DDi0KqFm.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-IQBgWTaa.js.map +0 -1
- package/dist/_chunks/ListViewPage-BPjljUsH.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-CZYGqlvF.js.map +0 -1
- package/dist/_chunks/Relations-DTowyge2.mjs.map +0 -1
- package/dist/_chunks/Relations-DU6B7irU.js.map +0 -1
- package/dist/_chunks/index-BaGHmIir.mjs.map +0 -1
- package/dist/_chunks/index-CCJeB7Rw.js.map +0 -1
- package/dist/_chunks/layout-BinjszSQ.mjs.map +0 -1
- package/dist/_chunks/layout-ni_L9kT1.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.js
CHANGED
@@ -199,7 +199,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
199
199
|
return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
|
200
200
|
};
|
201
201
|
const localesService = strapi2.plugin("i18n")?.service("locales");
|
202
|
+
const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
|
202
203
|
const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
|
204
|
+
const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
|
203
205
|
const getLocaleDictionary = async () => {
|
204
206
|
if (!localesService)
|
205
207
|
return {};
|
@@ -226,20 +228,25 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
226
228
|
const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
|
227
229
|
return documentMetadataService.getStatus(document, meta.availableStatus);
|
228
230
|
};
|
229
|
-
const getDeepPopulate2 = (uid2) => {
|
231
|
+
const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
|
230
232
|
const model = strapi2.getModel(uid2);
|
231
233
|
const attributes = Object.entries(model.attributes);
|
234
|
+
const fieldSelector = useDatabaseSyntax ? "select" : "fields";
|
232
235
|
return attributes.reduce((acc, [attributeName, attribute]) => {
|
233
236
|
switch (attribute.type) {
|
234
237
|
case "relation": {
|
238
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
239
|
+
if (isMorphRelation) {
|
240
|
+
break;
|
241
|
+
}
|
235
242
|
const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
|
236
243
|
if (isVisible2) {
|
237
|
-
acc[attributeName] = {
|
244
|
+
acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
|
238
245
|
}
|
239
246
|
break;
|
240
247
|
}
|
241
248
|
case "media": {
|
242
|
-
acc[attributeName] = {
|
249
|
+
acc[attributeName] = { [fieldSelector]: ["id"] };
|
243
250
|
break;
|
244
251
|
}
|
245
252
|
case "component": {
|
@@ -312,6 +319,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
|
|
312
319
|
getRelationRestoreValue,
|
313
320
|
getMediaRestoreValue,
|
314
321
|
getDefaultLocale,
|
322
|
+
isLocalizedContentType,
|
315
323
|
getLocaleDictionary,
|
316
324
|
getRetentionDays,
|
317
325
|
getVersionStatus,
|
@@ -334,7 +342,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
334
342
|
});
|
335
343
|
},
|
336
344
|
async findVersionsPage(params) {
|
337
|
-
const
|
345
|
+
const model = strapi2.getModel(params.query.contentType);
|
346
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
347
|
+
const defaultLocale = await serviceUtils.getDefaultLocale();
|
348
|
+
let locale = null;
|
349
|
+
if (isLocalizedContentType) {
|
350
|
+
locale = params.query.locale || defaultLocale;
|
351
|
+
}
|
338
352
|
const [{ results, pagination }, localeDictionary] = await Promise.all([
|
339
353
|
query.findPage({
|
340
354
|
...params.query,
|
@@ -379,7 +393,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
379
393
|
if (userToPopulate == null) {
|
380
394
|
return null;
|
381
395
|
}
|
382
|
-
return strapi2.query("admin::user").findOne({
|
396
|
+
return strapi2.query("admin::user").findOne({
|
397
|
+
where: {
|
398
|
+
...userToPopulate.id ? { id: userToPopulate.id } : {},
|
399
|
+
...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
|
400
|
+
}
|
401
|
+
});
|
383
402
|
})
|
384
403
|
);
|
385
404
|
return {
|
@@ -490,13 +509,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
|
|
490
509
|
}
|
491
510
|
};
|
492
511
|
};
|
512
|
+
const shouldCreateHistoryVersion = (context) => {
|
513
|
+
if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
514
|
+
return false;
|
515
|
+
}
|
516
|
+
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
517
|
+
return false;
|
518
|
+
}
|
519
|
+
if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
520
|
+
return false;
|
521
|
+
}
|
522
|
+
if (!context.contentType.uid.startsWith("api::")) {
|
523
|
+
return false;
|
524
|
+
}
|
525
|
+
return true;
|
526
|
+
};
|
527
|
+
const getSchemas = (uid2) => {
|
528
|
+
const attributesSchema = strapi.getModel(uid2).attributes;
|
529
|
+
const componentsSchemas = Object.keys(attributesSchema).reduce(
|
530
|
+
(currentComponentSchemas, key) => {
|
531
|
+
const fieldSchema = attributesSchema[key];
|
532
|
+
if (fieldSchema.type === "component") {
|
533
|
+
const componentSchema = strapi.getModel(fieldSchema.component).attributes;
|
534
|
+
return {
|
535
|
+
...currentComponentSchemas,
|
536
|
+
[fieldSchema.component]: componentSchema
|
537
|
+
};
|
538
|
+
}
|
539
|
+
return currentComponentSchemas;
|
540
|
+
},
|
541
|
+
{}
|
542
|
+
);
|
543
|
+
return {
|
544
|
+
schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
|
545
|
+
componentsSchemas
|
546
|
+
};
|
547
|
+
};
|
493
548
|
const createLifecyclesService = ({ strapi: strapi2 }) => {
|
494
549
|
const state = {
|
495
550
|
deleteExpiredJob: null,
|
496
551
|
isInitialized: false
|
497
552
|
};
|
498
|
-
const query = strapi2.db.query(HISTORY_VERSION_UID);
|
499
|
-
const historyService = getService(strapi2, "history");
|
500
553
|
const serviceUtils = createServiceUtils({ strapi: strapi2 });
|
501
554
|
return {
|
502
555
|
async bootstrap() {
|
@@ -504,66 +557,53 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
504
557
|
return;
|
505
558
|
}
|
506
559
|
strapi2.documents.use(async (context, next) => {
|
507
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
508
|
-
return next();
|
509
|
-
}
|
510
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
511
|
-
return next();
|
512
|
-
}
|
513
|
-
const contentTypeUid = context.contentType.uid;
|
514
|
-
if (!contentTypeUid.startsWith("api::")) {
|
515
|
-
return next();
|
516
|
-
}
|
517
560
|
const result = await next();
|
518
|
-
|
561
|
+
if (!shouldCreateHistoryVersion(context)) {
|
562
|
+
return result;
|
563
|
+
}
|
564
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
519
565
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
520
|
-
const
|
521
|
-
if (
|
522
|
-
|
523
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
524
|
-
);
|
525
|
-
return next();
|
566
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
567
|
+
if (!locales.length) {
|
568
|
+
return result;
|
526
569
|
}
|
527
|
-
const
|
528
|
-
|
529
|
-
|
530
|
-
|
570
|
+
const uid2 = context.contentType.uid;
|
571
|
+
const schemas = getSchemas(uid2);
|
572
|
+
const model = strapi2.getModel(uid2);
|
573
|
+
const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
|
574
|
+
const localeEntries = await strapi2.db.query(uid2).findMany({
|
575
|
+
where: {
|
576
|
+
documentId,
|
577
|
+
...isLocalizedContentType ? { locale: { $in: locales } } : {},
|
578
|
+
...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
|
579
|
+
},
|
580
|
+
populate: serviceUtils.getDeepPopulate(
|
581
|
+
uid2,
|
582
|
+
true
|
583
|
+
/* use database syntax */
|
584
|
+
)
|
531
585
|
});
|
532
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
533
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
534
|
-
const componentsSchemas = Object.keys(
|
535
|
-
attributesSchema
|
536
|
-
).reduce((currentComponentSchemas, key) => {
|
537
|
-
const fieldSchema = attributesSchema[key];
|
538
|
-
if (fieldSchema.type === "component") {
|
539
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
540
|
-
return {
|
541
|
-
...currentComponentSchemas,
|
542
|
-
[fieldSchema.component]: componentSchema
|
543
|
-
};
|
544
|
-
}
|
545
|
-
return currentComponentSchemas;
|
546
|
-
}, {});
|
547
586
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
548
|
-
onCommit(() => {
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
587
|
+
onCommit(async () => {
|
588
|
+
for (const entry of localeEntries) {
|
589
|
+
const status = await serviceUtils.getVersionStatus(uid2, entry);
|
590
|
+
await getService(strapi2, "history").createVersion({
|
591
|
+
contentType: uid2,
|
592
|
+
data: fp.omit(FIELDS_TO_IGNORE, entry),
|
593
|
+
relatedDocumentId: documentId,
|
594
|
+
locale: entry.locale,
|
595
|
+
status,
|
596
|
+
...schemas
|
597
|
+
});
|
598
|
+
}
|
558
599
|
});
|
559
600
|
});
|
560
601
|
return result;
|
561
602
|
});
|
562
|
-
const retentionDays = serviceUtils.getRetentionDays();
|
563
603
|
state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
|
564
|
-
const retentionDaysInMilliseconds =
|
604
|
+
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
|
565
605
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
566
|
-
query.deleteMany({
|
606
|
+
strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
|
567
607
|
where: {
|
568
608
|
created_at: {
|
569
609
|
$lt: expirationDate.toISOString()
|
@@ -655,7 +695,7 @@ const historyVersion = {
|
|
655
695
|
}
|
656
696
|
}
|
657
697
|
};
|
658
|
-
const getFeature = () => {
|
698
|
+
const getFeature$1 = () => {
|
659
699
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
660
700
|
return {
|
661
701
|
register({ strapi: strapi2 }) {
|
@@ -678,7 +718,7 @@ const getFeature = () => {
|
|
678
718
|
}
|
679
719
|
};
|
680
720
|
};
|
681
|
-
const history = getFeature();
|
721
|
+
const history = getFeature$1();
|
682
722
|
const register = async ({ strapi: strapi2 }) => {
|
683
723
|
await history.register?.({ strapi: strapi2 });
|
684
724
|
};
|
@@ -686,6 +726,18 @@ const ALLOWED_WEBHOOK_EVENTS = {
|
|
686
726
|
ENTRY_PUBLISH: "entry.publish",
|
687
727
|
ENTRY_UNPUBLISH: "entry.unpublish"
|
688
728
|
};
|
729
|
+
const FEATURE_ID = "preview";
|
730
|
+
const getFeature = () => {
|
731
|
+
if (!strapi.features.future.isEnabled(FEATURE_ID)) {
|
732
|
+
return {};
|
733
|
+
}
|
734
|
+
return {
|
735
|
+
bootstrap() {
|
736
|
+
console.log("Bootstrapping preview server");
|
737
|
+
}
|
738
|
+
};
|
739
|
+
};
|
740
|
+
const preview = getFeature();
|
689
741
|
const bootstrap = async () => {
|
690
742
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
691
743
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
@@ -695,6 +747,7 @@ const bootstrap = async () => {
|
|
695
747
|
await getService$1("content-types").syncConfigurations();
|
696
748
|
await getService$1("permission").registerPermissions();
|
697
749
|
await history.bootstrap?.({ strapi });
|
750
|
+
await preview.bootstrap?.({ strapi });
|
698
751
|
};
|
699
752
|
const destroy = async ({ strapi: strapi2 }) => {
|
700
753
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1195,6 +1248,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1195
1248
|
const hasPermissions = createPolicy({
|
1196
1249
|
name: "plugin::content-manager.hasPermissions",
|
1197
1250
|
validator: validateHasPermissionsInput,
|
1251
|
+
/**
|
1252
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1253
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1254
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1255
|
+
*/
|
1198
1256
|
handler(ctx, config = {}) {
|
1199
1257
|
const { actions = [], hasAtLeastOne = false } = config;
|
1200
1258
|
const { userAbility } = ctx.state;
|
@@ -1588,9 +1646,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
|
|
1588
1646
|
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1589
1647
|
);
|
1590
1648
|
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1591
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1649
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1592
1650
|
const { allowMultipleLocales } = opts;
|
1593
|
-
const { locale, status, ...rest } = request || {};
|
1651
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1652
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1653
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1594
1654
|
const schema = strapiUtils.yup.object().shape({
|
1595
1655
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1596
1656
|
status: statusSchema
|
@@ -1638,7 +1698,7 @@ const createDocument = async (ctx, opts) => {
|
|
1638
1698
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1639
1699
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1640
1700
|
const sanitizedBody = await sanitizeFn(body);
|
1641
|
-
const { locale, status
|
1701
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1642
1702
|
return documentManager2.create(model, {
|
1643
1703
|
data: sanitizedBody,
|
1644
1704
|
locale,
|
@@ -1657,7 +1717,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1657
1717
|
}
|
1658
1718
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1659
1719
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1660
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1720
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1661
1721
|
const [documentVersion, documentExists] = await Promise.all([
|
1662
1722
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1663
1723
|
documentManager2.exists(model, id)
|
@@ -1673,7 +1733,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1673
1733
|
throw new strapiUtils.errors.ForbiddenError();
|
1674
1734
|
}
|
1675
1735
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1676
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1736
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1677
1737
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1678
1738
|
const sanitizedBody = await sanitizeFn(body);
|
1679
1739
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1695,7 +1755,7 @@ const collectionTypes = {
|
|
1695
1755
|
}
|
1696
1756
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1697
1757
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1698
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1758
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1699
1759
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1700
1760
|
{ ...permissionQuery, populate, locale, status },
|
1701
1761
|
model
|
@@ -1730,7 +1790,7 @@ const collectionTypes = {
|
|
1730
1790
|
}
|
1731
1791
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1732
1792
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1733
|
-
const { locale, status
|
1793
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1734
1794
|
const version = await documentManager2.findOne(id, model, {
|
1735
1795
|
populate,
|
1736
1796
|
locale,
|
@@ -1745,7 +1805,7 @@ const collectionTypes = {
|
|
1745
1805
|
permissionChecker2,
|
1746
1806
|
model,
|
1747
1807
|
// @ts-expect-error TODO: fix
|
1748
|
-
{ id, locale, publishedAt: null },
|
1808
|
+
{ documentId: id, locale, publishedAt: null },
|
1749
1809
|
{ availableLocales: true, availableStatus: false }
|
1750
1810
|
);
|
1751
1811
|
ctx.body = { data: {}, meta };
|
@@ -1797,7 +1857,7 @@ const collectionTypes = {
|
|
1797
1857
|
}
|
1798
1858
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1799
1859
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1800
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1860
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1801
1861
|
const document = await documentManager2.findOne(id, model, {
|
1802
1862
|
populate,
|
1803
1863
|
locale,
|
@@ -1842,7 +1902,7 @@ const collectionTypes = {
|
|
1842
1902
|
}
|
1843
1903
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1844
1904
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1845
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1905
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1846
1906
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1847
1907
|
if (documentLocales.length === 0) {
|
1848
1908
|
return ctx.notFound();
|
@@ -1871,11 +1931,34 @@ const collectionTypes = {
|
|
1871
1931
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1872
1932
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1873
1933
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1874
|
-
|
1934
|
+
let document;
|
1935
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1936
|
+
const isCreate = fp.isNil(id);
|
1937
|
+
if (isCreate) {
|
1938
|
+
if (permissionChecker2.cannot.create()) {
|
1939
|
+
throw new strapiUtils.errors.ForbiddenError();
|
1940
|
+
}
|
1941
|
+
document = await createDocument(ctx, { populate });
|
1942
|
+
}
|
1943
|
+
const isUpdate = !isCreate;
|
1944
|
+
if (isUpdate) {
|
1945
|
+
const documentExists = documentManager2.exists(model, id);
|
1946
|
+
if (!documentExists) {
|
1947
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
1948
|
+
}
|
1949
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
1950
|
+
if (!document) {
|
1951
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
1952
|
+
throw new strapiUtils.errors.ForbiddenError();
|
1953
|
+
}
|
1954
|
+
document = await updateDocument(ctx);
|
1955
|
+
} else if (permissionChecker2.can.update(document)) {
|
1956
|
+
await updateDocument(ctx);
|
1957
|
+
}
|
1958
|
+
}
|
1875
1959
|
if (permissionChecker2.cannot.publish(document)) {
|
1876
1960
|
throw new strapiUtils.errors.ForbiddenError();
|
1877
1961
|
}
|
1878
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1879
1962
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1880
1963
|
locale
|
1881
1964
|
// TODO: Allow setting creator fields on publish
|
@@ -1902,7 +1985,9 @@ const collectionTypes = {
|
|
1902
1985
|
}
|
1903
1986
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1904
1987
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1905
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
1988
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
1989
|
+
allowMultipleLocales: true
|
1990
|
+
});
|
1906
1991
|
const entityPromises = documentIds.map(
|
1907
1992
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1908
1993
|
);
|
@@ -1929,7 +2014,9 @@ const collectionTypes = {
|
|
1929
2014
|
if (permissionChecker2.cannot.unpublish()) {
|
1930
2015
|
return ctx.forbidden();
|
1931
2016
|
}
|
1932
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2017
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2018
|
+
allowMultipleLocales: true
|
2019
|
+
});
|
1933
2020
|
const entityPromises = documentIds.map(
|
1934
2021
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1935
2022
|
);
|
@@ -1962,7 +2049,7 @@ const collectionTypes = {
|
|
1962
2049
|
}
|
1963
2050
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1964
2051
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1965
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2052
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1966
2053
|
const document = await documentManager2.findOne(id, model, {
|
1967
2054
|
populate,
|
1968
2055
|
locale,
|
@@ -1999,7 +2086,7 @@ const collectionTypes = {
|
|
1999
2086
|
}
|
2000
2087
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2001
2088
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2002
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2089
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2003
2090
|
const document = await documentManager2.findOne(id, model, {
|
2004
2091
|
populate,
|
2005
2092
|
locale,
|
@@ -2030,7 +2117,7 @@ const collectionTypes = {
|
|
2030
2117
|
}
|
2031
2118
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2032
2119
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2033
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2120
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2034
2121
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2035
2122
|
populate,
|
2036
2123
|
locale
|
@@ -2057,7 +2144,7 @@ const collectionTypes = {
|
|
2057
2144
|
}
|
2058
2145
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2059
2146
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2060
|
-
const { locale, status
|
2147
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2061
2148
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2062
2149
|
if (!entity) {
|
2063
2150
|
return ctx.notFound();
|
@@ -2080,7 +2167,7 @@ const collectionTypes = {
|
|
2080
2167
|
if (permissionChecker2.cannot.read()) {
|
2081
2168
|
return ctx.forbidden();
|
2082
2169
|
}
|
2083
|
-
const
|
2170
|
+
const documents = await documentManager2.findMany(
|
2084
2171
|
{
|
2085
2172
|
filters: {
|
2086
2173
|
documentId: ids
|
@@ -2089,7 +2176,7 @@ const collectionTypes = {
|
|
2089
2176
|
},
|
2090
2177
|
model
|
2091
2178
|
);
|
2092
|
-
if (!
|
2179
|
+
if (!documents) {
|
2093
2180
|
return ctx.notFound();
|
2094
2181
|
}
|
2095
2182
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2280,20 +2367,13 @@ const sanitizeMainField = (model, mainField, userAbility) => {
|
|
2280
2367
|
userAbility,
|
2281
2368
|
model: model.uid
|
2282
2369
|
});
|
2283
|
-
|
2370
|
+
const isMainFieldListable = isListable(model, mainField);
|
2371
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2372
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2284
2373
|
return "id";
|
2285
2374
|
}
|
2286
|
-
if (
|
2287
|
-
|
2288
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2289
|
-
userAbility,
|
2290
|
-
model: "plugin::users-permissions.user"
|
2291
|
-
});
|
2292
|
-
if (userPermissionChecker.can.read()) {
|
2293
|
-
return "name";
|
2294
|
-
}
|
2295
|
-
}
|
2296
|
-
return "id";
|
2375
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2376
|
+
return "name";
|
2297
2377
|
}
|
2298
2378
|
return mainField;
|
2299
2379
|
};
|
@@ -2326,11 +2406,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2326
2406
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2327
2407
|
const isSourceLocalized = isLocalized(sourceModel);
|
2328
2408
|
const isTargetLocalized = isLocalized(targetModel);
|
2329
|
-
let validatedLocale = locale;
|
2330
|
-
if (!targetModel || !isTargetLocalized)
|
2331
|
-
validatedLocale = void 0;
|
2332
2409
|
return {
|
2333
|
-
locale
|
2410
|
+
locale,
|
2334
2411
|
isSourceLocalized,
|
2335
2412
|
isTargetLocalized
|
2336
2413
|
};
|
@@ -2433,7 +2510,7 @@ const relations = {
|
|
2433
2510
|
attribute,
|
2434
2511
|
fieldsToSelect,
|
2435
2512
|
mainField,
|
2436
|
-
source: { schema: sourceSchema },
|
2513
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2437
2514
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2438
2515
|
sourceSchema,
|
2439
2516
|
targetSchema,
|
@@ -2455,7 +2532,8 @@ const relations = {
|
|
2455
2532
|
fieldsToSelect,
|
2456
2533
|
mainField,
|
2457
2534
|
source: {
|
2458
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2535
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2536
|
+
isLocalized: isSourceLocalized
|
2459
2537
|
},
|
2460
2538
|
target: {
|
2461
2539
|
schema: { uid: targetUid },
|
@@ -2493,12 +2571,16 @@ const relations = {
|
|
2493
2571
|
} else {
|
2494
2572
|
where.id = id;
|
2495
2573
|
}
|
2496
|
-
|
2497
|
-
|
2574
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2575
|
+
if (!fp.isEmpty(publishedAt)) {
|
2576
|
+
where[`${alias}.published_at`] = publishedAt;
|
2498
2577
|
}
|
2499
|
-
if (
|
2578
|
+
if (isTargetLocalized && locale) {
|
2500
2579
|
where[`${alias}.locale`] = locale;
|
2501
2580
|
}
|
2581
|
+
if (isSourceLocalized && locale) {
|
2582
|
+
where.locale = locale;
|
2583
|
+
}
|
2502
2584
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2503
2585
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2504
2586
|
}
|
@@ -2516,7 +2598,8 @@ const relations = {
|
|
2516
2598
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2517
2599
|
});
|
2518
2600
|
}
|
2519
|
-
const
|
2601
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2602
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2520
2603
|
ctx.body = {
|
2521
2604
|
...res,
|
2522
2605
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2551,9 +2634,7 @@ const relations = {
|
|
2551
2634
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2552
2635
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2553
2636
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2554
|
-
ordering: "desc"
|
2555
|
-
page: ctx.request.query.page,
|
2556
|
-
pageSize: ctx.request.query.pageSize
|
2637
|
+
ordering: "desc"
|
2557
2638
|
});
|
2558
2639
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2559
2640
|
ctx.body = {
|
@@ -2585,7 +2666,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2585
2666
|
throw new strapiUtils.errors.ForbiddenError();
|
2586
2667
|
}
|
2587
2668
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2588
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2669
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2589
2670
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2590
2671
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2591
2672
|
// Find the first document to check if it exists
|
@@ -2626,7 +2707,7 @@ const singleTypes = {
|
|
2626
2707
|
return ctx.forbidden();
|
2627
2708
|
}
|
2628
2709
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2629
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2710
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2630
2711
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2631
2712
|
if (!version) {
|
2632
2713
|
if (permissionChecker2.cannot.create()) {
|
@@ -2640,7 +2721,7 @@ const singleTypes = {
|
|
2640
2721
|
permissionChecker2,
|
2641
2722
|
model,
|
2642
2723
|
// @ts-expect-error - fix types
|
2643
|
-
{
|
2724
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2644
2725
|
{ availableLocales: true, availableStatus: false }
|
2645
2726
|
);
|
2646
2727
|
ctx.body = { data: {}, meta };
|
@@ -2671,7 +2752,7 @@ const singleTypes = {
|
|
2671
2752
|
}
|
2672
2753
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2673
2754
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2674
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2755
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2675
2756
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2676
2757
|
populate,
|
2677
2758
|
locale
|
@@ -2708,7 +2789,7 @@ const singleTypes = {
|
|
2708
2789
|
if (permissionChecker2.cannot.publish(document)) {
|
2709
2790
|
throw new strapiUtils.errors.ForbiddenError();
|
2710
2791
|
}
|
2711
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2792
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2712
2793
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2713
2794
|
return publishResult.at(0);
|
2714
2795
|
});
|
@@ -2731,7 +2812,7 @@ const singleTypes = {
|
|
2731
2812
|
return ctx.forbidden();
|
2732
2813
|
}
|
2733
2814
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2734
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2815
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2735
2816
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2736
2817
|
if (!document) {
|
2737
2818
|
return ctx.notFound();
|
@@ -2763,7 +2844,7 @@ const singleTypes = {
|
|
2763
2844
|
return ctx.forbidden();
|
2764
2845
|
}
|
2765
2846
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2766
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2847
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2767
2848
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2768
2849
|
if (!document) {
|
2769
2850
|
return ctx.notFound();
|
@@ -2783,7 +2864,7 @@ const singleTypes = {
|
|
2783
2864
|
const { query } = ctx.request;
|
2784
2865
|
const documentManager2 = getService$1("document-manager");
|
2785
2866
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2786
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2867
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2787
2868
|
if (permissionChecker2.cannot.read()) {
|
2788
2869
|
return ctx.forbidden();
|
2789
2870
|
}
|
@@ -2804,7 +2885,7 @@ const uid$1 = {
|
|
2804
2885
|
async generateUID(ctx) {
|
2805
2886
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2806
2887
|
const { query = {} } = ctx.request;
|
2807
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2888
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2808
2889
|
await validateUIDField(contentTypeUID, field);
|
2809
2890
|
const uidService = getService$1("uid");
|
2810
2891
|
ctx.body = {
|
@@ -2816,7 +2897,7 @@ const uid$1 = {
|
|
2816
2897
|
ctx.request.body
|
2817
2898
|
);
|
2818
2899
|
const { query = {} } = ctx.request;
|
2819
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2900
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2820
2901
|
await validateUIDField(contentTypeUID, field);
|
2821
2902
|
const uidService = getService$1("uid");
|
2822
2903
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -3459,12 +3540,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3459
3540
|
ability: userAbility,
|
3460
3541
|
model
|
3461
3542
|
});
|
3462
|
-
const
|
3543
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3544
|
+
const toSubject = (entity) => {
|
3545
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3546
|
+
};
|
3463
3547
|
const can = (action, entity, field) => {
|
3464
|
-
|
3548
|
+
const subject = toSubject(entity);
|
3549
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3550
|
+
return (
|
3551
|
+
// Test the original action to see if it passes
|
3552
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3553
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3554
|
+
);
|
3465
3555
|
};
|
3466
3556
|
const cannot = (action, entity, field) => {
|
3467
|
-
|
3557
|
+
const subject = toSubject(entity);
|
3558
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3559
|
+
return (
|
3560
|
+
// Test both the original action
|
3561
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3562
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3563
|
+
);
|
3468
3564
|
};
|
3469
3565
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3470
3566
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3741,6 +3837,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3741
3837
|
const attribute = model.attributes[attributeName];
|
3742
3838
|
switch (attribute.type) {
|
3743
3839
|
case "relation": {
|
3840
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3841
|
+
if (isMorphRelation) {
|
3842
|
+
break;
|
3843
|
+
}
|
3744
3844
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3745
3845
|
populateAcc[attributeName] = {
|
3746
3846
|
count: true,
|
@@ -3755,22 +3855,24 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3755
3855
|
attribute.component
|
3756
3856
|
);
|
3757
3857
|
if (childHasRelations) {
|
3758
|
-
populateAcc[attributeName] = {
|
3858
|
+
populateAcc[attributeName] = {
|
3859
|
+
populate: populate2
|
3860
|
+
};
|
3759
3861
|
hasRelations = true;
|
3760
3862
|
}
|
3761
3863
|
break;
|
3762
3864
|
}
|
3763
3865
|
case "dynamiczone": {
|
3764
|
-
const
|
3765
|
-
const { populate:
|
3766
|
-
if (
|
3866
|
+
const dzPopulateFragment = attribute.components?.reduce((acc, componentUID) => {
|
3867
|
+
const { populate: componentPopulate, hasRelations: componentHasRelations } = getDeepPopulateDraftCount(componentUID);
|
3868
|
+
if (componentHasRelations) {
|
3767
3869
|
hasRelations = true;
|
3768
|
-
return
|
3870
|
+
return { ...acc, [componentUID]: { populate: componentPopulate } };
|
3769
3871
|
}
|
3770
3872
|
return acc;
|
3771
3873
|
}, {});
|
3772
|
-
if (!fp.isEmpty(
|
3773
|
-
populateAcc[attributeName] = {
|
3874
|
+
if (!fp.isEmpty(dzPopulateFragment)) {
|
3875
|
+
populateAcc[attributeName] = { on: dzPopulateFragment };
|
3774
3876
|
}
|
3775
3877
|
break;
|
3776
3878
|
}
|
@@ -4116,7 +4218,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4116
4218
|
*/
|
4117
4219
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4118
4220
|
if (!document) {
|
4119
|
-
return
|
4221
|
+
return {
|
4222
|
+
data: document,
|
4223
|
+
meta: {
|
4224
|
+
availableLocales: [],
|
4225
|
+
availableStatus: []
|
4226
|
+
}
|
4227
|
+
};
|
4120
4228
|
}
|
4121
4229
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4122
4230
|
if (!hasDraftAndPublish) {
|
@@ -4224,10 +4332,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4224
4332
|
async clone(id, body, uid2) {
|
4225
4333
|
const populate = await buildDeepPopulate(uid2);
|
4226
4334
|
const params = {
|
4227
|
-
data:
|
4228
|
-
...omitIdField(body),
|
4229
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4230
|
-
},
|
4335
|
+
data: omitIdField(body),
|
4231
4336
|
populate
|
4232
4337
|
};
|
4233
4338
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|