@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d74a8e5e655230b243e2d61ab5bec2fcdb426993
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-DmwmiFQy.mjs → ComponentConfigurationPage-CIjXcRAB.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-CIjXcRAB.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-gsCd80MU.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-gsCd80MU.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-BglmD_BF.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-BglmD_BF.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-DHDQKBzw.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-DHDQKBzw.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-C4iTxUPU.js} +30 -9
- package/dist/_chunks/EditViewPage-C4iTxUPU.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-CiwVPMaK.mjs} +30 -9
- package/dist/_chunks/EditViewPage-CiwVPMaK.mjs.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-DIjL1b5d.mjs} +249 -152
- package/dist/_chunks/Field-DIjL1b5d.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-DhXEK8y1.js} +251 -154
- package/dist/_chunks/Field-DhXEK8y1.js.map +1 -0
- package/dist/_chunks/{Form-DHrru2AV.mjs → Form-CmNesrvR.mjs} +36 -17
- package/dist/_chunks/Form-CmNesrvR.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-CwmJ4sWe.js} +36 -17
- package/dist/_chunks/Form-CwmJ4sWe.js.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-BLCCNgCt.js} +64 -26
- package/dist/_chunks/History-BLCCNgCt.js.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-D-99Wh30.mjs} +65 -27
- package/dist/_chunks/History-D-99Wh30.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-DxWpeZrO.js} +21 -9
- package/dist/_chunks/ListConfigurationPage-DxWpeZrO.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-JPWZz7Kg.mjs} +21 -9
- package/dist/_chunks/ListConfigurationPage-JPWZz7Kg.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-CIQekSFz.js} +73 -44
- package/dist/_chunks/ListViewPage-CIQekSFz.js.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-DSK3f0ST.mjs} +71 -42
- package/dist/_chunks/ListViewPage-DSK3f0ST.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-C5cxKvC2.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-C5cxKvC2.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-D99LU1YP.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-D99LU1YP.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-DBrBw-0y.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-DBrBw-0y.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-Oy4tmUrW.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-Oy4tmUrW.js.map} +1 -1
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-BBmhcWFV.mjs} +70 -37
- package/dist/_chunks/Relations-BBmhcWFV.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-eG-9p_qS.js} +69 -36
- package/dist/_chunks/Relations-eG-9p_qS.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-Bm0D0IWz.js} +17 -15
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-DKV44jRb.mjs} +17 -15
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-DVPWZkbS.js → index-BIWDoFLK.js} +1003 -669
- package/dist/_chunks/index-BIWDoFLK.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-BrUzbQ30.mjs} +1021 -688
- package/dist/_chunks/index-BrUzbQ30.mjs.map +1 -0
- package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-_5-cXs34.mjs} +25 -12
- package/dist/_chunks/layout-_5-cXs34.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-lMc9i1-Z.js} +24 -11
- 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-CKnpRgrN.js → relations-BRHithi8.js} +3 -7
- package/dist/_chunks/relations-BRHithi8.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.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 +5 -4
- package/dist/admin/src/exports.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 +1 -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 +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- 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 +321 -148
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +322 -149
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +9 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +4 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +6 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +7 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
- package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
- package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
- package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
- package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
- package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
- package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
- package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
- package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
- package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
- package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
- package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
- package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
- package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
- package/dist/_chunks/relations-CKnpRgrN.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
@@ -121,7 +121,7 @@ const createHistoryVersionController = ({ strapi: strapi2 }) => {
|
|
121
121
|
}
|
122
122
|
};
|
123
123
|
};
|
124
|
-
const controllers$
|
124
|
+
const controllers$2 = {
|
125
125
|
"history-version": createHistoryVersionController
|
126
126
|
/**
|
127
127
|
* Casting is needed because the types aren't aware that Strapi supports
|
@@ -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,6 +509,42 @@ 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,
|
@@ -502,63 +557,45 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
502
557
|
return;
|
503
558
|
}
|
504
559
|
strapi2.documents.use(async (context, next) => {
|
505
|
-
if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
|
506
|
-
return next();
|
507
|
-
}
|
508
|
-
if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
|
509
|
-
return next();
|
510
|
-
}
|
511
|
-
if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
|
512
|
-
return next();
|
513
|
-
}
|
514
|
-
const contentTypeUid = context.contentType.uid;
|
515
|
-
if (!contentTypeUid.startsWith("api::")) {
|
516
|
-
return next();
|
517
|
-
}
|
518
560
|
const result = await next();
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
561
|
+
if (!shouldCreateHistoryVersion(context)) {
|
562
|
+
return result;
|
563
|
+
}
|
564
|
+
const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
|
523
565
|
const defaultLocale = await serviceUtils.getDefaultLocale();
|
524
|
-
const
|
525
|
-
if (
|
526
|
-
|
527
|
-
"[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
|
528
|
-
);
|
529
|
-
return next();
|
566
|
+
const locales = fp.castArray(context.params?.locale || defaultLocale);
|
567
|
+
if (!locales.length) {
|
568
|
+
return result;
|
530
569
|
}
|
531
|
-
const
|
532
|
-
|
533
|
-
|
534
|
-
|
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
|
+
)
|
535
585
|
});
|
536
|
-
const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
|
537
|
-
const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
|
538
|
-
const componentsSchemas = Object.keys(
|
539
|
-
attributesSchema
|
540
|
-
).reduce((currentComponentSchemas, key) => {
|
541
|
-
const fieldSchema = attributesSchema[key];
|
542
|
-
if (fieldSchema.type === "component") {
|
543
|
-
const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
|
544
|
-
return {
|
545
|
-
...currentComponentSchemas,
|
546
|
-
[fieldSchema.component]: componentSchema
|
547
|
-
};
|
548
|
-
}
|
549
|
-
return currentComponentSchemas;
|
550
|
-
}, {});
|
551
586
|
await strapi2.db.transaction(async ({ onCommit }) => {
|
552
|
-
onCommit(() => {
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
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
|
+
}
|
562
599
|
});
|
563
600
|
});
|
564
601
|
return result;
|
@@ -583,17 +620,17 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
|
|
583
620
|
}
|
584
621
|
};
|
585
622
|
};
|
586
|
-
const services$
|
623
|
+
const services$2 = {
|
587
624
|
history: createHistoryService,
|
588
625
|
lifecycles: createLifecyclesService
|
589
626
|
};
|
590
|
-
const info = { pluginName: "content-manager", type: "admin" };
|
627
|
+
const info$1 = { pluginName: "content-manager", type: "admin" };
|
591
628
|
const historyVersionRouter = {
|
592
629
|
type: "admin",
|
593
630
|
routes: [
|
594
631
|
{
|
595
632
|
method: "GET",
|
596
|
-
info,
|
633
|
+
info: info$1,
|
597
634
|
path: "/history-versions",
|
598
635
|
handler: "history-version.findMany",
|
599
636
|
config: {
|
@@ -602,7 +639,7 @@ const historyVersionRouter = {
|
|
602
639
|
},
|
603
640
|
{
|
604
641
|
method: "PUT",
|
605
|
-
info,
|
642
|
+
info: info$1,
|
606
643
|
path: "/history-versions/:versionId/restore",
|
607
644
|
handler: "history-version.restoreVersion",
|
608
645
|
config: {
|
@@ -611,7 +648,7 @@ const historyVersionRouter = {
|
|
611
648
|
}
|
612
649
|
]
|
613
650
|
};
|
614
|
-
const routes$
|
651
|
+
const routes$2 = {
|
615
652
|
"history-version": historyVersionRouter
|
616
653
|
};
|
617
654
|
const historyVersion = {
|
@@ -658,7 +695,7 @@ const historyVersion = {
|
|
658
695
|
}
|
659
696
|
}
|
660
697
|
};
|
661
|
-
const getFeature = () => {
|
698
|
+
const getFeature$1 = () => {
|
662
699
|
if (strapi.ee.features.isEnabled("cms-content-history")) {
|
663
700
|
return {
|
664
701
|
register({ strapi: strapi2 }) {
|
@@ -670,9 +707,9 @@ const getFeature = () => {
|
|
670
707
|
destroy({ strapi: strapi2 }) {
|
671
708
|
getService(strapi2, "lifecycles").destroy();
|
672
709
|
},
|
673
|
-
controllers: controllers$
|
674
|
-
services: services$
|
675
|
-
routes: routes$
|
710
|
+
controllers: controllers$2,
|
711
|
+
services: services$2,
|
712
|
+
routes: routes$2
|
676
713
|
};
|
677
714
|
}
|
678
715
|
return {
|
@@ -681,7 +718,7 @@ const getFeature = () => {
|
|
681
718
|
}
|
682
719
|
};
|
683
720
|
};
|
684
|
-
const history = getFeature();
|
721
|
+
const history = getFeature$1();
|
685
722
|
const register = async ({ strapi: strapi2 }) => {
|
686
723
|
await history.register?.({ strapi: strapi2 });
|
687
724
|
};
|
@@ -689,6 +726,62 @@ const ALLOWED_WEBHOOK_EVENTS = {
|
|
689
726
|
ENTRY_PUBLISH: "entry.publish",
|
690
727
|
ENTRY_UNPUBLISH: "entry.unpublish"
|
691
728
|
};
|
729
|
+
const FEATURE_ID = "preview";
|
730
|
+
const info = { pluginName: "content-manager", type: "admin" };
|
731
|
+
const previewRouter = {
|
732
|
+
type: "admin",
|
733
|
+
routes: [
|
734
|
+
{
|
735
|
+
method: "GET",
|
736
|
+
info,
|
737
|
+
path: "/preview/url/:contentType",
|
738
|
+
handler: "preview.getPreviewURL",
|
739
|
+
config: {
|
740
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
741
|
+
}
|
742
|
+
}
|
743
|
+
]
|
744
|
+
};
|
745
|
+
const routes$1 = {
|
746
|
+
preview: previewRouter
|
747
|
+
};
|
748
|
+
const createPreviewController = () => {
|
749
|
+
return {
|
750
|
+
async getPreviewURL(ctx) {
|
751
|
+
ctx.request;
|
752
|
+
return {
|
753
|
+
data: { url: "" }
|
754
|
+
};
|
755
|
+
}
|
756
|
+
};
|
757
|
+
};
|
758
|
+
const controllers$1 = {
|
759
|
+
preview: createPreviewController
|
760
|
+
/**
|
761
|
+
* Casting is needed because the types aren't aware that Strapi supports
|
762
|
+
* passing a controller factory as the value, instead of a controller object directly
|
763
|
+
*/
|
764
|
+
};
|
765
|
+
const createPreviewService = () => {
|
766
|
+
};
|
767
|
+
const services$1 = {
|
768
|
+
preview: createPreviewService
|
769
|
+
};
|
770
|
+
const getFeature = () => {
|
771
|
+
if (!strapi.features.future.isEnabled(FEATURE_ID)) {
|
772
|
+
return {};
|
773
|
+
}
|
774
|
+
return {
|
775
|
+
bootstrap() {
|
776
|
+
console.log("Bootstrapping preview server");
|
777
|
+
strapi.config.get("admin.preview");
|
778
|
+
},
|
779
|
+
routes: routes$1,
|
780
|
+
controllers: controllers$1,
|
781
|
+
services: services$1
|
782
|
+
};
|
783
|
+
};
|
784
|
+
const preview = getFeature();
|
692
785
|
const bootstrap = async () => {
|
693
786
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
694
787
|
strapi.get("webhookStore").addAllowedEvent(key, value);
|
@@ -698,6 +791,7 @@ const bootstrap = async () => {
|
|
698
791
|
await getService$1("content-types").syncConfigurations();
|
699
792
|
await getService$1("permission").registerPermissions();
|
700
793
|
await history.bootstrap?.({ strapi });
|
794
|
+
await preview.bootstrap?.({ strapi });
|
701
795
|
};
|
702
796
|
const destroy = async ({ strapi: strapi2 }) => {
|
703
797
|
await history.destroy?.({ strapi: strapi2 });
|
@@ -1187,7 +1281,8 @@ const admin = {
|
|
1187
1281
|
};
|
1188
1282
|
const routes = {
|
1189
1283
|
admin,
|
1190
|
-
...history.routes ? history.routes : {}
|
1284
|
+
...history.routes ? history.routes : {},
|
1285
|
+
...preview.routes ? preview.routes : {}
|
1191
1286
|
};
|
1192
1287
|
const hasPermissionsSchema = strapiUtils.yup.object({
|
1193
1288
|
actions: strapiUtils.yup.array().of(strapiUtils.yup.string()),
|
@@ -1198,6 +1293,11 @@ const { createPolicy } = strapiUtils.policy;
|
|
1198
1293
|
const hasPermissions = createPolicy({
|
1199
1294
|
name: "plugin::content-manager.hasPermissions",
|
1200
1295
|
validator: validateHasPermissionsInput,
|
1296
|
+
/**
|
1297
|
+
* NOTE: Action aliases are currently not checked at this level (policy).
|
1298
|
+
* This is currently the intended behavior to avoid changing the behavior of API related permissions.
|
1299
|
+
* If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
|
1300
|
+
*/
|
1201
1301
|
handler(ctx, config = {}) {
|
1202
1302
|
const { actions = [], hasAtLeastOne = false } = config;
|
1203
1303
|
const { userAbility } = ctx.state;
|
@@ -1591,9 +1691,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
|
|
1591
1691
|
(value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
|
1592
1692
|
);
|
1593
1693
|
const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
|
1594
|
-
const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
|
1694
|
+
const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
|
1595
1695
|
const { allowMultipleLocales } = opts;
|
1596
|
-
const { locale, status, ...rest } = request || {};
|
1696
|
+
const { locale, status: providedStatus, ...rest } = request || {};
|
1697
|
+
const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
|
1698
|
+
const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
|
1597
1699
|
const schema = strapiUtils.yup.object().shape({
|
1598
1700
|
locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
|
1599
1701
|
status: statusSchema
|
@@ -1641,7 +1743,7 @@ const createDocument = async (ctx, opts) => {
|
|
1641
1743
|
const setCreator = strapiUtils.setCreatorFields({ user });
|
1642
1744
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1643
1745
|
const sanitizedBody = await sanitizeFn(body);
|
1644
|
-
const { locale, status
|
1746
|
+
const { locale, status } = await getDocumentLocaleAndStatus(body, model);
|
1645
1747
|
return documentManager2.create(model, {
|
1646
1748
|
data: sanitizedBody,
|
1647
1749
|
locale,
|
@@ -1660,7 +1762,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1660
1762
|
}
|
1661
1763
|
const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
|
1662
1764
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1663
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1765
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1664
1766
|
const [documentVersion, documentExists] = await Promise.all([
|
1665
1767
|
documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
|
1666
1768
|
documentManager2.exists(model, id)
|
@@ -1676,7 +1778,7 @@ const updateDocument = async (ctx, opts) => {
|
|
1676
1778
|
throw new strapiUtils.errors.ForbiddenError();
|
1677
1779
|
}
|
1678
1780
|
const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
|
1679
|
-
const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
|
1781
|
+
const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
|
1680
1782
|
const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
|
1681
1783
|
const sanitizedBody = await sanitizeFn(body);
|
1682
1784
|
return documentManager2.update(documentVersion?.documentId || id, model, {
|
@@ -1698,7 +1800,7 @@ const collectionTypes = {
|
|
1698
1800
|
}
|
1699
1801
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
1700
1802
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
|
1701
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
1803
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
1702
1804
|
const { results: documents, pagination } = await documentManager2.findPage(
|
1703
1805
|
{ ...permissionQuery, populate, locale, status },
|
1704
1806
|
model
|
@@ -1733,7 +1835,7 @@ const collectionTypes = {
|
|
1733
1835
|
}
|
1734
1836
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
1735
1837
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1736
|
-
const { locale, status
|
1838
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1737
1839
|
const version = await documentManager2.findOne(id, model, {
|
1738
1840
|
populate,
|
1739
1841
|
locale,
|
@@ -1748,7 +1850,7 @@ const collectionTypes = {
|
|
1748
1850
|
permissionChecker2,
|
1749
1851
|
model,
|
1750
1852
|
// @ts-expect-error TODO: fix
|
1751
|
-
{ id, locale, publishedAt: null },
|
1853
|
+
{ documentId: id, locale, publishedAt: null },
|
1752
1854
|
{ availableLocales: true, availableStatus: false }
|
1753
1855
|
);
|
1754
1856
|
ctx.body = { data: {}, meta };
|
@@ -1800,7 +1902,7 @@ const collectionTypes = {
|
|
1800
1902
|
}
|
1801
1903
|
const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
|
1802
1904
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1803
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1905
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1804
1906
|
const document = await documentManager2.findOne(id, model, {
|
1805
1907
|
populate,
|
1806
1908
|
locale,
|
@@ -1845,7 +1947,7 @@ const collectionTypes = {
|
|
1845
1947
|
}
|
1846
1948
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
|
1847
1949
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1848
|
-
const { locale } = await getDocumentLocaleAndStatus(ctx.query);
|
1950
|
+
const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
|
1849
1951
|
const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
|
1850
1952
|
if (documentLocales.length === 0) {
|
1851
1953
|
return ctx.notFound();
|
@@ -1874,11 +1976,34 @@ const collectionTypes = {
|
|
1874
1976
|
const publishedDocument = await strapi.db.transaction(async () => {
|
1875
1977
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1876
1978
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1877
|
-
|
1979
|
+
let document;
|
1980
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1981
|
+
const isCreate = fp.isNil(id);
|
1982
|
+
if (isCreate) {
|
1983
|
+
if (permissionChecker2.cannot.create()) {
|
1984
|
+
throw new strapiUtils.errors.ForbiddenError();
|
1985
|
+
}
|
1986
|
+
document = await createDocument(ctx, { populate });
|
1987
|
+
}
|
1988
|
+
const isUpdate = !isCreate;
|
1989
|
+
if (isUpdate) {
|
1990
|
+
const documentExists = documentManager2.exists(model, id);
|
1991
|
+
if (!documentExists) {
|
1992
|
+
throw new strapiUtils.errors.NotFoundError("Document not found");
|
1993
|
+
}
|
1994
|
+
document = await documentManager2.findOne(id, model, { populate, locale });
|
1995
|
+
if (!document) {
|
1996
|
+
if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
|
1997
|
+
throw new strapiUtils.errors.ForbiddenError();
|
1998
|
+
}
|
1999
|
+
document = await updateDocument(ctx);
|
2000
|
+
} else if (permissionChecker2.can.update(document)) {
|
2001
|
+
await updateDocument(ctx);
|
2002
|
+
}
|
2003
|
+
}
|
1878
2004
|
if (permissionChecker2.cannot.publish(document)) {
|
1879
2005
|
throw new strapiUtils.errors.ForbiddenError();
|
1880
2006
|
}
|
1881
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
1882
2007
|
const publishResult = await documentManager2.publish(document.documentId, model, {
|
1883
2008
|
locale
|
1884
2009
|
// TODO: Allow setting creator fields on publish
|
@@ -1905,7 +2030,9 @@ const collectionTypes = {
|
|
1905
2030
|
}
|
1906
2031
|
const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
|
1907
2032
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
|
1908
|
-
const { locale } = await getDocumentLocaleAndStatus(body, {
|
2033
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2034
|
+
allowMultipleLocales: true
|
2035
|
+
});
|
1909
2036
|
const entityPromises = documentIds.map(
|
1910
2037
|
(documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
|
1911
2038
|
);
|
@@ -1932,7 +2059,9 @@ const collectionTypes = {
|
|
1932
2059
|
if (permissionChecker2.cannot.unpublish()) {
|
1933
2060
|
return ctx.forbidden();
|
1934
2061
|
}
|
1935
|
-
const { locale } = await getDocumentLocaleAndStatus(body
|
2062
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model, {
|
2063
|
+
allowMultipleLocales: true
|
2064
|
+
});
|
1936
2065
|
const entityPromises = documentIds.map(
|
1937
2066
|
(documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
|
1938
2067
|
);
|
@@ -1965,7 +2094,7 @@ const collectionTypes = {
|
|
1965
2094
|
}
|
1966
2095
|
const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
|
1967
2096
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
1968
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2097
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
1969
2098
|
const document = await documentManager2.findOne(id, model, {
|
1970
2099
|
populate,
|
1971
2100
|
locale,
|
@@ -2002,7 +2131,7 @@ const collectionTypes = {
|
|
2002
2131
|
}
|
2003
2132
|
const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
|
2004
2133
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2005
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2134
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2006
2135
|
const document = await documentManager2.findOne(id, model, {
|
2007
2136
|
populate,
|
2008
2137
|
locale,
|
@@ -2033,7 +2162,7 @@ const collectionTypes = {
|
|
2033
2162
|
}
|
2034
2163
|
const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2035
2164
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2036
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2165
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2037
2166
|
const documentLocales = await documentManager2.findLocales(documentIds, model, {
|
2038
2167
|
populate,
|
2039
2168
|
locale
|
@@ -2060,7 +2189,7 @@ const collectionTypes = {
|
|
2060
2189
|
}
|
2061
2190
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
|
2062
2191
|
const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
|
2063
|
-
const { locale, status
|
2192
|
+
const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
|
2064
2193
|
const entity = await documentManager2.findOne(id, model, { populate, locale, status });
|
2065
2194
|
if (!entity) {
|
2066
2195
|
return ctx.notFound();
|
@@ -2083,7 +2212,7 @@ const collectionTypes = {
|
|
2083
2212
|
if (permissionChecker2.cannot.read()) {
|
2084
2213
|
return ctx.forbidden();
|
2085
2214
|
}
|
2086
|
-
const
|
2215
|
+
const documents = await documentManager2.findMany(
|
2087
2216
|
{
|
2088
2217
|
filters: {
|
2089
2218
|
documentId: ids
|
@@ -2092,7 +2221,7 @@ const collectionTypes = {
|
|
2092
2221
|
},
|
2093
2222
|
model
|
2094
2223
|
);
|
2095
|
-
if (!
|
2224
|
+
if (!documents) {
|
2096
2225
|
return ctx.notFound();
|
2097
2226
|
}
|
2098
2227
|
const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
|
@@ -2283,32 +2412,37 @@ const sanitizeMainField = (model, mainField, userAbility) => {
|
|
2283
2412
|
userAbility,
|
2284
2413
|
model: model.uid
|
2285
2414
|
});
|
2286
|
-
|
2415
|
+
const isMainFieldListable = isListable(model, mainField);
|
2416
|
+
const canReadMainField = permissionChecker2.can.read(null, mainField);
|
2417
|
+
if (!isMainFieldListable || !canReadMainField) {
|
2287
2418
|
return "id";
|
2288
2419
|
}
|
2289
|
-
if (
|
2290
|
-
|
2291
|
-
const userPermissionChecker = getService$1("permission-checker").create({
|
2292
|
-
userAbility,
|
2293
|
-
model: "plugin::users-permissions.user"
|
2294
|
-
});
|
2295
|
-
if (userPermissionChecker.can.read()) {
|
2296
|
-
return "name";
|
2297
|
-
}
|
2298
|
-
}
|
2299
|
-
return "id";
|
2420
|
+
if (model.uid === "plugin::users-permissions.role") {
|
2421
|
+
return "name";
|
2300
2422
|
}
|
2301
2423
|
return mainField;
|
2302
2424
|
};
|
2303
|
-
const addStatusToRelations = async (
|
2304
|
-
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.
|
2425
|
+
const addStatusToRelations = async (targetUid, relations2) => {
|
2426
|
+
if (!strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {
|
2305
2427
|
return relations2;
|
2306
2428
|
}
|
2307
2429
|
const documentMetadata2 = getService$1("document-metadata");
|
2308
|
-
|
2430
|
+
if (!relations2.length) {
|
2431
|
+
return relations2;
|
2432
|
+
}
|
2433
|
+
const firstRelation = relations2[0];
|
2434
|
+
const filters = {
|
2435
|
+
documentId: { $in: relations2.map((r) => r.documentId) },
|
2436
|
+
// NOTE: find the "opposite" status
|
2437
|
+
publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true }
|
2438
|
+
};
|
2439
|
+
const availableStatus = await strapi.query(targetUid).findMany({
|
2440
|
+
select: ["id", "documentId", "locale", "updatedAt", "createdAt", "publishedAt"],
|
2441
|
+
filters
|
2442
|
+
});
|
2309
2443
|
return relations2.map((relation) => {
|
2310
|
-
const availableStatuses =
|
2311
|
-
(availableDocument) => availableDocument.documentId === relation.documentId
|
2444
|
+
const availableStatuses = availableStatus.filter(
|
2445
|
+
(availableDocument) => availableDocument.documentId === relation.documentId && (relation.locale ? availableDocument.locale === relation.locale : true)
|
2312
2446
|
);
|
2313
2447
|
return {
|
2314
2448
|
...relation,
|
@@ -2329,11 +2463,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
|
|
2329
2463
|
const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
|
2330
2464
|
const isSourceLocalized = isLocalized(sourceModel);
|
2331
2465
|
const isTargetLocalized = isLocalized(targetModel);
|
2332
|
-
let validatedLocale = locale;
|
2333
|
-
if (!targetModel || !isTargetLocalized)
|
2334
|
-
validatedLocale = void 0;
|
2335
2466
|
return {
|
2336
|
-
locale
|
2467
|
+
locale,
|
2337
2468
|
isSourceLocalized,
|
2338
2469
|
isTargetLocalized
|
2339
2470
|
};
|
@@ -2436,7 +2567,7 @@ const relations = {
|
|
2436
2567
|
attribute,
|
2437
2568
|
fieldsToSelect,
|
2438
2569
|
mainField,
|
2439
|
-
source: { schema: sourceSchema },
|
2570
|
+
source: { schema: sourceSchema, isLocalized: isSourceLocalized },
|
2440
2571
|
target: { schema: targetSchema, isLocalized: isTargetLocalized },
|
2441
2572
|
sourceSchema,
|
2442
2573
|
targetSchema,
|
@@ -2458,7 +2589,8 @@ const relations = {
|
|
2458
2589
|
fieldsToSelect,
|
2459
2590
|
mainField,
|
2460
2591
|
source: {
|
2461
|
-
schema: { uid: sourceUid, modelType: sourceModelType }
|
2592
|
+
schema: { uid: sourceUid, modelType: sourceModelType },
|
2593
|
+
isLocalized: isSourceLocalized
|
2462
2594
|
},
|
2463
2595
|
target: {
|
2464
2596
|
schema: { uid: targetUid },
|
@@ -2496,12 +2628,16 @@ const relations = {
|
|
2496
2628
|
} else {
|
2497
2629
|
where.id = id;
|
2498
2630
|
}
|
2499
|
-
|
2500
|
-
|
2631
|
+
const publishedAt = getPublishedAtClause(status, targetUid);
|
2632
|
+
if (!fp.isEmpty(publishedAt)) {
|
2633
|
+
where[`${alias}.published_at`] = publishedAt;
|
2501
2634
|
}
|
2502
|
-
if (
|
2635
|
+
if (isTargetLocalized && locale) {
|
2503
2636
|
where[`${alias}.locale`] = locale;
|
2504
2637
|
}
|
2638
|
+
if (isSourceLocalized && locale) {
|
2639
|
+
where.locale = locale;
|
2640
|
+
}
|
2505
2641
|
if ((idsToInclude?.length ?? 0) !== 0) {
|
2506
2642
|
where[`${alias}.id`].$notIn = idsToInclude;
|
2507
2643
|
}
|
@@ -2519,7 +2655,8 @@ const relations = {
|
|
2519
2655
|
id: { $notIn: fp.uniq(idsToOmit) }
|
2520
2656
|
});
|
2521
2657
|
}
|
2522
|
-
const
|
2658
|
+
const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
|
2659
|
+
const res = await strapi.db.query(targetUid).findPage(dbQuery);
|
2523
2660
|
ctx.body = {
|
2524
2661
|
...res,
|
2525
2662
|
results: await addStatusToRelations(targetUid, res.results)
|
@@ -2534,29 +2671,39 @@ const relations = {
|
|
2534
2671
|
attribute,
|
2535
2672
|
targetField,
|
2536
2673
|
fieldsToSelect,
|
2537
|
-
|
2538
|
-
|
2539
|
-
}
|
2540
|
-
target: {
|
2541
|
-
schema: { uid: targetUid }
|
2542
|
-
}
|
2674
|
+
status,
|
2675
|
+
source: { schema: sourceSchema },
|
2676
|
+
target: { schema: targetSchema }
|
2543
2677
|
} = await this.extractAndValidateRequestInfo(ctx, id);
|
2678
|
+
const { uid: sourceUid } = sourceSchema;
|
2679
|
+
const { uid: targetUid } = targetSchema;
|
2544
2680
|
const permissionQuery = await getService$1("permission-checker").create({ userAbility, model: targetUid }).sanitizedQuery.read({ fields: fieldsToSelect });
|
2545
2681
|
const dbQuery = strapi.db.query(sourceUid);
|
2546
2682
|
const loadRelations = strapiUtils.relations.isAnyToMany(attribute) ? (...args) => dbQuery.loadPages(...args) : (...args) => dbQuery.load(...args).then((res2) => ({ results: res2 ? [res2] : [] }));
|
2683
|
+
const filters = {};
|
2684
|
+
if (sourceSchema?.options?.draftAndPublish) {
|
2685
|
+
if (targetSchema?.options?.draftAndPublish) {
|
2686
|
+
if (status === "published") {
|
2687
|
+
filters.publishedAt = { $notNull: true };
|
2688
|
+
} else {
|
2689
|
+
filters.publishedAt = { $null: true };
|
2690
|
+
}
|
2691
|
+
}
|
2692
|
+
} else if (targetSchema?.options?.draftAndPublish) {
|
2693
|
+
filters.publishedAt = { $null: true };
|
2694
|
+
}
|
2547
2695
|
const res = await loadRelations({ id: entryId }, targetField, {
|
2548
|
-
select: ["id", "documentId", "locale", "publishedAt"],
|
2696
|
+
select: ["id", "documentId", "locale", "publishedAt", "updatedAt"],
|
2549
2697
|
ordering: "desc",
|
2550
2698
|
page: ctx.request.query.page,
|
2551
|
-
pageSize: ctx.request.query.pageSize
|
2699
|
+
pageSize: ctx.request.query.pageSize,
|
2700
|
+
filters
|
2552
2701
|
});
|
2553
2702
|
const loadedIds = res.results.map((item) => item.id);
|
2554
2703
|
addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
|
2555
2704
|
const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
|
2556
2705
|
...strapi.get("query-params").transform(targetUid, permissionQuery),
|
2557
|
-
ordering: "desc"
|
2558
|
-
page: ctx.request.query.page,
|
2559
|
-
pageSize: ctx.request.query.pageSize
|
2706
|
+
ordering: "desc"
|
2560
2707
|
});
|
2561
2708
|
const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
|
2562
2709
|
ctx.body = {
|
@@ -2588,7 +2735,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
|
|
2588
2735
|
throw new strapiUtils.errors.ForbiddenError();
|
2589
2736
|
}
|
2590
2737
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
|
2591
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2738
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2592
2739
|
const [documentVersion, otherDocumentVersion] = await Promise.all([
|
2593
2740
|
findDocument(sanitizedQuery, model, { locale, status: "draft" }),
|
2594
2741
|
// Find the first document to check if it exists
|
@@ -2629,7 +2776,7 @@ const singleTypes = {
|
|
2629
2776
|
return ctx.forbidden();
|
2630
2777
|
}
|
2631
2778
|
const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
|
2632
|
-
const { locale, status } = await getDocumentLocaleAndStatus(query);
|
2779
|
+
const { locale, status } = await getDocumentLocaleAndStatus(query, model);
|
2633
2780
|
const version = await findDocument(permissionQuery, model, { locale, status });
|
2634
2781
|
if (!version) {
|
2635
2782
|
if (permissionChecker2.cannot.create()) {
|
@@ -2643,7 +2790,7 @@ const singleTypes = {
|
|
2643
2790
|
permissionChecker2,
|
2644
2791
|
model,
|
2645
2792
|
// @ts-expect-error - fix types
|
2646
|
-
{
|
2793
|
+
{ documentId: document.documentId, locale, publishedAt: null },
|
2647
2794
|
{ availableLocales: true, availableStatus: false }
|
2648
2795
|
);
|
2649
2796
|
ctx.body = { data: {}, meta };
|
@@ -2674,7 +2821,7 @@ const singleTypes = {
|
|
2674
2821
|
}
|
2675
2822
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
|
2676
2823
|
const populate = await buildPopulateFromQuery(sanitizedQuery, model);
|
2677
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2824
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2678
2825
|
const documentLocales = await documentManager2.findLocales(void 0, model, {
|
2679
2826
|
populate,
|
2680
2827
|
locale
|
@@ -2711,7 +2858,7 @@ const singleTypes = {
|
|
2711
2858
|
if (permissionChecker2.cannot.publish(document)) {
|
2712
2859
|
throw new strapiUtils.errors.ForbiddenError();
|
2713
2860
|
}
|
2714
|
-
const { locale } = await getDocumentLocaleAndStatus(document);
|
2861
|
+
const { locale } = await getDocumentLocaleAndStatus(document, model);
|
2715
2862
|
const publishResult = await documentManager2.publish(document.documentId, model, { locale });
|
2716
2863
|
return publishResult.at(0);
|
2717
2864
|
});
|
@@ -2734,7 +2881,7 @@ const singleTypes = {
|
|
2734
2881
|
return ctx.forbidden();
|
2735
2882
|
}
|
2736
2883
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
|
2737
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2884
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2738
2885
|
const document = await findDocument(sanitizedQuery, model, { locale });
|
2739
2886
|
if (!document) {
|
2740
2887
|
return ctx.notFound();
|
@@ -2766,7 +2913,7 @@ const singleTypes = {
|
|
2766
2913
|
return ctx.forbidden();
|
2767
2914
|
}
|
2768
2915
|
const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
|
2769
|
-
const { locale } = await getDocumentLocaleAndStatus(body);
|
2916
|
+
const { locale } = await getDocumentLocaleAndStatus(body, model);
|
2770
2917
|
const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
|
2771
2918
|
if (!document) {
|
2772
2919
|
return ctx.notFound();
|
@@ -2786,7 +2933,7 @@ const singleTypes = {
|
|
2786
2933
|
const { query } = ctx.request;
|
2787
2934
|
const documentManager2 = getService$1("document-manager");
|
2788
2935
|
const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
|
2789
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2936
|
+
const { locale } = await getDocumentLocaleAndStatus(query, model);
|
2790
2937
|
if (permissionChecker2.cannot.read()) {
|
2791
2938
|
return ctx.forbidden();
|
2792
2939
|
}
|
@@ -2807,7 +2954,7 @@ const uid$1 = {
|
|
2807
2954
|
async generateUID(ctx) {
|
2808
2955
|
const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
|
2809
2956
|
const { query = {} } = ctx.request;
|
2810
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2957
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2811
2958
|
await validateUIDField(contentTypeUID, field);
|
2812
2959
|
const uidService = getService$1("uid");
|
2813
2960
|
ctx.body = {
|
@@ -2819,7 +2966,7 @@ const uid$1 = {
|
|
2819
2966
|
ctx.request.body
|
2820
2967
|
);
|
2821
2968
|
const { query = {} } = ctx.request;
|
2822
|
-
const { locale } = await getDocumentLocaleAndStatus(query);
|
2969
|
+
const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
|
2823
2970
|
await validateUIDField(contentTypeUID, field);
|
2824
2971
|
const uidService = getService$1("uid");
|
2825
2972
|
const isAvailable = await uidService.checkUIDAvailability({
|
@@ -2842,7 +2989,8 @@ const controllers = {
|
|
2842
2989
|
relations,
|
2843
2990
|
"single-types": singleTypes,
|
2844
2991
|
uid: uid$1,
|
2845
|
-
...history.controllers ? history.controllers : {}
|
2992
|
+
...history.controllers ? history.controllers : {},
|
2993
|
+
...preview.controllers ? preview.controllers : {}
|
2846
2994
|
};
|
2847
2995
|
const keys = {
|
2848
2996
|
CONFIGURATION: "configuration"
|
@@ -3462,12 +3610,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
|
|
3462
3610
|
ability: userAbility,
|
3463
3611
|
model
|
3464
3612
|
});
|
3465
|
-
const
|
3613
|
+
const { actionProvider } = strapi2.service("admin::permission");
|
3614
|
+
const toSubject = (entity) => {
|
3615
|
+
return entity ? permissionsManager.toSubject(entity, model) : model;
|
3616
|
+
};
|
3466
3617
|
const can = (action, entity, field) => {
|
3467
|
-
|
3618
|
+
const subject = toSubject(entity);
|
3619
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3620
|
+
return (
|
3621
|
+
// Test the original action to see if it passes
|
3622
|
+
userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
|
3623
|
+
aliases.some((alias) => userAbility.can(alias, subject, field))
|
3624
|
+
);
|
3468
3625
|
};
|
3469
3626
|
const cannot = (action, entity, field) => {
|
3470
|
-
|
3627
|
+
const subject = toSubject(entity);
|
3628
|
+
const aliases = actionProvider.unstable_aliases(action, model);
|
3629
|
+
return (
|
3630
|
+
// Test both the original action
|
3631
|
+
userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
|
3632
|
+
aliases.every((alias) => userAbility.cannot(alias, subject, field))
|
3633
|
+
);
|
3471
3634
|
};
|
3472
3635
|
const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
|
3473
3636
|
return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
|
@@ -3744,6 +3907,10 @@ const getDeepPopulateDraftCount = (uid2) => {
|
|
3744
3907
|
const attribute = model.attributes[attributeName];
|
3745
3908
|
switch (attribute.type) {
|
3746
3909
|
case "relation": {
|
3910
|
+
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
3911
|
+
if (isMorphRelation) {
|
3912
|
+
break;
|
3913
|
+
}
|
3747
3914
|
if (isVisibleAttribute$1(model, attributeName)) {
|
3748
3915
|
populateAcc[attributeName] = {
|
3749
3916
|
count: true,
|
@@ -3995,7 +4162,9 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
3995
4162
|
*/
|
3996
4163
|
async getAvailableLocales(uid2, version, allVersions, validatableFields = []) {
|
3997
4164
|
const versionsByLocale = fp.groupBy("locale", allVersions);
|
3998
|
-
|
4165
|
+
if (version.locale) {
|
4166
|
+
delete versionsByLocale[version.locale];
|
4167
|
+
}
|
3999
4168
|
const model = strapi2.getModel(uid2);
|
4000
4169
|
const keysToKeep = [...AVAILABLE_LOCALES_FIELDS, ...validatableFields];
|
4001
4170
|
const traversalFunction = async (localeVersion) => strapiUtils.traverseEntity(
|
@@ -4121,7 +4290,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
|
|
4121
4290
|
*/
|
4122
4291
|
async formatDocumentWithMetadata(uid2, document, opts = {}) {
|
4123
4292
|
if (!document) {
|
4124
|
-
return
|
4293
|
+
return {
|
4294
|
+
data: document,
|
4295
|
+
meta: {
|
4296
|
+
availableLocales: [],
|
4297
|
+
availableStatus: []
|
4298
|
+
}
|
4299
|
+
};
|
4125
4300
|
}
|
4126
4301
|
const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
|
4127
4302
|
if (!hasDraftAndPublish) {
|
@@ -4229,10 +4404,7 @@ const documentManager = ({ strapi: strapi2 }) => {
|
|
4229
4404
|
async clone(id, body, uid2) {
|
4230
4405
|
const populate = await buildDeepPopulate(uid2);
|
4231
4406
|
const params = {
|
4232
|
-
data:
|
4233
|
-
...omitIdField(body),
|
4234
|
-
[PUBLISHED_AT_ATTRIBUTE]: null
|
4235
|
-
},
|
4407
|
+
data: omitIdField(body),
|
4236
4408
|
populate
|
4237
4409
|
};
|
4238
4410
|
return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));
|
@@ -4348,7 +4520,8 @@ const services = {
|
|
4348
4520
|
permission,
|
4349
4521
|
"populate-builder": populateBuilder$1,
|
4350
4522
|
uid,
|
4351
|
-
...history.services ? history.services : {}
|
4523
|
+
...history.services ? history.services : {},
|
4524
|
+
...preview.services ? preview.services : {}
|
4352
4525
|
};
|
4353
4526
|
const index = () => {
|
4354
4527
|
return {
|