@abtnode/core 1.6.18 → 1.6.22
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/api/node.js +1 -1
- package/lib/blocklet/manager/disk.js +55 -30
- package/lib/event.js +3 -2
- package/lib/index.js +2 -2
- package/lib/migrations/1.6.21-rename-ip-echo-domain.js +35 -0
- package/lib/migrations/index.js +6 -2
- package/lib/router/helper.js +90 -55
- package/lib/router/index.js +7 -7
- package/lib/router/manager.js +4 -4
- package/lib/states/blocklet.js +80 -4
- package/lib/states/node.js +4 -3
- package/lib/util/blocklet.js +49 -2
- package/lib/util/get-accessible-external-node-ip.js +2 -2
- package/lib/util/index.js +5 -5
- package/lib/util/upgrade.js +8 -4
- package/lib/webhook/index.js +23 -24
- package/package.json +22 -22
package/lib/api/node.js
CHANGED
|
@@ -93,7 +93,7 @@ class NodeAPI {
|
|
|
93
93
|
async updateNodeInfo(entity = {}, context) {
|
|
94
94
|
await validateNodeInfo(entity, context);
|
|
95
95
|
|
|
96
|
-
if (entity.autoUpgrade) {
|
|
96
|
+
if (entity.autoUpgrade && process.env.NODE_ENV !== 'development') {
|
|
97
97
|
try {
|
|
98
98
|
canPackageReadWrite(process.env.ABT_NODE_BINARY_NAME, process.env.ABT_NODE_PACKAGE_NAME);
|
|
99
99
|
} catch (err) {
|
|
@@ -20,11 +20,12 @@ const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
|
|
|
20
20
|
const downloadFile = require('@abtnode/util/lib/download-file');
|
|
21
21
|
const Lock = require('@abtnode/util/lib/lock');
|
|
22
22
|
const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
|
|
23
|
-
const {
|
|
23
|
+
const { VC_TYPE_BLOCKLET_PURCHASE } = require('@abtnode/constant');
|
|
24
24
|
|
|
25
25
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
26
26
|
const {
|
|
27
27
|
isFreeBlocklet,
|
|
28
|
+
isComponentBlocklet,
|
|
28
29
|
isDeletableBlocklet,
|
|
29
30
|
getRequiredMissingConfigs,
|
|
30
31
|
hasRunnableComponent,
|
|
@@ -88,6 +89,8 @@ const {
|
|
|
88
89
|
checkDuplicateComponents,
|
|
89
90
|
getDiffFiles,
|
|
90
91
|
getBundleDir,
|
|
92
|
+
needBlockletDownload,
|
|
93
|
+
verifyPurchase,
|
|
91
94
|
} = require('../../util/blocklet');
|
|
92
95
|
const states = require('../../states');
|
|
93
96
|
const BlockletRegistry = require('../registry');
|
|
@@ -195,6 +198,20 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
195
198
|
throw new Error('Unknown source');
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
/**
|
|
202
|
+
* @param {String} rootDid
|
|
203
|
+
* @param {String} mountPoint
|
|
204
|
+
* @param {Boolean} context.blockletPurchaseVerified
|
|
205
|
+
*
|
|
206
|
+
* installFromUrl
|
|
207
|
+
* @param {String} url
|
|
208
|
+
*
|
|
209
|
+
* InstallFromUpload
|
|
210
|
+
* @param {Object} file
|
|
211
|
+
* @param {String} did for diff upload
|
|
212
|
+
* @param {String} diffVersion for diff upload
|
|
213
|
+
* @param {Array} deleteSet for diff upload
|
|
214
|
+
*/
|
|
198
215
|
async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet }, context = {}) {
|
|
199
216
|
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
200
217
|
|
|
@@ -242,8 +259,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
242
259
|
// FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
|
|
243
260
|
verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
|
|
244
261
|
|
|
245
|
-
if (!vc.type.includes(
|
|
246
|
-
throw new Error(`Expect ${
|
|
262
|
+
if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
|
|
263
|
+
throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
|
|
247
264
|
}
|
|
248
265
|
|
|
249
266
|
const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
|
|
@@ -819,21 +836,23 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
819
836
|
};
|
|
820
837
|
}
|
|
821
838
|
|
|
822
|
-
async updateChildren({ updateId, did: inputDid, children: inputChildren }, context) {
|
|
839
|
+
async updateChildren({ updateId, did: inputDid, children: inputChildren, oldBlocklet: inputOldBlocklet }, context) {
|
|
823
840
|
let did;
|
|
824
841
|
let children;
|
|
842
|
+
let oldBlocklet;
|
|
825
843
|
if (!updateId && inputDid && inputChildren) {
|
|
826
844
|
did = inputDid;
|
|
827
845
|
children = inputChildren;
|
|
846
|
+
oldBlocklet = inputOldBlocklet;
|
|
828
847
|
} else {
|
|
829
848
|
const sessionData = await states.session.end(updateId);
|
|
830
849
|
did = sessionData.did;
|
|
831
850
|
const { staticChildren = [], dynamicChildren = [] } = sessionData;
|
|
832
851
|
children = [...staticChildren, ...dynamicChildren.map((x) => ({ ...x, dynamic: true }))];
|
|
852
|
+
oldBlocklet = await states.blocklet.getBlocklet(did);
|
|
833
853
|
}
|
|
834
854
|
|
|
835
855
|
// get old blocklet
|
|
836
|
-
const oldBlocklet = await states.blocklet.getBlocklet(did);
|
|
837
856
|
const { meta } = oldBlocklet;
|
|
838
857
|
const { name, version } = meta;
|
|
839
858
|
|
|
@@ -1179,9 +1198,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1179
1198
|
return;
|
|
1180
1199
|
}
|
|
1181
1200
|
|
|
1182
|
-
const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading);
|
|
1183
|
-
this.emit(BlockletEvents.statusChange, blocklet1);
|
|
1184
|
-
|
|
1185
1201
|
preDownloadLock.release();
|
|
1186
1202
|
|
|
1187
1203
|
const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet);
|
|
@@ -1327,14 +1343,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1327
1343
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
1328
1344
|
const nodeInfo = await states.node.read();
|
|
1329
1345
|
|
|
1330
|
-
const rootSystemEnvironments =
|
|
1331
|
-
|
|
1346
|
+
const rootSystemEnvironments = {
|
|
1347
|
+
...getRootSystemEnvironments(blockletWithEnv, nodeInfo),
|
|
1348
|
+
...getOverwrittenEnvironments(blockletWithEnv, nodeInfo),
|
|
1349
|
+
};
|
|
1332
1350
|
|
|
1333
1351
|
// fill environments to blocklet and blocklet.children
|
|
1334
1352
|
blocklet.environments = formatEnvironments({
|
|
1335
1353
|
...getSystemEnvironments(blockletWithEnv),
|
|
1336
1354
|
...rootSystemEnvironments,
|
|
1337
|
-
...overwrittenEnvironments,
|
|
1338
1355
|
});
|
|
1339
1356
|
|
|
1340
1357
|
for (const child of blocklet.children) {
|
|
@@ -1343,11 +1360,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1343
1360
|
child.environments = formatEnvironments({
|
|
1344
1361
|
...getSystemEnvironments(childWithEnv), // system env of child blocklet
|
|
1345
1362
|
...rootSystemEnvironments, // system env of root blocklet
|
|
1346
|
-
...overwrittenEnvironments,
|
|
1347
1363
|
});
|
|
1348
1364
|
}
|
|
1349
1365
|
}
|
|
1350
1366
|
|
|
1367
|
+
// put BLOCKLET_APP_ID at root level for indexing
|
|
1368
|
+
blocklet.appDid = rootSystemEnvironments.BLOCKLET_APP_ID;
|
|
1369
|
+
|
|
1351
1370
|
// update state to db
|
|
1352
1371
|
return states.blocklet.updateBlocklet(did, blocklet);
|
|
1353
1372
|
}
|
|
@@ -1368,23 +1387,21 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1368
1387
|
|
|
1369
1388
|
const registryUrl = registry || (await states.node.getBlockletRegistry());
|
|
1370
1389
|
const info = await BlockletRegistry.getRegistryMeta(registryUrl);
|
|
1371
|
-
const
|
|
1372
|
-
if (!
|
|
1390
|
+
const meta = await this.registry.getBlocklet(did, registryUrl);
|
|
1391
|
+
if (!meta) {
|
|
1373
1392
|
throw new Error('Can not install blocklet that not found in registry');
|
|
1374
1393
|
}
|
|
1375
1394
|
|
|
1376
|
-
const state = await states.blocklet.getBlocklet(
|
|
1395
|
+
const state = await states.blocklet.getBlocklet(meta.did);
|
|
1377
1396
|
if (state) {
|
|
1378
1397
|
throw new Error('Can not install an already installed blocklet');
|
|
1379
1398
|
}
|
|
1380
1399
|
|
|
1381
|
-
|
|
1382
|
-
throw new Error('Can not install a non-free blocklet directly');
|
|
1383
|
-
}
|
|
1400
|
+
verifyPurchase(meta, context);
|
|
1384
1401
|
|
|
1385
1402
|
// install
|
|
1386
1403
|
return this._install({
|
|
1387
|
-
meta
|
|
1404
|
+
meta,
|
|
1388
1405
|
source: BlockletSource.registry,
|
|
1389
1406
|
deployedFrom: info.cdnUrl || registryUrl,
|
|
1390
1407
|
context,
|
|
@@ -1434,6 +1451,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1434
1451
|
throw new Error('Cannot add self as a component');
|
|
1435
1452
|
}
|
|
1436
1453
|
|
|
1454
|
+
if (!isComponentBlocklet(meta)) {
|
|
1455
|
+
throw new Error('The blocklet cannot be a component');
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
verifyPurchase(meta, context);
|
|
1459
|
+
|
|
1437
1460
|
const newChildren = await parseChildren(blocklet.meta, {
|
|
1438
1461
|
children: [
|
|
1439
1462
|
{
|
|
@@ -1447,10 +1470,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1447
1470
|
|
|
1448
1471
|
checkDuplicateComponents(blocklet.children, newChildren);
|
|
1449
1472
|
|
|
1473
|
+
// add component to db
|
|
1474
|
+
await states.blocklet.addChildren(rootDid, newChildren);
|
|
1475
|
+
|
|
1450
1476
|
return this.updateChildren(
|
|
1451
1477
|
{
|
|
1452
1478
|
did: rootDid,
|
|
1453
1479
|
children: [...blocklet.children, ...newChildren],
|
|
1480
|
+
oldBlocklet: blocklet,
|
|
1454
1481
|
},
|
|
1455
1482
|
context
|
|
1456
1483
|
);
|
|
@@ -2272,7 +2299,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2272
2299
|
} else {
|
|
2273
2300
|
const status =
|
|
2274
2301
|
oldBlocklet.status === BlockletStatus.installed ? BlockletStatus.installed : BlockletStatus.stopped;
|
|
2275
|
-
await states.blocklet.setBlockletStatus(did, status);
|
|
2302
|
+
await states.blocklet.setBlockletStatus(did, status, { children: 'all' });
|
|
2276
2303
|
}
|
|
2277
2304
|
|
|
2278
2305
|
blocklet = await this.ensureBlocklet(did, context);
|
|
@@ -2496,10 +2523,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2496
2523
|
} = blocklet;
|
|
2497
2524
|
|
|
2498
2525
|
const metas = [];
|
|
2499
|
-
if (
|
|
2500
|
-
![BlockletSource.upload, BlockletSource.local].includes(blocklet.source) &&
|
|
2501
|
-
get(oldBlocklet, 'meta.dist.integrity') !== get(blocklet, 'meta.dist.integrity')
|
|
2502
|
-
) {
|
|
2526
|
+
if (needBlockletDownload(blocklet)) {
|
|
2503
2527
|
metas.push(blocklet.meta);
|
|
2504
2528
|
}
|
|
2505
2529
|
|
|
@@ -2510,16 +2534,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2510
2534
|
|
|
2511
2535
|
for (const child of blocklet.children) {
|
|
2512
2536
|
const oldChild = oldChildren[child.meta.did];
|
|
2513
|
-
if (
|
|
2514
|
-
!oldChild ||
|
|
2515
|
-
(![BlockletSource.upload, BlockletSource.local].includes(child.source) &&
|
|
2516
|
-
child.sourceUrl &&
|
|
2517
|
-
get(oldChild, 'meta.dist.integrity') !== get(child, 'meta.dist.integrity'))
|
|
2518
|
-
) {
|
|
2537
|
+
if (needBlockletDownload(child, oldChild)) {
|
|
2519
2538
|
metas.push(child.meta);
|
|
2520
2539
|
}
|
|
2521
2540
|
}
|
|
2522
2541
|
|
|
2542
|
+
// update children status
|
|
2543
|
+
const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
|
|
2544
|
+
children: metas.map((x) => ({ did: x.did })),
|
|
2545
|
+
});
|
|
2546
|
+
this.emit(BlockletEvents.statusChange, blocklet1);
|
|
2547
|
+
|
|
2523
2548
|
try {
|
|
2524
2549
|
logger.info('Download Blocklet', { name, did, bundles: metas.map((x) => get(x, 'dist.tarball')) });
|
|
2525
2550
|
const tasks = [];
|
package/lib/event.js
CHANGED
|
@@ -132,7 +132,7 @@ module.exports = ({
|
|
|
132
132
|
onEvent(name, blocklet);
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
-
const
|
|
135
|
+
const handleServerEvent = (eventName) => {
|
|
136
136
|
const [, status] = eventName.split('.');
|
|
137
137
|
onEvent(eventName, {
|
|
138
138
|
title: `Blocklet Server ${status}`,
|
|
@@ -209,7 +209,8 @@ module.exports = ({
|
|
|
209
209
|
|
|
210
210
|
events.handleBlockletAdd = handleBlockletAdd;
|
|
211
211
|
events.handleBlockletRemove = handleBlockletRemove;
|
|
212
|
-
events.
|
|
212
|
+
events.handleServerEvent = handleServerEvent;
|
|
213
|
+
events.onEvent = onEvent;
|
|
213
214
|
|
|
214
215
|
return events;
|
|
215
216
|
};
|
package/lib/index.js
CHANGED
|
@@ -147,7 +147,7 @@ function ABTNode(options) {
|
|
|
147
147
|
getCertificates,
|
|
148
148
|
getSitesFromSnapshot,
|
|
149
149
|
getRoutingCrons,
|
|
150
|
-
|
|
150
|
+
ensureWildcardCerts,
|
|
151
151
|
} = getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager });
|
|
152
152
|
|
|
153
153
|
const teamManager = new TeamManager({ nodeDid: options.nodeDid, dataDirs, states });
|
|
@@ -318,7 +318,7 @@ function ABTNode(options) {
|
|
|
318
318
|
takeRoutingSnapshot,
|
|
319
319
|
getSitesFromSnapshot,
|
|
320
320
|
ensureDashboardRouting,
|
|
321
|
-
|
|
321
|
+
ensureWildcardCerts,
|
|
322
322
|
|
|
323
323
|
addDomainAlias: routerManager.addDomainAlias.bind(routerManager),
|
|
324
324
|
deleteDomainAlias: routerManager.deleteDomainAlias.bind(routerManager),
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const yaml = require('js-yaml');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const set = require('lodash/set');
|
|
4
|
+
const omit = require('lodash/omit');
|
|
5
|
+
const {
|
|
6
|
+
DEFAULT_WILDCARD_CERT_HOST,
|
|
7
|
+
DEFAULT_DID_DOMAIN,
|
|
8
|
+
DEFAULT_DID_REGISTRY,
|
|
9
|
+
DEFAULT_IP_DOMAIN,
|
|
10
|
+
} = require('@abtnode/constant');
|
|
11
|
+
|
|
12
|
+
module.exports = async ({ states, printInfo, configFile }) => {
|
|
13
|
+
printInfo('Try to rename dashboardDomain to ipWildcardDomain in db...');
|
|
14
|
+
|
|
15
|
+
let info = await states.node.read();
|
|
16
|
+
set(info, 'routing.ipWildcardDomain', info.routing.dashboardDomain || DEFAULT_IP_DOMAIN);
|
|
17
|
+
set(info, 'routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
|
|
18
|
+
set(info, 'didDomain', DEFAULT_DID_DOMAIN);
|
|
19
|
+
set(info, 'didRegistry', DEFAULT_DID_REGISTRY);
|
|
20
|
+
info = omit(info, 'routing.dashboardDomain');
|
|
21
|
+
|
|
22
|
+
await states.node.updateNodeInfo(info);
|
|
23
|
+
|
|
24
|
+
if (process.env.NODE_ENV !== 'development') {
|
|
25
|
+
let rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
|
|
26
|
+
set(rawConfig, 'node.routing.ipWildcardDomain', info.routing.ipWildcardDomain);
|
|
27
|
+
set(rawConfig, 'node.routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
|
|
28
|
+
set(rawConfig, 'node.didDomain', DEFAULT_DID_DOMAIN);
|
|
29
|
+
set(rawConfig, 'node.didRegistry', DEFAULT_DID_REGISTRY);
|
|
30
|
+
rawConfig = omit(rawConfig, 'node.routing.dashboardDomain');
|
|
31
|
+
fs.writeFileSync(configFile, yaml.dump(rawConfig));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
printInfo(`> Persist new config to file: ${configFile}`);
|
|
35
|
+
};
|
package/lib/migrations/index.js
CHANGED
|
@@ -132,9 +132,13 @@ const runMigrationScripts = async ({
|
|
|
132
132
|
for (let i = 0; i < scripts.length; i++) {
|
|
133
133
|
const { script, version } = scripts[i];
|
|
134
134
|
try {
|
|
135
|
-
|
|
136
|
-
if (executed === false) {
|
|
135
|
+
if (process.env.NODE_ENV === 'development') {
|
|
137
136
|
pending.push(scripts[i]);
|
|
137
|
+
} else {
|
|
138
|
+
const executed = await node.isMigrationExecuted({ script, version });
|
|
139
|
+
if (executed === false) {
|
|
140
|
+
pending.push(scripts[i]);
|
|
141
|
+
}
|
|
138
142
|
}
|
|
139
143
|
} catch (err) {
|
|
140
144
|
printError(`Failed to detect migration script execution status: ${script}, error: ${err.message}`);
|
package/lib/router/helper.js
CHANGED
|
@@ -223,6 +223,19 @@ const ensureServiceRule = async (sites) => {
|
|
|
223
223
|
return site;
|
|
224
224
|
});
|
|
225
225
|
};
|
|
226
|
+
const ensureRootRule = async (sites) => {
|
|
227
|
+
return sites.map((site) => {
|
|
228
|
+
if (!isBasicSite(site.domain) && !site.rules.some((x) => x.from.pathPrefix === '/')) {
|
|
229
|
+
site.rules.push({
|
|
230
|
+
from: { pathPrefix: '/' },
|
|
231
|
+
to: {
|
|
232
|
+
type: ROUTING_RULE_TYPES.NONE,
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return site;
|
|
237
|
+
});
|
|
238
|
+
};
|
|
226
239
|
|
|
227
240
|
const ensureLatestNodeInfo = async (sites = [], { withDefaultCors = true } = {}) => {
|
|
228
241
|
const info = await states.node.read();
|
|
@@ -419,6 +432,13 @@ const decompressCertificates = async (source, dest) => {
|
|
|
419
432
|
return dest;
|
|
420
433
|
};
|
|
421
434
|
|
|
435
|
+
const joinCertDownUrl = (baseUrl, name) => joinUrl(baseUrl, '/certs', name);
|
|
436
|
+
|
|
437
|
+
const getIpEchoCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'ip-abtnet-io.tar.gz');
|
|
438
|
+
const getDidDomainCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'did-abtnet-io.tar.gz');
|
|
439
|
+
const getDownloadCertBaseUrl = (info) =>
|
|
440
|
+
process.env.ABT_NODE_WILDCARD_CERT_HOST || get(info, 'routing.wildcardCertHost', '');
|
|
441
|
+
|
|
422
442
|
module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager }) {
|
|
423
443
|
const nodeState = states.node;
|
|
424
444
|
const blockletState = states.blocklet;
|
|
@@ -428,46 +448,13 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
428
448
|
// site level duplication detection
|
|
429
449
|
const hasRuleByPrefix = (site, value) => site.rules.find((x) => x.isProtected && get(x, 'from.pathPrefix') === value);
|
|
430
450
|
|
|
431
|
-
const
|
|
432
|
-
const info = await nodeState.read();
|
|
433
|
-
const provider = getProviderFromNodeInfo(info);
|
|
434
|
-
if (provider === ROUTER_PROVIDER_NONE) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
const https = get(info, 'routing.https', true);
|
|
439
|
-
const dashboardDomain = get(info, 'routing.dashboardDomain', '');
|
|
440
|
-
const certDownloadAddress =
|
|
441
|
-
process.env.ABT_NODE_DASHBOARD_CERT_DOWN_URL || get(info, 'routing.dashboardCertDownloadAddress', '');
|
|
442
|
-
if (!https || !dashboardDomain || !certDownloadAddress) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
if (checkExpire) {
|
|
447
|
-
try {
|
|
448
|
-
const cert = await routerManager.findCertificateByDomain(dashboardDomain);
|
|
449
|
-
if (!cert) {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const now = Date.now();
|
|
454
|
-
const certInfo = getHttpsCertInfo(cert.certificate);
|
|
455
|
-
if (certInfo.validTo - now >= CERTIFICATE_EXPIRES_OFFSET) {
|
|
456
|
-
logger.info('skip dashboard certificate update before not expired');
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
} catch (err) {
|
|
460
|
-
logger.error('failed to check dashboard certificate expiration', { error: err });
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
451
|
+
const downloadCert = async ({ domain, url }) => {
|
|
465
452
|
const destFolder = getTmpDirectory(path.join(`certificate-${Date.now()}`));
|
|
466
453
|
try {
|
|
467
454
|
const filename = path.join(destFolder, 'certificate.tar.gz');
|
|
468
455
|
fs.ensureDirSync(destFolder);
|
|
469
456
|
|
|
470
|
-
await downloadFile(
|
|
457
|
+
await downloadFile(url, filename);
|
|
471
458
|
await decompressCertificates(filename, destFolder);
|
|
472
459
|
|
|
473
460
|
const certificateFilePath = path.join(destFolder, 'cert.pem');
|
|
@@ -485,7 +472,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
485
472
|
const privateKey = fs.readFileSync(privateKeyFilePath).toString();
|
|
486
473
|
|
|
487
474
|
await certManager.upsertByDomain({
|
|
488
|
-
domain
|
|
475
|
+
domain,
|
|
489
476
|
privateKey,
|
|
490
477
|
certificate,
|
|
491
478
|
isProtected: true,
|
|
@@ -499,23 +486,68 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
499
486
|
}
|
|
500
487
|
};
|
|
501
488
|
|
|
502
|
-
const
|
|
489
|
+
const updateCert = async (domain, url) => {
|
|
490
|
+
try {
|
|
491
|
+
const cert = await routerManager.findCertificateByDomain(domain);
|
|
492
|
+
if (!cert) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const now = Date.now();
|
|
497
|
+
const certInfo = getHttpsCertInfo(cert.certificate);
|
|
498
|
+
if (certInfo.validTo - now >= CERTIFICATE_EXPIRES_OFFSET) {
|
|
499
|
+
logger.info('skip dashboard certificate update before not expired', { domain, url });
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
await downloadCert({
|
|
504
|
+
domain,
|
|
505
|
+
url,
|
|
506
|
+
});
|
|
507
|
+
} catch (err) {
|
|
508
|
+
logger.error('failed to check dashboard certificate expiration', { error: err, domain, url });
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
const updateDashboardCertificates = async () => {
|
|
503
513
|
const info = await nodeState.read();
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
throw new Error('dashboardCertDownloadAddress and dashboardDomain are not found in the routing configs');
|
|
514
|
+
const provider = getProviderFromNodeInfo(info);
|
|
515
|
+
if (provider === ROUTER_PROVIDER_NONE) {
|
|
516
|
+
return;
|
|
508
517
|
}
|
|
509
518
|
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
519
|
+
const https = get(info, 'routing.https', true);
|
|
520
|
+
const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
|
|
521
|
+
const didDomain = info.didDomain;
|
|
522
|
+
const certDownloadAddress = getDownloadCertBaseUrl(info);
|
|
523
|
+
if (!https || !certDownloadAddress) {
|
|
524
|
+
return;
|
|
513
525
|
}
|
|
514
526
|
|
|
515
|
-
|
|
516
|
-
await
|
|
517
|
-
|
|
518
|
-
|
|
527
|
+
await updateCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certDownloadAddress));
|
|
528
|
+
await updateCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certDownloadAddress));
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const ensureWildcardCerts = async () => {
|
|
532
|
+
const info = await nodeState.read();
|
|
533
|
+
const didDomain = info.didDomain;
|
|
534
|
+
const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
|
|
535
|
+
|
|
536
|
+
const ensureDomainCert = async (domain, url) => {
|
|
537
|
+
const cert = await certManager.getByDomain(domain);
|
|
538
|
+
if (!cert) {
|
|
539
|
+
await downloadCert({
|
|
540
|
+
domain,
|
|
541
|
+
url,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
const certBaseUrl = getDownloadCertBaseUrl(info);
|
|
547
|
+
await Promise.all([
|
|
548
|
+
ensureDomainCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certBaseUrl)),
|
|
549
|
+
ensureDomainCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certBaseUrl)),
|
|
550
|
+
]);
|
|
519
551
|
};
|
|
520
552
|
|
|
521
553
|
const upsertSiteRule = async ({ site, rule }, context) => {
|
|
@@ -658,9 +690,9 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
658
690
|
return domainAlias === item;
|
|
659
691
|
});
|
|
660
692
|
|
|
661
|
-
const
|
|
693
|
+
const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
|
|
662
694
|
const didDomain = `${info.did.toLowerCase()}.${info.didDomain}`;
|
|
663
|
-
let dashboardAliasDomains = [
|
|
695
|
+
let dashboardAliasDomains = [ipWildcardDomain, didDomain];
|
|
664
696
|
|
|
665
697
|
dashboardAliasDomains = dashboardAliasDomains
|
|
666
698
|
.filter((item) => item && !isExistsInAlias(item))
|
|
@@ -748,8 +780,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
748
780
|
|
|
749
781
|
const existSite = await states.site.findOne({ domain: domainGroup });
|
|
750
782
|
if (!existSite) {
|
|
751
|
-
const
|
|
752
|
-
const domainAliases = [{ value: ipEchoDnsDomain, isProtected: true }];
|
|
783
|
+
const domainAliases = [];
|
|
753
784
|
|
|
754
785
|
const didDomain = getDidDomainForBlocklet({
|
|
755
786
|
name: blocklet.meta.name,
|
|
@@ -757,7 +788,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
757
788
|
didDomain: nodeInfo.didDomain,
|
|
758
789
|
});
|
|
759
790
|
|
|
760
|
-
|
|
791
|
+
const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet, webInterface, nodeInfo.did);
|
|
792
|
+
|
|
793
|
+
// let didDomain in front of ipEchoDnsDomain
|
|
794
|
+
domainAliases.push({ value: didDomain, isProtected: true }, { value: ipEchoDnsDomain, isProtected: true });
|
|
761
795
|
|
|
762
796
|
await routerManager.addRoutingSite(
|
|
763
797
|
{
|
|
@@ -1157,6 +1191,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1157
1191
|
sites = await ensureLatestInfo(sites);
|
|
1158
1192
|
sites = await ensureAuthService(sites, blockletManager);
|
|
1159
1193
|
sites = await ensureServiceRule(sites);
|
|
1194
|
+
sites = await ensureRootRule(sites);
|
|
1160
1195
|
|
|
1161
1196
|
const certificates = httpsEnabled ? await certManager.getAllNormal() : [];
|
|
1162
1197
|
|
|
@@ -1386,7 +1421,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1386
1421
|
getSitesFromSnapshot,
|
|
1387
1422
|
getCertificates,
|
|
1388
1423
|
checkDomain,
|
|
1389
|
-
|
|
1424
|
+
ensureWildcardCerts,
|
|
1390
1425
|
addWellknownSite,
|
|
1391
1426
|
upsertSiteRule,
|
|
1392
1427
|
|
|
@@ -1394,7 +1429,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1394
1429
|
{
|
|
1395
1430
|
name: 'update-dashboard-certificate',
|
|
1396
1431
|
time: '0 1 */6 * * *', // refetch on 0:00, 6:00, etc.
|
|
1397
|
-
fn: () =>
|
|
1432
|
+
fn: () => updateDashboardCertificates(),
|
|
1398
1433
|
options: { runOnInit: true },
|
|
1399
1434
|
},
|
|
1400
1435
|
{
|
package/lib/router/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const {
|
|
|
5
5
|
DOMAIN_FOR_DEFAULT_SITE,
|
|
6
6
|
DOMAIN_FOR_IP_SITE_REGEXP,
|
|
7
7
|
ROUTING_RULE_TYPES,
|
|
8
|
-
|
|
8
|
+
DEFAULT_IP_DOMAIN,
|
|
9
9
|
BLOCKLET_PROXY_PATH_PREFIX,
|
|
10
10
|
BLOCKLET_SITE_GROUP_SUFFIX,
|
|
11
11
|
} = require('@abtnode/constant');
|
|
@@ -60,12 +60,12 @@ const getRoutingTable = ({ sites, nodeInfo }) => {
|
|
|
60
60
|
let routingTable = Router.formatSites(sites);
|
|
61
61
|
routingTable = expandSites(routingTable);
|
|
62
62
|
|
|
63
|
-
// put
|
|
63
|
+
// put ipWildcardDomain to last, to let blockletDomain match first
|
|
64
64
|
// e.g.
|
|
65
|
-
//
|
|
65
|
+
// ipWildcardDomain: 192-168-3-2.ip.abtnet.io
|
|
66
66
|
// blockletDomain: static-demo-xxx-192-168-3-2.ip.abtnet.io
|
|
67
|
-
const
|
|
68
|
-
const index = routingTable.findIndex((x) => x.domain ===
|
|
67
|
+
const ipWildcardDomain = get(nodeInfo, 'routing.ipWildcardDomain', '');
|
|
68
|
+
const index = routingTable.findIndex((x) => x.domain === ipWildcardDomain);
|
|
69
69
|
if (index > -1) {
|
|
70
70
|
routingTable.push(...routingTable.splice(index, 1));
|
|
71
71
|
}
|
|
@@ -219,11 +219,11 @@ Router.formatSites = (sites = []) => {
|
|
|
219
219
|
|
|
220
220
|
Router.flattenSitesToRules = (sites = [], info = {}) => {
|
|
221
221
|
const result = [];
|
|
222
|
-
const
|
|
222
|
+
const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', DEFAULT_IP_DOMAIN);
|
|
223
223
|
sites.forEach((site) => {
|
|
224
224
|
const aliases = (site.domainAliases || [])
|
|
225
225
|
.map((x) => (typeof x === 'string' ? x : x.value))
|
|
226
|
-
.filter((x) => x !==
|
|
226
|
+
.filter((x) => x !== ipWildcardDomain)
|
|
227
227
|
.filter(Boolean);
|
|
228
228
|
|
|
229
229
|
if (Array.isArray(site.rules) && site.rules.length > 0) {
|
package/lib/router/manager.js
CHANGED
|
@@ -221,10 +221,10 @@ class RouterManager extends EventEmitter {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
);
|
|
224
|
+
// let custom domain in front of protected domain
|
|
225
|
+
const domainAliases = [{ value: domainAlias, isProtected: false }, ...dbSite.domainAliases];
|
|
226
|
+
|
|
227
|
+
const updateResult = await states.site.update({ _id: id }, { $set: { domainAliases } });
|
|
228
228
|
logger.debug('add domain alias update result', { id, updateResult, domainAlias });
|
|
229
229
|
|
|
230
230
|
const newSite = await states.site.findOne({ _id: id });
|
package/lib/states/blocklet.js
CHANGED
|
@@ -20,7 +20,7 @@ const {
|
|
|
20
20
|
const logger = require('@abtnode/logger')('state-blocklet');
|
|
21
21
|
|
|
22
22
|
const BaseState = require('./base');
|
|
23
|
-
const { forEachBlocklet } = require('../util/blocklet');
|
|
23
|
+
const { forEachBlocklet, checkDuplicateComponents } = require('../util/blocklet');
|
|
24
24
|
const { validateBlockletMeta } = require('../util');
|
|
25
25
|
|
|
26
26
|
const lock = new Lock('blocklet-port-assign-lock');
|
|
@@ -80,7 +80,11 @@ class BlockletState extends BaseState {
|
|
|
80
80
|
|
|
81
81
|
getBlocklet(did) {
|
|
82
82
|
return new Promise((resolve, reject) => {
|
|
83
|
-
|
|
83
|
+
if (!did) {
|
|
84
|
+
resolve(null);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.db.findOne({ $or: [{ 'meta.did': did }, { appDid: did }] }, (err, doc) => {
|
|
84
88
|
if (err) {
|
|
85
89
|
return reject(err);
|
|
86
90
|
}
|
|
@@ -160,6 +164,7 @@ class BlockletState extends BaseState {
|
|
|
160
164
|
// add to db
|
|
161
165
|
this.db.insert(
|
|
162
166
|
{
|
|
167
|
+
appDid: null, // will updated later when updating blocklet environments
|
|
163
168
|
mode,
|
|
164
169
|
meta: omit(sanitized, ['htmlAst']),
|
|
165
170
|
status,
|
|
@@ -391,13 +396,20 @@ class BlockletState extends BaseState {
|
|
|
391
396
|
return result;
|
|
392
397
|
}
|
|
393
398
|
|
|
394
|
-
|
|
399
|
+
/**
|
|
400
|
+
* @param {String} did blocklet did
|
|
401
|
+
* @param {BlockletStatus} status blocklet status
|
|
402
|
+
*
|
|
403
|
+
* children status only different with parent before blocklet installation
|
|
404
|
+
* @param {Array<{did}>} children
|
|
405
|
+
*/
|
|
406
|
+
async setBlockletStatus(did, status, { children } = {}) {
|
|
395
407
|
if (typeof status === 'undefined') {
|
|
396
408
|
throw new Error('Unsupported blocklet status');
|
|
397
409
|
}
|
|
398
410
|
|
|
399
411
|
const doc = await this.getBlocklet(did);
|
|
400
|
-
if (doc.status === status) {
|
|
412
|
+
if (doc.status === status && !children) {
|
|
401
413
|
return formatBlocklet(doc, 'onRead', this.options.dek);
|
|
402
414
|
}
|
|
403
415
|
|
|
@@ -412,6 +424,28 @@ class BlockletState extends BaseState {
|
|
|
412
424
|
updates.stoppedAt = new Date();
|
|
413
425
|
}
|
|
414
426
|
|
|
427
|
+
// update children status
|
|
428
|
+
updates.children = doc.children.map((child) => {
|
|
429
|
+
if (children === 'all') {
|
|
430
|
+
child.status = status;
|
|
431
|
+
return child;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (!children) {
|
|
435
|
+
if (![BlockletStatus.waiting, BlockletStatus.upgrading, BlockletStatus.installing].includes(status)) {
|
|
436
|
+
child.status = status;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return child;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const inputChild = children.find((x) => x.did === child.meta.did);
|
|
443
|
+
if (inputChild) {
|
|
444
|
+
child.status = status;
|
|
445
|
+
}
|
|
446
|
+
return child;
|
|
447
|
+
});
|
|
448
|
+
|
|
415
449
|
await this.update(doc._id, { $set: updates });
|
|
416
450
|
return formatBlocklet({ ...doc, ...updates }, 'onRead', this.options.dek);
|
|
417
451
|
}
|
|
@@ -463,6 +497,48 @@ class BlockletState extends BaseState {
|
|
|
463
497
|
|
|
464
498
|
return children;
|
|
465
499
|
}
|
|
500
|
+
|
|
501
|
+
async addChildren(did, children) {
|
|
502
|
+
const parent = await this.getBlocklet(did);
|
|
503
|
+
if (!parent) {
|
|
504
|
+
throw new Error('Blocklet does not exist');
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const oldChildren = parent.children || [];
|
|
508
|
+
|
|
509
|
+
const newChildren = [...oldChildren];
|
|
510
|
+
for (const child of children) {
|
|
511
|
+
const { meta, mountPoint, sourceUrl = '', source = '', deployedFrom = '' } = child;
|
|
512
|
+
|
|
513
|
+
if (!mountPoint) {
|
|
514
|
+
throw new Error(`mountPoint is required when adding component ${meta.title || meta.name}`);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (meta.did === parent.meta.did) {
|
|
518
|
+
throw new Error('Cannot add self as a component');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
checkDuplicateComponents([child], newChildren);
|
|
522
|
+
|
|
523
|
+
newChildren.push({
|
|
524
|
+
mountPoint,
|
|
525
|
+
meta,
|
|
526
|
+
sourceUrl,
|
|
527
|
+
source,
|
|
528
|
+
deployedFrom,
|
|
529
|
+
dynamic: true,
|
|
530
|
+
status: BlockletStatus.added,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// use upgradeBlocklet to assign ports to children and write new data to db
|
|
535
|
+
return this.upgradeBlocklet({
|
|
536
|
+
meta: parent.meta,
|
|
537
|
+
source: parent.source,
|
|
538
|
+
deployedFrom: parent.deployedFrom,
|
|
539
|
+
children: newChildren,
|
|
540
|
+
});
|
|
541
|
+
}
|
|
466
542
|
}
|
|
467
543
|
|
|
468
544
|
BlockletState.BlockletStatus = BlockletStatus;
|
package/lib/states/node.js
CHANGED
|
@@ -92,7 +92,7 @@ class NodeState extends BaseState {
|
|
|
92
92
|
mode,
|
|
93
93
|
runtimeConfig,
|
|
94
94
|
ownerNft,
|
|
95
|
-
|
|
95
|
+
launcher,
|
|
96
96
|
didRegistry,
|
|
97
97
|
didDomain,
|
|
98
98
|
enablePassportIssuance = true,
|
|
@@ -128,7 +128,7 @@ class NodeState extends BaseState {
|
|
|
128
128
|
runtimeConfig,
|
|
129
129
|
ownerNft,
|
|
130
130
|
diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
|
|
131
|
-
|
|
131
|
+
launcher: launcher || undefined,
|
|
132
132
|
didRegistry,
|
|
133
133
|
didDomain,
|
|
134
134
|
enablePassportIssuance,
|
|
@@ -162,7 +162,8 @@ class NodeState extends BaseState {
|
|
|
162
162
|
// FIXME: 这个接口比较危险,可能会修改一些本不应该修改的字段,后续需要考虑改进
|
|
163
163
|
async updateNodeInfo(entity = {}) {
|
|
164
164
|
const record = await this.read();
|
|
165
|
-
|
|
165
|
+
|
|
166
|
+
const updateResult = await this.update(record._id, { $set: omit(entity, ['ownerNft', 'sk']) });
|
|
166
167
|
this.emit('node.updated', updateResult, record);
|
|
167
168
|
return updateResult;
|
|
168
169
|
}
|
package/lib/util/blocklet.js
CHANGED
|
@@ -42,7 +42,7 @@ const validateBlockletEntry = require('@blocklet/meta/lib/entry');
|
|
|
42
42
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
43
43
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
44
44
|
const { validateMeta, fixAndValidateService } = require('@blocklet/meta/lib/validate');
|
|
45
|
-
const { forEachBlocklet } = require('@blocklet/meta/lib/util');
|
|
45
|
+
const { forEachBlocklet, isFreeBlocklet } = require('@blocklet/meta/lib/util');
|
|
46
46
|
|
|
47
47
|
const { validate: validateEngine, get: getEngine } = require('../blocklet/manager/engine');
|
|
48
48
|
|
|
@@ -951,7 +951,7 @@ const getRuntimeInfo = async (appId) => {
|
|
|
951
951
|
|
|
952
952
|
/**
|
|
953
953
|
* merge services
|
|
954
|
-
* from meta.children[].mountPoints[].services
|
|
954
|
+
* from meta.children[].mountPoints[].services, meta.children[].services
|
|
955
955
|
* to childrenMeta[].interfaces[].services
|
|
956
956
|
*
|
|
957
957
|
* @param {array<child>|object{children:array}} source e.g. [<config>] or { children: [<config>] }
|
|
@@ -993,6 +993,23 @@ const mergeMeta = (source, childrenMeta = []) => {
|
|
|
993
993
|
childInterface.services = services;
|
|
994
994
|
}
|
|
995
995
|
});
|
|
996
|
+
|
|
997
|
+
if (config.services) {
|
|
998
|
+
const childInterface = findWebInterface(childMeta);
|
|
999
|
+
if (childInterface) {
|
|
1000
|
+
// merge
|
|
1001
|
+
const services = childInterface.services || [];
|
|
1002
|
+
config.services.forEach((x) => {
|
|
1003
|
+
const index = services.findIndex((y) => y.name === x.name);
|
|
1004
|
+
if (index >= 0) {
|
|
1005
|
+
services.splice(index, 1, x);
|
|
1006
|
+
} else {
|
|
1007
|
+
services.push(x);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
childInterface.services = services;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
996
1013
|
});
|
|
997
1014
|
};
|
|
998
1015
|
|
|
@@ -1101,6 +1118,34 @@ const getDiffFiles = async (inputFiles, sourceDir) => {
|
|
|
1101
1118
|
|
|
1102
1119
|
const getBundleDir = (installDir, bundle) => path.join(installDir, bundle.name, bundle.version);
|
|
1103
1120
|
|
|
1121
|
+
const needBlockletDownload = (blocklet, oldBlocklet) => {
|
|
1122
|
+
if ([BlockletSource.upload, BlockletSource.local, BlockletSource.custom].includes(blocklet.source)) {
|
|
1123
|
+
return false;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
if (!get(oldBlocklet, 'meta.dist.integrity')) {
|
|
1127
|
+
return true;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (get(oldBlocklet, 'meta.dist.integrity') === get(blocklet, 'meta.dist.integrity')) {
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
return true;
|
|
1135
|
+
};
|
|
1136
|
+
|
|
1137
|
+
const verifyPurchase = (meta, opts = {}) => {
|
|
1138
|
+
if (opts.blockletPurchaseVerified) {
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
if (isFreeBlocklet(meta)) {
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
throw new Error('Can not install a non-free blocklet directly');
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1104
1149
|
module.exports = {
|
|
1105
1150
|
forEachBlocklet,
|
|
1106
1151
|
getBlockletMetaFromUrl,
|
|
@@ -1135,4 +1180,6 @@ module.exports = {
|
|
|
1135
1180
|
checkDuplicateComponents,
|
|
1136
1181
|
getDiffFiles,
|
|
1137
1182
|
getBundleDir,
|
|
1183
|
+
needBlockletDownload,
|
|
1184
|
+
verifyPurchase,
|
|
1138
1185
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const joinUrl = require('url-join');
|
|
2
2
|
const axios = require('@abtnode/util/lib/axios');
|
|
3
|
-
const {
|
|
3
|
+
const { DEFAULT_IP_DOMAIN, DEFAULT_ADMIN_PATH } = require('@abtnode/constant');
|
|
4
4
|
const { get: getIp } = require('./ip');
|
|
5
5
|
|
|
6
|
-
const getNodeDomain = (ip) => (ip ?
|
|
6
|
+
const getNodeDomain = (ip) => (ip ? DEFAULT_IP_DOMAIN.replace(/^\*/, ip.replace(/\./g, '-')) : '');
|
|
7
7
|
|
|
8
8
|
let cache = null;
|
|
9
9
|
|
package/lib/util/index.js
CHANGED
|
@@ -373,7 +373,7 @@ const getBaseUrls = async (node, ips) => {
|
|
|
373
373
|
if (info.routing.provider !== ROUTER_PROVIDER_NONE && info.routing.snapshotHash && info.routing.adminPath) {
|
|
374
374
|
const sites = await node.getSitesFromSnapshot();
|
|
375
375
|
|
|
376
|
-
const {
|
|
376
|
+
const { ipWildcardDomain } = info.routing;
|
|
377
377
|
const adminPath = normalizePathPrefix(info.routing.adminPath);
|
|
378
378
|
const tmpHttpPort = getPort(httpPort, DEFAULT_HTTP_PORT);
|
|
379
379
|
|
|
@@ -383,12 +383,12 @@ const getBaseUrls = async (node, ips) => {
|
|
|
383
383
|
};
|
|
384
384
|
});
|
|
385
385
|
|
|
386
|
-
if (
|
|
387
|
-
const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value ===
|
|
386
|
+
if (ipWildcardDomain) {
|
|
387
|
+
const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value === ipWildcardDomain));
|
|
388
388
|
if (site) {
|
|
389
|
-
const httpInfo = await getHttpInfo(
|
|
389
|
+
const httpInfo = await getHttpInfo(ipWildcardDomain);
|
|
390
390
|
const httpsUrls = availableIps.map((ip) => ({
|
|
391
|
-
url: `${httpInfo.protocol}://${transformIPToDomain(ip)}.${
|
|
391
|
+
url: `${httpInfo.protocol}://${transformIPToDomain(ip)}.${ipWildcardDomain.substring(2)}${
|
|
392
392
|
httpInfo.port
|
|
393
393
|
}${adminPath}`,
|
|
394
394
|
}));
|
package/lib/util/upgrade.js
CHANGED
|
@@ -27,9 +27,6 @@ const waitUpdaterRpc = async (message) =>
|
|
|
27
27
|
const checkNewVersion = async (params, context) => {
|
|
28
28
|
try {
|
|
29
29
|
const info = await states.node.read();
|
|
30
|
-
if (!info.autoUpgrade) {
|
|
31
|
-
return '';
|
|
32
|
-
}
|
|
33
30
|
|
|
34
31
|
if (!process.env.ABT_NODE_PACKAGE_NAME) {
|
|
35
32
|
logger.error('ABT_NODE_PACKAGE_NAME name was not found in environment');
|
|
@@ -176,7 +173,14 @@ const getCron = () => ({
|
|
|
176
173
|
name: 'check-update',
|
|
177
174
|
time: '0 0 8 * * *', // check every day
|
|
178
175
|
// time: '0 */5 * * * *', // check every 5 minutes
|
|
179
|
-
fn:
|
|
176
|
+
fn: async () => {
|
|
177
|
+
const info = await states.node.read();
|
|
178
|
+
if (!info.autoUpgrade) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
checkNewVersion();
|
|
183
|
+
},
|
|
180
184
|
options: { runOnInit: false },
|
|
181
185
|
});
|
|
182
186
|
|
package/lib/webhook/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const logger = require('@abtnode/logger')('@abtnode/core:webhook:index');
|
|
2
|
-
const upperFirst = require('lodash/upperFirst');
|
|
3
2
|
|
|
3
|
+
const sortPriorityUrl = require('@abtnode/util/lib/sort-priority-url');
|
|
4
4
|
const WebHookSender = require('./sender');
|
|
5
5
|
const createQueue = require('../queue');
|
|
6
6
|
const IP = require('../util/ip');
|
|
7
7
|
const states = require('../states');
|
|
8
8
|
const { getBaseUrls } = require('../util');
|
|
9
9
|
|
|
10
|
-
const getSlackUrlInfo = (actionPath = '/notifications', urls) => {
|
|
10
|
+
const getSlackUrlInfo = async (actionPath = '/notifications', urls) => {
|
|
11
11
|
const info = [];
|
|
12
12
|
|
|
13
13
|
if (actionPath && actionPath.startsWith('/blocklet/')) {
|
|
@@ -28,29 +28,27 @@ const getSlackUrlInfo = (actionPath = '/notifications', urls) => {
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const normalized = `${x.url}${actionPath}`.replace(`${protocol}//`, '').replace(/\/+/g, '/');
|
|
39
|
-
const url = `${protocol}//${normalized}`;
|
|
40
|
-
elements.push({
|
|
41
|
-
type: 'button',
|
|
42
|
-
text: {
|
|
43
|
-
type: 'plain_text',
|
|
44
|
-
text: `${upperFirst(x.type)} Address`,
|
|
45
|
-
},
|
|
46
|
-
style: 'primary',
|
|
47
|
-
value: `${upperFirst(x.type)} Address`,
|
|
48
|
-
url,
|
|
49
|
-
});
|
|
50
|
-
});
|
|
31
|
+
const prioritys = await sortPriorityUrl(urls);
|
|
32
|
+
const priorityUrl = prioritys[0].url;
|
|
33
|
+
|
|
34
|
+
const { protocol } = new URL(priorityUrl);
|
|
35
|
+
const normalized = `${priorityUrl}${actionPath}`.replace(`${protocol}//`, '').replace(/\/+/g, '/');
|
|
36
|
+
const url = `${protocol}//${normalized}`;
|
|
37
|
+
|
|
51
38
|
info.push({
|
|
52
39
|
type: 'actions',
|
|
53
|
-
elements
|
|
40
|
+
elements: [
|
|
41
|
+
{
|
|
42
|
+
type: 'button',
|
|
43
|
+
text: {
|
|
44
|
+
type: 'plain_text',
|
|
45
|
+
text: 'Click Me',
|
|
46
|
+
},
|
|
47
|
+
style: 'primary',
|
|
48
|
+
value: 'Click Me',
|
|
49
|
+
url,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
54
52
|
});
|
|
55
53
|
|
|
56
54
|
return info;
|
|
@@ -79,7 +77,8 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
79
77
|
const { name } = nodeInfo;
|
|
80
78
|
const options = { ...message, nodeInfo: `*${name}*` };
|
|
81
79
|
if (item.type === 'slack') {
|
|
82
|
-
|
|
80
|
+
// eslint-disable-next-line
|
|
81
|
+
options.urlInfo = await getSlackUrlInfo(message.action, baseUrls);
|
|
83
82
|
}
|
|
84
83
|
try {
|
|
85
84
|
// eslint-disable-next-line
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.6.
|
|
6
|
+
"version": "1.6.22",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,30 +19,30 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/certificate-manager": "1.6.
|
|
23
|
-
"@abtnode/constant": "1.6.
|
|
24
|
-
"@abtnode/cron": "1.6.
|
|
25
|
-
"@abtnode/db": "1.6.
|
|
26
|
-
"@abtnode/logger": "1.6.
|
|
27
|
-
"@abtnode/queue": "1.6.
|
|
28
|
-
"@abtnode/rbac": "1.6.
|
|
29
|
-
"@abtnode/router-provider": "1.6.
|
|
30
|
-
"@abtnode/static-server": "1.6.
|
|
31
|
-
"@abtnode/timemachine": "1.6.
|
|
32
|
-
"@abtnode/util": "1.6.
|
|
33
|
-
"@arcblock/did": "^1.14.
|
|
34
|
-
"@arcblock/event-hub": "1.14.
|
|
22
|
+
"@abtnode/certificate-manager": "1.6.22",
|
|
23
|
+
"@abtnode/constant": "1.6.22",
|
|
24
|
+
"@abtnode/cron": "1.6.22",
|
|
25
|
+
"@abtnode/db": "1.6.22",
|
|
26
|
+
"@abtnode/logger": "1.6.22",
|
|
27
|
+
"@abtnode/queue": "1.6.22",
|
|
28
|
+
"@abtnode/rbac": "1.6.22",
|
|
29
|
+
"@abtnode/router-provider": "1.6.22",
|
|
30
|
+
"@abtnode/static-server": "1.6.22",
|
|
31
|
+
"@abtnode/timemachine": "1.6.22",
|
|
32
|
+
"@abtnode/util": "1.6.22",
|
|
33
|
+
"@arcblock/did": "^1.14.16",
|
|
34
|
+
"@arcblock/event-hub": "1.14.16",
|
|
35
35
|
"@arcblock/pm2-events": "^0.0.5",
|
|
36
|
-
"@arcblock/vc": "^1.14.
|
|
37
|
-
"@blocklet/meta": "1.6.
|
|
36
|
+
"@arcblock/vc": "^1.14.16",
|
|
37
|
+
"@blocklet/meta": "1.6.22",
|
|
38
38
|
"@fidm/x509": "^1.2.1",
|
|
39
39
|
"@nedb/core": "^1.2.2",
|
|
40
40
|
"@nedb/multi": "^1.2.2",
|
|
41
|
-
"@ocap/mcrypto": "^1.14.
|
|
42
|
-
"@ocap/util": "^1.14.
|
|
43
|
-
"@ocap/wallet": "^1.14.
|
|
41
|
+
"@ocap/mcrypto": "^1.14.16",
|
|
42
|
+
"@ocap/util": "^1.14.16",
|
|
43
|
+
"@ocap/wallet": "^1.14.16",
|
|
44
44
|
"@slack/webhook": "^5.0.3",
|
|
45
|
-
"axios": "^0.
|
|
45
|
+
"axios": "^0.25.0",
|
|
46
46
|
"axon": "^2.0.3",
|
|
47
47
|
"chalk": "^4.0.0",
|
|
48
48
|
"deep-diff": "^1.0.2",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"is-base64": "^1.1.0",
|
|
54
54
|
"is-ip": "^3.1.0",
|
|
55
55
|
"is-url": "^1.2.4",
|
|
56
|
-
"joi": "^17.
|
|
56
|
+
"joi": "^17.6.0",
|
|
57
57
|
"js-yaml": "^3.14.0",
|
|
58
58
|
"lodash": "^4.17.21",
|
|
59
59
|
"lru-cache": "^6.0.0",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"express": "^4.17.1",
|
|
76
76
|
"jest": "^27.4.5"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "18ac52a439dbd04e4ace98d796b6de517503fb14"
|
|
79
79
|
}
|