@nocobase/plugin-multi-portal 3.0.0-alpha.3 → 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/RootLanding.d.ts +4 -5
- package/dist/client-v2/index.js +1 -1
- package/dist/client-v2/layoutRegistration.d.ts +3 -6
- package/dist/client-v2/pages/MultiPortalsPage.d.ts +10 -6
- package/dist/client-v2/routeUrl.d.ts +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +30 -2
- package/dist/externalVersion.js +9 -9
- package/dist/locale/en-US.json +30 -12
- package/dist/locale/zh-CN.json +28 -10
- package/dist/node_modules/tar/package.json +1 -1
- package/dist/server/collections/multiPortals.js +12 -11
- package/dist/server/plugin.d.ts +3 -3
- package/dist/server/plugin.js +339 -146
- package/package.json +3 -3
- package/dist/client-v2/499.ef2ff0c022687485.js +0 -10
- package/dist/client-v2/556.5faf86d4f8faef40.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";
|
|
@@ -100,6 +99,7 @@ const MULTI_PORTAL_MANAGEMENT_ACTIONS = [
|
|
|
100
99
|
"multiPortals:create",
|
|
101
100
|
"multiPortals:update",
|
|
102
101
|
"multiPortals:firstOrCreate",
|
|
102
|
+
"multiPortals:setDefault",
|
|
103
103
|
"multiPortals:destroy",
|
|
104
104
|
"multiPortals:deploy",
|
|
105
105
|
"multiPortals:pullSource",
|
|
@@ -168,7 +168,7 @@ function formatInitPortalTitle(portalName) {
|
|
|
168
168
|
const title = portalName.split(/[-_]/).filter(Boolean).map((segment) => `${segment.charAt(0).toUpperCase()}${segment.slice(1)}`).join(" ");
|
|
169
169
|
return title || portalName;
|
|
170
170
|
}
|
|
171
|
-
function getDefaultMultiPortalRecord() {
|
|
171
|
+
function getDefaultMultiPortalRecord(options = {}) {
|
|
172
172
|
const portalName = getInitPortalName();
|
|
173
173
|
return {
|
|
174
174
|
uid: DEFAULT_MULTI_PORTAL_UID,
|
|
@@ -179,11 +179,12 @@ function getDefaultMultiPortalRecord() {
|
|
|
179
179
|
routePath: `/${portalName}`,
|
|
180
180
|
authCheck: true,
|
|
181
181
|
enabled: true,
|
|
182
|
-
|
|
182
|
+
...options.isDefault ? { isDefault: true } : {},
|
|
183
|
+
uiLayoutUid: import_constants.ADMIN_UI_LAYOUT_UID
|
|
183
184
|
};
|
|
184
185
|
}
|
|
185
186
|
function getFreshMultiPortalRecords() {
|
|
186
|
-
return [getDefaultMultiPortalRecord()];
|
|
187
|
+
return [getDefaultMultiPortalRecord({ isDefault: true })];
|
|
187
188
|
}
|
|
188
189
|
function getFixedLayoutMultiPortalRecords() {
|
|
189
190
|
return [
|
|
@@ -196,7 +197,7 @@ function getFixedLayoutMultiPortalRecords() {
|
|
|
196
197
|
routePath: "/admin",
|
|
197
198
|
authCheck: true,
|
|
198
199
|
enabled: true,
|
|
199
|
-
uiLayoutUid:
|
|
200
|
+
uiLayoutUid: import_constants.ADMIN_UI_LAYOUT_UID
|
|
200
201
|
},
|
|
201
202
|
{
|
|
202
203
|
uid: import_constants.DEFAULT_MOBILE_MULTI_PORTAL_UID,
|
|
@@ -207,7 +208,7 @@ function getFixedLayoutMultiPortalRecords() {
|
|
|
207
208
|
routePath: "/mobile",
|
|
208
209
|
authCheck: true,
|
|
209
210
|
enabled: true,
|
|
210
|
-
uiLayoutUid:
|
|
211
|
+
uiLayoutUid: import_constants.MOBILE_UI_LAYOUT_UID
|
|
211
212
|
}
|
|
212
213
|
];
|
|
213
214
|
}
|
|
@@ -292,6 +293,13 @@ function getPortalDeployBasePath(appName, portalName) {
|
|
|
292
293
|
const portalPath = appName === MAIN_APP_NAME ? `/${PORTAL_CLIENT_PREFIX}/${portalName}/` : `/${PORTAL_CLIENT_PREFIX}/apps/${appName}/${portalName}/`;
|
|
293
294
|
return resolvePortalStoragePublicPath(joinPortalStoragePublicPath(process.env.APP_PUBLIC_PATH || "/", portalPath));
|
|
294
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
|
+
}
|
|
295
303
|
function createPortalDeployUploadMiddleware() {
|
|
296
304
|
const storage = import_utils.koaMulter.diskStorage({
|
|
297
305
|
destination: import_os.default.tmpdir(),
|
|
@@ -618,9 +626,9 @@ function validatePortalDeployBasePath(appName, portalName, basePath) {
|
|
|
618
626
|
if (normalizedBasePath.includes("..")) {
|
|
619
627
|
throw new Error('basePath cannot contain ".."');
|
|
620
628
|
}
|
|
621
|
-
const
|
|
622
|
-
if (normalizedBasePath
|
|
623
|
-
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 ")}`);
|
|
624
632
|
}
|
|
625
633
|
}
|
|
626
634
|
function isPortalDeployTarEntry(entry) {
|
|
@@ -858,19 +866,11 @@ function collectDesktopRouteIds(record) {
|
|
|
858
866
|
}
|
|
859
867
|
return uniqueDesktopRouteIds(routeIds);
|
|
860
868
|
}
|
|
861
|
-
function pickMultiPortalUiLayoutRuntimeFields(record) {
|
|
862
|
-
const result = {};
|
|
863
|
-
for (const field of MULTI_PORTAL_UI_LAYOUT_RUNTIME_FIELDS) {
|
|
864
|
-
result[field] = getRecordField(record, field);
|
|
865
|
-
}
|
|
866
|
-
return result;
|
|
867
|
-
}
|
|
868
869
|
function pickMultiPortalRuntimeFields(record) {
|
|
869
870
|
const result = {};
|
|
870
871
|
for (const field of MULTI_PORTAL_RUNTIME_FIELDS) {
|
|
871
872
|
result[field] = getRecordField(record, field);
|
|
872
873
|
}
|
|
873
|
-
result.uiLayout = pickMultiPortalUiLayoutRuntimeFields(getRecordField(record, "uiLayout"));
|
|
874
874
|
return result;
|
|
875
875
|
}
|
|
876
876
|
function pickMultiPortalAccessibleFields(record) {
|
|
@@ -878,7 +878,6 @@ function pickMultiPortalAccessibleFields(record) {
|
|
|
878
878
|
for (const field of MULTI_PORTAL_ACCESSIBLE_FIELDS) {
|
|
879
879
|
result[field] = getRecordField(record, field) ?? null;
|
|
880
880
|
}
|
|
881
|
-
result.uiLayout = pickMultiPortalUiLayoutRuntimeFields(getRecordField(record, "uiLayout"));
|
|
882
881
|
return result;
|
|
883
882
|
}
|
|
884
883
|
function getExplicitRequestedLayoutUid(layout) {
|
|
@@ -1035,6 +1034,37 @@ async function normalizeMultiPortalSlugValues(ctx, next) {
|
|
|
1035
1034
|
values.portalName = slug;
|
|
1036
1035
|
values.routePath = `/${slug}`;
|
|
1037
1036
|
}
|
|
1037
|
+
const repository = ctx.db.getRepository("multiPortals");
|
|
1038
|
+
const pendingPortalNames = /* @__PURE__ */ new Set();
|
|
1039
|
+
const targets = await getMultiPortalWriteTargets(ctx, ["uid"]);
|
|
1040
|
+
for (const { existing, values } of targets) {
|
|
1041
|
+
const portalName = values.portalName;
|
|
1042
|
+
if (typeof portalName !== "string" || !portalName) {
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
1045
|
+
if (pendingPortalNames.has(portalName)) {
|
|
1046
|
+
ctx.throw(409, ctx.t('Portal name "{{portalName}}" already exists', { ns: import_constants.NAMESPACE, portalName }));
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
pendingPortalNames.add(portalName);
|
|
1050
|
+
const conflict = await repository.findOne({
|
|
1051
|
+
filter: { portalName },
|
|
1052
|
+
fields: ["uid"]
|
|
1053
|
+
});
|
|
1054
|
+
if (conflict && conflict.get("uid") !== (existing == null ? void 0 : existing.get("uid"))) {
|
|
1055
|
+
ctx.throw(409, ctx.t('Portal name "{{portalName}}" already exists', { ns: import_constants.NAMESPACE, portalName }));
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
await next();
|
|
1060
|
+
}
|
|
1061
|
+
async function preventDirectDefaultPortalMutation(ctx, next) {
|
|
1062
|
+
for (const values of getMultiPortalWriteRecords(ctx)) {
|
|
1063
|
+
if (Object.prototype.hasOwnProperty.call(values, "isDefault")) {
|
|
1064
|
+
ctx.throw(400, ctx.t("Use multiPortals:setDefault to update the default Portal", { ns: import_constants.NAMESPACE }));
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1038
1068
|
await next();
|
|
1039
1069
|
}
|
|
1040
1070
|
function isUniqueConstraintViolation(error) {
|
|
@@ -1097,14 +1127,27 @@ async function seedHistoricalMultiPortals(db) {
|
|
|
1097
1127
|
}
|
|
1098
1128
|
await repairFixedLayoutMultiPortalRecords(db);
|
|
1099
1129
|
}
|
|
1100
|
-
async function
|
|
1130
|
+
async function validateMultiPortalUiLayoutUidWrite(ctx, next) {
|
|
1131
|
+
var _a;
|
|
1101
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";
|
|
1102
1135
|
for (const { existing, values } of targets) {
|
|
1103
|
-
|
|
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) {
|
|
1104
1142
|
continue;
|
|
1105
1143
|
}
|
|
1106
|
-
if (
|
|
1107
|
-
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");
|
|
1108
1151
|
return;
|
|
1109
1152
|
}
|
|
1110
1153
|
}
|
|
@@ -1132,20 +1175,8 @@ async function findRequestedMultiPortal(ctx, transaction) {
|
|
|
1132
1175
|
ctx.throw(400, `Portal '${portalUid}' does not support desktop routes`);
|
|
1133
1176
|
}
|
|
1134
1177
|
const uiLayoutUid = portal.get("uiLayoutUid");
|
|
1135
|
-
if (
|
|
1136
|
-
ctx.throw(400, `Portal '${portalUid}' has
|
|
1137
|
-
}
|
|
1138
|
-
const uiLayout = await ctx.db.getRepository("uiLayouts").findOne({
|
|
1139
|
-
filter: {
|
|
1140
|
-
uid: uiLayoutUid,
|
|
1141
|
-
enabled: true
|
|
1142
|
-
},
|
|
1143
|
-
fields: ["uid"],
|
|
1144
|
-
...transaction ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1145
|
-
transaction
|
|
1146
|
-
});
|
|
1147
|
-
if (!uiLayout) {
|
|
1148
|
-
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`);
|
|
1149
1180
|
}
|
|
1150
1181
|
const usesLayoutPermissions = (0, import_constants.isDefaultLayoutMultiPortalUid)(portalUid);
|
|
1151
1182
|
return {
|
|
@@ -1330,7 +1361,7 @@ async function removeRouteIdsWithUnauthorizedAncestors(ctx, routeIds) {
|
|
|
1330
1361
|
}
|
|
1331
1362
|
}
|
|
1332
1363
|
}
|
|
1333
|
-
async function getMultiPortalAccessibleRouteIds(ctx,
|
|
1364
|
+
async function getMultiPortalAccessibleRouteIds(ctx, portalContext) {
|
|
1334
1365
|
const currentRoles = getCurrentRoles(ctx);
|
|
1335
1366
|
if (currentRoles.includes("root")) {
|
|
1336
1367
|
return;
|
|
@@ -1338,11 +1369,11 @@ async function getMultiPortalAccessibleRouteIds(ctx, multiPortalUid) {
|
|
|
1338
1369
|
if (!currentRoles.length) {
|
|
1339
1370
|
return /* @__PURE__ */ new Set();
|
|
1340
1371
|
}
|
|
1341
|
-
const routePermissions = await ctx.db.getRepository("rolesMultiPortalDesktopRoutes").find({
|
|
1372
|
+
const routePermissions = await ctx.db.getRepository(portalContext.relation === "uiLayouts" ? "rolesDesktopRoutes" : "rolesMultiPortalDesktopRoutes").find({
|
|
1342
1373
|
fields: ["desktopRouteId"],
|
|
1343
1374
|
filter: {
|
|
1344
1375
|
roleName: currentRoles,
|
|
1345
|
-
multiPortalUid
|
|
1376
|
+
...portalContext.relation === "multiPortals" ? { multiPortalUid: portalContext.portalUid } : {}
|
|
1346
1377
|
}
|
|
1347
1378
|
});
|
|
1348
1379
|
const routeIds = /* @__PURE__ */ new Set();
|
|
@@ -1358,7 +1389,7 @@ async function getMultiPortalAccessibleRouteIds(ctx, multiPortalUid) {
|
|
|
1358
1389
|
const portalRoutes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1359
1390
|
fields: ["id"],
|
|
1360
1391
|
filter: {
|
|
1361
|
-
...
|
|
1392
|
+
...portalContext.filter,
|
|
1362
1393
|
id: Array.from(routeIds)
|
|
1363
1394
|
}
|
|
1364
1395
|
});
|
|
@@ -1388,9 +1419,107 @@ function setDesktopRouteChildren(route, children) {
|
|
|
1388
1419
|
const maybeModel = route;
|
|
1389
1420
|
if (typeof maybeModel.setDataValue === "function") {
|
|
1390
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"];
|
|
1391
1430
|
return;
|
|
1392
1431
|
}
|
|
1393
|
-
|
|
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);
|
|
1394
1523
|
}
|
|
1395
1524
|
function removeDesktopRoutesByIds(routes, routeIds) {
|
|
1396
1525
|
return routes.map((route) => {
|
|
@@ -1457,23 +1586,26 @@ async function removeMultiPortalOwnedRouteFromGetResponse(ctx) {
|
|
|
1457
1586
|
ctx.body = void 0;
|
|
1458
1587
|
}
|
|
1459
1588
|
async function replaceListAccessibleRoutesWithPortalScopedRoutes(ctx, portalContext) {
|
|
1460
|
-
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext
|
|
1589
|
+
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext);
|
|
1461
1590
|
if (routeIds && routeIds.size === 0) {
|
|
1462
1591
|
ctx.body = [];
|
|
1463
1592
|
return;
|
|
1464
1593
|
}
|
|
1465
|
-
|
|
1594
|
+
const routes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1466
1595
|
tree: true,
|
|
1467
1596
|
sort: "sort",
|
|
1468
1597
|
filter: {
|
|
1469
|
-
...
|
|
1598
|
+
...portalContext.filter,
|
|
1470
1599
|
...routeIds ? { id: Array.from(routeIds) } : {}
|
|
1471
1600
|
}
|
|
1472
1601
|
});
|
|
1602
|
+
ctx.body = removeNestedRootDesktopRoutes(
|
|
1603
|
+
await includeDesktopRouteAncestorsForListAccessible(ctx, routes, portalContext.filter)
|
|
1604
|
+
);
|
|
1473
1605
|
}
|
|
1474
1606
|
async function replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext) {
|
|
1475
1607
|
var _a;
|
|
1476
|
-
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext
|
|
1608
|
+
const routeIds = await getMultiPortalAccessibleRouteIds(ctx, portalContext);
|
|
1477
1609
|
if (routeIds && routeIds.size === 0) {
|
|
1478
1610
|
ctx.status = 204;
|
|
1479
1611
|
ctx.body = void 0;
|
|
@@ -1483,7 +1615,7 @@ async function replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext
|
|
|
1483
1615
|
sort: "sort",
|
|
1484
1616
|
filterByTk: (_a = ctx.action) == null ? void 0 : _a.params.filterByTk,
|
|
1485
1617
|
filter: {
|
|
1486
|
-
...
|
|
1618
|
+
...portalContext.filter,
|
|
1487
1619
|
...routeIds ? { id: Array.from(routeIds) } : {}
|
|
1488
1620
|
}
|
|
1489
1621
|
});
|
|
@@ -1520,13 +1652,10 @@ async function addMultiPortalListAccessibleGuard(ctx, next) {
|
|
|
1520
1652
|
return;
|
|
1521
1653
|
}
|
|
1522
1654
|
await next();
|
|
1523
|
-
if (
|
|
1655
|
+
if (portalContext) {
|
|
1524
1656
|
await replaceListAccessibleRoutesWithPortalScopedRoutes(ctx, portalContext);
|
|
1525
1657
|
return;
|
|
1526
1658
|
}
|
|
1527
|
-
if ((portalContext == null ? void 0 : portalContext.relation) === "uiLayouts") {
|
|
1528
|
-
return;
|
|
1529
|
-
}
|
|
1530
1659
|
await removeMultiPortalOwnedRoutesFromListResponse(ctx);
|
|
1531
1660
|
}
|
|
1532
1661
|
async function addMultiPortalGetAccessibleGuard(ctx, next) {
|
|
@@ -1537,17 +1666,13 @@ async function addMultiPortalGetAccessibleGuard(ctx, next) {
|
|
|
1537
1666
|
return;
|
|
1538
1667
|
}
|
|
1539
1668
|
await next();
|
|
1540
|
-
if (
|
|
1669
|
+
if (portalContext) {
|
|
1541
1670
|
await replaceGetAccessibleRouteWithPortalScopedRoute(ctx, portalContext);
|
|
1542
1671
|
return;
|
|
1543
1672
|
}
|
|
1544
|
-
if ((portalContext == null ? void 0 : portalContext.relation) === "uiLayouts") {
|
|
1545
|
-
return;
|
|
1546
|
-
}
|
|
1547
1673
|
await removeMultiPortalOwnedRouteFromGetResponse(ctx);
|
|
1548
1674
|
}
|
|
1549
1675
|
async function mapMultiPortalLayoutToUiLayoutForRolePermissionTargets(ctx, next) {
|
|
1550
|
-
var _a;
|
|
1551
1676
|
const portalRequest = await findRequestedMultiPortal(ctx);
|
|
1552
1677
|
if (portalRequest.requested && !portalRequest.portal) {
|
|
1553
1678
|
ctx.status = 200;
|
|
@@ -1555,22 +1680,19 @@ async function mapMultiPortalLayoutToUiLayoutForRolePermissionTargets(ctx, next)
|
|
|
1555
1680
|
return;
|
|
1556
1681
|
}
|
|
1557
1682
|
const scope = portalRequest.scope;
|
|
1558
|
-
if (
|
|
1559
|
-
if ((_a = ctx.action) == null ? void 0 : _a.params) {
|
|
1560
|
-
ctx.action.params.layout = scope.uiLayoutUid;
|
|
1561
|
-
}
|
|
1562
|
-
await next();
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1565
|
-
if ((scope == null ? void 0 : scope.relation) === "multiPortals") {
|
|
1683
|
+
if (scope) {
|
|
1566
1684
|
const routes = await ctx.db.getRepository("desktopRoutes").find({
|
|
1567
|
-
tree: true,
|
|
1568
1685
|
sort: "sort",
|
|
1569
1686
|
filter: scope.filter,
|
|
1570
1687
|
fields: [...DESKTOP_ROUTE_ROLE_PERMISSION_TARGET_FIELDS]
|
|
1571
1688
|
});
|
|
1689
|
+
const routeIds = /* @__PURE__ */ new Set();
|
|
1690
|
+
collectDesktopRouteStringIds(routes, routeIds);
|
|
1691
|
+
const routeTree = buildAccessibleDesktopRouteTreeWithAncestors(routes, routeIds);
|
|
1572
1692
|
ctx.status = 200;
|
|
1573
|
-
ctx.body =
|
|
1693
|
+
ctx.body = removeNestedRootDesktopRoutes(routeTree).map(
|
|
1694
|
+
(route) => pickDesktopRouteRolePermissionTargetFields(route)
|
|
1695
|
+
);
|
|
1574
1696
|
return;
|
|
1575
1697
|
}
|
|
1576
1698
|
await next();
|
|
@@ -2158,24 +2280,119 @@ async function listEnabledMultiPortals(ctx, next) {
|
|
|
2158
2280
|
const records = await ctx.db.getRepository("multiPortals").find({
|
|
2159
2281
|
filter: {
|
|
2160
2282
|
enabled: true,
|
|
2161
|
-
|
|
2283
|
+
uiLayoutUid: {
|
|
2284
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2285
|
+
}
|
|
2162
2286
|
},
|
|
2163
|
-
fields: [...
|
|
2164
|
-
appends: ["uiLayout"],
|
|
2287
|
+
fields: [...MULTI_PORTAL_RUNTIME_FIELDS],
|
|
2165
2288
|
sort: ["uid"]
|
|
2166
2289
|
});
|
|
2167
2290
|
ctx.body = records.map((record) => pickMultiPortalRuntimeFields(record));
|
|
2168
2291
|
await next();
|
|
2169
2292
|
}
|
|
2293
|
+
const DEFAULT_MULTI_PORTAL_RESPONSE_FIELDS = ["uid", "portalType", "routePath"];
|
|
2294
|
+
function getDefaultMultiPortalType(record) {
|
|
2295
|
+
const portalType = record.get("portalType");
|
|
2296
|
+
if (portalType === null || portalType === void 0) {
|
|
2297
|
+
return "no-code";
|
|
2298
|
+
}
|
|
2299
|
+
return typeof portalType === "string" && isInitPortalType(portalType) ? portalType : null;
|
|
2300
|
+
}
|
|
2301
|
+
function pickDefaultMultiPortalFields(record) {
|
|
2302
|
+
return {
|
|
2303
|
+
uid: String(record.get("uid")),
|
|
2304
|
+
portalType: getDefaultMultiPortalType(record) || "no-code",
|
|
2305
|
+
routePath: String(record.get("routePath"))
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
async function findEnabledDefaultMultiPortal(ctx, transaction) {
|
|
2309
|
+
const record = await ctx.db.getRepository("multiPortals").findOne({
|
|
2310
|
+
filter: {
|
|
2311
|
+
enabled: true,
|
|
2312
|
+
isDefault: true
|
|
2313
|
+
},
|
|
2314
|
+
fields: [...DEFAULT_MULTI_PORTAL_RESPONSE_FIELDS, "uiLayoutUid"],
|
|
2315
|
+
transaction
|
|
2316
|
+
});
|
|
2317
|
+
if (!record) {
|
|
2318
|
+
return null;
|
|
2319
|
+
}
|
|
2320
|
+
const portalType = getDefaultMultiPortalType(record);
|
|
2321
|
+
if (!portalType) {
|
|
2322
|
+
return null;
|
|
2323
|
+
}
|
|
2324
|
+
if (!(0, import_constants.isMultiPortalUiLayoutUid)(record.get("uiLayoutUid"))) {
|
|
2325
|
+
return null;
|
|
2326
|
+
}
|
|
2327
|
+
return record;
|
|
2328
|
+
}
|
|
2329
|
+
async function getDefaultMultiPortal(ctx, next) {
|
|
2330
|
+
const record = await findEnabledDefaultMultiPortal(ctx);
|
|
2331
|
+
ctx.body = record ? pickDefaultMultiPortalFields(record) : null;
|
|
2332
|
+
ctx.status = 200;
|
|
2333
|
+
await next();
|
|
2334
|
+
}
|
|
2335
|
+
async function setDefaultMultiPortal(ctx, next) {
|
|
2336
|
+
var _a;
|
|
2337
|
+
const filterByTk = (_a = ctx.action) == null ? void 0 : _a.params.filterByTk;
|
|
2338
|
+
if (filterByTk === void 0 || filterByTk === null || filterByTk === "") {
|
|
2339
|
+
ctx.throw(400, ctx.t("filterByTk is required", { ns: import_constants.NAMESPACE }));
|
|
2340
|
+
return;
|
|
2341
|
+
}
|
|
2342
|
+
const repository = ctx.db.getRepository("multiPortals");
|
|
2343
|
+
const updated = await ctx.db.sequelize.transaction(async (transaction) => {
|
|
2344
|
+
const target = await repository.findOne({
|
|
2345
|
+
filterByTk,
|
|
2346
|
+
fields: [...DEFAULT_MULTI_PORTAL_RESPONSE_FIELDS, "enabled", "uiLayoutUid"],
|
|
2347
|
+
lock: transaction.LOCK.UPDATE,
|
|
2348
|
+
transaction
|
|
2349
|
+
});
|
|
2350
|
+
if (!target) {
|
|
2351
|
+
ctx.throw(404, ctx.t("Portal not found", { ns: import_constants.NAMESPACE }));
|
|
2352
|
+
return null;
|
|
2353
|
+
}
|
|
2354
|
+
if (target.get("enabled") !== true) {
|
|
2355
|
+
ctx.throw(400, ctx.t("Disabled Portal cannot be set as default", { ns: import_constants.NAMESPACE }));
|
|
2356
|
+
return null;
|
|
2357
|
+
}
|
|
2358
|
+
const portalType = getDefaultMultiPortalType(target);
|
|
2359
|
+
if (!portalType) {
|
|
2360
|
+
ctx.throw(400, ctx.t("Unsupported Portal type cannot be set as default", { ns: import_constants.NAMESPACE }));
|
|
2361
|
+
return null;
|
|
2362
|
+
}
|
|
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;
|
|
2366
|
+
}
|
|
2367
|
+
await repository.update({
|
|
2368
|
+
filter: { isDefault: true },
|
|
2369
|
+
values: { isDefault: null },
|
|
2370
|
+
transaction
|
|
2371
|
+
});
|
|
2372
|
+
await repository.update({
|
|
2373
|
+
filterByTk,
|
|
2374
|
+
values: { isDefault: true },
|
|
2375
|
+
transaction
|
|
2376
|
+
});
|
|
2377
|
+
return repository.findOne({
|
|
2378
|
+
filterByTk,
|
|
2379
|
+
fields: [...DEFAULT_MULTI_PORTAL_RESPONSE_FIELDS],
|
|
2380
|
+
transaction
|
|
2381
|
+
});
|
|
2382
|
+
});
|
|
2383
|
+
ctx.body = updated ? pickDefaultMultiPortalFields(updated) : null;
|
|
2384
|
+
await next();
|
|
2385
|
+
}
|
|
2170
2386
|
async function listAccessibleMultiPortals(ctx, next) {
|
|
2171
2387
|
const accessiblePortalUids = await listCurrentRoleAccessibleMultiPortalUids(ctx);
|
|
2172
2388
|
const records = await ctx.db.getRepository("multiPortals").find({
|
|
2173
2389
|
filter: {
|
|
2174
2390
|
enabled: true,
|
|
2175
|
-
|
|
2391
|
+
uiLayoutUid: {
|
|
2392
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2393
|
+
}
|
|
2176
2394
|
},
|
|
2177
|
-
fields: [...
|
|
2178
|
-
appends: ["uiLayout"],
|
|
2395
|
+
fields: [...MULTI_PORTAL_ACCESSIBLE_FIELDS],
|
|
2179
2396
|
sort: ["uid"]
|
|
2180
2397
|
});
|
|
2181
2398
|
const accessiblePortalUidSet = Array.isArray(accessiblePortalUids) ? new Set(accessiblePortalUids) : void 0;
|
|
@@ -2319,6 +2536,9 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2319
2536
|
getAppName() {
|
|
2320
2537
|
return this.app.name || MAIN_APP_NAME;
|
|
2321
2538
|
}
|
|
2539
|
+
getCurrentStorageAppName() {
|
|
2540
|
+
return normalizePortalStorageName(this.getAppName()) || MAIN_APP_NAME;
|
|
2541
|
+
}
|
|
2322
2542
|
getMultiPortalStorageItem(multiPortal, previous = false) {
|
|
2323
2543
|
const record = multiPortal;
|
|
2324
2544
|
const readField = (field) => previous && typeof record.previous === "function" ? record.previous(field) : getRecordField(record, field);
|
|
@@ -2416,8 +2636,6 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2416
2636
|
return;
|
|
2417
2637
|
}
|
|
2418
2638
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2419
|
-
await this.removePortalStorageIndexHtml(item);
|
|
2420
|
-
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2421
2639
|
} catch (error) {
|
|
2422
2640
|
await appendPortalStorageLog(
|
|
2423
2641
|
logPath,
|
|
@@ -2459,14 +2677,12 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2459
2677
|
return;
|
|
2460
2678
|
}
|
|
2461
2679
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2462
|
-
await this.removePortalStorageIndexHtml(item);
|
|
2463
|
-
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2464
2680
|
}
|
|
2465
2681
|
async syncMultiPortalStorageItem(multiPortal, options, syncPrevious = false, forceBuild = false) {
|
|
2466
2682
|
const currentItem = this.getMultiPortalStorageItem(multiPortal);
|
|
2467
2683
|
const previousItem = syncPrevious ? this.getMultiPortalStorageItem(multiPortal, true) : null;
|
|
2468
2684
|
await this.runPortalStorageTask(async () => {
|
|
2469
|
-
if (previousItem && (!currentItem || previousItem.appName !== currentItem.appName || previousItem.portalName !== currentItem.portalName
|
|
2685
|
+
if (previousItem && (!currentItem || previousItem.appName !== currentItem.appName || previousItem.portalName !== currentItem.portalName)) {
|
|
2470
2686
|
await this.removePortalStorageIndexHtml(previousItem);
|
|
2471
2687
|
}
|
|
2472
2688
|
if (currentItem) {
|
|
@@ -2513,12 +2729,12 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2513
2729
|
await next();
|
|
2514
2730
|
}
|
|
2515
2731
|
async deployPortalDist(ctx, next) {
|
|
2516
|
-
var _a, _b, _c
|
|
2732
|
+
var _a, _b, _c;
|
|
2517
2733
|
const deployCtx = ctx;
|
|
2518
|
-
const appName =
|
|
2519
|
-
const portalName = normalizePortalStorageName((
|
|
2520
|
-
const basePath = trimString((
|
|
2521
|
-
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);
|
|
2522
2738
|
try {
|
|
2523
2739
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2524
2740
|
throw new Error("Invalid app");
|
|
@@ -2555,9 +2771,9 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2555
2771
|
}
|
|
2556
2772
|
}
|
|
2557
2773
|
async pullPortalSource(ctx, next) {
|
|
2558
|
-
var _a
|
|
2559
|
-
const appName =
|
|
2560
|
-
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);
|
|
2561
2777
|
try {
|
|
2562
2778
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2563
2779
|
throw new Error("Invalid app");
|
|
@@ -2577,11 +2793,11 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2577
2793
|
}
|
|
2578
2794
|
}
|
|
2579
2795
|
async pushPortalSource(ctx, next) {
|
|
2580
|
-
var _a, _b
|
|
2796
|
+
var _a, _b;
|
|
2581
2797
|
const sourceCtx = ctx;
|
|
2582
|
-
const appName =
|
|
2583
|
-
const portalName = normalizePortalStorageName((
|
|
2584
|
-
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);
|
|
2585
2801
|
try {
|
|
2586
2802
|
if (!isValidPortalDeploySegment(appName)) {
|
|
2587
2803
|
throw new Error("Invalid app");
|
|
@@ -2635,38 +2851,20 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2635
2851
|
const records = await this.db.getRepository("multiPortals").find({
|
|
2636
2852
|
filter: {
|
|
2637
2853
|
enabled: true,
|
|
2638
|
-
|
|
2854
|
+
uiLayoutUid: {
|
|
2855
|
+
$in: [...import_constants.MULTI_PORTAL_UI_LAYOUT_UIDS]
|
|
2856
|
+
}
|
|
2639
2857
|
},
|
|
2640
|
-
fields: [...
|
|
2641
|
-
appends: ["uiLayout"],
|
|
2858
|
+
fields: [...MULTI_PORTAL_ACCESSIBLE_FIELDS],
|
|
2642
2859
|
sort: ["uid"],
|
|
2643
2860
|
transaction: options == null ? void 0 : options.transaction
|
|
2644
2861
|
});
|
|
2645
|
-
return records.
|
|
2646
|
-
const
|
|
2647
|
-
|
|
2648
|
-
const uid = typeof portal.uid === "string" ? portal.uid : "";
|
|
2649
|
-
const title = typeof portal.title === "string" ? portal.title : "";
|
|
2650
|
-
return {
|
|
2651
|
-
uid,
|
|
2652
|
-
title,
|
|
2653
|
-
icon: typeof portal.icon === "string" ? portal.icon : null,
|
|
2654
|
-
portalType: typeof portal.portalType === "string" ? portal.portalType : null,
|
|
2655
|
-
routePath: String(portal.routePath || ""),
|
|
2656
|
-
layout: typeof (uiLayout == null ? void 0 : uiLayout.layoutType) === "string" ? uiLayout.layoutType : null
|
|
2657
|
-
};
|
|
2862
|
+
return records.flatMap((record) => {
|
|
2863
|
+
const item = this.toAppPortalManifestItem(record);
|
|
2864
|
+
return item ? [item] : [];
|
|
2658
2865
|
});
|
|
2659
2866
|
}
|
|
2660
|
-
|
|
2661
|
-
if (typeof uid !== "string" || !uid) {
|
|
2662
|
-
return null;
|
|
2663
|
-
}
|
|
2664
|
-
return this.db.getRepository("uiLayouts").findOne({
|
|
2665
|
-
filterByTk: uid,
|
|
2666
|
-
transaction: options == null ? void 0 : options.transaction
|
|
2667
|
-
});
|
|
2668
|
-
}
|
|
2669
|
-
async toAppPortalManifestItem(multiPortal, options) {
|
|
2867
|
+
toAppPortalManifestItem(multiPortal) {
|
|
2670
2868
|
const uid = getRecordField(multiPortal, "uid");
|
|
2671
2869
|
const title = getRecordField(multiPortal, "title");
|
|
2672
2870
|
const portalType = getRecordField(multiPortal, "portalType");
|
|
@@ -2676,19 +2874,18 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2676
2874
|
return null;
|
|
2677
2875
|
}
|
|
2678
2876
|
const uiLayoutUid = getRecordField(multiPortal, "uiLayoutUid");
|
|
2679
|
-
const
|
|
2680
|
-
if (!
|
|
2877
|
+
const layout = (0, import_constants.getMultiPortalLayoutType)(uiLayoutUid);
|
|
2878
|
+
if (!layout) {
|
|
2681
2879
|
return null;
|
|
2682
2880
|
}
|
|
2683
2881
|
const icon = getRecordField(multiPortal, "icon");
|
|
2684
|
-
const layoutType = getRecordField(uiLayout, "layoutType");
|
|
2685
2882
|
return {
|
|
2686
2883
|
uid,
|
|
2687
2884
|
title,
|
|
2688
2885
|
icon: typeof icon === "string" ? icon : null,
|
|
2689
2886
|
portalType: typeof portalType === "string" ? portalType : null,
|
|
2690
2887
|
routePath,
|
|
2691
|
-
layout
|
|
2888
|
+
layout
|
|
2692
2889
|
};
|
|
2693
2890
|
}
|
|
2694
2891
|
async setAppManifestItem(item, options) {
|
|
@@ -2731,30 +2928,13 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2731
2928
|
if (typeof uid !== "string" || !uid) {
|
|
2732
2929
|
return;
|
|
2733
2930
|
}
|
|
2734
|
-
const item =
|
|
2931
|
+
const item = this.toAppPortalManifestItem(multiPortal);
|
|
2735
2932
|
if (item) {
|
|
2736
2933
|
await this.setAppManifestItem(item, options);
|
|
2737
2934
|
return;
|
|
2738
2935
|
}
|
|
2739
2936
|
await this.removeAppManifestItem(uid, options);
|
|
2740
2937
|
}
|
|
2741
|
-
async publishUiLayoutManifestItems(uiLayout, options) {
|
|
2742
|
-
const uiLayoutUid = getRecordField(uiLayout, "uid");
|
|
2743
|
-
if (typeof uiLayoutUid !== "string" || !uiLayoutUid) {
|
|
2744
|
-
return;
|
|
2745
|
-
}
|
|
2746
|
-
const records = await this.db.getRepository("multiPortals").find({
|
|
2747
|
-
filter: {
|
|
2748
|
-
uiLayoutUid
|
|
2749
|
-
},
|
|
2750
|
-
fields: [...MULTI_PORTAL_ACCESSIBLE_QUERY_FIELDS],
|
|
2751
|
-
transaction: options == null ? void 0 : options.transaction
|
|
2752
|
-
});
|
|
2753
|
-
for (const record of records) {
|
|
2754
|
-
record.set("uiLayout", uiLayout);
|
|
2755
|
-
await this.publishAppManifestItem(record, options);
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
2938
|
async reconcilePortalStorage(options) {
|
|
2759
2939
|
const records = await this.db.getRepository("multiPortals").find({
|
|
2760
2940
|
filter: {
|
|
@@ -2817,19 +2997,27 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2817
2997
|
"desktopRoutes:listRolePermissionTargets",
|
|
2818
2998
|
mapMultiPortalLayoutToUiLayoutForRolePermissionTargets
|
|
2819
2999
|
);
|
|
3000
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:create", preventDirectDefaultPortalMutation);
|
|
3001
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:create", validateMultiPortalUiLayoutUidWrite);
|
|
2820
3002
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", captureSkipCreatePortalDirectory);
|
|
2821
3003
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", normalizeMultiPortalSlugValues);
|
|
2822
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:update",
|
|
3004
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:update", preventDirectDefaultPortalMutation);
|
|
3005
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:update", validateMultiPortalUiLayoutUidWrite);
|
|
2823
3006
|
this.app.resourceManager.registerPreActionHandler("multiPortals:update", normalizeMultiPortalSlugValues);
|
|
3007
|
+
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", preventDirectDefaultPortalMutation);
|
|
2824
3008
|
this.app.resourceManager.registerPreActionHandler(
|
|
2825
3009
|
"multiPortals:firstOrCreate",
|
|
2826
|
-
|
|
3010
|
+
validateMultiPortalUiLayoutUidWrite
|
|
2827
3011
|
);
|
|
2828
3012
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", captureSkipCreatePortalDirectory);
|
|
2829
3013
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", normalizeMultiPortalSlugValues);
|
|
2830
3014
|
this.app.resourceManager.registerPreActionHandler(
|
|
2831
3015
|
"multiPortals:updateOrCreate",
|
|
2832
|
-
|
|
3016
|
+
preventDirectDefaultPortalMutation
|
|
3017
|
+
);
|
|
3018
|
+
this.app.resourceManager.registerPreActionHandler(
|
|
3019
|
+
"multiPortals:updateOrCreate",
|
|
3020
|
+
validateMultiPortalUiLayoutUidWrite
|
|
2833
3021
|
);
|
|
2834
3022
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", captureSkipCreatePortalDirectory);
|
|
2835
3023
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", normalizeMultiPortalSlugValues);
|
|
@@ -2857,12 +3045,15 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2857
3045
|
actions: ROLE_MULTI_PORTAL_PERMISSION_ACTIONS
|
|
2858
3046
|
});
|
|
2859
3047
|
this.app.acl.allow("multiPortals", "listEnabled", "public");
|
|
3048
|
+
this.app.acl.allow("multiPortals", "getDefault", "public");
|
|
2860
3049
|
this.app.acl.allow("multiPortals", "listAccessible", "loggedIn");
|
|
2861
3050
|
this.app.resourceManager.use(createPortalDeployUploadMiddleware(), {
|
|
2862
3051
|
tag: "multiPortalDeployUpload",
|
|
2863
3052
|
after: "acl"
|
|
2864
3053
|
});
|
|
2865
3054
|
this.app.resourceManager.registerActionHandler("multiPortals:listEnabled", listEnabledMultiPortals);
|
|
3055
|
+
this.app.resourceManager.registerActionHandler("multiPortals:getDefault", getDefaultMultiPortal);
|
|
3056
|
+
this.app.resourceManager.registerActionHandler("multiPortals:setDefault", setDefaultMultiPortal);
|
|
2866
3057
|
this.app.resourceManager.registerActionHandler("multiPortals:listAccessible", listAccessibleMultiPortals);
|
|
2867
3058
|
this.app.resourceManager.registerActionHandler("multiPortals:deploy", async (ctx, next) => {
|
|
2868
3059
|
await this.deployPortalDist(ctx, next);
|
|
@@ -2887,6 +3078,11 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2887
3078
|
(0, import_ensureDefaultRoleMultiPortalAccess.applyDefaultRoleMultiPortalAccess)(role);
|
|
2888
3079
|
});
|
|
2889
3080
|
this.app.db.on("desktopRoutes.afterCreate", reconcileCreatedDesktopRoutePermissions);
|
|
3081
|
+
this.app.db.on("multiPortals.beforeUpdate", (multiPortal) => {
|
|
3082
|
+
if (multiPortal.get("enabled") === false && multiPortal.get("isDefault") === true) {
|
|
3083
|
+
multiPortal.set("isDefault", null);
|
|
3084
|
+
}
|
|
3085
|
+
});
|
|
2890
3086
|
this.app.db.on("multiPortals.afterCreate", async (multiPortal, options) => {
|
|
2891
3087
|
await grantDefaultAccessToNewMultiPortal(this.app.db, multiPortal, options);
|
|
2892
3088
|
await this.publishAppManifestItem(multiPortal, options);
|
|
@@ -2906,9 +3102,6 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2906
3102
|
}
|
|
2907
3103
|
await this.removeMultiPortalStorageItem(multiPortal, options);
|
|
2908
3104
|
});
|
|
2909
|
-
this.app.db.on("uiLayouts.afterUpdate", async (uiLayout, options) => {
|
|
2910
|
-
await this.publishUiLayoutManifestItems(uiLayout, options);
|
|
2911
|
-
});
|
|
2912
3105
|
}
|
|
2913
3106
|
async install() {
|
|
2914
3107
|
const version = await this.app.version.get();
|