@nocobase/plugin-multi-portal 3.0.0-alpha.4 → 3.0.0-alpha.5
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 +7 -5
- package/dist/client-v2/499.245037eea4cc7266.js +10 -0
- package/dist/client-v2/556.30bcd5e9d0a66adc.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/client-v2/layoutRegistration.d.ts +1 -5
- package/dist/client-v2/pages/MultiPortalsPage.d.ts +0 -5
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +27 -2
- package/dist/externalVersion.js +8 -8
- package/dist/locale/en-US.json +17 -12
- package/dist/locale/zh-CN.json +15 -10
- package/dist/node_modules/tar/package.json +1 -1
- package/dist/server/collections/multiPortals.js +2 -11
- package/dist/server/plugin.d.ts +3 -3
- package/dist/server/plugin.js +201 -165
- package/package.json +3 -3
- package/dist/client-v2/499.ef2ff0c022687485.js +0 -10
- package/dist/client-v2/556.37df9197ce5c3452.js +0 -10
package/dist/server/plugin.js
CHANGED
|
@@ -60,9 +60,9 @@ const MULTI_PORTAL_RUNTIME_FIELDS = [
|
|
|
60
60
|
"portalName",
|
|
61
61
|
"routePath",
|
|
62
62
|
"authCheck",
|
|
63
|
-
"enabled"
|
|
63
|
+
"enabled",
|
|
64
|
+
"uiLayoutUid"
|
|
64
65
|
];
|
|
65
|
-
const MULTI_PORTAL_RUNTIME_QUERY_FIELDS = [...MULTI_PORTAL_RUNTIME_FIELDS, "uiLayoutUid"];
|
|
66
66
|
const MULTI_PORTAL_ACCESSIBLE_FIELDS = [
|
|
67
67
|
"uid",
|
|
68
68
|
"title",
|
|
@@ -71,10 +71,9 @@ const MULTI_PORTAL_ACCESSIBLE_FIELDS = [
|
|
|
71
71
|
"portalName",
|
|
72
72
|
"routePath",
|
|
73
73
|
"authCheck",
|
|
74
|
-
"enabled"
|
|
74
|
+
"enabled",
|
|
75
|
+
"uiLayoutUid"
|
|
75
76
|
];
|
|
76
|
-
const MULTI_PORTAL_ACCESSIBLE_QUERY_FIELDS = [...MULTI_PORTAL_ACCESSIBLE_FIELDS, "uiLayoutUid"];
|
|
77
|
-
const MULTI_PORTAL_UI_LAYOUT_RUNTIME_FIELDS = ["layoutType"];
|
|
78
77
|
const DESKTOP_ROUTE_ROLE_PERMISSION_TARGET_FIELDS = ["id", "title", "hidden", "parentId", "options"];
|
|
79
78
|
const UI_LAYOUT_DESKTOP_ROUTE_WRITE_LAYOUT_HANDLER_TAG = "plugin-ui-layout:desktop-route-write-layout";
|
|
80
79
|
const MAIN_APP_NAME = "main";
|
|
@@ -181,7 +180,7 @@ function getDefaultMultiPortalRecord(options = {}) {
|
|
|
181
180
|
authCheck: true,
|
|
182
181
|
enabled: true,
|
|
183
182
|
...options.isDefault ? { isDefault: true } : {},
|
|
184
|
-
uiLayoutUid:
|
|
183
|
+
uiLayoutUid: import_constants.ADMIN_UI_LAYOUT_UID
|
|
185
184
|
};
|
|
186
185
|
}
|
|
187
186
|
function getFreshMultiPortalRecords() {
|
|
@@ -198,7 +197,7 @@ function getFixedLayoutMultiPortalRecords() {
|
|
|
198
197
|
routePath: "/admin",
|
|
199
198
|
authCheck: true,
|
|
200
199
|
enabled: true,
|
|
201
|
-
uiLayoutUid:
|
|
200
|
+
uiLayoutUid: import_constants.ADMIN_UI_LAYOUT_UID
|
|
202
201
|
},
|
|
203
202
|
{
|
|
204
203
|
uid: import_constants.DEFAULT_MOBILE_MULTI_PORTAL_UID,
|
|
@@ -209,7 +208,7 @@ function getFixedLayoutMultiPortalRecords() {
|
|
|
209
208
|
routePath: "/mobile",
|
|
210
209
|
authCheck: true,
|
|
211
210
|
enabled: true,
|
|
212
|
-
uiLayoutUid:
|
|
211
|
+
uiLayoutUid: import_constants.MOBILE_UI_LAYOUT_UID
|
|
213
212
|
}
|
|
214
213
|
];
|
|
215
214
|
}
|
|
@@ -294,6 +293,13 @@ function getPortalDeployBasePath(appName, portalName) {
|
|
|
294
293
|
const portalPath = appName === MAIN_APP_NAME ? `/${PORTAL_CLIENT_PREFIX}/${portalName}/` : `/${PORTAL_CLIENT_PREFIX}/apps/${appName}/${portalName}/`;
|
|
295
294
|
return resolvePortalStoragePublicPath(joinPortalStoragePublicPath(process.env.APP_PUBLIC_PATH || "/", portalPath));
|
|
296
295
|
}
|
|
296
|
+
function getPortalDeployBasePathCandidates(appName, portalName) {
|
|
297
|
+
const expectedBasePaths = [getPortalDeployBasePath(appName, portalName)];
|
|
298
|
+
if (appName !== MAIN_APP_NAME) {
|
|
299
|
+
expectedBasePaths.push(getPortalDeployBasePath(MAIN_APP_NAME, portalName));
|
|
300
|
+
}
|
|
301
|
+
return expectedBasePaths;
|
|
302
|
+
}
|
|
297
303
|
function createPortalDeployUploadMiddleware() {
|
|
298
304
|
const storage = import_utils.koaMulter.diskStorage({
|
|
299
305
|
destination: import_os.default.tmpdir(),
|
|
@@ -620,9 +626,9 @@ function validatePortalDeployBasePath(appName, portalName, basePath) {
|
|
|
620
626
|
if (normalizedBasePath.includes("..")) {
|
|
621
627
|
throw new Error('basePath cannot contain ".."');
|
|
622
628
|
}
|
|
623
|
-
const
|
|
624
|
-
if (normalizedBasePath
|
|
625
|
-
throw new Error(`basePath must be ${
|
|
629
|
+
const expectedBasePaths = getPortalDeployBasePathCandidates(appName, portalName);
|
|
630
|
+
if (!expectedBasePaths.includes(normalizedBasePath)) {
|
|
631
|
+
throw new Error(`basePath must be ${expectedBasePaths.join(" or ")}`);
|
|
626
632
|
}
|
|
627
633
|
}
|
|
628
634
|
function isPortalDeployTarEntry(entry) {
|
|
@@ -860,19 +866,11 @@ function collectDesktopRouteIds(record) {
|
|
|
860
866
|
}
|
|
861
867
|
return uniqueDesktopRouteIds(routeIds);
|
|
862
868
|
}
|
|
863
|
-
function pickMultiPortalUiLayoutRuntimeFields(record) {
|
|
864
|
-
const result = {};
|
|
865
|
-
for (const field of MULTI_PORTAL_UI_LAYOUT_RUNTIME_FIELDS) {
|
|
866
|
-
result[field] = getRecordField(record, field);
|
|
867
|
-
}
|
|
868
|
-
return result;
|
|
869
|
-
}
|
|
870
869
|
function pickMultiPortalRuntimeFields(record) {
|
|
871
870
|
const result = {};
|
|
872
871
|
for (const field of MULTI_PORTAL_RUNTIME_FIELDS) {
|
|
873
872
|
result[field] = getRecordField(record, field);
|
|
874
873
|
}
|
|
875
|
-
result.uiLayout = pickMultiPortalUiLayoutRuntimeFields(getRecordField(record, "uiLayout"));
|
|
876
874
|
return result;
|
|
877
875
|
}
|
|
878
876
|
function pickMultiPortalAccessibleFields(record) {
|
|
@@ -880,7 +878,6 @@ function pickMultiPortalAccessibleFields(record) {
|
|
|
880
878
|
for (const field of MULTI_PORTAL_ACCESSIBLE_FIELDS) {
|
|
881
879
|
result[field] = getRecordField(record, field) ?? null;
|
|
882
880
|
}
|
|
883
|
-
result.uiLayout = pickMultiPortalUiLayoutRuntimeFields(getRecordField(record, "uiLayout"));
|
|
884
881
|
return result;
|
|
885
882
|
}
|
|
886
883
|
function getExplicitRequestedLayoutUid(layout) {
|
|
@@ -1130,14 +1127,27 @@ async function seedHistoricalMultiPortals(db) {
|
|
|
1130
1127
|
}
|
|
1131
1128
|
await repairFixedLayoutMultiPortalRecords(db);
|
|
1132
1129
|
}
|
|
1133
|
-
async function
|
|
1130
|
+
async function validateMultiPortalUiLayoutUidWrite(ctx, next) {
|
|
1131
|
+
var _a;
|
|
1134
1132
|
const targets = await getMultiPortalWriteTargets(ctx, ["uiLayoutUid"]);
|
|
1133
|
+
const actionName = (_a = ctx.action) == null ? void 0 : _a.actionName;
|
|
1134
|
+
const createsWhenMissing = actionName === "create" || actionName === "firstOrCreate" || actionName === "updateOrCreate";
|
|
1135
1135
|
for (const { existing, values } of targets) {
|
|
1136
|
-
|
|
1136
|
+
const hasUiLayoutUid = Object.prototype.hasOwnProperty.call(values, "uiLayoutUid");
|
|
1137
|
+
if (!existing && createsWhenMissing && !hasUiLayoutUid) {
|
|
1138
|
+
ctx.throw(400, `Portal UI layout must be one of: ${import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS.join(", ")}`);
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
if (!hasUiLayoutUid) {
|
|
1137
1142
|
continue;
|
|
1138
1143
|
}
|
|
1139
|
-
if (
|
|
1140
|
-
ctx.throw(400,
|
|
1144
|
+
if (!(0, import_constants.isMultiPortalUiLayoutUid)(values.uiLayoutUid)) {
|
|
1145
|
+
ctx.throw(400, `Portal UI layout must be one of: ${import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS.join(", ")}`);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
const existingUiLayoutUid = existing == null ? void 0 : existing.get("uiLayoutUid");
|
|
1149
|
+
if (existing && existingUiLayoutUid !== values.uiLayoutUid) {
|
|
1150
|
+
ctx.throw(400, "Portal UI layout cannot be changed");
|
|
1141
1151
|
return;
|
|
1142
1152
|
}
|
|
1143
1153
|
}
|
|
@@ -1165,20 +1175,8 @@ async function findRequestedMultiPortal(ctx, transaction) {
|
|
|
1165
1175
|
ctx.throw(400, `Portal '${portalUid}' does not support desktop routes`);
|
|
1166
1176
|
}
|
|
1167
1177
|
const uiLayoutUid = portal.get("uiLayoutUid");
|
|
1168
|
-
if (
|
|
1169
|
-
ctx.throw(400, `Portal '${portalUid}' has
|
|
1170
|
-
}
|
|
1171
|
-
const uiLayout = await ctx.db.getRepository("uiLayouts").findOne({
|
|
1172
|
-
filter: {
|
|
1173
|
-
uid: uiLayoutUid,
|
|
1174
|
-
enabled: true
|
|
1175
|
-
},
|
|
1176
|
-
fields: ["uid"],
|
|
1177
|
-
...transaction ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1178
|
-
transaction
|
|
1179
|
-
});
|
|
1180
|
-
if (!uiLayout) {
|
|
1181
|
-
ctx.throw(400, `Portal '${portalUid}' has no enabled backing UI layout`);
|
|
1178
|
+
if (!(0, import_constants.isMultiPortalUiLayoutUid)(uiLayoutUid)) {
|
|
1179
|
+
ctx.throw(400, `Portal '${portalUid}' has an unsupported UI layout UID`);
|
|
1182
1180
|
}
|
|
1183
1181
|
const usesLayoutPermissions = (0, import_constants.isDefaultLayoutMultiPortalUid)(portalUid);
|
|
1184
1182
|
return {
|
|
@@ -1363,7 +1361,7 @@ async function removeRouteIdsWithUnauthorizedAncestors(ctx, routeIds) {
|
|
|
1363
1361
|
}
|
|
1364
1362
|
}
|
|
1365
1363
|
}
|
|
1366
|
-
async function getMultiPortalAccessibleRouteIds(ctx,
|
|
1364
|
+
async function getMultiPortalAccessibleRouteIds(ctx, portalContext) {
|
|
1367
1365
|
const currentRoles = getCurrentRoles(ctx);
|
|
1368
1366
|
if (currentRoles.includes("root")) {
|
|
1369
1367
|
return;
|
|
@@ -1371,11 +1369,11 @@ async function getMultiPortalAccessibleRouteIds(ctx, multiPortalUid) {
|
|
|
1371
1369
|
if (!currentRoles.length) {
|
|
1372
1370
|
return /* @__PURE__ */ new Set();
|
|
1373
1371
|
}
|
|
1374
|
-
const routePermissions = await ctx.db.getRepository("rolesMultiPortalDesktopRoutes").find({
|
|
1372
|
+
const routePermissions = await ctx.db.getRepository(portalContext.relation === "uiLayouts" ? "rolesDesktopRoutes" : "rolesMultiPortalDesktopRoutes").find({
|
|
1375
1373
|
fields: ["desktopRouteId"],
|
|
1376
1374
|
filter: {
|
|
1377
1375
|
roleName: currentRoles,
|
|
1378
|
-
multiPortalUid
|
|
1376
|
+
...portalContext.relation === "multiPortals" ? { multiPortalUid: portalContext.portalUid } : {}
|
|
1379
1377
|
}
|
|
1380
1378
|
});
|
|
1381
1379
|
const routeIds = /* @__PURE__ */ new Set();
|
|
@@ -1391,7 +1389,7 @@ async function getMultiPortalAccessibleRouteIds(ctx, multiPortalUid) {
|
|
|
1391
1389
|
const portalRoutes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1392
1390
|
fields: ["id"],
|
|
1393
1391
|
filter: {
|
|
1394
|
-
...
|
|
1392
|
+
...portalContext.filter,
|
|
1395
1393
|
id: Array.from(routeIds)
|
|
1396
1394
|
}
|
|
1397
1395
|
});
|
|
@@ -1421,9 +1419,107 @@ function setDesktopRouteChildren(route, children) {
|
|
|
1421
1419
|
const maybeModel = route;
|
|
1422
1420
|
if (typeof maybeModel.setDataValue === "function") {
|
|
1423
1421
|
maybeModel.setDataValue("children", children);
|
|
1422
|
+
} else {
|
|
1423
|
+
maybeModel.children = children;
|
|
1424
|
+
}
|
|
1425
|
+
if (!maybeModel._options) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
if (!maybeModel._options.includeNames) {
|
|
1429
|
+
maybeModel._options.includeNames = ["children"];
|
|
1424
1430
|
return;
|
|
1425
1431
|
}
|
|
1426
|
-
|
|
1432
|
+
if (!maybeModel._options.includeNames.includes("children")) {
|
|
1433
|
+
maybeModel._options.includeNames.push("children");
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
function getDesktopRouteId(route) {
|
|
1437
|
+
const id = getRecordField(route, "id");
|
|
1438
|
+
return id === null || id === void 0 ? void 0 : String(id);
|
|
1439
|
+
}
|
|
1440
|
+
function getDesktopRouteParentId(route) {
|
|
1441
|
+
const parentId = getRecordField(route, "parentId");
|
|
1442
|
+
return parentId === null || parentId === void 0 ? void 0 : String(parentId);
|
|
1443
|
+
}
|
|
1444
|
+
function collectDesktopRouteStringIds(routes, routeIds) {
|
|
1445
|
+
for (const route of routes) {
|
|
1446
|
+
const routeId = getDesktopRouteId(route);
|
|
1447
|
+
if (routeId) {
|
|
1448
|
+
routeIds.add(routeId);
|
|
1449
|
+
}
|
|
1450
|
+
const children = getRecordField(route, "children");
|
|
1451
|
+
if (Array.isArray(children)) {
|
|
1452
|
+
collectDesktopRouteStringIds(children, routeIds);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
function removeNestedRootDesktopRoutes(routes) {
|
|
1457
|
+
if (!Array.isArray(routes)) {
|
|
1458
|
+
return [];
|
|
1459
|
+
}
|
|
1460
|
+
const routeIds = /* @__PURE__ */ new Set();
|
|
1461
|
+
collectDesktopRouteStringIds(routes, routeIds);
|
|
1462
|
+
return routes.filter((route) => {
|
|
1463
|
+
const parentId = getDesktopRouteParentId(route);
|
|
1464
|
+
return !parentId || !routeIds.has(parentId);
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
function buildAccessibleDesktopRouteTreeWithAncestors(routes, accessibleRouteIds) {
|
|
1468
|
+
const routeById = /* @__PURE__ */ new Map();
|
|
1469
|
+
const childrenByParentId = /* @__PURE__ */ new Map();
|
|
1470
|
+
const roots = [];
|
|
1471
|
+
for (const route of routes) {
|
|
1472
|
+
const routeId = getDesktopRouteId(route);
|
|
1473
|
+
if (!routeId) {
|
|
1474
|
+
continue;
|
|
1475
|
+
}
|
|
1476
|
+
setDesktopRouteChildren(route, void 0);
|
|
1477
|
+
routeById.set(routeId, route);
|
|
1478
|
+
}
|
|
1479
|
+
for (const route of routes) {
|
|
1480
|
+
const routeId = getDesktopRouteId(route);
|
|
1481
|
+
if (!routeId || !routeById.has(routeId)) {
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
const parentId = getDesktopRouteParentId(route);
|
|
1485
|
+
if (!parentId || !routeById.has(parentId)) {
|
|
1486
|
+
roots.push(route);
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
const children = childrenByParentId.get(parentId) ?? [];
|
|
1490
|
+
children.push(route);
|
|
1491
|
+
childrenByParentId.set(parentId, children);
|
|
1492
|
+
}
|
|
1493
|
+
const visitRoute = (route, visitingRouteIds) => {
|
|
1494
|
+
const routeId = getDesktopRouteId(route);
|
|
1495
|
+
if (!routeId || visitingRouteIds.has(routeId)) {
|
|
1496
|
+
return void 0;
|
|
1497
|
+
}
|
|
1498
|
+
visitingRouteIds.add(routeId);
|
|
1499
|
+
const visibleChildren = (childrenByParentId.get(routeId) ?? []).map((child) => visitRoute(child, visitingRouteIds)).filter((child) => child !== void 0);
|
|
1500
|
+
visitingRouteIds.delete(routeId);
|
|
1501
|
+
if (!accessibleRouteIds.has(routeId) && visibleChildren.length === 0) {
|
|
1502
|
+
return void 0;
|
|
1503
|
+
}
|
|
1504
|
+
setDesktopRouteChildren(route, visibleChildren.length ? visibleChildren : void 0);
|
|
1505
|
+
return route;
|
|
1506
|
+
};
|
|
1507
|
+
return roots.map((route) => visitRoute(route, /* @__PURE__ */ new Set())).filter((route) => route !== void 0);
|
|
1508
|
+
}
|
|
1509
|
+
async function includeDesktopRouteAncestorsForListAccessible(ctx, routes, portalFilter) {
|
|
1510
|
+
if (!Array.isArray(routes)) {
|
|
1511
|
+
return routes;
|
|
1512
|
+
}
|
|
1513
|
+
const accessibleRouteIds = /* @__PURE__ */ new Set();
|
|
1514
|
+
collectDesktopRouteStringIds(routes, accessibleRouteIds);
|
|
1515
|
+
if (!accessibleRouteIds.size) {
|
|
1516
|
+
return routes;
|
|
1517
|
+
}
|
|
1518
|
+
const portalRoutes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1519
|
+
sort: "sort",
|
|
1520
|
+
filter: portalFilter
|
|
1521
|
+
});
|
|
1522
|
+
return buildAccessibleDesktopRouteTreeWithAncestors(portalRoutes, accessibleRouteIds);
|
|
1427
1523
|
}
|
|
1428
1524
|
function removeDesktopRoutesByIds(routes, routeIds) {
|
|
1429
1525
|
return routes.map((route) => {
|
|
@@ -1490,23 +1586,26 @@ async function removeMultiPortalOwnedRouteFromGetResponse(ctx) {
|
|
|
1490
1586
|
ctx.body = void 0;
|
|
1491
1587
|
}
|
|
1492
1588
|
async function replaceListAccessibleRoutesWithPortalScopedRoutes(ctx, portalContext) {
|
|
1493
|
-
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext
|
|
1589
|
+
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext);
|
|
1494
1590
|
if (routeIds && routeIds.size === 0) {
|
|
1495
1591
|
ctx.body = [];
|
|
1496
1592
|
return;
|
|
1497
1593
|
}
|
|
1498
|
-
|
|
1594
|
+
const routes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1499
1595
|
tree: true,
|
|
1500
1596
|
sort: "sort",
|
|
1501
1597
|
filter: {
|
|
1502
|
-
...
|
|
1598
|
+
...portalContext.filter,
|
|
1503
1599
|
...routeIds ? { id: Array.from(routeIds) } : {}
|
|
1504
1600
|
}
|
|
1505
1601
|
});
|
|
1602
|
+
ctx.body = removeNestedRootDesktopRoutes(
|
|
1603
|
+
await includeDesktopRouteAncestorsForListAccessible(ctx, routes, portalContext.filter)
|
|
1604
|
+
);
|
|
1506
1605
|
}
|
|
1507
1606
|
async function replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext) {
|
|
1508
1607
|
var _a;
|
|
1509
|
-
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext
|
|
1608
|
+
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext);
|
|
1510
1609
|
if (routeIds && routeIds.size === 0) {
|
|
1511
1610
|
ctx.status = 204;
|
|
1512
1611
|
ctx.body = void 0;
|
|
@@ -1516,7 +1615,7 @@ async function replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext
|
|
|
1516
1615
|
sort: "sort",
|
|
1517
1616
|
filterByTk: (_a = ctx.action) == null ? void 0 : _a.params.filterByTk,
|
|
1518
1617
|
filter: {
|
|
1519
|
-
...
|
|
1618
|
+
...portalContext.filter,
|
|
1520
1619
|
...routeIds ? { id: Array.from(routeIds) } : {}
|
|
1521
1620
|
}
|
|
1522
1621
|
});
|
|
@@ -1553,13 +1652,10 @@ async function addMultiPortalListAccessibleGuard(ctx, next) {
|
|
|
1553
1652
|
return;
|
|
1554
1653
|
}
|
|
1555
1654
|
await next();
|
|
1556
|
-
if (
|
|
1655
|
+
if (portalContext) {
|
|
1557
1656
|
await replaceListAccessibleRoutesWithPortalScopedRoutes(ctx, portalContext);
|
|
1558
1657
|
return;
|
|
1559
1658
|
}
|
|
1560
|
-
if ((portalContext == null ? void 0 : portalContext.relation) === "uiLayouts") {
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
1659
|
await removeMultiPortalOwnedRoutesFromListResponse(ctx);
|
|
1564
1660
|
}
|
|
1565
1661
|
async function addMultiPortalGetAccessibleGuard(ctx, next) {
|
|
@@ -1570,17 +1666,13 @@ async function addMultiPortalGetAccessibleGuard(ctx, next) {
|
|
|
1570
1666
|
return;
|
|
1571
1667
|
}
|
|
1572
1668
|
await next();
|
|
1573
|
-
if (
|
|
1669
|
+
if (portalContext) {
|
|
1574
1670
|
await replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext);
|
|
1575
1671
|
return;
|
|
1576
1672
|
}
|
|
1577
|
-
if ((portalContext == null ? void 0 : portalContext.relation) === "uiLayouts") {
|
|
1578
|
-
return;
|
|
1579
|
-
}
|
|
1580
1673
|
await removeMultiPortalOwnedRouteFromGetResponse(ctx);
|
|
1581
1674
|
}
|
|
1582
1675
|
async function mapMultiPortalLayoutToUiLayoutForRolePermissionTargets(ctx, next) {
|
|
1583
|
-
var _a;
|
|
1584
1676
|
const portalRequest = await findRequestedMultiPortal(ctx);
|
|
1585
1677
|
if (portalRequest.requested && !portalRequest.portal) {
|
|
1586
1678
|
ctx.status = 200;
|
|
@@ -1588,22 +1680,19 @@ async function mapMultiPortalLayoutToUiLayoutForRolePermissionTargets(ctx, next)
|
|
|
1588
1680
|
return;
|
|
1589
1681
|
}
|
|
1590
1682
|
const scope = portalRequest.scope;
|
|
1591
|
-
if (
|
|
1592
|
-
if ((_a = ctx.action) == null ? void 0 : _a.params) {
|
|
1593
|
-
ctx.action.params.layout = scope.uiLayoutUid;
|
|
1594
|
-
}
|
|
1595
|
-
await next();
|
|
1596
|
-
return;
|
|
1597
|
-
}
|
|
1598
|
-
if ((scope == null ? void 0 : scope.relation) === "multiPortals") {
|
|
1683
|
+
if (scope) {
|
|
1599
1684
|
const routes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1600
|
-
tree: true,
|
|
1601
1685
|
sort: "sort",
|
|
1602
1686
|
filter: scope.filter,
|
|
1603
1687
|
fields: [...DESKTOP_ROUTE_ROLE_PERMISSION_TARGET_FIELDS]
|
|
1604
1688
|
});
|
|
1689
|
+
const routeIds = /* @__PURE__ */ new Set();
|
|
1690
|
+
collectDesktopRouteStringIds(routes, routeIds);
|
|
1691
|
+
const routeTree = buildAccessibleDesktopRouteTreeWithAncestors(routes, routeIds);
|
|
1605
1692
|
ctx.status = 200;
|
|
1606
|
-
ctx.body =
|
|
1693
|
+
ctx.body = removeNestedRootDesktopRoutes(routeTree).map(
|
|
1694
|
+
(route) => pickDesktopRouteRolePermissionTargetFields(route)
|
|
1695
|
+
);
|
|
1607
1696
|
return;
|
|
1608
1697
|
}
|
|
1609
1698
|
await next();
|
|
@@ -2191,10 +2280,11 @@ async function listEnabledMultiPortals(ctx, next) {
|
|
|
2191
2280
|
const records = await ctx.db.getRepository("multiPortals").find({
|
|
2192
2281
|
filter: {
|
|
2193
2282
|
enabled: true,
|
|
2194
|
-
|
|
2283
|
+
uiLayoutUid: {
|
|
2284
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2285
|
+
}
|
|
2195
2286
|
},
|
|
2196
|
-
fields: [...
|
|
2197
|
-
appends: ["uiLayout"],
|
|
2287
|
+
fields: [...MULTI_PORTAL_RUNTIME_FIELDS],
|
|
2198
2288
|
sort: ["uid"]
|
|
2199
2289
|
});
|
|
2200
2290
|
ctx.body = records.map((record) => pickMultiPortalRuntimeFields(record));
|
|
@@ -2222,7 +2312,6 @@ async function findEnabledDefaultMultiPortal(ctx, transaction) {
|
|
|
2222
2312
|
isDefault: true
|
|
2223
2313
|
},
|
|
2224
2314
|
fields: [...DEFAULT_MULTI_PORTAL_RESPONSE_FIELDS, "uiLayoutUid"],
|
|
2225
|
-
appends: ["uiLayout"],
|
|
2226
2315
|
transaction
|
|
2227
2316
|
});
|
|
2228
2317
|
if (!record) {
|
|
@@ -2232,11 +2321,8 @@ async function findEnabledDefaultMultiPortal(ctx, transaction) {
|
|
|
2232
2321
|
if (!portalType) {
|
|
2233
2322
|
return null;
|
|
2234
2323
|
}
|
|
2235
|
-
if (
|
|
2236
|
-
|
|
2237
|
-
if (!uiLayout || uiLayout.get("enabled") !== true) {
|
|
2238
|
-
return null;
|
|
2239
|
-
}
|
|
2324
|
+
if (!(0, import_constants.isMultiPortalUiLayoutUid)(record.get("uiLayoutUid"))) {
|
|
2325
|
+
return null;
|
|
2240
2326
|
}
|
|
2241
2327
|
return record;
|
|
2242
2328
|
}
|
|
@@ -2274,21 +2360,9 @@ async function setDefaultMultiPortal(ctx, next) {
|
|
|
2274
2360
|
ctx.throw(400, ctx.t("Unsupported Portal type cannot be set as default", { ns: import_constants.NAMESPACE }));
|
|
2275
2361
|
return null;
|
|
2276
2362
|
}
|
|
2277
|
-
if (
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
filter: {
|
|
2281
|
-
uid: uiLayoutUid,
|
|
2282
|
-
enabled: true
|
|
2283
|
-
},
|
|
2284
|
-
fields: ["uid"],
|
|
2285
|
-
lock: transaction.LOCK.UPDATE,
|
|
2286
|
-
transaction
|
|
2287
|
-
}) : null;
|
|
2288
|
-
if (!uiLayout) {
|
|
2289
|
-
ctx.throw(400, ctx.t("Portal layout must be enabled before setting it as default", { ns: import_constants.NAMESPACE }));
|
|
2290
|
-
return null;
|
|
2291
|
-
}
|
|
2363
|
+
if (!(0, import_constants.isMultiPortalUiLayoutUid)(target.get("uiLayoutUid"))) {
|
|
2364
|
+
ctx.throw(400, ctx.t("Portal device configuration is invalid", { ns: import_constants.NAMESPACE }));
|
|
2365
|
+
return null;
|
|
2292
2366
|
}
|
|
2293
2367
|
await repository.update({
|
|
2294
2368
|
filter: { isDefault: true },
|
|
@@ -2314,10 +2388,11 @@ async function listAccessibleMultiPortals(ctx, next) {
|
|
|
2314
2388
|
const records = await ctx.db.getRepository("multiPortals").find({
|
|
2315
2389
|
filter: {
|
|
2316
2390
|
enabled: true,
|
|
2317
|
-
|
|
2391
|
+
uiLayoutUid: {
|
|
2392
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2393
|
+
}
|
|
2318
2394
|
},
|
|
2319
|
-
fields: [...
|
|
2320
|
-
appends: ["uiLayout"],
|
|
2395
|
+
fields: [...MULTI_PORTAL_ACCESSIBLE_FIELDS],
|
|
2321
2396
|
sort: ["uid"]
|
|
2322
2397
|
});
|
|
2323
2398
|
const accessiblePortalUidSet = Array.isArray(accessiblePortalUids) ? new Set(accessiblePortalUids) : void 0;
|
|
@@ -2461,6 +2536,9 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2461
2536
|
getAppName() {
|
|
2462
2537
|
return this.app.name || MAIN_APP_NAME;
|
|
2463
2538
|
}
|
|
2539
|
+
getCurrentStorageAppName() {
|
|
2540
|
+
return normalizePortalStorageName(this.getAppName()) || MAIN_APP_NAME;
|
|
2541
|
+
}
|
|
2464
2542
|
getMultiPortalStorageItem(multiPortal, previous = false) {
|
|
2465
2543
|
const record = multiPortal;
|
|
2466
2544
|
const readField = (field) => previous && typeof record.previous === "function" ? record.previous(field) : getRecordField(record, field);
|
|
@@ -2558,8 +2636,6 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2558
2636
|
return;
|
|
2559
2637
|
}
|
|
2560
2638
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2561
|
-
await this.removePortalStorageIndexHtml(item);
|
|
2562
|
-
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2563
2639
|
} catch (error) {
|
|
2564
2640
|
await appendPortalStorageLog(
|
|
2565
2641
|
logPath,
|
|
@@ -2601,14 +2677,12 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2601
2677
|
return;
|
|
2602
2678
|
}
|
|
2603
2679
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2604
|
-
await this.removePortalStorageIndexHtml(item);
|
|
2605
|
-
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2606
2680
|
}
|
|
2607
2681
|
async syncMultiPortalStorageItem(multiPortal, options, syncPrevious = false, forceBuild = false) {
|
|
2608
2682
|
const currentItem = this.getMultiPortalStorageItem(multiPortal);
|
|
2609
2683
|
const previousItem = syncPrevious ? this.getMultiPortalStorageItem(multiPortal, true) : null;
|
|
2610
2684
|
await this.runPortalStorageTask(async () => {
|
|
2611
|
-
if (previousItem && (!currentItem || previousItem.appName !== currentItem.appName || previousItem.portalName !== currentItem.portalName
|
|
2685
|
+
if (previousItem && (!currentItem || previousItem.appName !== currentItem.appName || previousItem.portalName !== currentItem.portalName)) {
|
|
2612
2686
|
await this.removePortalStorageIndexHtml(previousItem);
|
|
2613
2687
|
}
|
|
2614
2688
|
if (currentItem) {
|
|
@@ -2655,12 +2729,12 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2655
2729
|
await next();
|
|
2656
2730
|
}
|
|
2657
2731
|
async deployPortalDist(ctx, next) {
|
|
2658
|
-
var _a, _b, _c
|
|
2732
|
+
var _a, _b, _c;
|
|
2659
2733
|
const deployCtx = ctx;
|
|
2660
|
-
const appName =
|
|
2661
|
-
const portalName = normalizePortalStorageName((
|
|
2662
|
-
const basePath = trimString((
|
|
2663
|
-
const filePath = trimString((
|
|
2734
|
+
const appName = this.getCurrentStorageAppName();
|
|
2735
|
+
const portalName = normalizePortalStorageName((_a = deployCtx.request.body) == null ? void 0 : _a.portal);
|
|
2736
|
+
const basePath = trimString((_b = deployCtx.request.body) == null ? void 0 : _b.basePath);
|
|
2737
|
+
const filePath = trimString((_c = deployCtx.request.file) == null ? void 0 : _c.path);
|
|
2664
2738
|
try {
|
|
2665
2739
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2666
2740
|
throw new Error("Invalid app");
|
|
@@ -2697,9 +2771,9 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2697
2771
|
}
|
|
2698
2772
|
}
|
|
2699
2773
|
async pullPortalSource(ctx, next) {
|
|
2700
|
-
var _a
|
|
2701
|
-
const appName =
|
|
2702
|
-
const portalName = normalizePortalStorageName((
|
|
2774
|
+
var _a;
|
|
2775
|
+
const appName = this.getCurrentStorageAppName();
|
|
2776
|
+
const portalName = normalizePortalStorageName((_a = ctx.action.params.values) == null ? void 0 : _a.portal);
|
|
2703
2777
|
try {
|
|
2704
2778
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2705
2779
|
throw new Error("Invalid app");
|
|
@@ -2719,11 +2793,11 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2719
2793
|
}
|
|
2720
2794
|
}
|
|
2721
2795
|
async pushPortalSource(ctx, next) {
|
|
2722
|
-
var _a, _b
|
|
2796
|
+
var _a, _b;
|
|
2723
2797
|
const sourceCtx = ctx;
|
|
2724
|
-
const appName =
|
|
2725
|
-
const portalName = normalizePortalStorageName((
|
|
2726
|
-
const filePath = trimString((
|
|
2798
|
+
const appName = this.getCurrentStorageAppName();
|
|
2799
|
+
const portalName = normalizePortalStorageName((_a = sourceCtx.request.body) == null ? void 0 : _a.portal);
|
|
2800
|
+
const filePath = trimString((_b = sourceCtx.request.file) == null ? void 0 : _b.path);
|
|
2727
2801
|
try {
|
|
2728
2802
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2729
2803
|
throw new Error("Invalid app");
|
|
@@ -2777,38 +2851,20 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2777
2851
|
const records = await this.db.getRepository("multiPortals").find({
|
|
2778
2852
|
filter: {
|
|
2779
2853
|
enabled: true,
|
|
2780
|
-
|
|
2854
|
+
uiLayoutUid: {
|
|
2855
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2856
|
+
}
|
|
2781
2857
|
},
|
|
2782
|
-
fields: [...
|
|
2783
|
-
appends: ["uiLayout"],
|
|
2858
|
+
fields: [...MULTI_PORTAL_ACCESSIBLE_FIELDS],
|
|
2784
2859
|
sort: ["uid"],
|
|
2785
2860
|
transaction: options == null ? void 0 : options.transaction
|
|
2786
2861
|
});
|
|
2787
|
-
return records.
|
|
2788
|
-
const
|
|
2789
|
-
|
|
2790
|
-
const uid = typeof portal.uid === "string" ? portal.uid : "";
|
|
2791
|
-
const title = typeof portal.title === "string" ? portal.title : "";
|
|
2792
|
-
return {
|
|
2793
|
-
uid,
|
|
2794
|
-
title,
|
|
2795
|
-
icon: typeof portal.icon === "string" ? portal.icon : null,
|
|
2796
|
-
portalType: typeof portal.portalType === "string" ? portal.portalType : null,
|
|
2797
|
-
routePath: String(portal.routePath || ""),
|
|
2798
|
-
layout: typeof (uiLayout == null ? void 0 : uiLayout.layoutType) === "string" ? uiLayout.layoutType : null
|
|
2799
|
-
};
|
|
2862
|
+
return records.flatMap((record) => {
|
|
2863
|
+
const item = this.toAppPortalManifestItem(record);
|
|
2864
|
+
return item ? [item] : [];
|
|
2800
2865
|
});
|
|
2801
2866
|
}
|
|
2802
|
-
|
|
2803
|
-
if (typeof uid !== "string" || !uid) {
|
|
2804
|
-
return null;
|
|
2805
|
-
}
|
|
2806
|
-
return this.db.getRepository("uiLayouts").findOne({
|
|
2807
|
-
filterByTk: uid,
|
|
2808
|
-
transaction: options == null ? void 0 : options.transaction
|
|
2809
|
-
});
|
|
2810
|
-
}
|
|
2811
|
-
async toAppPortalManifestItem(multiPortal, options) {
|
|
2867
|
+
toAppPortalManifestItem(multiPortal) {
|
|
2812
2868
|
const uid = getRecordField(multiPortal, "uid");
|
|
2813
2869
|
const title = getRecordField(multiPortal, "title");
|
|
2814
2870
|
const portalType = getRecordField(multiPortal, "portalType");
|
|
@@ -2818,19 +2874,18 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2818
2874
|
return null;
|
|
2819
2875
|
}
|
|
2820
2876
|
const uiLayoutUid = getRecordField(multiPortal, "uiLayoutUid");
|
|
2821
|
-
const
|
|
2822
|
-
if (!
|
|
2877
|
+
const layout = (0, import_constants.getMultiPortalLayoutType)(uiLayoutUid);
|
|
2878
|
+
if (!layout) {
|
|
2823
2879
|
return null;
|
|
2824
2880
|
}
|
|
2825
2881
|
const icon = getRecordField(multiPortal, "icon");
|
|
2826
|
-
const layoutType = getRecordField(uiLayout, "layoutType");
|
|
2827
2882
|
return {
|
|
2828
2883
|
uid,
|
|
2829
2884
|
title,
|
|
2830
2885
|
icon: typeof icon === "string" ? icon : null,
|
|
2831
2886
|
portalType: typeof portalType === "string" ? portalType : null,
|
|
2832
2887
|
routePath,
|
|
2833
|
-
layout
|
|
2888
|
+
layout
|
|
2834
2889
|
};
|
|
2835
2890
|
}
|
|
2836
2891
|
async setAppManifestItem(item, options) {
|
|
@@ -2873,30 +2928,13 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2873
2928
|
if (typeof uid !== "string" || !uid) {
|
|
2874
2929
|
return;
|
|
2875
2930
|
}
|
|
2876
|
-
const item =
|
|
2931
|
+
const item = this.toAppPortalManifestItem(multiPortal);
|
|
2877
2932
|
if (item) {
|
|
2878
2933
|
await this.setAppManifestItem(item, options);
|
|
2879
2934
|
return;
|
|
2880
2935
|
}
|
|
2881
2936
|
await this.removeAppManifestItem(uid, options);
|
|
2882
2937
|
}
|
|
2883
|
-
async publishUiLayoutManifestItems(uiLayout, options) {
|
|
2884
|
-
const uiLayoutUid = getRecordField(uiLayout, "uid");
|
|
2885
|
-
if (typeof uiLayoutUid !== "string" || !uiLayoutUid) {
|
|
2886
|
-
return;
|
|
2887
|
-
}
|
|
2888
|
-
const records = await this.db.getRepository("multiPortals").find({
|
|
2889
|
-
filter: {
|
|
2890
|
-
uiLayoutUid
|
|
2891
|
-
},
|
|
2892
|
-
fields: [...MULTI_PORTAL_ACCESSIBLE_QUERY_FIELDS],
|
|
2893
|
-
transaction: options == null ? void 0 : options.transaction
|
|
2894
|
-
});
|
|
2895
|
-
for (const record of records) {
|
|
2896
|
-
record.set("uiLayout", uiLayout);
|
|
2897
|
-
await this.publishAppManifestItem(record, options);
|
|
2898
|
-
}
|
|
2899
|
-
}
|
|
2900
2938
|
async reconcilePortalStorage(options) {
|
|
2901
2939
|
const records = await this.db.getRepository("multiPortals").find({
|
|
2902
2940
|
filter: {
|
|
@@ -2960,15 +2998,16 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2960
2998
|
mapMultiPortalLayoutToUiLayoutForRolePermissionTargets
|
|
2961
2999
|
);
|
|
2962
3000
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", preventDirectDefaultPortalMutation);
|
|
3001
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:create", validateMultiPortalUiLayoutUidWrite);
|
|
2963
3002
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", captureSkipCreatePortalDirectory);
|
|
2964
3003
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", normalizeMultiPortalSlugValues);
|
|
2965
3004
|
this.app.resourceManager.registerPreActionHandler("multiPortals:update", preventDirectDefaultPortalMutation);
|
|
2966
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:update",
|
|
3005
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:update", validateMultiPortalUiLayoutUidWrite);
|
|
2967
3006
|
this.app.resourceManager.registerPreActionHandler("multiPortals:update", normalizeMultiPortalSlugValues);
|
|
2968
3007
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", preventDirectDefaultPortalMutation);
|
|
2969
3008
|
this.app.resourceManager.registerPreActionHandler(
|
|
2970
3009
|
"multiPortals:firstOrCreate",
|
|
2971
|
-
|
|
3010
|
+
validateMultiPortalUiLayoutUidWrite
|
|
2972
3011
|
);
|
|
2973
3012
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", captureSkipCreatePortalDirectory);
|
|
2974
3013
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", normalizeMultiPortalSlugValues);
|
|
@@ -2978,7 +3017,7 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2978
3017
|
);
|
|
2979
3018
|
this.app.resourceManager.registerPreActionHandler(
|
|
2980
3019
|
"multiPortals:updateOrCreate",
|
|
2981
|
-
|
|
3020
|
+
validateMultiPortalUiLayoutUidWrite
|
|
2982
3021
|
);
|
|
2983
3022
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", captureSkipCreatePortalDirectory);
|
|
2984
3023
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", normalizeMultiPortalSlugValues);
|
|
@@ -3063,9 +3102,6 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
3063
3102
|
}
|
|
3064
3103
|
await this.removeMultiPortalStorageItem(multiPortal, options);
|
|
3065
3104
|
});
|
|
3066
|
-
this.app.db.on("uiLayouts.afterUpdate", async (uiLayout, options) => {
|
|
3067
|
-
await this.publishUiLayoutManifestItems(uiLayout, options);
|
|
3068
|
-
});
|
|
3069
3105
|
}
|
|
3070
3106
|
async install() {
|
|
3071
3107
|
const version = await this.app.version.get();
|