@micelio/strapi-plugin-core 0.1.0 → 0.2.0
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/README.md +5 -3
- package/dist/admin/MicelioLayout-Bmu5xCw9.js +1023 -0
- package/dist/admin/MicelioLayout-DMMsKnMo.mjs +1021 -0
- package/dist/admin/PreviewHeaderAction-BaduMvYy.mjs +61 -0
- package/dist/admin/PreviewHeaderAction-CGHycv4I.js +61 -0
- package/dist/admin/{en-D-T8z3qh.js → en-BDVuq0fN.js} +37 -1
- package/dist/admin/{en-C2O-S2ym.mjs → en-Bahc6y6N.mjs} +37 -1
- package/dist/admin/{es-RV0vkOHh.js → es-DStBGkm7.js} +37 -1
- package/dist/admin/{es-CQ2tv9N8.mjs → es-nUHBIoZG.mjs} +37 -1
- package/dist/admin/{index-D3TGbaQ7.js → index-D_Dbvo2F.js} +8 -2
- package/dist/admin/{index-CiSujTES.mjs → index-Dwr15ZsB.mjs} +8 -2
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/permissions-BAI0qDr9.js +24 -0
- package/dist/admin/permissions-CYirM30e.mjs +25 -0
- package/dist/admin/src/components/EyeIcon.d.ts +8 -0
- package/dist/admin/src/components/PreviewFrame.d.ts +47 -0
- package/dist/admin/src/components/PreviewHeaderAction.d.ts +28 -0
- package/dist/admin/src/hooks/useEntry.d.ts +31 -0
- package/dist/admin/src/hooks/usePreviewSource.d.ts +31 -0
- package/dist/admin/src/pages/MicelioLayout.d.ts +2 -1
- package/dist/admin/src/pages/PreviewPage.d.ts +2 -0
- package/dist/admin/src/permissions.d.ts +5 -0
- package/dist/admin/src/translations/en.json.d.ts +37 -1
- package/dist/admin/src/utils/fetchError.d.ts +2 -0
- package/dist/admin/src/utils/previewAction.d.ts +22 -0
- package/dist/admin/src/utils/previewPane.d.ts +59 -0
- package/dist/server/index.js +796 -105
- package/dist/server/index.mjs +796 -105
- package/dist/server/src/constants/preview.d.ts +2 -0
- package/dist/server/src/constants/taxonomy.d.ts +13 -0
- package/dist/server/src/content-types/category/schema.json.d.ts +78 -0
- package/dist/server/src/content-types/index.d.ts +125 -2
- package/dist/server/src/content-types/preview-credential/schema.json.d.ts +7 -6
- package/dist/server/src/content-types/tag/schema.json.d.ts +46 -0
- package/dist/server/src/controllers/index.d.ts +6 -0
- package/dist/server/src/editorial/transitions.d.ts +5 -2
- package/dist/server/src/index.d.ts +140 -2
- package/dist/server/src/migrations/rename-legacy-uids.d.ts +26 -0
- package/dist/server/src/migrations/site-backfill.d.ts +13 -0
- package/dist/server/src/preview/credentials.d.ts +7 -5
- package/dist/server/src/preview/draft-query.d.ts +62 -0
- package/dist/server/src/preview/revocation.d.ts +9 -1
- package/dist/server/src/preview/shortcut.d.ts +24 -0
- package/dist/server/src/routes/index.d.ts +2 -0
- package/dist/server/src/routes/taxonomy.d.ts +12 -0
- package/dist/server/src/services/index.d.ts +6 -0
- package/dist/server/src/services/preview.d.ts +25 -6
- package/dist/server/src/site-scope/documents.d.ts +13 -3
- package/dist/server/src/types/hooks.d.ts +5 -4
- package/dist/server/src/types/preview.d.ts +35 -10
- package/package.json +4 -3
- package/dist/admin/MicelioLayout-3sKGPS_0.mjs +0 -443
- package/dist/admin/MicelioLayout-DXzRS4l3.js +0 -443
package/dist/server/index.js
CHANGED
|
@@ -4,9 +4,9 @@ const zod = require("zod");
|
|
|
4
4
|
const node_async_hooks = require("node:async_hooks");
|
|
5
5
|
const node_crypto = require("node:crypto");
|
|
6
6
|
const strapi = require("@strapi/strapi");
|
|
7
|
+
const utils = require("@strapi/utils");
|
|
7
8
|
const node_module = require("node:module");
|
|
8
9
|
const path = require("node:path");
|
|
9
|
-
const utils = require("@strapi/utils");
|
|
10
10
|
const node_stream = require("node:stream");
|
|
11
11
|
const promises = require("node:stream/promises");
|
|
12
12
|
const node_zlib = require("node:zlib");
|
|
@@ -17,7 +17,7 @@ const node_events = require("node:events");
|
|
|
17
17
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
18
18
|
const path__default = /* @__PURE__ */ _interopDefault(path);
|
|
19
19
|
const os__default = /* @__PURE__ */ _interopDefault(os);
|
|
20
|
-
const SITE_UID = "plugin::micelio.site";
|
|
20
|
+
const SITE_UID$1 = "plugin::micelio.site";
|
|
21
21
|
const SITE_COMPONENT_CATEGORY = "micelio-site";
|
|
22
22
|
const DEFAULT_SITE_SLUG = "default";
|
|
23
23
|
const LOCALISED_LOCALES = ["en", "es"];
|
|
@@ -118,7 +118,7 @@ function parseExportSection(value) {
|
|
|
118
118
|
function missingLocales(value) {
|
|
119
119
|
return LOCALISED_LOCALES.filter((locale) => !value[locale]?.trim());
|
|
120
120
|
}
|
|
121
|
-
const attributeOf = (id2) => `${SITE_SECTION_ATTRIBUTE_PREFIX}${id2.replace(/-/g, "_")}`;
|
|
121
|
+
const attributeOf$1 = (id2) => `${SITE_SECTION_ATTRIBUTE_PREFIX}${id2.replace(/-/g, "_")}`;
|
|
122
122
|
function createExtensionRegistry(strapi2) {
|
|
123
123
|
const pages = [];
|
|
124
124
|
const sections = [];
|
|
@@ -155,8 +155,8 @@ function createExtensionRegistry(strapi2) {
|
|
|
155
155
|
"micelio: registerSiteSection: call it in `register`, before the models are built"
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
|
-
const attribute = attributeOf(section.id);
|
|
159
|
-
strapi2.get("content-types").extend(SITE_UID, (contentType) => {
|
|
158
|
+
const attribute = attributeOf$1(section.id);
|
|
159
|
+
strapi2.get("content-types").extend(SITE_UID$1, (contentType) => {
|
|
160
160
|
Object.assign(contentType.attributes, {
|
|
161
161
|
[attribute]: {
|
|
162
162
|
type: "component",
|
|
@@ -185,7 +185,7 @@ function createExtensionRegistry(strapi2) {
|
|
|
185
185
|
siteSections: () => [...sections],
|
|
186
186
|
statusChecks: () => [...checks],
|
|
187
187
|
exportSections: () => [...exports2],
|
|
188
|
-
siteSectionAttribute: attributeOf,
|
|
188
|
+
siteSectionAttribute: attributeOf$1,
|
|
189
189
|
async runStatusChecks(sites) {
|
|
190
190
|
for (const registration of checks) {
|
|
191
191
|
const found = [];
|
|
@@ -209,12 +209,12 @@ function createExtensionRegistry(strapi2) {
|
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
211
|
function hasDatabaseModels(strapi2) {
|
|
212
|
-
return strapi2.db.metadata.has(SITE_UID);
|
|
212
|
+
return strapi2.db.metadata.has(SITE_UID$1);
|
|
213
213
|
}
|
|
214
214
|
function extensionsOf(strapi2) {
|
|
215
215
|
return strapi2.plugin("micelio").service("extensions");
|
|
216
216
|
}
|
|
217
|
-
const SITE$1 = SITE_UID;
|
|
217
|
+
const SITE$1 = SITE_UID$1;
|
|
218
218
|
function siteSectionInstances(strapi2) {
|
|
219
219
|
return async (context, next) => {
|
|
220
220
|
if (context.uid === SITE$1 && context.action === "create") {
|
|
@@ -347,7 +347,7 @@ function deepFreeze(value) {
|
|
|
347
347
|
}
|
|
348
348
|
return value;
|
|
349
349
|
}
|
|
350
|
-
const SITE_ATTRIBUTE = "site";
|
|
350
|
+
const SITE_ATTRIBUTE$1 = "site";
|
|
351
351
|
const SITE_SCOPE_MIDDLEWARE = "plugin::micelio.site-scope";
|
|
352
352
|
function withSiteScope(schema) {
|
|
353
353
|
return {
|
|
@@ -358,10 +358,10 @@ function withSiteScope(schema) {
|
|
|
358
358
|
},
|
|
359
359
|
attributes: {
|
|
360
360
|
...schema.attributes,
|
|
361
|
-
[SITE_ATTRIBUTE]: {
|
|
361
|
+
[SITE_ATTRIBUTE$1]: {
|
|
362
362
|
type: "relation",
|
|
363
363
|
relation: "manyToOne",
|
|
364
|
-
target: SITE_UID,
|
|
364
|
+
target: SITE_UID$1,
|
|
365
365
|
required: true,
|
|
366
366
|
pluginOptions: { i18n: { localized: false } }
|
|
367
367
|
}
|
|
@@ -386,7 +386,8 @@ const TRANSITIONS = [
|
|
|
386
386
|
{ from: "draft", to: "scheduled" },
|
|
387
387
|
{ from: "scheduled", to: "draft" },
|
|
388
388
|
{ from: "scheduled", to: "published" },
|
|
389
|
-
{ from: "published", to: "draft" }
|
|
389
|
+
{ from: "published", to: "draft" },
|
|
390
|
+
{ from: "published", to: "published" }
|
|
390
391
|
];
|
|
391
392
|
const SYSTEM_TRANSITIONS = /* @__PURE__ */ new Set(["scheduled->published"]);
|
|
392
393
|
const SUPER_ADMIN = "strapi-super-admin";
|
|
@@ -398,7 +399,8 @@ const DEFAULT_EDITORIAL_POLICY = {
|
|
|
398
399
|
"in_review->published": [EDITOR, SUPER_ADMIN],
|
|
399
400
|
"draft->scheduled": [EDITOR, SUPER_ADMIN],
|
|
400
401
|
"scheduled->draft": [EDITOR, SUPER_ADMIN],
|
|
401
|
-
"published->draft": [EDITOR, SUPER_ADMIN]
|
|
402
|
+
"published->draft": [EDITOR, SUPER_ADMIN],
|
|
403
|
+
"published->published": [EDITOR, SUPER_ADMIN]
|
|
402
404
|
};
|
|
403
405
|
function transitionKey({ from, to }) {
|
|
404
406
|
return `${from}->${to}`;
|
|
@@ -454,7 +456,7 @@ async function performTransition(strapi2, request) {
|
|
|
454
456
|
status: "draft",
|
|
455
457
|
populate: {
|
|
456
458
|
[EDITORIAL_ATTRIBUTE]: { populate: ["reviewedBy", "publishedBy"] },
|
|
457
|
-
[SITE_ATTRIBUTE]: { fields: ["documentId", "editorialPolicy"] },
|
|
459
|
+
[SITE_ATTRIBUTE$1]: { fields: ["documentId", "editorialPolicy"] },
|
|
458
460
|
createdBy: true
|
|
459
461
|
}
|
|
460
462
|
});
|
|
@@ -513,7 +515,9 @@ async function performTransition(strapi2, request) {
|
|
|
513
515
|
throw new TransitionError(409, "editorialTransitionRefused", refusalMessage(error));
|
|
514
516
|
}
|
|
515
517
|
await runAsTransition(async () => {
|
|
516
|
-
if (transition.from === "published"
|
|
518
|
+
if (transition.from === "published" && transition.to !== "published") {
|
|
519
|
+
await documents.unpublish(target);
|
|
520
|
+
}
|
|
517
521
|
await documents.update({ ...target, data: { [EDITORIAL_ATTRIBUTE]: editorial2 } });
|
|
518
522
|
if (transition.to === "published") await documents.publish(target);
|
|
519
523
|
});
|
|
@@ -1040,10 +1044,10 @@ async function storedFingerprint(strapi2) {
|
|
|
1040
1044
|
}
|
|
1041
1045
|
const SITE_LOCALES = ["en", "es"];
|
|
1042
1046
|
async function ensureDefaultSite(strapi2) {
|
|
1043
|
-
if (await strapi2.db.query(SITE_UID).count() > 0) return false;
|
|
1047
|
+
if (await strapi2.db.query(SITE_UID$1).count() > 0) return false;
|
|
1044
1048
|
const locales = strapi2.plugin("i18n").service("locales");
|
|
1045
1049
|
const locale = await locales.getDefaultLocale();
|
|
1046
|
-
await strapi2.documents(SITE_UID).create({
|
|
1050
|
+
await strapi2.documents(SITE_UID$1).create({
|
|
1047
1051
|
locale,
|
|
1048
1052
|
data: {
|
|
1049
1053
|
name: "Micelio",
|
|
@@ -1057,6 +1061,28 @@ async function ensureDefaultSite(strapi2) {
|
|
|
1057
1061
|
});
|
|
1058
1062
|
return true;
|
|
1059
1063
|
}
|
|
1064
|
+
const SITE_UID = "plugin::micelio.site";
|
|
1065
|
+
const SITE_ATTRIBUTE = "site";
|
|
1066
|
+
const BACKFILLED = ["plugin::micelio.category", "plugin::micelio.tag"];
|
|
1067
|
+
async function backfillSite(strapi2) {
|
|
1068
|
+
const site2 = await strapi2.db.query(SITE_UID).findOne({
|
|
1069
|
+
where: { isDefault: true },
|
|
1070
|
+
select: ["id"]
|
|
1071
|
+
});
|
|
1072
|
+
if (!site2) return 0;
|
|
1073
|
+
let linked = 0;
|
|
1074
|
+
for (const uid of BACKFILLED) {
|
|
1075
|
+
const rows = await strapi2.db.query(uid).findMany({
|
|
1076
|
+
where: { [SITE_ATTRIBUTE]: null },
|
|
1077
|
+
select: ["id"]
|
|
1078
|
+
});
|
|
1079
|
+
for (const row of rows) {
|
|
1080
|
+
await strapi2.db.query(uid).update({ where: { id: row.id }, data: { [SITE_ATTRIBUTE]: site2.id } });
|
|
1081
|
+
}
|
|
1082
|
+
linked += rows.length;
|
|
1083
|
+
}
|
|
1084
|
+
return linked;
|
|
1085
|
+
}
|
|
1060
1086
|
async function registerPreviewPermission(strapi2) {
|
|
1061
1087
|
await strapi2.service("admin::permission").actionProvider.registerMany([
|
|
1062
1088
|
{
|
|
@@ -1067,9 +1093,13 @@ async function registerPreviewPermission(strapi2) {
|
|
|
1067
1093
|
}
|
|
1068
1094
|
]);
|
|
1069
1095
|
}
|
|
1096
|
+
const ADMIN_LOGOUT_HANDLER = "authentication.logout";
|
|
1070
1097
|
function registerPreviewRevocation(strapi2) {
|
|
1071
|
-
strapi2.
|
|
1072
|
-
|
|
1098
|
+
strapi2.server.use(async (ctx, next) => {
|
|
1099
|
+
await next();
|
|
1100
|
+
const route = ctx.state.route;
|
|
1101
|
+
if (route?.info?.pluginName !== "admin" || route.handler !== ADMIN_LOGOUT_HANDLER) return;
|
|
1102
|
+
const id2 = ctx.state.user?.id;
|
|
1073
1103
|
if (typeof id2 !== "number") return;
|
|
1074
1104
|
try {
|
|
1075
1105
|
await strapi2.plugin("micelio").service("preview").revoke(id2);
|
|
@@ -1092,6 +1122,9 @@ async function registerStatusPermission(strapi2) {
|
|
|
1092
1122
|
}
|
|
1093
1123
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
1094
1124
|
await ensureDefaultSite(strapi2);
|
|
1125
|
+
const backfilled = await backfillSite(strapi2);
|
|
1126
|
+
if (backfilled > 0)
|
|
1127
|
+
strapi2.log.info(`[micelio] gave the default site to ${backfilled} categories and tags`);
|
|
1095
1128
|
await ensureSiteSections(strapi2);
|
|
1096
1129
|
await strapi2.plugin("micelio").service("hostCheck").enforce();
|
|
1097
1130
|
registerScheduler(strapi2);
|
|
@@ -1105,7 +1138,7 @@ const DEFAULT_CONFIG = {
|
|
|
1105
1138
|
scheduledPublishRule: "* * * * *",
|
|
1106
1139
|
statusRefreshRule: "0 4 * * *"
|
|
1107
1140
|
};
|
|
1108
|
-
const config = {
|
|
1141
|
+
const config$1 = {
|
|
1109
1142
|
default: DEFAULT_CONFIG,
|
|
1110
1143
|
validator(config2) {
|
|
1111
1144
|
for (const key of ["scheduledPublishRule", "statusRefreshRule"]) {
|
|
@@ -1116,13 +1149,41 @@ const config = {
|
|
|
1116
1149
|
}
|
|
1117
1150
|
}
|
|
1118
1151
|
};
|
|
1152
|
+
const kind$3 = "collectionType";
|
|
1153
|
+
const collectionName$a = "categories";
|
|
1154
|
+
const info$a = { "singularName": "category", "pluralName": "categories", "displayName": "Category", "description": "Organize your content into categories" };
|
|
1155
|
+
const options$a = { "draftAndPublish": false };
|
|
1156
|
+
const pluginOptions$3 = { "content-manager": { "visible": true }, "i18n": { "localized": true } };
|
|
1157
|
+
const attributes$a = { "name": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "uid", "regex": "^(?!\\.{1,2}$)[A-Za-z0-9-_.~]*$", "pluginOptions": { "i18n": { "localized": false } } }, "description": { "type": "text", "pluginOptions": { "i18n": { "localized": true } } }, "order": { "type": "integer", "pluginOptions": { "i18n": { "localized": false } } }, "featured": { "type": "boolean", "default": false, "pluginOptions": { "i18n": { "localized": false } } }, "color": { "type": "integer", "min": 1, "max": 5, "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1158
|
+
const category = {
|
|
1159
|
+
kind: kind$3,
|
|
1160
|
+
collectionName: collectionName$a,
|
|
1161
|
+
info: info$a,
|
|
1162
|
+
options: options$a,
|
|
1163
|
+
pluginOptions: pluginOptions$3,
|
|
1164
|
+
attributes: attributes$a
|
|
1165
|
+
};
|
|
1166
|
+
const kind$2 = "collectionType";
|
|
1167
|
+
const collectionName$9 = "micelio_preview_credentials";
|
|
1168
|
+
const info$9 = { "singularName": "preview-credential", "pluralName": "preview-credentials", "displayName": "Preview credential", "description": "A preview token, grant or system grant of ADR-0019, stored as the hash of its value and bound to one draft (and, but for a system grant, to one admin user)" };
|
|
1169
|
+
const options$9 = { "draftAndPublish": false };
|
|
1170
|
+
const pluginOptions$2 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false }, "i18n": { "localized": false }, "micelio": { "export": "never" } };
|
|
1171
|
+
const attributes$9 = { "kind": { "type": "enumeration", "enum": ["token", "grant", "system"], "required": true }, "hash": { "type": "string", "required": true, "unique": true, "private": true }, "adminUser": { "type": "integer" }, "adminOrigin": { "type": "string" }, "entryVersion": { "type": "string" }, "siteDocumentId": { "type": "string", "required": true }, "contentType": { "type": "string", "required": true }, "entryDocumentId": { "type": "string", "required": true }, "entryLocale": { "type": "string" }, "expiresAt": { "type": "datetime", "required": true }, "usedAt": { "type": "datetime" }, "revokedAt": { "type": "datetime" } };
|
|
1172
|
+
const previewCredential = {
|
|
1173
|
+
kind: kind$2,
|
|
1174
|
+
collectionName: collectionName$9,
|
|
1175
|
+
info: info$9,
|
|
1176
|
+
options: options$9,
|
|
1177
|
+
pluginOptions: pluginOptions$2,
|
|
1178
|
+
attributes: attributes$9
|
|
1179
|
+
};
|
|
1119
1180
|
const kind$1 = "collectionType";
|
|
1120
|
-
const collectionName$8 = "
|
|
1121
|
-
const info$8 = { "singularName": "
|
|
1181
|
+
const collectionName$8 = "micelio_sites";
|
|
1182
|
+
const info$8 = { "singularName": "site", "pluralName": "sites", "displayName": "Site", "description": "One site the CMS serves: its identity, its host names and the modules the frontend turns on" };
|
|
1122
1183
|
const options$8 = { "draftAndPublish": false };
|
|
1123
|
-
const pluginOptions$1 = { "content-manager": { "visible":
|
|
1124
|
-
const attributes$8 = { "
|
|
1125
|
-
const
|
|
1184
|
+
const pluginOptions$1 = { "content-manager": { "visible": true }, "content-type-builder": { "visible": false }, "i18n": { "localized": true } };
|
|
1185
|
+
const attributes$8 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "string", "regex": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "maxLength": 64, "required": true, "unique": true, "pluginOptions": { "i18n": { "localized": false } } }, "hosts": { "type": "json", "pluginOptions": { "i18n": { "localized": false } } }, "isDefault": { "type": "boolean", "default": false, "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "editorialPolicy": { "type": "json", "pluginOptions": { "i18n": { "localized": false } } }, "description": { "type": "text", "pluginOptions": { "i18n": { "localized": true } } }, "tagline": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "url": { "type": "string", "regex": "^https?://\\S+$", "pluginOptions": { "i18n": { "localized": false } } }, "defaultLocale": { "type": "enumeration", "enum": ["en", "es"], "default": "en", "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "author": { "type": "component", "repeatable": false, "component": "micelio-site.author", "pluginOptions": { "i18n": { "localized": false } } }, "logo": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "favicon": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "defaultOgImage": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "socialLinks": { "type": "component", "repeatable": true, "component": "micelio-site.social-link", "pluginOptions": { "i18n": { "localized": false } } }, "contactEmail": { "type": "email", "pluginOptions": { "i18n": { "localized": false } } }, "privacyContactEmail": { "type": "email", "pluginOptions": { "i18n": { "localized": false } } }, "securityContact": { "type": "string", "maxLength": 512, "pluginOptions": { "i18n": { "localized": false } } }, "privacyJurisdiction": { "type": "enumeration", "enum": ["colombia"], "pluginOptions": { "i18n": { "localized": false } } }, "privacyUpdatedAt": { "type": "datetime", "pluginOptions": { "i18n": { "localized": false } } }, "supportHandle": { "type": "string", "regex": "^[A-Za-z0-9_-]+$", "pluginOptions": { "i18n": { "localized": false } } }, "timezone": { "type": "string", "regex": "^[A-Za-z][A-Za-z0-9]*(?:[/_+-][A-Za-z0-9]+)*$", "pluginOptions": { "i18n": { "localized": false } } }, "addressLocality": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "modules": { "type": "component", "repeatable": false, "component": "micelio-site.modules", "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "theme": { "type": "component", "repeatable": false, "component": "micelio-site.theme", "pluginOptions": { "i18n": { "localized": false } } }, "fediverse": { "type": "component", "repeatable": false, "component": "micelio-site.fediverse", "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1186
|
+
const site = {
|
|
1126
1187
|
kind: kind$1,
|
|
1127
1188
|
collectionName: collectionName$8,
|
|
1128
1189
|
info: info$8,
|
|
@@ -1131,12 +1192,12 @@ const previewCredential = {
|
|
|
1131
1192
|
attributes: attributes$8
|
|
1132
1193
|
};
|
|
1133
1194
|
const kind = "collectionType";
|
|
1134
|
-
const collectionName$7 = "
|
|
1135
|
-
const info$7 = { "singularName": "
|
|
1195
|
+
const collectionName$7 = "tags";
|
|
1196
|
+
const info$7 = { "singularName": "tag", "pluralName": "tags", "displayName": "Tag", "description": "Topics an article covers, used to filter the blog" };
|
|
1136
1197
|
const options$7 = { "draftAndPublish": false };
|
|
1137
|
-
const pluginOptions = { "content-manager": { "visible": true }, "
|
|
1138
|
-
const attributes$7 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "
|
|
1139
|
-
const
|
|
1198
|
+
const pluginOptions = { "content-manager": { "visible": true }, "i18n": { "localized": true } };
|
|
1199
|
+
const attributes$7 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "uid", "regex": "^(?!\\.{1,2}$)[A-Za-z0-9-_.~]*$", "targetField": "name", "required": true, "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1200
|
+
const tag = {
|
|
1140
1201
|
kind,
|
|
1141
1202
|
collectionName: collectionName$7,
|
|
1142
1203
|
info: info$7,
|
|
@@ -1146,8 +1207,13 @@ const site = {
|
|
|
1146
1207
|
};
|
|
1147
1208
|
const contentTypes = {
|
|
1148
1209
|
site: { schema: site },
|
|
1210
|
+
category: { schema: withSiteScope(category) },
|
|
1211
|
+
tag: { schema: withSiteScope(tag) },
|
|
1149
1212
|
"preview-credential": { schema: withSiteScope(previewCredential) }
|
|
1150
1213
|
};
|
|
1214
|
+
const CATEGORY_UID = "plugin::micelio.category";
|
|
1215
|
+
const TAG_UID = "plugin::micelio.tag";
|
|
1216
|
+
const READ_ACTIONS$1 = [`${CATEGORY_UID}.find`, `${TAG_UID}.find`];
|
|
1151
1217
|
const blocks = () => ({
|
|
1152
1218
|
find(ctx) {
|
|
1153
1219
|
ctx.body = {
|
|
@@ -1165,18 +1231,19 @@ const PREVIEW_PATH = "/_preview";
|
|
|
1165
1231
|
const PREVIEW_GRANT_HEADER = "x-micelio-preview-grant";
|
|
1166
1232
|
const PREVIEW_TOKEN_TTL_SECONDS = 60;
|
|
1167
1233
|
const PREVIEW_GRANT_TTL_SECONDS = 15 * 60;
|
|
1234
|
+
const PREVIEW_SYSTEM_GRANT_TTL_SECONDS = 60;
|
|
1168
1235
|
const PREVIEW_CREDENTIAL_RETENTION_SECONDS = 60 * 60;
|
|
1169
1236
|
const PREVIEW_RATE_WINDOW_SECONDS = 60;
|
|
1170
1237
|
const PREVIEW_TOKEN_RATE_LIMIT = 20;
|
|
1171
1238
|
const PREVIEW_EXCHANGE_RATE_LIMIT = 60;
|
|
1172
1239
|
async function readableDraft(strapi2, userAbility, contentType, documentId, locale) {
|
|
1173
1240
|
const uid = contentType;
|
|
1174
|
-
if (!strapi2.contentType(uid)?.attributes?.[SITE_ATTRIBUTE]) return { status: "not-site-scoped" };
|
|
1241
|
+
if (!strapi2.contentType(uid)?.attributes?.[SITE_ATTRIBUTE$1]) return { status: "not-site-scoped" };
|
|
1175
1242
|
const entry = await strapi2.documents(uid).findOne({
|
|
1176
1243
|
documentId,
|
|
1177
1244
|
locale: locale ?? void 0,
|
|
1178
1245
|
status: "draft",
|
|
1179
|
-
populate: { [SITE_ATTRIBUTE]: { fields: ["documentId"] }, createdBy: true }
|
|
1246
|
+
populate: { [SITE_ATTRIBUTE$1]: { fields: ["documentId"] }, createdBy: true }
|
|
1180
1247
|
});
|
|
1181
1248
|
if (!entry?.site) return { status: "missing" };
|
|
1182
1249
|
const checker = strapi2.plugin("content-manager").service("permission-checker").create({ userAbility, model: contentType });
|
|
@@ -1191,9 +1258,338 @@ async function abilityOf(strapi2, adminUser) {
|
|
|
1191
1258
|
if (!user || user.isActive === false) return null;
|
|
1192
1259
|
return strapi2.service("admin::permission").engine.generateUserAbility(user);
|
|
1193
1260
|
}
|
|
1261
|
+
const FILE_UID = "plugin::upload.file";
|
|
1262
|
+
const QUERY_KEYS = /* @__PURE__ */ new Set(["populate", "site"]);
|
|
1263
|
+
const ALWAYS_FIELDS = /* @__PURE__ */ new Set(["id", "documentId", "createdAt", "updatedAt"]);
|
|
1264
|
+
const NOT_SCALAR = /* @__PURE__ */ new Set(["relation", "component", "dynamiczone", "media"]);
|
|
1265
|
+
const NO_POPULATE = { all: false, children: /* @__PURE__ */ new Map() };
|
|
1266
|
+
class QueryProblem extends Error {
|
|
1267
|
+
}
|
|
1268
|
+
function readDraftQuery(strapi2, query, schema) {
|
|
1269
|
+
try {
|
|
1270
|
+
for (const key of Object.keys(query)) {
|
|
1271
|
+
if (!QUERY_KEYS.has(key)) {
|
|
1272
|
+
throw new QueryProblem(
|
|
1273
|
+
`The draft read takes only documentId, locale and populate, not "${key}"`
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return { populate: parsePopulate(strapi2, query.populate, schema, "document", "populate") };
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
if (error instanceof QueryProblem) return { problem: error.message };
|
|
1280
|
+
throw error;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
async function readDraft(strapi2, options2) {
|
|
1284
|
+
const schema = strapi2.contentType(options2.uid);
|
|
1285
|
+
const params = await strapi2.contentAPI.sanitize.query(
|
|
1286
|
+
{ populate: draftPopulate(strapi2, options2.populate, schema) },
|
|
1287
|
+
schema,
|
|
1288
|
+
{ auth: options2.auth }
|
|
1289
|
+
);
|
|
1290
|
+
const entry = await strapi2.documents(options2.uid).findOne({
|
|
1291
|
+
...params,
|
|
1292
|
+
documentId: options2.documentId,
|
|
1293
|
+
locale: options2.locale,
|
|
1294
|
+
status: "draft"
|
|
1295
|
+
});
|
|
1296
|
+
if (!entry) return null;
|
|
1297
|
+
await publishedRelations(strapi2, entry, schema, options2.populate);
|
|
1298
|
+
await keepToSite(strapi2, entry, schema, options2.siteDocumentId);
|
|
1299
|
+
return entry;
|
|
1300
|
+
}
|
|
1301
|
+
function fail(message) {
|
|
1302
|
+
throw new QueryProblem(message);
|
|
1303
|
+
}
|
|
1304
|
+
function attributeOf(schema, name2) {
|
|
1305
|
+
return Object.prototype.hasOwnProperty.call(schema.attributes, name2) ? schema.attributes[name2] : void 0;
|
|
1306
|
+
}
|
|
1307
|
+
function expand(value, path2) {
|
|
1308
|
+
const found = { all: false, pairs: [] };
|
|
1309
|
+
const add2 = (part2) => {
|
|
1310
|
+
if (part2 === void 0 || part2 === null || part2 === false || part2 === "false") return;
|
|
1311
|
+
if (part2 === true || part2 === "true") {
|
|
1312
|
+
found.all = true;
|
|
1313
|
+
} else if (typeof part2 === "string") {
|
|
1314
|
+
for (const name2 of part2.split(",").map((piece) => piece.trim())) {
|
|
1315
|
+
if (name2 === "") continue;
|
|
1316
|
+
if (name2 === "*") found.all = true;
|
|
1317
|
+
else {
|
|
1318
|
+
const [head = "", ...rest] = name2.split(".");
|
|
1319
|
+
found.pairs.push([head, rest.length > 0 ? { populate: rest.join(".") } : true]);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
} else if (Array.isArray(part2)) {
|
|
1323
|
+
for (const item of part2) {
|
|
1324
|
+
if (typeof item !== "string" && (typeof item !== "object" || item === null)) {
|
|
1325
|
+
fail(`${path2} must be a name, a list of names or an object`);
|
|
1326
|
+
}
|
|
1327
|
+
add2(item);
|
|
1328
|
+
}
|
|
1329
|
+
} else if (typeof part2 === "object") {
|
|
1330
|
+
found.pairs.push(...Object.entries(part2));
|
|
1331
|
+
} else {
|
|
1332
|
+
fail(`${path2} must be a name, a list of names or an object`);
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
add2(value);
|
|
1336
|
+
return found;
|
|
1337
|
+
}
|
|
1338
|
+
function parsePopulate(strapi2, value, schema, scope, path2) {
|
|
1339
|
+
const { all: all2, pairs } = expand(value, path2);
|
|
1340
|
+
if (all2 && pairs.length > 0) fail(`${path2} cannot mix "*" with names`);
|
|
1341
|
+
if (all2 && scope === "related") fail(`${path2} cannot be "*" under a relation`);
|
|
1342
|
+
const children = /* @__PURE__ */ new Map();
|
|
1343
|
+
for (const [name2, sub] of pairs) {
|
|
1344
|
+
const here = `${path2}[${name2}]`;
|
|
1345
|
+
const attribute = attributeOf(schema, name2);
|
|
1346
|
+
if (!attribute || attribute.private === true) fail(`${here} is not an attribute of the type`);
|
|
1347
|
+
if (scope === "related" && attribute.type !== "media") {
|
|
1348
|
+
fail(`${here}: under a relation only a media attribute may be populated`);
|
|
1349
|
+
}
|
|
1350
|
+
if (children.has(name2)) fail(`${here} is named twice`);
|
|
1351
|
+
const node = parseNode(strapi2, sub, attribute, here);
|
|
1352
|
+
if (node) children.set(name2, node);
|
|
1353
|
+
}
|
|
1354
|
+
return { all: all2, children };
|
|
1355
|
+
}
|
|
1356
|
+
function parseNode(strapi2, sub, attribute, path2) {
|
|
1357
|
+
if (sub === false || sub === "false") return void 0;
|
|
1358
|
+
const options2 = sub === true || sub === "true" || sub === "" ? {} : sub;
|
|
1359
|
+
if (typeof options2 !== "object" || options2 === null || Array.isArray(options2)) {
|
|
1360
|
+
fail(`${path2} must be true or an object`);
|
|
1361
|
+
}
|
|
1362
|
+
const given = options2;
|
|
1363
|
+
const only = (...keys) => {
|
|
1364
|
+
for (const key of Object.keys(given)) {
|
|
1365
|
+
if (!keys.includes(key)) fail(`${path2} does not take "${key}"`);
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1368
|
+
switch (attribute.type) {
|
|
1369
|
+
case "media":
|
|
1370
|
+
only("fields");
|
|
1371
|
+
return { fields: fieldsOf(given.fields, strapi2.contentType(FILE_UID), path2) };
|
|
1372
|
+
case "relation": {
|
|
1373
|
+
only("fields", "populate");
|
|
1374
|
+
const target = relationTarget(strapi2, attribute, path2);
|
|
1375
|
+
const schema = strapi2.contentType(target);
|
|
1376
|
+
const node = { fields: fieldsOf(given.fields, schema, path2) };
|
|
1377
|
+
if (given.populate !== void 0) {
|
|
1378
|
+
node.populate = parsePopulate(
|
|
1379
|
+
strapi2,
|
|
1380
|
+
given.populate,
|
|
1381
|
+
schema,
|
|
1382
|
+
"related",
|
|
1383
|
+
`${path2}[populate]`
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
return node;
|
|
1387
|
+
}
|
|
1388
|
+
case "component":
|
|
1389
|
+
only("fields", "populate");
|
|
1390
|
+
return componentNode(strapi2, given, attribute.component, path2);
|
|
1391
|
+
case "dynamiczone": {
|
|
1392
|
+
only("on");
|
|
1393
|
+
if (given.on === void 0) return {};
|
|
1394
|
+
if (typeof given.on !== "object" || given.on === null || Array.isArray(given.on)) {
|
|
1395
|
+
fail(`${path2}[on] must be an object`);
|
|
1396
|
+
}
|
|
1397
|
+
const on = /* @__PURE__ */ new Map();
|
|
1398
|
+
for (const [uid, fragment] of Object.entries(given.on)) {
|
|
1399
|
+
if (!attribute.components?.includes(uid))
|
|
1400
|
+
fail(`${path2}[on][${uid}] is not a component of the zone`);
|
|
1401
|
+
const node = parseNode(
|
|
1402
|
+
strapi2,
|
|
1403
|
+
fragment,
|
|
1404
|
+
{ type: "component", component: uid },
|
|
1405
|
+
`${path2}[on][${uid}]`
|
|
1406
|
+
);
|
|
1407
|
+
if (node) on.set(uid, node);
|
|
1408
|
+
}
|
|
1409
|
+
return { on };
|
|
1410
|
+
}
|
|
1411
|
+
default:
|
|
1412
|
+
return fail(`${path2} is not a relation, a component, a dynamic zone or a media attribute`);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
function componentNode(strapi2, given, uid, path2) {
|
|
1416
|
+
const component2 = strapi2.components[uid];
|
|
1417
|
+
const node = { fields: fieldsOf(given.fields, component2, path2) };
|
|
1418
|
+
if (given.populate !== void 0) {
|
|
1419
|
+
node.populate = parsePopulate(
|
|
1420
|
+
strapi2,
|
|
1421
|
+
given.populate,
|
|
1422
|
+
component2,
|
|
1423
|
+
"document",
|
|
1424
|
+
`${path2}[populate]`
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
return node;
|
|
1428
|
+
}
|
|
1429
|
+
function relationTarget(strapi2, attribute, path2) {
|
|
1430
|
+
const target = attribute.target;
|
|
1431
|
+
if (typeof target !== "string" || target.startsWith("admin::") || !(target in strapi2.contentTypes)) {
|
|
1432
|
+
return fail(`${path2} is a relation the draft read does not follow`);
|
|
1433
|
+
}
|
|
1434
|
+
return target;
|
|
1435
|
+
}
|
|
1436
|
+
function fieldsOf(value, schema, path2) {
|
|
1437
|
+
if (value === void 0) return void 0;
|
|
1438
|
+
const names = (Array.isArray(value) ? value : [value]).flatMap((item) => {
|
|
1439
|
+
if (typeof item !== "string") return fail(`${path2}[fields] must be names of fields`);
|
|
1440
|
+
return item.split(",").map((piece) => piece.trim());
|
|
1441
|
+
});
|
|
1442
|
+
for (const name2 of names) {
|
|
1443
|
+
const attribute = attributeOf(schema, name2);
|
|
1444
|
+
const known = ALWAYS_FIELDS.has(name2) || attribute !== void 0 && attribute.private !== true;
|
|
1445
|
+
if (!known || attribute !== void 0 && NOT_SCALAR.has(attribute.type)) {
|
|
1446
|
+
fail(`${path2}[fields]: "${name2}" is not a field of the type`);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
return names.filter((name2) => name2 !== "");
|
|
1450
|
+
}
|
|
1451
|
+
function draftPopulate(strapi2, spec, schema) {
|
|
1452
|
+
if (spec.all) return "*";
|
|
1453
|
+
const populate = {};
|
|
1454
|
+
for (const [name2, node] of spec.children) {
|
|
1455
|
+
const attribute = attributeOf(schema, name2);
|
|
1456
|
+
if (attribute?.type === "media") {
|
|
1457
|
+
populate[name2] = node.fields ? { fields: node.fields } : true;
|
|
1458
|
+
} else if (attribute?.type === "component") {
|
|
1459
|
+
populate[name2] = componentPopulate(strapi2, node, attribute.component);
|
|
1460
|
+
} else if (attribute?.type === "dynamiczone") {
|
|
1461
|
+
populate[name2] = node.on ? {
|
|
1462
|
+
on: Object.fromEntries(
|
|
1463
|
+
[...node.on].map(([uid, fragment]) => [
|
|
1464
|
+
uid,
|
|
1465
|
+
componentPopulate(strapi2, fragment, uid)
|
|
1466
|
+
])
|
|
1467
|
+
)
|
|
1468
|
+
} : true;
|
|
1469
|
+
} else {
|
|
1470
|
+
populate[name2] = true;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
return populate;
|
|
1474
|
+
}
|
|
1475
|
+
function componentPopulate(strapi2, node, uid) {
|
|
1476
|
+
const options2 = {};
|
|
1477
|
+
if (node.fields) options2.fields = node.fields;
|
|
1478
|
+
if (node.populate) options2.populate = draftPopulate(strapi2, node.populate, strapi2.components[uid]);
|
|
1479
|
+
return Object.keys(options2).length > 0 ? options2 : true;
|
|
1480
|
+
}
|
|
1481
|
+
async function publishedRelations(strapi2, entry, schema, spec) {
|
|
1482
|
+
for (const [name2, attribute] of Object.entries(schema.attributes)) {
|
|
1483
|
+
const value = entry[name2];
|
|
1484
|
+
if (value === void 0 || value === null) continue;
|
|
1485
|
+
const node = spec.children.get(name2) ?? (spec.all ? {} : void 0);
|
|
1486
|
+
if (attribute.type === "relation") {
|
|
1487
|
+
if (typeof attribute.target !== "string") {
|
|
1488
|
+
delete entry[name2];
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
const target = attribute.target;
|
|
1492
|
+
const published = [];
|
|
1493
|
+
for (const related of Array.isArray(value) ? value : [value]) {
|
|
1494
|
+
const read = await publishedOf(strapi2, target, related, node ?? {});
|
|
1495
|
+
if (read) published.push(read);
|
|
1496
|
+
}
|
|
1497
|
+
entry[name2] = Array.isArray(value) ? published : published[0] ?? null;
|
|
1498
|
+
} else if (attribute.type === "component") {
|
|
1499
|
+
const component2 = strapi2.components[attribute.component];
|
|
1500
|
+
for (const child of Array.isArray(value) ? value : [value]) {
|
|
1501
|
+
await publishedRelations(strapi2, child, component2, node?.populate ?? NO_POPULATE);
|
|
1502
|
+
}
|
|
1503
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1504
|
+
for (const child of value) {
|
|
1505
|
+
const uid = child.__component;
|
|
1506
|
+
if (!(uid in strapi2.components)) continue;
|
|
1507
|
+
await publishedRelations(
|
|
1508
|
+
strapi2,
|
|
1509
|
+
child,
|
|
1510
|
+
strapi2.components[uid],
|
|
1511
|
+
node?.on?.get(uid)?.populate ?? NO_POPULATE
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
async function publishedOf(strapi2, target, related, node) {
|
|
1518
|
+
if (typeof related.documentId !== "string") return null;
|
|
1519
|
+
const media2 = {};
|
|
1520
|
+
for (const [name2, child] of node.populate?.children ?? []) {
|
|
1521
|
+
media2[name2] = child.fields ? { fields: child.fields } : true;
|
|
1522
|
+
}
|
|
1523
|
+
return await strapi2.documents(target).findOne({
|
|
1524
|
+
documentId: related.documentId,
|
|
1525
|
+
locale: typeof related.locale === "string" ? related.locale : void 0,
|
|
1526
|
+
status: "published",
|
|
1527
|
+
fields: node.fields,
|
|
1528
|
+
populate: Object.keys(media2).length > 0 ? media2 : void 0
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
async function keepToSite(strapi2, entry, schema, siteDocumentId) {
|
|
1532
|
+
const found = /* @__PURE__ */ new Map();
|
|
1533
|
+
await walk(strapi2, entry, schema, async (target, entries) => {
|
|
1534
|
+
if (!isSiteScoped(strapi2.contentType(target))) return entries;
|
|
1535
|
+
const ids = found.get(target) ?? /* @__PURE__ */ new Set();
|
|
1536
|
+
for (const { documentId } of entries) if (typeof documentId === "string") ids.add(documentId);
|
|
1537
|
+
found.set(target, ids);
|
|
1538
|
+
return entries;
|
|
1539
|
+
});
|
|
1540
|
+
if (found.size === 0) return;
|
|
1541
|
+
const owned = /* @__PURE__ */ new Map();
|
|
1542
|
+
for (const [target, ids] of found) {
|
|
1543
|
+
const published = strapi2.contentType(target).options?.draftAndPublish === true;
|
|
1544
|
+
const rows = await strapi2.db.query(target).findMany({
|
|
1545
|
+
select: ["documentId"],
|
|
1546
|
+
where: {
|
|
1547
|
+
documentId: { $in: [...ids] },
|
|
1548
|
+
[SITE_ATTRIBUTE$1]: { documentId: siteDocumentId },
|
|
1549
|
+
...published ? { publishedAt: { $notNull: true } } : {}
|
|
1550
|
+
}
|
|
1551
|
+
});
|
|
1552
|
+
owned.set(target, new Set(rows.map((row) => row.documentId)));
|
|
1553
|
+
}
|
|
1554
|
+
await walk(strapi2, entry, schema, async (target, entries) => {
|
|
1555
|
+
const ids = owned.get(target);
|
|
1556
|
+
if (!isSiteScoped(strapi2.contentType(target))) return entries;
|
|
1557
|
+
return entries.filter(
|
|
1558
|
+
({ documentId }) => typeof documentId === "string" && ids?.has(documentId) === true
|
|
1559
|
+
);
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
async function walk(strapi2, entry, schema, visit) {
|
|
1563
|
+
for (const [name2, attribute] of Object.entries(schema.attributes)) {
|
|
1564
|
+
const value = entry[name2];
|
|
1565
|
+
if (value === void 0 || value === null) continue;
|
|
1566
|
+
if (attribute.type === "relation") {
|
|
1567
|
+
if (!("target" in attribute) || typeof attribute.target !== "string") {
|
|
1568
|
+
delete entry[name2];
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
const target = attribute.target;
|
|
1572
|
+
const many = Array.isArray(value);
|
|
1573
|
+
const kept = await visit(target, many ? value : [value]);
|
|
1574
|
+
for (const child of kept) await walk(strapi2, child, strapi2.contentType(target), visit);
|
|
1575
|
+
entry[name2] = many ? kept : kept[0] ?? null;
|
|
1576
|
+
} else if (attribute.type === "component") {
|
|
1577
|
+
const component2 = strapi2.components[attribute.component];
|
|
1578
|
+
for (const child of Array.isArray(value) ? value : [value]) {
|
|
1579
|
+
await walk(strapi2, child, component2, visit);
|
|
1580
|
+
}
|
|
1581
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1582
|
+
for (const child of value) {
|
|
1583
|
+
const component2 = strapi2.components[child.__component];
|
|
1584
|
+
if (component2) await walk(strapi2, child, component2, visit);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1194
1589
|
const LIFETIME_SECONDS = {
|
|
1195
1590
|
token: PREVIEW_TOKEN_TTL_SECONDS,
|
|
1196
|
-
grant: PREVIEW_GRANT_TTL_SECONDS
|
|
1591
|
+
grant: PREVIEW_GRANT_TTL_SECONDS,
|
|
1592
|
+
system: PREVIEW_SYSTEM_GRANT_TTL_SECONDS
|
|
1197
1593
|
};
|
|
1198
1594
|
function hashCredential(value) {
|
|
1199
1595
|
return node_crypto.createHash("sha256").update(value).digest("hex");
|
|
@@ -1201,6 +1597,9 @@ function hashCredential(value) {
|
|
|
1201
1597
|
function issueCredential(kind2, binding, now = /* @__PURE__ */ new Date()) {
|
|
1202
1598
|
const value = node_crypto.randomBytes(32).toString("base64url");
|
|
1203
1599
|
const record = {
|
|
1600
|
+
adminUser: null,
|
|
1601
|
+
adminOrigin: null,
|
|
1602
|
+
entryVersion: null,
|
|
1204
1603
|
...binding,
|
|
1205
1604
|
kind: kind2,
|
|
1206
1605
|
hash: hashCredential(value),
|
|
@@ -1229,15 +1628,22 @@ class PreviewUnavailableError extends Error {
|
|
|
1229
1628
|
const preview$1 = ({ strapi: strapi2 }) => {
|
|
1230
1629
|
const store2 = () => strapi2.db.query(PREVIEW_CREDENTIAL_UID);
|
|
1231
1630
|
async function save(record) {
|
|
1232
|
-
const site2 = await strapi2.db.query(SITE_UID).findOne({ where: { documentId: record.siteDocumentId }, select: ["id"] });
|
|
1631
|
+
const site2 = await strapi2.db.query(SITE_UID$1).findOne({ where: { documentId: record.siteDocumentId }, select: ["id"] });
|
|
1233
1632
|
await store2().create({ data: { ...record, site: site2?.id } });
|
|
1234
1633
|
}
|
|
1235
|
-
async function find(
|
|
1634
|
+
async function find(kinds, value) {
|
|
1236
1635
|
const row = await store2().findOne({
|
|
1237
|
-
where: { hash: hashCredential(value), kind:
|
|
1636
|
+
where: { hash: hashCredential(value), kind: { $in: kinds } }
|
|
1238
1637
|
});
|
|
1239
1638
|
return row;
|
|
1240
1639
|
}
|
|
1640
|
+
async function removeExpired() {
|
|
1641
|
+
await store2().deleteMany({
|
|
1642
|
+
where: {
|
|
1643
|
+
expiresAt: { $lt: new Date(Date.now() - PREVIEW_CREDENTIAL_RETENTION_SECONDS * 1e3) }
|
|
1644
|
+
}
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1241
1647
|
async function revoke(adminUser, entryDocumentId) {
|
|
1242
1648
|
await store2().updateMany({
|
|
1243
1649
|
where: {
|
|
@@ -1258,43 +1664,56 @@ const preview$1 = ({ strapi: strapi2 }) => {
|
|
|
1258
1664
|
}
|
|
1259
1665
|
return {
|
|
1260
1666
|
async issueToken(binding) {
|
|
1261
|
-
const site2 = await strapi2.db.query(SITE_UID).findOne({ where: { documentId: binding.siteDocumentId }, select: ["url"] });
|
|
1667
|
+
const site2 = await strapi2.db.query(SITE_UID$1).findOne({ where: { documentId: binding.siteDocumentId }, select: ["url"] });
|
|
1262
1668
|
const url = previewUrlOf(site2?.url);
|
|
1263
1669
|
if (!url) throw new PreviewUnavailableError(binding.siteDocumentId);
|
|
1264
|
-
await
|
|
1265
|
-
where: {
|
|
1266
|
-
expiresAt: { $lt: new Date(Date.now() - PREVIEW_CREDENTIAL_RETENTION_SECONDS * 1e3) }
|
|
1267
|
-
}
|
|
1268
|
-
});
|
|
1670
|
+
await removeExpired();
|
|
1269
1671
|
const { value, record } = issueCredential("token", binding);
|
|
1270
1672
|
await save(record);
|
|
1271
1673
|
url.searchParams.set("token", value);
|
|
1272
1674
|
return { url: url.toString(), expiresAt: record.expiresAt.toISOString() };
|
|
1273
1675
|
},
|
|
1274
1676
|
async exchange(token, siteDocumentId) {
|
|
1275
|
-
const row = await find("token", token);
|
|
1677
|
+
const row = await find(["token"], token);
|
|
1276
1678
|
if (!row || !mayUseCredential(toRecord(row), "token", { siteDocumentId })) return null;
|
|
1277
1679
|
const claimed = await store2().updateMany({
|
|
1278
1680
|
where: { id: row.id, usedAt: null, revokedAt: null },
|
|
1279
1681
|
data: { usedAt: /* @__PURE__ */ new Date() }
|
|
1280
1682
|
});
|
|
1281
1683
|
if (claimed.count !== 1) return null;
|
|
1282
|
-
|
|
1283
|
-
|
|
1684
|
+
const binding = adminBindingOf(row);
|
|
1685
|
+
if (!binding || !await stillReadable(binding)) return null;
|
|
1686
|
+
const { value, record } = issueCredential("grant", binding);
|
|
1284
1687
|
await save(record);
|
|
1285
1688
|
return {
|
|
1286
1689
|
grant: value,
|
|
1287
1690
|
expiresAt: record.expiresAt.toISOString(),
|
|
1288
|
-
adminOrigin:
|
|
1691
|
+
adminOrigin: binding.adminOrigin,
|
|
1289
1692
|
contentType: row.contentType,
|
|
1290
1693
|
documentId: row.entryDocumentId,
|
|
1291
1694
|
locale: row.entryLocale
|
|
1292
1695
|
};
|
|
1293
1696
|
},
|
|
1697
|
+
async issueSystemGrant(binding) {
|
|
1698
|
+
await removeExpired();
|
|
1699
|
+
const { value, record } = issueCredential("system", binding);
|
|
1700
|
+
await save(record);
|
|
1701
|
+
return value;
|
|
1702
|
+
},
|
|
1294
1703
|
async resolveGrant(grant, expected) {
|
|
1295
|
-
const row = await find("grant", grant);
|
|
1296
|
-
if (!row || !mayUseCredential(toRecord(row),
|
|
1297
|
-
|
|
1704
|
+
const row = await find(["grant", "system"], grant);
|
|
1705
|
+
if (!row || !mayUseCredential(toRecord(row), row.kind, expected)) return null;
|
|
1706
|
+
if (row.kind === "system") {
|
|
1707
|
+
const claimed = await store2().updateMany({
|
|
1708
|
+
where: { id: row.id, usedAt: null, revokedAt: null },
|
|
1709
|
+
data: { usedAt: /* @__PURE__ */ new Date() }
|
|
1710
|
+
});
|
|
1711
|
+
if (claimed.count !== 1) return null;
|
|
1712
|
+
return { ...targetOf(row), actor: "system", entryVersion: row.entryVersion };
|
|
1713
|
+
}
|
|
1714
|
+
const binding = adminBindingOf(row);
|
|
1715
|
+
if (!binding || !await stillReadable(binding)) return null;
|
|
1716
|
+
return { ...targetOf(row), actor: "admin", entryVersion: null };
|
|
1298
1717
|
},
|
|
1299
1718
|
revoke
|
|
1300
1719
|
};
|
|
@@ -1311,21 +1730,26 @@ function previewUrlOf(url) {
|
|
|
1311
1730
|
return void 0;
|
|
1312
1731
|
}
|
|
1313
1732
|
}
|
|
1314
|
-
function
|
|
1733
|
+
function targetOf(row) {
|
|
1315
1734
|
return {
|
|
1316
|
-
adminUser: row.adminUser,
|
|
1317
|
-
adminOrigin: row.adminOrigin,
|
|
1318
1735
|
siteDocumentId: row.siteDocumentId,
|
|
1319
1736
|
contentType: row.contentType,
|
|
1320
1737
|
entryDocumentId: row.entryDocumentId,
|
|
1321
1738
|
entryLocale: row.entryLocale
|
|
1322
1739
|
};
|
|
1323
1740
|
}
|
|
1741
|
+
function adminBindingOf(row) {
|
|
1742
|
+
if (row.adminUser === null || row.adminOrigin === null) return null;
|
|
1743
|
+
return { ...targetOf(row), adminUser: row.adminUser, adminOrigin: row.adminOrigin };
|
|
1744
|
+
}
|
|
1324
1745
|
function toRecord(row) {
|
|
1325
1746
|
return {
|
|
1326
|
-
...
|
|
1747
|
+
...targetOf(row),
|
|
1327
1748
|
kind: row.kind,
|
|
1328
1749
|
hash: row.hash,
|
|
1750
|
+
adminUser: row.adminUser,
|
|
1751
|
+
adminOrigin: row.adminOrigin,
|
|
1752
|
+
entryVersion: row.entryVersion,
|
|
1329
1753
|
expiresAt: new Date(row.expiresAt),
|
|
1330
1754
|
usedAt: row.usedAt ? new Date(row.usedAt) : null,
|
|
1331
1755
|
revokedAt: row.revokedAt ? new Date(row.revokedAt) : null
|
|
@@ -1363,6 +1787,16 @@ const preview = ({ strapi: strapi2 }) => {
|
|
|
1363
1787
|
const previews = () => strapi2.plugin("micelio").service("preview");
|
|
1364
1788
|
const tokenLimit = createRateLimiter(PREVIEW_TOKEN_RATE_LIMIT, PREVIEW_RATE_WINDOW_SECONDS);
|
|
1365
1789
|
const exchangeLimit = createRateLimiter(PREVIEW_EXCHANGE_RATE_LIMIT, PREVIEW_RATE_WINDOW_SECONDS);
|
|
1790
|
+
async function isVersionOf(uid, binding) {
|
|
1791
|
+
const current = await strapi2.documents(uid).findOne({
|
|
1792
|
+
documentId: binding.entryDocumentId,
|
|
1793
|
+
locale: binding.entryLocale ?? void 0,
|
|
1794
|
+
status: "draft",
|
|
1795
|
+
fields: ["updatedAt"]
|
|
1796
|
+
});
|
|
1797
|
+
if (!current?.updatedAt || !binding.entryVersion) return false;
|
|
1798
|
+
return new Date(current.updatedAt).getTime() === new Date(binding.entryVersion).getTime();
|
|
1799
|
+
}
|
|
1366
1800
|
return {
|
|
1367
1801
|
async token(ctx) {
|
|
1368
1802
|
const ability = ctx.state.userAbility;
|
|
@@ -1466,22 +1900,37 @@ const preview = ({ strapi: strapi2 }) => {
|
|
|
1466
1900
|
}
|
|
1467
1901
|
const uid = binding.contentType;
|
|
1468
1902
|
const schema = strapi2.contentType(uid);
|
|
1903
|
+
const read = readDraftQuery(strapi2, query, schema);
|
|
1904
|
+
if ("problem" in read) {
|
|
1905
|
+
refuse(ctx, 400, "previewRequestInvalid", read.problem);
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1469
1908
|
const auth = ctx.state.auth;
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1909
|
+
let entry;
|
|
1910
|
+
try {
|
|
1911
|
+
entry = await readDraft(strapi2, {
|
|
1912
|
+
uid,
|
|
1913
|
+
documentId: binding.entryDocumentId,
|
|
1914
|
+
locale: binding.entryLocale ?? void 0,
|
|
1915
|
+
populate: read.populate,
|
|
1916
|
+
siteDocumentId: siteOf(ctx),
|
|
1917
|
+
auth
|
|
1918
|
+
});
|
|
1919
|
+
} catch (error) {
|
|
1920
|
+
if (!(error instanceof utils.errors.ValidationError || error instanceof utils.errors.PaginationError)) {
|
|
1921
|
+
throw error;
|
|
1922
|
+
}
|
|
1923
|
+
refuse(ctx, 400, "previewRequestInvalid", error.message);
|
|
1924
|
+
return;
|
|
1925
|
+
}
|
|
1926
|
+
if (!entry || binding.actor === "system" && !await isVersionOf(uid, binding)) {
|
|
1478
1927
|
refuse(ctx, 404, "previewRefused", REFUSED);
|
|
1479
1928
|
return;
|
|
1480
1929
|
}
|
|
1481
1930
|
ctx.set("Cache-Control", "private, no-store");
|
|
1482
1931
|
ctx.body = {
|
|
1483
1932
|
data: await strapi2.contentAPI.sanitize.output(entry, schema, { auth }),
|
|
1484
|
-
meta: {}
|
|
1933
|
+
meta: { actor: binding.actor }
|
|
1485
1934
|
};
|
|
1486
1935
|
}
|
|
1487
1936
|
};
|
|
@@ -1514,8 +1963,8 @@ function readTokenBody(body) {
|
|
|
1514
1963
|
return { uid, documentId, locale };
|
|
1515
1964
|
}
|
|
1516
1965
|
const name = "@micelio/strapi-plugin-core";
|
|
1517
|
-
const version$1 = "0.
|
|
1518
|
-
const engines = { "node": ">=22.
|
|
1966
|
+
const version$1 = "0.2.0";
|
|
1967
|
+
const engines = { "node": ">=22.19.0" };
|
|
1519
1968
|
const micelio = "0.6";
|
|
1520
1969
|
const packageJson = {
|
|
1521
1970
|
name,
|
|
@@ -1760,7 +2209,7 @@ function runSanitiser(loaded, html) {
|
|
|
1760
2209
|
return void 0;
|
|
1761
2210
|
}
|
|
1762
2211
|
async function readSiteOrigins(strapi2) {
|
|
1763
|
-
const sites = await strapi2.db.query(SITE_UID).findMany({ select: ["url"] });
|
|
2212
|
+
const sites = await strapi2.db.query(SITE_UID$1).findMany({ select: ["url"] });
|
|
1764
2213
|
const origins = /* @__PURE__ */ new Set();
|
|
1765
2214
|
for (const { url } of sites) {
|
|
1766
2215
|
if (!url) continue;
|
|
@@ -1818,7 +2267,7 @@ async function readSitesWithSections(strapi2, sections) {
|
|
|
1818
2267
|
async function readSiteRows(strapi2, populate) {
|
|
1819
2268
|
const locales = strapi2.plugin("i18n").service("locales");
|
|
1820
2269
|
const defaultLocale = await locales.getDefaultLocale();
|
|
1821
|
-
const rows = await strapi2.db.query(SITE_UID).findMany({
|
|
2270
|
+
const rows = await strapi2.db.query(SITE_UID$1).findMany({
|
|
1822
2271
|
select: ["documentId", "locale", "name", "slug", "hosts", "isDefault", "url"],
|
|
1823
2272
|
populate,
|
|
1824
2273
|
orderBy: { slug: "asc" }
|
|
@@ -1881,7 +2330,7 @@ const extensions$1 = ({ strapi: strapi2 }) => {
|
|
|
1881
2330
|
},
|
|
1882
2331
|
async sites(ctx) {
|
|
1883
2332
|
const ability = abilityOf2(ctx);
|
|
1884
|
-
if (ability?.can(READ_SITES, SITE_UID) !== true) {
|
|
2333
|
+
if (ability?.can(READ_SITES, SITE_UID$1) !== true) {
|
|
1885
2334
|
sendProblem(ctx, {
|
|
1886
2335
|
type: "about:blank",
|
|
1887
2336
|
title: "Forbidden",
|
|
@@ -1980,7 +2429,9 @@ function readBody(body) {
|
|
|
1980
2429
|
return { uid, documentId, to, locale, publishAt };
|
|
1981
2430
|
}
|
|
1982
2431
|
const controllers = {
|
|
1983
|
-
site: strapi.factories.createCoreController(SITE_UID),
|
|
2432
|
+
site: strapi.factories.createCoreController(SITE_UID$1),
|
|
2433
|
+
category: strapi.factories.createCoreController(CATEGORY_UID),
|
|
2434
|
+
tag: strapi.factories.createCoreController(TAG_UID),
|
|
1984
2435
|
blocks,
|
|
1985
2436
|
transitions: transitions$1,
|
|
1986
2437
|
status: status$1,
|
|
@@ -2020,7 +2471,7 @@ const siteScope = (_config, { strapi: strapi2 }) => {
|
|
|
2020
2471
|
};
|
|
2021
2472
|
};
|
|
2022
2473
|
async function loadSites(strapi2) {
|
|
2023
|
-
const rows = await strapi2.db.query(SITE_UID).findMany({
|
|
2474
|
+
const rows = await strapi2.db.query(SITE_UID$1).findMany({
|
|
2024
2475
|
select: ["documentId", "slug", "hosts", "isDefault"]
|
|
2025
2476
|
});
|
|
2026
2477
|
const sites = /* @__PURE__ */ new Map();
|
|
@@ -2122,16 +2573,16 @@ const COMPONENTS = {
|
|
|
2122
2573
|
function registerComponents(strapi2) {
|
|
2123
2574
|
const components = Object.fromEntries(
|
|
2124
2575
|
Object.entries(COMPONENTS).flatMap(
|
|
2125
|
-
([
|
|
2126
|
-
const uid = `${
|
|
2576
|
+
([category2, schemas]) => Object.entries(schemas).map(([name2, schema]) => {
|
|
2577
|
+
const uid = `${category2}.${name2}`;
|
|
2127
2578
|
const component2 = {
|
|
2128
2579
|
...structuredClone(schema),
|
|
2129
2580
|
__schema__: structuredClone(schema),
|
|
2130
2581
|
uid,
|
|
2131
|
-
category,
|
|
2582
|
+
category: category2,
|
|
2132
2583
|
modelType: "component",
|
|
2133
2584
|
modelName: name2,
|
|
2134
|
-
globalId: `Component${pascalCase(
|
|
2585
|
+
globalId: `Component${pascalCase(category2)}${pascalCase(name2)}`
|
|
2135
2586
|
};
|
|
2136
2587
|
return [uid, component2];
|
|
2137
2588
|
})
|
|
@@ -2179,10 +2630,120 @@ async function storedState(strapi2, uid, params) {
|
|
|
2179
2630
|
});
|
|
2180
2631
|
return entry?.editorial?.state ?? "draft";
|
|
2181
2632
|
}
|
|
2633
|
+
const LEGACY_TO_PLUGIN = {
|
|
2634
|
+
"api::category.category": "plugin::micelio.category",
|
|
2635
|
+
"api::tag.tag": "plugin::micelio.tag"
|
|
2636
|
+
};
|
|
2637
|
+
const CONFIGURATION_KEY_PREFIX = "plugin_content_manager_configuration_content_types::";
|
|
2638
|
+
const ACTION_TABLES = [
|
|
2639
|
+
{ uid: "plugin::users-permissions.permission", owner: "role" },
|
|
2640
|
+
{ uid: "admin::api-token-permission", owner: "token" }
|
|
2641
|
+
];
|
|
2642
|
+
async function renameLegacyUids(strapi2) {
|
|
2643
|
+
const report = { actions: 0, subjects: 0, layouts: 0 };
|
|
2644
|
+
for (const [legacy, current] of Object.entries(LEGACY_TO_PLUGIN)) {
|
|
2645
|
+
if (strapi2.contentTypes[legacy]) {
|
|
2646
|
+
strapi2.log.info(
|
|
2647
|
+
`micelio: kept the grants and layouts of ${legacy}: the host still registers that type`
|
|
2648
|
+
);
|
|
2649
|
+
continue;
|
|
2650
|
+
}
|
|
2651
|
+
for (const { uid, owner } of ACTION_TABLES) {
|
|
2652
|
+
report.actions += await renameActions(strapi2, uid, owner, legacy, current);
|
|
2653
|
+
}
|
|
2654
|
+
report.subjects += await renameSubjects(strapi2, legacy, current);
|
|
2655
|
+
report.layouts += await renameLayouts(strapi2, legacy, current);
|
|
2656
|
+
}
|
|
2657
|
+
return report;
|
|
2658
|
+
}
|
|
2659
|
+
async function hasTable(strapi2, uid) {
|
|
2660
|
+
if (!strapi2.db.metadata.has(uid)) return false;
|
|
2661
|
+
const tableName = strapi2.db.metadata.get(uid).tableName;
|
|
2662
|
+
return Boolean(tableName) && await strapi2.db.getSchemaConnection().hasTable(tableName);
|
|
2663
|
+
}
|
|
2664
|
+
async function renameActions(strapi2, uid, owner, legacy, current) {
|
|
2665
|
+
if (!await hasTable(strapi2, uid)) return 0;
|
|
2666
|
+
const rows = await strapi2.db.query(uid).findMany({
|
|
2667
|
+
where: { action: { $startsWith: `${legacy}.` } },
|
|
2668
|
+
populate: { [owner]: { select: ["id"] } }
|
|
2669
|
+
});
|
|
2670
|
+
for (const row of rows) {
|
|
2671
|
+
const action = `${current}${row.action.slice(legacy.length)}`;
|
|
2672
|
+
const ownerRow = row[owner];
|
|
2673
|
+
const twin = ownerRow ? await strapi2.db.query(uid).findOne({ where: { action, [owner]: ownerRow.id } }) : null;
|
|
2674
|
+
if (twin) {
|
|
2675
|
+
await strapi2.db.query(uid).delete({ where: { id: row.id } });
|
|
2676
|
+
} else {
|
|
2677
|
+
await strapi2.db.query(uid).update({ where: { id: row.id }, data: { action } });
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
return rows.length;
|
|
2681
|
+
}
|
|
2682
|
+
async function renameSubjects(strapi2, legacy, current) {
|
|
2683
|
+
const uid = "admin::permission";
|
|
2684
|
+
if (!await hasTable(strapi2, uid)) return 0;
|
|
2685
|
+
const rows = await strapi2.db.query(uid).findMany({
|
|
2686
|
+
where: { subject: legacy },
|
|
2687
|
+
populate: { role: { select: ["id"] } }
|
|
2688
|
+
});
|
|
2689
|
+
for (const row of rows) {
|
|
2690
|
+
const twin = row.role ? await strapi2.db.query(uid).findOne({ where: { action: row.action, subject: current, role: row.role.id } }) : null;
|
|
2691
|
+
if (twin) {
|
|
2692
|
+
await strapi2.db.query(uid).delete({ where: { id: row.id } });
|
|
2693
|
+
} else {
|
|
2694
|
+
await strapi2.db.query(uid).update({ where: { id: row.id }, data: { subject: current } });
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
return rows.length;
|
|
2698
|
+
}
|
|
2699
|
+
function replaceWholeUid(text2, legacy, current) {
|
|
2700
|
+
const escaped = legacy.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2701
|
+
return text2.replace(new RegExp(`${escaped}(?![A-Za-z0-9_-])`, "g"), () => current);
|
|
2702
|
+
}
|
|
2703
|
+
async function renameLayouts(strapi2, legacy, current) {
|
|
2704
|
+
const uid = "strapi::core-store";
|
|
2705
|
+
if (!await hasTable(strapi2, uid)) return 0;
|
|
2706
|
+
const rows = await strapi2.db.query(uid).findMany({
|
|
2707
|
+
where: { key: { $startsWith: CONFIGURATION_KEY_PREFIX } }
|
|
2708
|
+
});
|
|
2709
|
+
let changed = 0;
|
|
2710
|
+
for (const row of rows) {
|
|
2711
|
+
const key = replaceWholeUid(row.key, legacy, current);
|
|
2712
|
+
const value = row.value ? replaceWholeUid(row.value, legacy, current) : row.value;
|
|
2713
|
+
if (key === row.key && value === row.value) continue;
|
|
2714
|
+
changed += 1;
|
|
2715
|
+
if (key !== row.key && await strapi2.db.query(uid).findOne({ where: { key } })) {
|
|
2716
|
+
await strapi2.db.query(uid).delete({ where: { id: row.id } });
|
|
2717
|
+
} else {
|
|
2718
|
+
await strapi2.db.query(uid).update({ where: { id: row.id }, data: { key, value } });
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
return changed;
|
|
2722
|
+
}
|
|
2723
|
+
function previewPageUrl(strapi2, uid, { documentId, locale }) {
|
|
2724
|
+
const schema = strapi2.contentType(uid);
|
|
2725
|
+
const hasDynamicZone = Object.values(schema?.attributes ?? {}).some(
|
|
2726
|
+
({ type }) => type === "dynamiczone"
|
|
2727
|
+
);
|
|
2728
|
+
if (!documentId || schema?.kind !== "collectionType") return void 0;
|
|
2729
|
+
if (!isSiteScoped(schema) || !hasDynamicZone) return void 0;
|
|
2730
|
+
const base = strapi2.config.get("admin.url", "/admin");
|
|
2731
|
+
const page = `${base.replace(/\/$/, "")}/plugins/micelio/preview/${encodeURIComponent(uid)}/${encodeURIComponent(documentId)}`;
|
|
2732
|
+
return locale ? `${page}?locale=${encodeURIComponent(locale)}` : page;
|
|
2733
|
+
}
|
|
2734
|
+
function registerPreviewShortcut(strapi2) {
|
|
2735
|
+
if (strapi2.config.get("admin.preview") !== void 0) return;
|
|
2736
|
+
strapi2.config.set("admin.preview", {
|
|
2737
|
+
enabled: true,
|
|
2738
|
+
config: {
|
|
2739
|
+
handler: (uid, params) => previewPageUrl(strapi2, uid, params)
|
|
2740
|
+
}
|
|
2741
|
+
});
|
|
2742
|
+
}
|
|
2182
2743
|
function siteCreatedHook(strapi2) {
|
|
2183
2744
|
return async (context, next) => {
|
|
2184
2745
|
const result = await next();
|
|
2185
|
-
if (context.uid !== SITE_UID || context.action !== "create") return result;
|
|
2746
|
+
if (context.uid !== SITE_UID$1 || context.action !== "create") return result;
|
|
2186
2747
|
const site2 = result;
|
|
2187
2748
|
await hooksOf(strapi2).runAfter("siteCreated", {
|
|
2188
2749
|
site: site2.documentId,
|
|
@@ -2201,14 +2762,16 @@ function siteScopeDocuments(strapi2) {
|
|
|
2201
2762
|
const site2 = currentSite(strapi2);
|
|
2202
2763
|
if (context.action === "create") {
|
|
2203
2764
|
params.data = params.data ?? {};
|
|
2204
|
-
if (
|
|
2205
|
-
|
|
2206
|
-
|
|
2765
|
+
if (site2) params.data[SITE_ATTRIBUTE$1] = site2.documentId;
|
|
2766
|
+
else if (isMissing(params.data[SITE_ATTRIBUTE$1])) {
|
|
2767
|
+
throw new utils.errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2207
2768
|
}
|
|
2208
2769
|
}
|
|
2209
|
-
if (context.action === "update" && params.data && SITE_ATTRIBUTE in params.data) {
|
|
2210
|
-
if (
|
|
2211
|
-
|
|
2770
|
+
if (context.action === "update" && params.data && SITE_ATTRIBUTE$1 in params.data) {
|
|
2771
|
+
if (site2) delete params.data[SITE_ATTRIBUTE$1];
|
|
2772
|
+
else if (isUnchanged(params.data[SITE_ATTRIBUTE$1])) delete params.data[SITE_ATTRIBUTE$1];
|
|
2773
|
+
else if (isMissing(params.data[SITE_ATTRIBUTE$1])) {
|
|
2774
|
+
throw new utils.errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2212
2775
|
}
|
|
2213
2776
|
}
|
|
2214
2777
|
if (site2 && READ_ACTIONS.has(context.action)) {
|
|
@@ -2220,21 +2783,119 @@ function siteScopeDocuments(strapi2) {
|
|
|
2220
2783
|
});
|
|
2221
2784
|
if (owned === 0) throw new utils.errors.NotFoundError("Not Found");
|
|
2222
2785
|
}
|
|
2223
|
-
|
|
2786
|
+
if (context.action === "update" && params.documentId) {
|
|
2787
|
+
await keepSiteOfLocales(strapi2, context.uid, params);
|
|
2788
|
+
}
|
|
2789
|
+
const result = await next();
|
|
2790
|
+
if (rebuildsRelations(context.action, params) && params.documentId) {
|
|
2791
|
+
await repairSiteOfLocales(strapi2, context.uid, params);
|
|
2792
|
+
}
|
|
2793
|
+
return result;
|
|
2224
2794
|
};
|
|
2225
2795
|
}
|
|
2796
|
+
async function keepSiteOfLocales(strapi2, uid, params) {
|
|
2797
|
+
if (!isLocalized(strapi2, uid)) return;
|
|
2798
|
+
const locale = typeof params.locale === "string" ? params.locale : await strapi2.plugin("i18n").service("locales").getDefaultLocale();
|
|
2799
|
+
const { documentId } = params;
|
|
2800
|
+
const rows = await strapi2.db.query(uid).findMany({
|
|
2801
|
+
where: { documentId },
|
|
2802
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["id", "documentId"] } }
|
|
2803
|
+
});
|
|
2804
|
+
if (rows.length === 0) return;
|
|
2805
|
+
const named = params.data?.[SITE_ATTRIBUTE$1];
|
|
2806
|
+
if (rows.some((row) => row.locale === locale)) {
|
|
2807
|
+
if (named !== void 0) await refuseMoveAwayFromOtherLocales(strapi2, rows, locale, named);
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
const sites = new Map(
|
|
2811
|
+
rows.flatMap((row) => row.site ? [[row.site.documentId, row.site.id]] : [])
|
|
2812
|
+
);
|
|
2813
|
+
const data = params.data = params.data ?? {};
|
|
2814
|
+
if (named !== void 0) {
|
|
2815
|
+
if (sites.size !== 1) return;
|
|
2816
|
+
const [[shared]] = [...sites];
|
|
2817
|
+
for (const documentIdOfNamed of await namedSites(strapi2, named)) {
|
|
2818
|
+
if (documentIdOfNamed !== shared) {
|
|
2819
|
+
throw new utils.errors.ValidationError(`${SITE_ATTRIBUTE$1} must be the site of the other locales`);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
} else if (sites.size !== 1) {
|
|
2823
|
+
throw new utils.errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2824
|
+
}
|
|
2825
|
+
data[SITE_ATTRIBUTE$1] = { connect: [{ id: [...sites.values()][0] }] };
|
|
2826
|
+
}
|
|
2827
|
+
async function refuseMoveAwayFromOtherLocales(strapi2, rows, locale, named) {
|
|
2828
|
+
const target = new Set(await namedSites(strapi2, named));
|
|
2829
|
+
const own = rows.filter((row) => row.locale === locale).flatMap((row) => row.site?.documentId ?? []);
|
|
2830
|
+
if (target.size === 0 || [...target].every((site2) => own.includes(site2))) return;
|
|
2831
|
+
const staysElsewhere = rows.some(
|
|
2832
|
+
(row) => row.locale !== locale && row.site && !target.has(row.site.documentId)
|
|
2833
|
+
);
|
|
2834
|
+
if (staysElsewhere) {
|
|
2835
|
+
throw new utils.errors.ValidationError(
|
|
2836
|
+
`${SITE_ATTRIBUTE$1} cannot change while other locales of the document stay on another site`
|
|
2837
|
+
);
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
async function namedSites(strapi2, value) {
|
|
2841
|
+
if (typeof value === "string") return [value];
|
|
2842
|
+
if (typeof value === "number") return [await documentIdOfSite(strapi2, value)];
|
|
2843
|
+
if (Array.isArray(value))
|
|
2844
|
+
return (await Promise.all(value.map((v) => namedSites(strapi2, v)))).flat();
|
|
2845
|
+
if (typeof value !== "object" || value === null) return [];
|
|
2846
|
+
const { documentId, id: id2, connect, set } = value;
|
|
2847
|
+
if (typeof documentId === "string") return [documentId];
|
|
2848
|
+
if (typeof id2 === "number") return [await documentIdOfSite(strapi2, id2)];
|
|
2849
|
+
return [...await namedSites(strapi2, connect), ...await namedSites(strapi2, set)];
|
|
2850
|
+
}
|
|
2851
|
+
async function documentIdOfSite(strapi2, id2) {
|
|
2852
|
+
const row = await strapi2.db.query(SITE_UID$1).findOne({ where: { id: id2 } });
|
|
2853
|
+
return row?.documentId ?? String(id2);
|
|
2854
|
+
}
|
|
2855
|
+
function isLocalized(strapi2, uid) {
|
|
2856
|
+
const model = strapi2.contentType(uid);
|
|
2857
|
+
const options2 = model.pluginOptions;
|
|
2858
|
+
return options2?.i18n?.localized === true;
|
|
2859
|
+
}
|
|
2860
|
+
function rebuildsRelations(action, params) {
|
|
2861
|
+
return action === "publish" || action === "discardDraft" || action === "update" && params.status === "published";
|
|
2862
|
+
}
|
|
2863
|
+
async function repairSiteOfLocales(strapi2, uid, params) {
|
|
2864
|
+
if (!isLocalized(strapi2, uid)) return;
|
|
2865
|
+
const query = strapi2.db.query(uid);
|
|
2866
|
+
const rows = await query.findMany({
|
|
2867
|
+
where: {
|
|
2868
|
+
documentId: params.documentId,
|
|
2869
|
+
...typeof params.locale === "string" && params.locale !== "*" ? { locale: params.locale } : {}
|
|
2870
|
+
},
|
|
2871
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["id"] } }
|
|
2872
|
+
});
|
|
2873
|
+
for (const row of rows.filter((candidate) => !candidate.site)) {
|
|
2874
|
+
const other = rows.find((candidate) => candidate.locale === row.locale && candidate.site);
|
|
2875
|
+
if (other?.site) {
|
|
2876
|
+
await query.update({ where: { id: row.id }, data: { [SITE_ATTRIBUTE$1]: other.site.id } });
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2226
2880
|
function currentSite(strapi2) {
|
|
2227
2881
|
const state = strapi2.requestContext.get()?.state;
|
|
2228
2882
|
return state?.micelio?.site;
|
|
2229
2883
|
}
|
|
2230
2884
|
function siteFilter(site2) {
|
|
2231
|
-
return { [SITE_ATTRIBUTE]: { documentId: { $eq: site2.documentId } } };
|
|
2885
|
+
return { [SITE_ATTRIBUTE$1]: { documentId: { $eq: site2.documentId } } };
|
|
2886
|
+
}
|
|
2887
|
+
function isUnchanged(value) {
|
|
2888
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
2889
|
+
const { connect, disconnect, ...rest } = value;
|
|
2890
|
+
const isEmpty = (list2) => list2 === void 0 || Array.isArray(list2) && list2.length === 0;
|
|
2891
|
+
return Object.keys(rest).length === 0 && isEmpty(connect) && isEmpty(disconnect);
|
|
2232
2892
|
}
|
|
2233
2893
|
function isMissing(value) {
|
|
2234
2894
|
if (value === void 0 || value === null || value === "") return true;
|
|
2235
2895
|
if (Array.isArray(value)) return value.length === 0;
|
|
2236
2896
|
if (typeof value === "object") {
|
|
2237
|
-
const { connect, set } = value;
|
|
2897
|
+
const { connect, set, documentId, id: id2 } = value;
|
|
2898
|
+
if (documentId !== void 0 || id2 !== void 0) return !(documentId || id2);
|
|
2238
2899
|
const list2 = set ?? connect;
|
|
2239
2900
|
return Array.isArray(list2) ? list2.length === 0 : list2 === void 0;
|
|
2240
2901
|
}
|
|
@@ -2255,7 +2916,7 @@ function normalizeHosts(value) {
|
|
|
2255
2916
|
}
|
|
2256
2917
|
return hosts;
|
|
2257
2918
|
}
|
|
2258
|
-
const SITE = SITE_UID;
|
|
2919
|
+
const SITE = SITE_UID$1;
|
|
2259
2920
|
function siteRules(strapi2) {
|
|
2260
2921
|
return async (context, next) => {
|
|
2261
2922
|
if (context.uid !== SITE) return next();
|
|
@@ -2304,6 +2965,13 @@ async function hostsOfOtherSites(strapi2, documentId) {
|
|
|
2304
2965
|
}
|
|
2305
2966
|
const register = ({ strapi: strapi2 }) => {
|
|
2306
2967
|
registerComponents(strapi2);
|
|
2968
|
+
registerPreviewShortcut(strapi2);
|
|
2969
|
+
strapi2.hook("strapi::content-types.beforeSync").register(async () => {
|
|
2970
|
+
const report = await renameLegacyUids(strapi2);
|
|
2971
|
+
if (report.actions + report.subjects + report.layouts > 0) {
|
|
2972
|
+
strapi2.log.info(`[micelio] moved legacy category and tag UIDs: ${JSON.stringify(report)}`);
|
|
2973
|
+
}
|
|
2974
|
+
});
|
|
2307
2975
|
strapi2.documents.use(siteCreatedHook(strapi2));
|
|
2308
2976
|
strapi2.documents.use(siteRules(strapi2));
|
|
2309
2977
|
strapi2.documents.use(siteSectionInstances(strapi2));
|
|
@@ -2380,14 +3048,32 @@ const contentApiRoutes = () => ({
|
|
|
2380
3048
|
}
|
|
2381
3049
|
]
|
|
2382
3050
|
});
|
|
2383
|
-
const siteRoutes = strapi.factories.createCoreRouter(SITE_UID, {
|
|
3051
|
+
const siteRoutes = strapi.factories.createCoreRouter(SITE_UID$1, {
|
|
2384
3052
|
prefix: "/micelio",
|
|
2385
3053
|
only: ["find", "findOne"]
|
|
2386
3054
|
});
|
|
3055
|
+
const scoped = () => ({ middlewares: [SITE_SCOPE_MIDDLEWARE] });
|
|
3056
|
+
const config = () => ({
|
|
3057
|
+
find: scoped(),
|
|
3058
|
+
findOne: scoped(),
|
|
3059
|
+
create: scoped(),
|
|
3060
|
+
update: scoped(),
|
|
3061
|
+
delete: scoped()
|
|
3062
|
+
});
|
|
3063
|
+
const categoryRoutes = strapi.factories.createCoreRouter(CATEGORY_UID, {
|
|
3064
|
+
prefix: "",
|
|
3065
|
+
config: config()
|
|
3066
|
+
});
|
|
3067
|
+
const tagRoutes = strapi.factories.createCoreRouter(TAG_UID, {
|
|
3068
|
+
prefix: "",
|
|
3069
|
+
config: config()
|
|
3070
|
+
});
|
|
2387
3071
|
const routes = {
|
|
2388
3072
|
"content-api": contentApiRoutes,
|
|
2389
3073
|
admin: adminRoutes,
|
|
2390
|
-
site: siteRoutes
|
|
3074
|
+
site: siteRoutes,
|
|
3075
|
+
category: categoryRoutes,
|
|
3076
|
+
tag: tagRoutes
|
|
2391
3077
|
};
|
|
2392
3078
|
const extensions = ({ strapi: strapi2 }) => createExtensionRegistry(strapi2);
|
|
2393
3079
|
const hooks = ({ strapi: strapi2 }) => createHookRegistry(strapi2.log);
|
|
@@ -2630,7 +3316,7 @@ function asList(value) {
|
|
|
2630
3316
|
function exportedTypes(strapi2, personal) {
|
|
2631
3317
|
const types = [];
|
|
2632
3318
|
for (const [uid, schema] of Object.entries(strapi2.contentTypes)) {
|
|
2633
|
-
if (uid !== SITE_UID && !isSiteScoped(schema)) continue;
|
|
3319
|
+
if (uid !== SITE_UID$1 && !isSiteScoped(schema)) continue;
|
|
2634
3320
|
if (!isWritten(exportPolicyOf(schema), personal)) continue;
|
|
2635
3321
|
types.push({
|
|
2636
3322
|
uid,
|
|
@@ -2646,20 +3332,20 @@ async function siteRowsOf(strapi2, type, site2, context) {
|
|
|
2646
3332
|
const query = strapi2.db.query(type.uid);
|
|
2647
3333
|
const owned = await query.findMany({
|
|
2648
3334
|
select: ["documentId"],
|
|
2649
|
-
where: { [SITE_ATTRIBUTE]: { documentId: site2.documentId } }
|
|
3335
|
+
where: { [SITE_ATTRIBUTE$1]: { documentId: site2.documentId } }
|
|
2650
3336
|
});
|
|
2651
3337
|
const documentIds = [...new Set(owned.map((row) => row.documentId))];
|
|
2652
3338
|
if (documentIds.length === 0) return [];
|
|
2653
3339
|
return await query.findMany({
|
|
2654
3340
|
where: { documentId: { $in: documentIds } },
|
|
2655
|
-
populate: populateOf(type.attributes, context, /* @__PURE__ */ new Set([SITE_ATTRIBUTE]))
|
|
3341
|
+
populate: populateOf(type.attributes, context, /* @__PURE__ */ new Set([SITE_ATTRIBUTE$1]))
|
|
2656
3342
|
});
|
|
2657
3343
|
}
|
|
2658
3344
|
function attributesOf(strapi2, uid) {
|
|
2659
3345
|
return strapi2.contentType(uid).attributes;
|
|
2660
3346
|
}
|
|
2661
3347
|
function documentsOf(type, rows, context) {
|
|
2662
|
-
const skip = new Set(type.uid === SITE_UID ? [] : [SITE_ATTRIBUTE]);
|
|
3348
|
+
const skip = new Set(type.uid === SITE_UID$1 ? [] : [SITE_ATTRIBUTE$1]);
|
|
2663
3349
|
const documents = /* @__PURE__ */ new Map();
|
|
2664
3350
|
for (const row of rows) {
|
|
2665
3351
|
const version2 = {
|
|
@@ -2869,15 +3555,15 @@ async function exportSite(strapi2, request, output) {
|
|
|
2869
3555
|
},
|
|
2870
3556
|
personal
|
|
2871
3557
|
};
|
|
2872
|
-
const siteRows = await strapi2.db.query(SITE_UID).findMany({
|
|
3558
|
+
const siteRows = await strapi2.db.query(SITE_UID$1).findMany({
|
|
2873
3559
|
where: { slug: request.site },
|
|
2874
|
-
populate: populateOf(attributesOf(strapi2, SITE_UID), context)
|
|
3560
|
+
populate: populateOf(attributesOf(strapi2, SITE_UID$1), context)
|
|
2875
3561
|
});
|
|
2876
3562
|
const site2 = siteRows[0];
|
|
2877
3563
|
if (!site2) throw new ExportError("exportSiteNotFound", `There is no site "${request.site}"`);
|
|
2878
3564
|
const contents = [];
|
|
2879
3565
|
for (const type of types) {
|
|
2880
|
-
const rows = type.uid === SITE_UID ? siteRows : await siteRowsOf(strapi2, type, site2, context);
|
|
3566
|
+
const rows = type.uid === SITE_UID$1 ? siteRows : await siteRowsOf(strapi2, type, site2, context);
|
|
2881
3567
|
contents.push({ type: type.name, documents: documentsOf(type, rows, context) });
|
|
2882
3568
|
}
|
|
2883
3569
|
const index2 = await mediaIndex(strapi2, media2);
|
|
@@ -3413,7 +4099,7 @@ function all(types, strapi2) {
|
|
|
3413
4099
|
async function targetSite(strapi2, staged, request) {
|
|
3414
4100
|
const archived = staged.contents.get("site").documents[0];
|
|
3415
4101
|
const data = archived.versions[0].data;
|
|
3416
|
-
const rows = await strapi2.db.query(SITE_UID).findMany({
|
|
4102
|
+
const rows = await strapi2.db.query(SITE_UID$1).findMany({
|
|
3417
4103
|
select: ["documentId", "slug", "hosts", "isDefault"]
|
|
3418
4104
|
});
|
|
3419
4105
|
const sites = [...new Map(rows.map((row) => [row.documentId, row])).values()];
|
|
@@ -3707,7 +4393,7 @@ async function writeContent(strapi2, plan2, files, request, report) {
|
|
|
3707
4393
|
const context = deserialiseContext(strapi2, plan2, files, written);
|
|
3708
4394
|
const shaOf = new Map([...files.entries()].map(([sha256, id2]) => [id2, sha256]));
|
|
3709
4395
|
const ordered = [...plan2.types].sort(
|
|
3710
|
-
(a, b) => a.uid === SITE_UID ? -1 : b.uid === SITE_UID ? 1 : compare(a.name, b.name)
|
|
4396
|
+
(a, b) => a.uid === SITE_UID$1 ? -1 : b.uid === SITE_UID$1 ? 1 : compare(a.name, b.name)
|
|
3711
4397
|
);
|
|
3712
4398
|
const pending = [];
|
|
3713
4399
|
for (const type of ordered) {
|
|
@@ -3723,7 +4409,7 @@ async function writeContent(strapi2, plan2, files, request, report) {
|
|
|
3723
4409
|
}
|
|
3724
4410
|
if (request.mode === "replace") {
|
|
3725
4411
|
for (const type of ordered) {
|
|
3726
|
-
if (type.uid === SITE_UID) continue;
|
|
4412
|
+
if (type.uid === SITE_UID$1) continue;
|
|
3727
4413
|
const kept = new Set(plan2.staged.contents.get(type.name).documents.map((d) => d.documentId));
|
|
3728
4414
|
const rows = await siteRowsOf(strapi2, type, plan2.site, serialiseContext(strapi2, plan2, shaOf));
|
|
3729
4415
|
for (const documentId of new Set(rows.map((row) => row.documentId))) {
|
|
@@ -3735,9 +4421,9 @@ async function writeContent(strapi2, plan2, files, request, report) {
|
|
|
3735
4421
|
}
|
|
3736
4422
|
}
|
|
3737
4423
|
async function writeDocument(strapi2, plan2, type, document, context, shaOf) {
|
|
3738
|
-
const isSite = type.uid === SITE_UID;
|
|
4424
|
+
const isSite = type.uid === SITE_UID$1;
|
|
3739
4425
|
const documentId = isSite ? plan2.site.documentId : document.documentId;
|
|
3740
|
-
const skip = new Set(isSite ? [] : [SITE_ATTRIBUTE]);
|
|
4426
|
+
const skip = new Set(isSite ? [] : [SITE_ATTRIBUTE$1]);
|
|
3741
4427
|
const query = strapi2.db.query(type.uid);
|
|
3742
4428
|
const rows = await query.findMany({
|
|
3743
4429
|
where: { documentId },
|
|
@@ -3760,7 +4446,7 @@ async function writeDocument(strapi2, plan2, type, document, context, shaOf) {
|
|
|
3760
4446
|
pending ||= result.pending > 0;
|
|
3761
4447
|
const data = { ...result.data };
|
|
3762
4448
|
if (!exists) {
|
|
3763
|
-
if (!isSite) data[SITE_ATTRIBUTE] = plan2.site.documentId;
|
|
4449
|
+
if (!isSite) data[SITE_ATTRIBUTE$1] = plan2.site.documentId;
|
|
3764
4450
|
await documents.create({ locale, data: { ...data, documentId } });
|
|
3765
4451
|
exists = true;
|
|
3766
4452
|
} else {
|
|
@@ -3813,7 +4499,7 @@ async function writeDocument(strapi2, plan2, type, document, context, shaOf) {
|
|
|
3813
4499
|
}
|
|
3814
4500
|
function desiredData(type, version2, plan2, rows) {
|
|
3815
4501
|
const data = knownData(type.attributes, version2.data);
|
|
3816
|
-
if (type.uid === SITE_UID) {
|
|
4502
|
+
if (type.uid === SITE_UID$1) {
|
|
3817
4503
|
data.isDefault = rows[0]?.isDefault === true;
|
|
3818
4504
|
if (!plan2.site.isNew) data.slug = plan2.site.slug;
|
|
3819
4505
|
}
|
|
@@ -3822,7 +4508,7 @@ function desiredData(type, version2, plan2, rows) {
|
|
|
3822
4508
|
async function checkOwner(strapi2, type, documentId, site2) {
|
|
3823
4509
|
const rows = await strapi2.db.query(type.uid).findMany({
|
|
3824
4510
|
where: { documentId },
|
|
3825
|
-
populate: { [SITE_ATTRIBUTE]: { select: ["documentId"] } }
|
|
4511
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["documentId"] } }
|
|
3826
4512
|
});
|
|
3827
4513
|
if (rows.some((row) => row.site?.documentId && row.site.documentId !== site2)) {
|
|
3828
4514
|
throw new ExportError(
|
|
@@ -3900,7 +4586,9 @@ const transitions = ({ strapi: strapi2 }) => ({
|
|
|
3900
4586
|
}
|
|
3901
4587
|
});
|
|
3902
4588
|
const services = {
|
|
3903
|
-
site: strapi.factories.createCoreService(SITE_UID),
|
|
4589
|
+
site: strapi.factories.createCoreService(SITE_UID$1),
|
|
4590
|
+
category: strapi.factories.createCoreService(CATEGORY_UID),
|
|
4591
|
+
tag: strapi.factories.createCoreService(TAG_UID),
|
|
3904
4592
|
transitions,
|
|
3905
4593
|
hostCheck,
|
|
3906
4594
|
hooks,
|
|
@@ -3913,7 +4601,7 @@ const index = {
|
|
|
3913
4601
|
register,
|
|
3914
4602
|
bootstrap,
|
|
3915
4603
|
destroy,
|
|
3916
|
-
config,
|
|
4604
|
+
config: config$1,
|
|
3917
4605
|
controllers,
|
|
3918
4606
|
routes,
|
|
3919
4607
|
services,
|
|
@@ -3921,10 +4609,13 @@ const index = {
|
|
|
3921
4609
|
policies,
|
|
3922
4610
|
middlewares
|
|
3923
4611
|
};
|
|
4612
|
+
exports.CATEGORY_UID = CATEGORY_UID;
|
|
3924
4613
|
exports.EDITORIAL_STATES = EDITORIAL_STATES;
|
|
3925
|
-
exports.
|
|
4614
|
+
exports.READ_ACTIONS = READ_ACTIONS$1;
|
|
4615
|
+
exports.SITE_ATTRIBUTE = SITE_ATTRIBUTE$1;
|
|
3926
4616
|
exports.SITE_SCOPE_MIDDLEWARE = SITE_SCOPE_MIDDLEWARE;
|
|
3927
|
-
exports.SITE_UID = SITE_UID;
|
|
4617
|
+
exports.SITE_UID = SITE_UID$1;
|
|
4618
|
+
exports.TAG_UID = TAG_UID;
|
|
3928
4619
|
exports.default = index;
|
|
3929
4620
|
exports.formatHostCheckReport = formatHostCheckReport;
|
|
3930
4621
|
exports.missingLocales = missingLocales;
|