@abtnode/core 1.6.14 → 1.6.18
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/lib/blocklet/hooks.js +16 -63
- package/lib/blocklet/manager/disk.js +426 -144
- package/lib/blocklet/migration.js +16 -52
- package/lib/event.js +1 -1
- package/lib/index.js +3 -11
- package/lib/migrations/1.6.17-blocklet-children.js +48 -0
- package/lib/router/helper.js +33 -19
- package/lib/router/manager.js +64 -42
- package/lib/states/blocklet-extras.js +39 -3
- package/lib/states/blocklet.js +18 -20
- package/lib/states/node.js +17 -2
- package/lib/util/blocklet.js +276 -67
- package/lib/util/default-node-config.js +1 -1
- package/lib/util/get-domain-for-blocklet.js +2 -2
- package/lib/util/router.js +13 -0
- package/lib/validators/node.js +11 -12
- package/lib/validators/permission.js +16 -1
- package/package.json +21 -21
|
@@ -1,67 +1,25 @@
|
|
|
1
1
|
/* eslint-disable no-await-in-loop */
|
|
2
|
-
const childProcess = require('child_process');
|
|
3
2
|
const fs = require('fs-extra');
|
|
4
3
|
const path = require('path');
|
|
5
4
|
const semver = require('semver');
|
|
5
|
+
const runScript = require('@abtnode/util/lib/run-script');
|
|
6
6
|
|
|
7
7
|
const { getMigrationScripts: getScripts } = require('../migrations');
|
|
8
8
|
const { getSafeEnv } = require('../util');
|
|
9
9
|
const { name } = require('../../package.json');
|
|
10
10
|
const logger = require('@abtnode/logger')(`${name}:blocklet:migration`); // eslint-disable-line
|
|
11
11
|
|
|
12
|
-
const _runScript = ({ appDir, env, migrationScript, progress = false }) => {
|
|
13
|
-
const safeEnv = getSafeEnv(env);
|
|
14
|
-
|
|
15
|
-
const child = childProcess.exec(`node ${migrationScript}`, {
|
|
16
|
-
cwd: appDir,
|
|
17
|
-
env: safeEnv,
|
|
18
|
-
stdio: 'inherit',
|
|
19
|
-
});
|
|
20
|
-
let hasUnhandledRejection = false;
|
|
21
|
-
|
|
22
|
-
if (progress) {
|
|
23
|
-
child.stdout.pipe(process.stdout);
|
|
24
|
-
child.stderr.pipe(process.stderr);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return new Promise((resolve, reject) => {
|
|
28
|
-
const errorMessages = [];
|
|
29
|
-
|
|
30
|
-
child.stderr.on('data', (err) => {
|
|
31
|
-
// Check if has unhandledRejection in childProcess
|
|
32
|
-
// https://stackoverflow.com/questions/32784649/gracefully-handle-errors-in-child-processes-in-nodejs
|
|
33
|
-
if (err.includes('UnhandledPromiseRejectionWarning')) {
|
|
34
|
-
hasUnhandledRejection = true;
|
|
35
|
-
}
|
|
36
|
-
errorMessages.push(err);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
child.on('exit', (code) => {
|
|
40
|
-
if (errorMessages.length > 0) {
|
|
41
|
-
if (code !== 0 || hasUnhandledRejection) {
|
|
42
|
-
return reject(new Error(errorMessages.join('\r\n')));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!progress) {
|
|
46
|
-
errorMessages.forEach((message) => process.stderr.write(message));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return resolve();
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
|
|
55
12
|
async function runScripts({
|
|
13
|
+
blocklet,
|
|
14
|
+
appDir,
|
|
15
|
+
env,
|
|
16
|
+
oldVersion,
|
|
56
17
|
dbDir,
|
|
57
18
|
backupDir,
|
|
58
19
|
scriptsDir,
|
|
59
20
|
printInfo,
|
|
60
21
|
printSuccess,
|
|
61
22
|
printError,
|
|
62
|
-
appDir,
|
|
63
|
-
env,
|
|
64
|
-
oldVersion,
|
|
65
23
|
}) {
|
|
66
24
|
let scripts = [];
|
|
67
25
|
try {
|
|
@@ -90,7 +48,11 @@ async function runScripts({
|
|
|
90
48
|
const { script: scriptPath } = pendingScripts[i];
|
|
91
49
|
try {
|
|
92
50
|
printInfo(`Migration script started: ${scriptPath}`);
|
|
93
|
-
await
|
|
51
|
+
await runScript(`node ${path.join(scriptsDir, scriptPath)}`, [blocklet.env.appId, 'migration'].join(':'), {
|
|
52
|
+
cwd: appDir,
|
|
53
|
+
env: getSafeEnv(env),
|
|
54
|
+
silent: false,
|
|
55
|
+
});
|
|
94
56
|
printInfo(`Migration script executed: ${scriptPath}`);
|
|
95
57
|
} catch (migrationErr) {
|
|
96
58
|
printError(`Failed to execute migration script: ${scriptPath}, error: ${migrationErr.message}`);
|
|
@@ -123,6 +85,7 @@ async function doRestore({ dbDir, backupDir, printInfo, printSuccess }) {
|
|
|
123
85
|
}
|
|
124
86
|
|
|
125
87
|
module.exports = async ({
|
|
88
|
+
blocklet,
|
|
126
89
|
appDir,
|
|
127
90
|
env,
|
|
128
91
|
oldVersion,
|
|
@@ -142,15 +105,16 @@ module.exports = async ({
|
|
|
142
105
|
fs.ensureDirSync(backupDir);
|
|
143
106
|
|
|
144
107
|
await runScripts({
|
|
108
|
+
blocklet,
|
|
109
|
+
appDir,
|
|
110
|
+
env,
|
|
111
|
+
oldVersion,
|
|
112
|
+
newVersion,
|
|
145
113
|
dbDir,
|
|
146
114
|
backupDir,
|
|
147
115
|
scriptsDir,
|
|
148
116
|
printError,
|
|
149
117
|
printInfo,
|
|
150
118
|
printSuccess,
|
|
151
|
-
appDir,
|
|
152
|
-
env,
|
|
153
|
-
oldVersion,
|
|
154
|
-
newVersion,
|
|
155
119
|
});
|
|
156
120
|
};
|
package/lib/event.js
CHANGED
|
@@ -182,7 +182,7 @@ module.exports = ({
|
|
|
182
182
|
.catch((error) => logger.error('refresh blocklets failed on initialize the registry', { error }));
|
|
183
183
|
|
|
184
184
|
// We need update router on some fields change
|
|
185
|
-
const fields = ['enableWelcomePage', 'webWalletUrl'];
|
|
185
|
+
const fields = ['enableWelcomePage', 'webWalletUrl', 'registerUrl'];
|
|
186
186
|
const shouldUpdateRouter = fields.some((x) => nodeInfo[x] !== oldInfo[x]);
|
|
187
187
|
if (shouldUpdateRouter) {
|
|
188
188
|
handleRouting(nodeInfo).catch((err) => {
|
package/lib/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const { toStatus, fromStatus, ensureDataDirs, getQueueConcurrencyByMem } = requi
|
|
|
50
50
|
* version
|
|
51
51
|
* runtimeConfig: {}
|
|
52
52
|
* autoUpgrade
|
|
53
|
+
* registerUrl
|
|
53
54
|
* webWalletUrl
|
|
54
55
|
*/
|
|
55
56
|
function ABTNode(options) {
|
|
@@ -196,16 +197,17 @@ function ABTNode(options) {
|
|
|
196
197
|
// Blocklet manager
|
|
197
198
|
installBlocklet: blockletManager.install.bind(blockletManager),
|
|
198
199
|
installBlockletFromVc: blockletManager.installBlockletFromVc.bind(blockletManager),
|
|
200
|
+
installComponent: blockletManager.installComponent.bind(blockletManager),
|
|
199
201
|
startBlocklet: blockletManager.start.bind(blockletManager),
|
|
200
202
|
stopBlocklet: blockletManager.stop.bind(blockletManager),
|
|
201
203
|
reloadBlocklet: blockletManager.reload.bind(blockletManager),
|
|
202
204
|
restartBlocklet: blockletManager.restart.bind(blockletManager),
|
|
203
205
|
deleteBlocklet: blockletManager.delete.bind(blockletManager),
|
|
206
|
+
deleteComponent: blockletManager.deleteComponent.bind(blockletManager),
|
|
204
207
|
cancelDownloadBlocklet: blockletManager.cancelDownload.bind(blockletManager),
|
|
205
208
|
upgradeBlocklet: blockletManager.upgrade.bind(blockletManager),
|
|
206
209
|
configBlocklet: blockletManager.config.bind(blockletManager),
|
|
207
210
|
devBlocklet: blockletManager.dev.bind(blockletManager),
|
|
208
|
-
getBlockletStatus: blockletManager.getStatus.bind(blockletManager),
|
|
209
211
|
checkChildBlockletsForUpdates: blockletManager.checkChildrenForUpdates.bind(blockletManager),
|
|
210
212
|
updateChildBlocklets: blockletManager.updateChildren.bind(blockletManager),
|
|
211
213
|
getLatestBlockletVersion: blockletManager.getLatestBlockletVersion.bind(blockletManager),
|
|
@@ -400,16 +402,6 @@ function ABTNode(options) {
|
|
|
400
402
|
} else {
|
|
401
403
|
// We should only respond to pm2 events when node is alive
|
|
402
404
|
events.on('node.started', async () => {
|
|
403
|
-
const info = await states.node.read();
|
|
404
|
-
certManager
|
|
405
|
-
.issue({ domain: `${info.did.toLowerCase()}.${info.didDomain}` })
|
|
406
|
-
.then(() => {
|
|
407
|
-
logger.info('add issue daemon certificate job');
|
|
408
|
-
})
|
|
409
|
-
.catch((error) => {
|
|
410
|
-
logger.error('issue daemon certificate job failed', { error });
|
|
411
|
-
});
|
|
412
|
-
|
|
413
405
|
pm2Events.resume();
|
|
414
406
|
initCron();
|
|
415
407
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* eslint-disable no-continue */
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
/* eslint-disable no-underscore-dangle */
|
|
4
|
+
|
|
5
|
+
module.exports = async ({ states, printInfo }) => {
|
|
6
|
+
printInfo('Try to update blocklet to 1.6.17...');
|
|
7
|
+
const blockletState = states.blocklet;
|
|
8
|
+
|
|
9
|
+
const blocklets = await blockletState.getBlocklets();
|
|
10
|
+
for (const blocklet of blocklets) {
|
|
11
|
+
if (!blocklet) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!blocklet.children || !blocklet.children.length) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const meta = blocklet.meta || {};
|
|
20
|
+
const { did } = meta;
|
|
21
|
+
if (!did) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const children = (blocklet.children || []).map((child) => {
|
|
26
|
+
if (child.mountPoint) {
|
|
27
|
+
return child;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const config = (meta.children || []).find((x) => x.name === child.meta.name);
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
config &&
|
|
34
|
+
config.mountPoints &&
|
|
35
|
+
config.mountPoints[0] &&
|
|
36
|
+
config.mountPoints[0].root &&
|
|
37
|
+
config.mountPoints[0].root.prefix
|
|
38
|
+
) {
|
|
39
|
+
child.mountPoint = config.mountPoints[0].root.prefix;
|
|
40
|
+
}
|
|
41
|
+
printInfo(`Set mountPoint: ${child.mountPoint} to child ${child.meta.name} in ${blocklet.meta.name}`);
|
|
42
|
+
|
|
43
|
+
return child;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await blockletState.update(blocklet._id, { $set: { children } });
|
|
47
|
+
}
|
|
48
|
+
};
|
package/lib/router/helper.js
CHANGED
|
@@ -55,6 +55,7 @@ const { getFromCache: getAccessibleExternalNodeIp } = require('../util/get-acces
|
|
|
55
55
|
|
|
56
56
|
const Router = require('./index');
|
|
57
57
|
const states = require('../states');
|
|
58
|
+
const { getBlockletDomainGroupName, getDidFromDomainGroupName } = require('../util/router');
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
61
|
* replace 888-888-888-888 with accessible ip for domain
|
|
@@ -243,6 +244,9 @@ const ensureLatestNodeInfo = async (sites = [], { withDefaultCors = true } = {})
|
|
|
243
244
|
site.domain = DOMAIN_FOR_IP_SITE_REGEXP;
|
|
244
245
|
|
|
245
246
|
if (withDefaultCors) {
|
|
247
|
+
// Allow CORS from "Install on ABT Node"
|
|
248
|
+
addCorsToSite(site, info.registerUrl);
|
|
249
|
+
|
|
246
250
|
// Allow CORS from "Web Wallet"
|
|
247
251
|
addCorsToSite(site, info.webWalletUrl);
|
|
248
252
|
}
|
|
@@ -313,7 +317,7 @@ const ensureWellknownRule = async (sites) => {
|
|
|
313
317
|
rules.forEach((rule) => {
|
|
314
318
|
if (
|
|
315
319
|
rule.to.type !== ROUTING_RULE_TYPES.BLOCKLET || // is not blocklet
|
|
316
|
-
rule.to.did !== rule.to.realDid // is a component endpoint
|
|
320
|
+
(rule.to.did !== rule.to.realDid && rule.from.pathPrefix !== '/') // is a component endpoint in sub path
|
|
317
321
|
) {
|
|
318
322
|
return;
|
|
319
323
|
}
|
|
@@ -353,6 +357,18 @@ const ensureCorsForWebWallet = async (sites) => {
|
|
|
353
357
|
return sites;
|
|
354
358
|
};
|
|
355
359
|
|
|
360
|
+
const filterSitesForRemovedBlocklets = async (sites = []) => {
|
|
361
|
+
const blocklets = await states.blocklet.getBlocklets();
|
|
362
|
+
return sites.filter((site) => {
|
|
363
|
+
if (!site.domain.endsWith(BLOCKLET_SITE_GROUP_SUFFIX)) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const did = getDidFromDomainGroupName(site.domain);
|
|
368
|
+
return blocklets.some((x) => x.meta.did === did);
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
|
|
356
372
|
const ensureLatestInfo = async (sites = [], { withDefaultCors = true } = {}) => {
|
|
357
373
|
let result = await ensureLatestNodeInfo(sites, { withDefaultCors });
|
|
358
374
|
result = await ensureWellknownRule(result);
|
|
@@ -421,7 +437,8 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
421
437
|
|
|
422
438
|
const https = get(info, 'routing.https', true);
|
|
423
439
|
const dashboardDomain = get(info, 'routing.dashboardDomain', '');
|
|
424
|
-
const certDownloadAddress =
|
|
440
|
+
const certDownloadAddress =
|
|
441
|
+
process.env.ABT_NODE_DASHBOARD_CERT_DOWN_URL || get(info, 'routing.dashboardCertDownloadAddress', '');
|
|
425
442
|
if (!https || !dashboardDomain || !certDownloadAddress) {
|
|
426
443
|
return;
|
|
427
444
|
}
|
|
@@ -495,9 +512,9 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
495
512
|
return { status: 'existed' };
|
|
496
513
|
}
|
|
497
514
|
|
|
498
|
-
logger.debug('downloading certificate', { url: downloadUrl, dashboardDomain });
|
|
515
|
+
logger.debug('downloading dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
|
|
499
516
|
await updateDashboardCertificate({ checkExpire: false });
|
|
500
|
-
logger.debug('
|
|
517
|
+
logger.debug('downloaded dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
|
|
501
518
|
return { status: 'downloaded' };
|
|
502
519
|
};
|
|
503
520
|
|
|
@@ -643,7 +660,9 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
643
660
|
|
|
644
661
|
const dashboardDomain = get(info, 'routing.dashboardDomain', '');
|
|
645
662
|
const didDomain = `${info.did.toLowerCase()}.${info.didDomain}`;
|
|
646
|
-
|
|
663
|
+
let dashboardAliasDomains = [dashboardDomain, didDomain];
|
|
664
|
+
|
|
665
|
+
dashboardAliasDomains = dashboardAliasDomains
|
|
647
666
|
.filter((item) => item && !isExistsInAlias(item))
|
|
648
667
|
.map((item) => ({ value: item, isProtected: true }));
|
|
649
668
|
|
|
@@ -713,7 +732,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
713
732
|
return `/${str}`.replace(/^\/+/, '/');
|
|
714
733
|
};
|
|
715
734
|
|
|
716
|
-
const domainGroup =
|
|
735
|
+
const domainGroup = getBlockletDomainGroupName(blocklet.meta.did);
|
|
717
736
|
|
|
718
737
|
const pathPrefix = getPrefix(webInterface.prefix);
|
|
719
738
|
const rule = {
|
|
@@ -730,17 +749,15 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
730
749
|
const existSite = await states.site.findOne({ domain: domainGroup });
|
|
731
750
|
if (!existSite) {
|
|
732
751
|
const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet, webInterface, nodeInfo.did);
|
|
733
|
-
const appIdEnv = blocklet.environments.find((e) => e.key === 'BLOCKLET_APP_ID');
|
|
734
752
|
const domainAliases = [{ value: ipEchoDnsDomain, isProtected: true }];
|
|
735
753
|
|
|
736
754
|
const didDomain = getDidDomainForBlocklet({
|
|
737
|
-
|
|
755
|
+
name: blocklet.meta.name,
|
|
756
|
+
daemonDid: nodeInfo.did,
|
|
738
757
|
didDomain: nodeInfo.didDomain,
|
|
739
758
|
});
|
|
740
759
|
|
|
741
|
-
|
|
742
|
-
domainAliases.push({ value: didDomain, isProtected: true });
|
|
743
|
-
}
|
|
760
|
+
domainAliases.push({ value: didDomain, isProtected: true });
|
|
744
761
|
|
|
745
762
|
await routerManager.addRoutingSite(
|
|
746
763
|
{
|
|
@@ -755,13 +772,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
755
772
|
context
|
|
756
773
|
);
|
|
757
774
|
logger.info('add routing site', { site: domainGroup });
|
|
758
|
-
if (
|
|
759
|
-
process.env.NODE_ENV !== 'development' &&
|
|
760
|
-
process.env.NODE_ENV !== 'test' &&
|
|
761
|
-
blocklet.mode !== 'development'
|
|
762
|
-
) {
|
|
763
|
-
await certManager.issue({ domain: didDomain });
|
|
764
|
-
}
|
|
765
775
|
|
|
766
776
|
return true;
|
|
767
777
|
}
|
|
@@ -1080,7 +1090,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1080
1090
|
const nodeInfo = await nodeState.read();
|
|
1081
1091
|
|
|
1082
1092
|
const ruleChanged = await routerManager.deleteRoutingRulesItemByDid({ did: blocklet.meta.did }, context);
|
|
1083
|
-
|
|
1093
|
+
let siteChanged;
|
|
1094
|
+
if (!context.keepRouting) {
|
|
1095
|
+
siteChanged = await _removeBlockletSites(blocklet, nodeInfo, context);
|
|
1096
|
+
}
|
|
1084
1097
|
|
|
1085
1098
|
return ruleChanged || siteChanged;
|
|
1086
1099
|
};
|
|
@@ -1140,6 +1153,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1140
1153
|
try {
|
|
1141
1154
|
const info = await nodeState.read();
|
|
1142
1155
|
let { sites } = await readRoutingSites();
|
|
1156
|
+
sites = await filterSitesForRemovedBlocklets(sites);
|
|
1143
1157
|
sites = await ensureLatestInfo(sites);
|
|
1144
1158
|
sites = await ensureAuthService(sites, blockletManager);
|
|
1145
1159
|
sites = await ensureServiceRule(sites);
|
package/lib/router/manager.js
CHANGED
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
BLOCKLET_BUNDLE_FOLDER,
|
|
28
28
|
BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
29
29
|
BLOCKLET_INTERFACE_TYPE_WEB,
|
|
30
|
+
BlockletGroup,
|
|
30
31
|
} = require('@blocklet/meta/lib/constants');
|
|
31
32
|
|
|
32
33
|
const {
|
|
@@ -37,6 +38,7 @@ const {
|
|
|
37
38
|
validateUpdateSite,
|
|
38
39
|
} = require('../validators/router');
|
|
39
40
|
const { getProviderFromNodeInfo, findInterfaceByName, isCLI, findInterfacePortByName } = require('../util');
|
|
41
|
+
const { findWebInterface } = require('../util/blocklet');
|
|
40
42
|
const { attachInterfaceUrls, ensureLatestInfo } = require('./helper');
|
|
41
43
|
const Router = require('./index');
|
|
42
44
|
const states = require('../states');
|
|
@@ -186,19 +188,37 @@ class RouterManager extends EventEmitter {
|
|
|
186
188
|
return dbSite;
|
|
187
189
|
}
|
|
188
190
|
|
|
189
|
-
async addDomainAlias({ id, domainAlias }, context = {}) {
|
|
191
|
+
async addDomainAlias({ id, domainAlias, force }, context = {}) {
|
|
190
192
|
await validateAddDomainAlias(domainAlias, context);
|
|
191
193
|
const dbSite = await states.site.findOne({ _id: id });
|
|
192
194
|
if (!dbSite) {
|
|
193
195
|
throw new Error(`site ${id} does not exist`);
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
// check domain exists in site domain
|
|
199
|
+
const mainDomainSiteCount = await states.site.count({
|
|
200
|
+
domain: domainAlias,
|
|
198
201
|
});
|
|
199
202
|
|
|
200
|
-
if (
|
|
201
|
-
|
|
203
|
+
if (mainDomainSiteCount > 0) {
|
|
204
|
+
if (!force) {
|
|
205
|
+
throw new Error(`${domainAlias} already exists`);
|
|
206
|
+
} else {
|
|
207
|
+
throw new Error(`${domainAlias} cannot be forced-added`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// check domain exists in site alias domain
|
|
212
|
+
const aliasDomainSite = await states.site.findOne({
|
|
213
|
+
$or: [{ domainAliases: domainAlias }, { 'domainAliases.value': domainAlias }],
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (aliasDomainSite) {
|
|
217
|
+
if (!force) {
|
|
218
|
+
throw new Error(`${domainAlias} already exists`);
|
|
219
|
+
} else {
|
|
220
|
+
await this.deleteDomainAlias({ id: aliasDomainSite.id, domainAlias });
|
|
221
|
+
}
|
|
202
222
|
}
|
|
203
223
|
|
|
204
224
|
const updateResult = await states.site.update(
|
|
@@ -661,49 +681,51 @@ class RouterManager extends EventEmitter {
|
|
|
661
681
|
|
|
662
682
|
// get child rules
|
|
663
683
|
const blocklet = await states.blocklet.getBlocklet(rule.to.did);
|
|
664
|
-
for (const
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
684
|
+
for (const child of blocklet.children || []) {
|
|
685
|
+
const { mountPoint } = child;
|
|
686
|
+
if (!mountPoint) {
|
|
687
|
+
logger.error(`mountPoint of child ${child.meta.name} does not exist`);
|
|
688
|
+
// eslint-disable-next-line no-continue
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
673
691
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
692
|
+
const childWebInterface = findWebInterface(child);
|
|
693
|
+
if (!childWebInterface) {
|
|
694
|
+
logger.error(`web interface of child ${child.meta.name} does not exist`);
|
|
695
|
+
// eslint-disable-next-line no-continue
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
680
698
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
from: {
|
|
686
|
-
pathPrefix: normalizePathPrefix(pathPrefix),
|
|
687
|
-
groupPathPrefix: rule.from.pathPrefix,
|
|
688
|
-
},
|
|
689
|
-
to: {
|
|
690
|
-
type: ROUTING_RULE_TYPES.BLOCKLET,
|
|
691
|
-
port: findInterfacePortByName(child, mountPoint.child.interfaceName),
|
|
692
|
-
did: rule.to.did, // root blocklet did
|
|
693
|
-
interfaceName: rule.to.interfaceName, // root blocklet interface
|
|
694
|
-
realDid: child.meta.did, // child blocklet did
|
|
695
|
-
realInterfaceName: mountPoint.child.interfaceName,
|
|
696
|
-
},
|
|
697
|
-
isProtected: isRootPath ? rule.isProtected : true,
|
|
698
|
-
};
|
|
699
|
-
|
|
700
|
-
rules.push(childRule);
|
|
701
|
-
}
|
|
699
|
+
const pathPrefix = path.join(rule.from.pathPrefix, mountPoint);
|
|
700
|
+
const isRootPath = pathPrefix === rule.from.pathPrefix;
|
|
701
|
+
if (isRootPath) {
|
|
702
|
+
occupied = true;
|
|
702
703
|
}
|
|
704
|
+
|
|
705
|
+
// if is root path, child rule become root rule
|
|
706
|
+
const childRule = {
|
|
707
|
+
id: isRootPath ? rule.id : uuid.v4(),
|
|
708
|
+
groupId: rule.id,
|
|
709
|
+
from: {
|
|
710
|
+
pathPrefix: normalizePathPrefix(pathPrefix),
|
|
711
|
+
groupPathPrefix: rule.from.pathPrefix,
|
|
712
|
+
},
|
|
713
|
+
to: {
|
|
714
|
+
type: ROUTING_RULE_TYPES.BLOCKLET,
|
|
715
|
+
port: findInterfacePortByName(child, childWebInterface.name),
|
|
716
|
+
did: rule.to.did, // root blocklet did
|
|
717
|
+
interfaceName: rule.to.interfaceName, // root blocklet interface
|
|
718
|
+
realDid: child.meta.did, // child blocklet did
|
|
719
|
+
realInterfaceName: childWebInterface.name,
|
|
720
|
+
},
|
|
721
|
+
isProtected: isRootPath ? rule.isProtected : true,
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
rules.push(childRule);
|
|
703
725
|
}
|
|
704
726
|
|
|
705
727
|
// get root rule
|
|
706
|
-
if (!occupied) {
|
|
728
|
+
if (!occupied && blocklet.meta.group !== BlockletGroup.gateway) {
|
|
707
729
|
rules.push(rule);
|
|
708
730
|
}
|
|
709
731
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
/* eslint-disable consistent-return */
|
|
4
4
|
const logger = require('@abtnode/logger')('state-blocklet-extras');
|
|
5
5
|
const camelCase = require('lodash/camelCase');
|
|
6
|
+
const get = require('lodash/get');
|
|
6
7
|
|
|
7
8
|
const BaseState = require('./base');
|
|
8
9
|
|
|
@@ -36,16 +37,28 @@ class BlockletExtrasState extends BaseState {
|
|
|
36
37
|
},
|
|
37
38
|
},
|
|
38
39
|
];
|
|
40
|
+
|
|
41
|
+
this.childExtras = this.extras.filter((x) => ['configs'].includes(x.name));
|
|
42
|
+
|
|
39
43
|
this.generateExtraFns();
|
|
40
44
|
}
|
|
41
45
|
|
|
46
|
+
delete(did) {
|
|
47
|
+
return this.remove({ did });
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
generateExtraFns() {
|
|
43
|
-
const methods = ['get', 'set', 'del'];
|
|
51
|
+
const methods = ['get', 'set', 'del', 'list'];
|
|
44
52
|
methods.forEach((method) => {
|
|
45
53
|
this.extras.forEach((extra) => {
|
|
46
54
|
const fn = camelCase(`${method} ${extra.name}`); // getConfigs, getRules
|
|
47
55
|
this[fn] = this.generateExtraFn(method, extra);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
48
58
|
|
|
59
|
+
const childMethods = ['get', 'set', 'del'];
|
|
60
|
+
childMethods.forEach((method) => {
|
|
61
|
+
this.childExtras.forEach((extra) => {
|
|
49
62
|
const childFn = camelCase(`${method} child ${extra.name}`); // getChildConfigs, getChildRules
|
|
50
63
|
this[childFn] = this.generateExtraChildFn(method, extra);
|
|
51
64
|
});
|
|
@@ -66,14 +79,22 @@ class BlockletExtrasState extends BaseState {
|
|
|
66
79
|
if (method === 'del') {
|
|
67
80
|
return this.generateDelFn(extra);
|
|
68
81
|
}
|
|
82
|
+
|
|
83
|
+
if (method === 'list') {
|
|
84
|
+
return this.generateListFn(extra);
|
|
85
|
+
}
|
|
69
86
|
}
|
|
70
87
|
|
|
71
88
|
generateGetFn(extra) {
|
|
72
|
-
return async (did) => {
|
|
89
|
+
return async (did, path, defaultValue) => {
|
|
73
90
|
const { dek } = this.options;
|
|
74
91
|
const { name, afterGet = noop('data') } = extra;
|
|
75
92
|
const item = await this.asyncDB.findOne({ did });
|
|
76
|
-
|
|
93
|
+
const data = afterGet({ data: item ? item[name] : item, did, dek });
|
|
94
|
+
if (!path) {
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
return get(data, path, defaultValue);
|
|
77
98
|
};
|
|
78
99
|
}
|
|
79
100
|
|
|
@@ -118,6 +139,21 @@ class BlockletExtrasState extends BaseState {
|
|
|
118
139
|
};
|
|
119
140
|
}
|
|
120
141
|
|
|
142
|
+
generateListFn(extra) {
|
|
143
|
+
return async () => {
|
|
144
|
+
const { dek } = this.options;
|
|
145
|
+
const { name, afterGet = noop('data') } = extra;
|
|
146
|
+
const docs = await this.asyncDB.find({});
|
|
147
|
+
const list = docs
|
|
148
|
+
.filter((x) => x[name])
|
|
149
|
+
.map((x) => ({
|
|
150
|
+
did: x.did,
|
|
151
|
+
[name]: afterGet({ data: x[name], did: x.did, dek }),
|
|
152
|
+
}));
|
|
153
|
+
return list;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
121
157
|
// generate extra child functions
|
|
122
158
|
|
|
123
159
|
generateExtraChildFn(method, extra) {
|