@abtnode/core 1.6.8 → 1.6.12
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/manager/disk.js +56 -15
- package/lib/cert.js +8 -0
- package/lib/event.js +9 -2
- package/lib/index.js +14 -4
- package/lib/migrations/1.6.9-update-node-info-and-certificate.js +38 -0
- package/lib/router/helper.js +33 -8
- package/lib/router/manager.js +3 -3
- package/lib/states/node.js +8 -0
- package/lib/util/blocklet.js +29 -4
- package/lib/util/{get-ip-dns-domain-for-blocklet.js → get-domain-for-blocklet.js} +5 -1
- package/lib/util/index.js +31 -19
- package/lib/util/ready.js +1 -1
- package/lib/webhook/index.js +3 -3
- package/package.json +14 -14
|
@@ -20,12 +20,13 @@ const hashFiles = require('@abtnode/util/lib/hash-files');
|
|
|
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 { updateBlocklet: updateDidDocument } = require('@abtnode/util/lib/did-document');
|
|
23
24
|
const { BLOCKLET_PURCHASE_NFT_TYPE } = require('@abtnode/constant');
|
|
24
25
|
|
|
25
26
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
26
|
-
const { isFreeBlocklet } = require('@blocklet/meta/lib/util');
|
|
27
|
+
const { isFreeBlocklet, isDeletableBlocklet, getRequiredMissingConfigs } = require('@blocklet/meta/lib/util');
|
|
27
28
|
const validateBlockletEntry = require('@blocklet/meta/lib/entry');
|
|
28
|
-
const {
|
|
29
|
+
const { getBlockletInfo } = require('@blocklet/meta/lib');
|
|
29
30
|
|
|
30
31
|
const {
|
|
31
32
|
BlockletStatus,
|
|
@@ -243,7 +244,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
243
244
|
hooks.preStart(b, {
|
|
244
245
|
appDir: b.env.appDir,
|
|
245
246
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
246
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
247
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
247
248
|
did, // root blocklet did,
|
|
248
249
|
progress: blocklet.mode === BLOCKLET_MODES.DEVELOPMENT,
|
|
249
250
|
}),
|
|
@@ -315,7 +316,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
315
316
|
hooks.preStop({
|
|
316
317
|
appDir: b.env.appDir,
|
|
317
318
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
318
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
319
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
319
320
|
did, // root blocklet did
|
|
320
321
|
notification: states.notification,
|
|
321
322
|
context,
|
|
@@ -380,6 +381,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
380
381
|
|
|
381
382
|
try {
|
|
382
383
|
const blocklet = await this.ensureBlocklet(did);
|
|
384
|
+
if (isDeletableBlocklet(blocklet) === false) {
|
|
385
|
+
throw new Error('Blocklet is protected from accidental deletion');
|
|
386
|
+
}
|
|
383
387
|
|
|
384
388
|
const nodeEnvironments = await states.node.getEnvironments();
|
|
385
389
|
|
|
@@ -388,7 +392,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
388
392
|
hooks.preUninstall({
|
|
389
393
|
appDir: b.env.appDir,
|
|
390
394
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
391
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
395
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
392
396
|
did, // root blocklet did
|
|
393
397
|
notification: states.notification,
|
|
394
398
|
context,
|
|
@@ -513,7 +517,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
513
517
|
|
|
514
518
|
// run hook
|
|
515
519
|
const nodeEnvironments = await states.node.getEnvironments();
|
|
516
|
-
|
|
520
|
+
for (const x of newConfigs) {
|
|
517
521
|
if (x.key === 'BLOCKLET_APP_SK') {
|
|
518
522
|
try {
|
|
519
523
|
fromSecretKey(x.value);
|
|
@@ -524,6 +528,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
524
528
|
throw new Error('Invalid custom blocklet secret key');
|
|
525
529
|
}
|
|
526
530
|
}
|
|
531
|
+
|
|
532
|
+
// Ensure sk is not used by other blocklets, otherwise we may encounter appDid collision
|
|
533
|
+
const blocklets = await states.blocklet.getBlocklets({});
|
|
534
|
+
const others = blocklets.filter((b) => b.meta.did !== did);
|
|
535
|
+
if (others.some((b) => b.environments.find((e) => e.key === 'BLOCKLET_APP_SK').value === x.value)) {
|
|
536
|
+
throw new Error('Invalid custom blocklet secret key: already used by another blocklet');
|
|
537
|
+
}
|
|
527
538
|
}
|
|
528
539
|
|
|
529
540
|
if (x.key === 'BLOCKLET_WALLET_TYPE') {
|
|
@@ -532,8 +543,16 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
532
543
|
}
|
|
533
544
|
}
|
|
534
545
|
|
|
546
|
+
if (x.key === 'BLOCKLET_DELETABLE') {
|
|
547
|
+
if (['yes', 'no'].includes(x.value) === false) {
|
|
548
|
+
throw new Error('BLOCKLET_DELETABLE must be either "yes" or "no"');
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
535
552
|
blocklet.configObj[x.key] = x.value;
|
|
536
|
-
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// FIXME: we should also call preConfig for child blocklets
|
|
537
556
|
await hooks.preConfig({
|
|
538
557
|
appDir: blocklet.env.appDir,
|
|
539
558
|
hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
|
|
@@ -897,7 +916,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
897
916
|
};
|
|
898
917
|
|
|
899
918
|
const childConfigs = await states.blockletExtras.getChildConfigs(did, childDid);
|
|
900
|
-
fillBlockletConfigs(child, childConfigs);
|
|
919
|
+
fillBlockletConfigs(child, childConfigs, blocklet);
|
|
901
920
|
}
|
|
902
921
|
|
|
903
922
|
return blocklet;
|
|
@@ -1496,6 +1515,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1496
1515
|
return null;
|
|
1497
1516
|
}
|
|
1498
1517
|
|
|
1518
|
+
// When new version found from the store where the blocklet was installed from, we should use that store first
|
|
1519
|
+
if (blocklet.source === BlockletSource.registry && blocklet.deployedFrom) {
|
|
1520
|
+
const latestFromSameRegistry = versions.find((x) => x.registryUrl === blocklet.deployedFrom);
|
|
1521
|
+
if (latestFromSameRegistry) {
|
|
1522
|
+
return latestFromSameRegistry;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// Otherwise try upgrading from other store
|
|
1499
1527
|
let latestBlockletVersion = versions[0];
|
|
1500
1528
|
versions.forEach((item) => {
|
|
1501
1529
|
if (semver.lt(latestBlockletVersion.version, item.version)) {
|
|
@@ -1561,7 +1589,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1561
1589
|
|
|
1562
1590
|
await this._setConfigs(did);
|
|
1563
1591
|
|
|
1564
|
-
logger.info('blocklet added to database', { meta });
|
|
1592
|
+
logger.info('blocklet added to database', { did: meta.did });
|
|
1565
1593
|
|
|
1566
1594
|
const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
|
|
1567
1595
|
this.emit(BlockletEvents.added, blocklet1);
|
|
@@ -1855,7 +1883,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1855
1883
|
const postInstall = (b) =>
|
|
1856
1884
|
hooks.postInstall({
|
|
1857
1885
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
1858
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
1886
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
1859
1887
|
appDir: blocklet.env.appDir,
|
|
1860
1888
|
did, // root blocklet did
|
|
1861
1889
|
notification: states.notification,
|
|
@@ -1865,7 +1893,19 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1865
1893
|
|
|
1866
1894
|
await states.blocklet.setBlockletStatus(did, BlockletStatus.installed);
|
|
1867
1895
|
blocklet = await this.ensureBlocklet(did);
|
|
1868
|
-
logger.info('blocklet installed', { source, meta });
|
|
1896
|
+
logger.info('blocklet installed', { source, did: meta.did });
|
|
1897
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
1898
|
+
const nodeInfo = await states.node.read();
|
|
1899
|
+
const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
|
|
1900
|
+
const updateDidDnsResult = await updateDidDocument({
|
|
1901
|
+
wallet: blockletInfo.wallet,
|
|
1902
|
+
domain: nodeInfo.didDomain,
|
|
1903
|
+
nodeDid: nodeInfo.did,
|
|
1904
|
+
didRegistryUrl: nodeInfo.didRegistry,
|
|
1905
|
+
});
|
|
1906
|
+
logger.info('updated did document', { updateDidDnsResult, blockletId: blocklet.meta.did });
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1869
1909
|
this.emit(BlockletEvents.installed, { blocklet, context });
|
|
1870
1910
|
|
|
1871
1911
|
states.notification.create({
|
|
@@ -1943,7 +1983,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1943
1983
|
const postInstall = (b) =>
|
|
1944
1984
|
hooks.postInstall({
|
|
1945
1985
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
1946
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
1986
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
1947
1987
|
appDir: b.env.appDir,
|
|
1948
1988
|
did, // root blocklet did
|
|
1949
1989
|
notification: states.notification,
|
|
@@ -1959,7 +1999,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1959
1999
|
blocklet: b,
|
|
1960
2000
|
oldVersion,
|
|
1961
2001
|
newVersion: version,
|
|
1962
|
-
env: getRuntimeEnvironments(b, nodeEnvironments),
|
|
2002
|
+
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
1963
2003
|
appDir: b.env.appDir,
|
|
1964
2004
|
did: b.meta.did,
|
|
1965
2005
|
notification: states.notification,
|
|
@@ -2251,8 +2291,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2251
2291
|
try {
|
|
2252
2292
|
const state = await states.blocklet.getBlocklet(did);
|
|
2253
2293
|
if (state && util.shouldUpdateBlockletStatus(state.status)) {
|
|
2254
|
-
const
|
|
2255
|
-
|
|
2294
|
+
const newStatus = pm2StatusMap[pm2Status];
|
|
2295
|
+
await states.blocklet.setBlockletStatus(did, newStatus);
|
|
2296
|
+
logger.info('sync pm2 status to blocklet', { did, pm2Status, newStatus });
|
|
2256
2297
|
}
|
|
2257
2298
|
} catch (error) {
|
|
2258
2299
|
logger.error('sync pm2 status to blocklet failed', { did, pm2Status, error });
|
package/lib/cert.js
CHANGED
|
@@ -70,6 +70,10 @@ class Cert extends EventEmitter {
|
|
|
70
70
|
return this.manager.getAllNormal();
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
getNormalByDomain(domain) {
|
|
74
|
+
return this.manager.getNormalByDomain(domain);
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
getByDomain(domain) {
|
|
74
78
|
return this.manager.getByDomain(domain);
|
|
75
79
|
}
|
|
@@ -111,6 +115,10 @@ class Cert extends EventEmitter {
|
|
|
111
115
|
async addWithoutValidations(data) {
|
|
112
116
|
return this.manager.addWithoutValidations(data);
|
|
113
117
|
}
|
|
118
|
+
|
|
119
|
+
async updateWithoutValidations(id, data) {
|
|
120
|
+
return this.manager.updateWithoutValidations(id, data);
|
|
121
|
+
}
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
module.exports = Cert;
|
package/lib/event.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
const get = require('lodash/get');
|
|
2
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
1
3
|
const { EventEmitter } = require('events');
|
|
2
4
|
const { BLOCKLET_MODES } = require('@blocklet/meta/lib/constants');
|
|
5
|
+
const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
|
|
3
6
|
const logger = require('@abtnode/logger')('@abtnode/core:event');
|
|
4
7
|
const { BlockletStatus, BlockletSource, BlockletEvents } = require('@blocklet/meta/lib/constants');
|
|
5
8
|
|
|
@@ -43,9 +46,13 @@ module.exports = ({
|
|
|
43
46
|
let eventHandler = null;
|
|
44
47
|
|
|
45
48
|
const onEvent = (name, data) => {
|
|
46
|
-
|
|
49
|
+
let safeData = data;
|
|
50
|
+
if (get(data, 'meta.did', '')) {
|
|
51
|
+
safeData = wipeSensitiveData(cloneDeep(data));
|
|
52
|
+
}
|
|
53
|
+
events.emit(name, safeData);
|
|
47
54
|
if (typeof eventHandler === 'function') {
|
|
48
|
-
eventHandler({ name, data });
|
|
55
|
+
eventHandler({ name, data: safeData });
|
|
49
56
|
}
|
|
50
57
|
};
|
|
51
58
|
|
package/lib/index.js
CHANGED
|
@@ -132,8 +132,6 @@ function ABTNode(options) {
|
|
|
132
132
|
daemon: options.daemon,
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
-
certManager.start(); // 启动证书服务
|
|
136
|
-
|
|
137
135
|
const {
|
|
138
136
|
handleRouting,
|
|
139
137
|
getRoutingRulesByDid,
|
|
@@ -169,10 +167,10 @@ function ABTNode(options) {
|
|
|
169
167
|
ensureBlockletRoutingForUpgrade,
|
|
170
168
|
removeBlockletRouting,
|
|
171
169
|
takeRoutingSnapshot,
|
|
172
|
-
routerManager,
|
|
173
170
|
handleRouting,
|
|
174
171
|
domainStatus,
|
|
175
172
|
teamAPI,
|
|
173
|
+
certManager,
|
|
176
174
|
});
|
|
177
175
|
|
|
178
176
|
const isInitialized = async () => {
|
|
@@ -395,11 +393,23 @@ function ABTNode(options) {
|
|
|
395
393
|
};
|
|
396
394
|
|
|
397
395
|
if (options.daemon) {
|
|
396
|
+
certManager.start(); // 启动证书服务
|
|
397
|
+
|
|
398
398
|
if (process.env.NODE_ENV === 'development') {
|
|
399
399
|
initCron();
|
|
400
400
|
} else {
|
|
401
401
|
// We should only respond to pm2 events when node is alive
|
|
402
|
-
events.on('node.started', () => {
|
|
402
|
+
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
|
+
|
|
403
413
|
pm2Events.resume();
|
|
404
414
|
initCron();
|
|
405
415
|
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
|
|
3
|
+
const { DEFAULT_DID_REGISTRY, DEFAULT_DID_DOMAIN } = require('@abtnode/constant');
|
|
4
|
+
const { isEmpty, omit } = require('lodash');
|
|
5
|
+
|
|
6
|
+
const updateNodeInfo = async ({ printInfo, states }) => {
|
|
7
|
+
// add didRegistry and didDomain
|
|
8
|
+
const info = await states.node.read();
|
|
9
|
+
const data = {};
|
|
10
|
+
if (!info.didRegistry) {
|
|
11
|
+
data.didRegistry = DEFAULT_DID_REGISTRY;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!info.didDomain) {
|
|
15
|
+
data.didDomain = DEFAULT_DID_DOMAIN;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!isEmpty(data)) {
|
|
19
|
+
await states.node.update({ _id: info._id }, { $set: data });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
printInfo('update did registry and did domain successfully');
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const updateCertificate = async ({ node, printInfo }) => {
|
|
26
|
+
const certs = await node.certManager.getAllNormal();
|
|
27
|
+
for (const cert of certs || []) {
|
|
28
|
+
await node.certManager.updateWithoutValidations(cert.id, omit(cert, 'id'));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
printInfo('update certificate successfully');
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/* eslint-disable no-underscore-dangle */
|
|
35
|
+
module.exports = async ({ node, printInfo, states }) => {
|
|
36
|
+
await updateNodeInfo({ printInfo, states });
|
|
37
|
+
await updateCertificate({ node, printInfo, states });
|
|
38
|
+
};
|
package/lib/router/helper.js
CHANGED
|
@@ -48,7 +48,7 @@ const {
|
|
|
48
48
|
getWellknownSitePort,
|
|
49
49
|
} = require('../util');
|
|
50
50
|
const { getServicesFromBlockletInterface } = require('../util/service');
|
|
51
|
-
const getIpDnsDomainForBlocklet = require('../util/get-
|
|
51
|
+
const { getIpDnsDomainForBlocklet, getDidDomainForBlocklet } = require('../util/get-domain-for-blocklet');
|
|
52
52
|
const { getFromCache: getAccessibleExternalNodeIp } = require('../util/get-accessible-external-node-ip');
|
|
53
53
|
|
|
54
54
|
const Router = require('./index');
|
|
@@ -623,11 +623,16 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
623
623
|
});
|
|
624
624
|
|
|
625
625
|
const dashboardDomain = get(info, 'routing.dashboardDomain', '');
|
|
626
|
-
|
|
626
|
+
const didDomain = `${info.did.toLowerCase()}.${info.didDomain}`;
|
|
627
|
+
const dashboardAliasDomains = [dashboardDomain, didDomain]
|
|
628
|
+
.filter((item) => item && !isExistsInAlias(item))
|
|
629
|
+
.map((item) => ({ value: item, isProtected: true }));
|
|
630
|
+
|
|
631
|
+
if (dashboardAliasDomains.length > 0) {
|
|
627
632
|
try {
|
|
628
633
|
const result = await siteState.update(
|
|
629
634
|
{ _id: dashboardSite.id },
|
|
630
|
-
{ $push: { domainAliases: {
|
|
635
|
+
{ $push: { domainAliases: { $each: dashboardAliasDomains } } }
|
|
631
636
|
);
|
|
632
637
|
|
|
633
638
|
updatedResult.push(result);
|
|
@@ -690,7 +695,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
690
695
|
};
|
|
691
696
|
|
|
692
697
|
const domainGroup = `${blocklet.meta.did}${BLOCKLET_SITE_GROUP_SUFFIX}`;
|
|
693
|
-
|
|
698
|
+
|
|
694
699
|
const pathPrefix = getPrefix(webInterface.prefix);
|
|
695
700
|
const rule = {
|
|
696
701
|
from: { pathPrefix },
|
|
@@ -705,11 +710,24 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
705
710
|
|
|
706
711
|
const existSite = await states.site.findOne({ domain: domainGroup });
|
|
707
712
|
if (!existSite) {
|
|
713
|
+
const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet, webInterface, nodeInfo.did);
|
|
714
|
+
const appIdEnv = blocklet.environments.find((e) => e.key === 'BLOCKLET_APP_ID');
|
|
715
|
+
const domainAliases = [{ value: ipEchoDnsDomain, isProtected: true }];
|
|
716
|
+
|
|
717
|
+
const didDomain = getDidDomainForBlocklet({
|
|
718
|
+
appId: appIdEnv.value,
|
|
719
|
+
didDomain: nodeInfo.didDomain,
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
if (blocklet.mode !== 'development') {
|
|
723
|
+
domainAliases.push({ value: didDomain, isProtected: true });
|
|
724
|
+
}
|
|
725
|
+
|
|
708
726
|
await routerManager.addRoutingSite(
|
|
709
727
|
{
|
|
710
728
|
site: {
|
|
711
729
|
domain: domainGroup,
|
|
712
|
-
domainAliases
|
|
730
|
+
domainAliases,
|
|
713
731
|
isProtected: true,
|
|
714
732
|
rules: [rule],
|
|
715
733
|
},
|
|
@@ -717,7 +735,14 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
717
735
|
},
|
|
718
736
|
context
|
|
719
737
|
);
|
|
720
|
-
logger.info('add routing site', { site:
|
|
738
|
+
logger.info('add routing site', { site: domainGroup });
|
|
739
|
+
if (
|
|
740
|
+
process.env.NODE_ENV !== 'development' &&
|
|
741
|
+
process.env.NODE_ENV !== 'test' &&
|
|
742
|
+
blocklet.mode !== 'development'
|
|
743
|
+
) {
|
|
744
|
+
await certManager.issue({ domain: didDomain });
|
|
745
|
+
}
|
|
721
746
|
|
|
722
747
|
return true;
|
|
723
748
|
}
|
|
@@ -732,13 +757,13 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
732
757
|
},
|
|
733
758
|
skipProtectedRuleChecking: true,
|
|
734
759
|
});
|
|
735
|
-
logger.info('update routing rule for site', { site:
|
|
760
|
+
logger.info('update routing rule for site', { site: domainGroup });
|
|
736
761
|
} else {
|
|
737
762
|
await routerManager.addRoutingRule({
|
|
738
763
|
id: existSite.id,
|
|
739
764
|
rule,
|
|
740
765
|
});
|
|
741
|
-
logger.info('add routing rule for site', { site:
|
|
766
|
+
logger.info('add routing rule for site', { site: domainGroup });
|
|
742
767
|
}
|
|
743
768
|
|
|
744
769
|
return true;
|
package/lib/router/manager.js
CHANGED
|
@@ -459,9 +459,9 @@ class RouterManager extends EventEmitter {
|
|
|
459
459
|
return {
|
|
460
460
|
id: matchedCert.id,
|
|
461
461
|
domain: matchedCert.domain,
|
|
462
|
-
issuer: matchedCert.issuer,
|
|
463
|
-
validFrom: matchedCert.validFrom,
|
|
464
|
-
validTo: matchedCert.validTo,
|
|
462
|
+
issuer: matchedCert.meta.issuer,
|
|
463
|
+
validFrom: matchedCert.meta.validFrom,
|
|
464
|
+
validTo: matchedCert.meta.validTo,
|
|
465
465
|
};
|
|
466
466
|
}
|
|
467
467
|
|
package/lib/states/node.js
CHANGED
|
@@ -90,6 +90,8 @@ class NodeState extends BaseState {
|
|
|
90
90
|
runtimeConfig,
|
|
91
91
|
ownerNft,
|
|
92
92
|
launcherInfo,
|
|
93
|
+
didRegistry,
|
|
94
|
+
didDomain,
|
|
93
95
|
} = this.options;
|
|
94
96
|
|
|
95
97
|
if (nodeOwner && !validateOwner(nodeOwner)) {
|
|
@@ -122,6 +124,8 @@ class NodeState extends BaseState {
|
|
|
122
124
|
ownerNft,
|
|
123
125
|
diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
|
|
124
126
|
launcherInfo: launcherInfo || undefined,
|
|
127
|
+
didRegistry,
|
|
128
|
+
didDomain,
|
|
125
129
|
},
|
|
126
130
|
async (e, data) => {
|
|
127
131
|
if (e) {
|
|
@@ -134,6 +138,10 @@ class NodeState extends BaseState {
|
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
logger.info('create', { data });
|
|
141
|
+
if (dek) {
|
|
142
|
+
data.sk = security.decrypt(data.sk, data.did, dek);
|
|
143
|
+
}
|
|
144
|
+
|
|
137
145
|
return resolve(data);
|
|
138
146
|
}
|
|
139
147
|
)
|
package/lib/util/blocklet.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const tar = require('tar');
|
|
7
7
|
const get = require('lodash/get');
|
|
8
|
+
const intersection = require('lodash/intersection');
|
|
8
9
|
const streamToPromise = require('stream-to-promise');
|
|
9
10
|
const { Throttle } = require('stream-throttle');
|
|
10
11
|
const ssri = require('ssri');
|
|
@@ -69,7 +70,7 @@ const statusMap = {
|
|
|
69
70
|
stopped: BlockletStatus.stopped,
|
|
70
71
|
};
|
|
71
72
|
|
|
72
|
-
const
|
|
73
|
+
const PRIVATE_NODE_ENVS = [
|
|
73
74
|
// 'NEDB_MULTI_PORT', // FIXME: 排查 abtnode 对外提供的 SDK(比如 @abtnode/queue), SDK 中不要自动使用 NEDB_MULTI_PORT 环境变量
|
|
74
75
|
'ABT_NODE_UPDATER_PORT',
|
|
75
76
|
'ABT_NODE_SESSION_TTL',
|
|
@@ -186,7 +187,7 @@ const getBlockletDirs = (blocklet, { rootBlocklet, dataDirs, ensure = false } =
|
|
|
186
187
|
* @param {*} blocklet
|
|
187
188
|
* @param {*} configs
|
|
188
189
|
*/
|
|
189
|
-
const fillBlockletConfigs = (blocklet, configs) => {
|
|
190
|
+
const fillBlockletConfigs = (blocklet, configs, parent) => {
|
|
190
191
|
blocklet.configs = configs || [];
|
|
191
192
|
blocklet.configObj = blocklet.configs.reduce((acc, x) => {
|
|
192
193
|
acc[x.key] = x.value;
|
|
@@ -196,6 +197,13 @@ const fillBlockletConfigs = (blocklet, configs) => {
|
|
|
196
197
|
acc[x.key] = x.value;
|
|
197
198
|
return acc;
|
|
198
199
|
}, {});
|
|
200
|
+
|
|
201
|
+
const sharedConfigs = getSharedConfigs(blocklet, parent);
|
|
202
|
+
Object.keys(sharedConfigs).forEach((key) => {
|
|
203
|
+
blocklet.configObj[key] = sharedConfigs[key];
|
|
204
|
+
const item = blocklet.configs.find((x) => x.key === key);
|
|
205
|
+
item.value = sharedConfigs[key];
|
|
206
|
+
});
|
|
199
207
|
};
|
|
200
208
|
|
|
201
209
|
const ensureBlockletExpanded = async (meta, appDir) => {
|
|
@@ -297,10 +305,10 @@ const getSystemEnvironments = (blocklet) => {
|
|
|
297
305
|
};
|
|
298
306
|
};
|
|
299
307
|
|
|
300
|
-
const getRuntimeEnvironments = (blocklet, nodeEnvironments) => {
|
|
308
|
+
const getRuntimeEnvironments = (blocklet, nodeEnvironments, parent) => {
|
|
301
309
|
// pm2 will force inject env variables of daemon process to blocklet process
|
|
302
310
|
// we can only rewrite these private env variables to empty
|
|
303
|
-
const safeNodeEnvironments =
|
|
311
|
+
const safeNodeEnvironments = PRIVATE_NODE_ENVS.reduce((o, x) => {
|
|
304
312
|
o[x] = '';
|
|
305
313
|
return o;
|
|
306
314
|
}, {});
|
|
@@ -308,11 +316,28 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments) => {
|
|
|
308
316
|
return {
|
|
309
317
|
...blocklet.environmentObj,
|
|
310
318
|
...blocklet.configObj,
|
|
319
|
+
...getSharedConfigs(blocklet, parent),
|
|
311
320
|
...nodeEnvironments,
|
|
312
321
|
...safeNodeEnvironments,
|
|
313
322
|
};
|
|
314
323
|
};
|
|
315
324
|
|
|
325
|
+
// we support share insecure same configs between parent and child blocklets
|
|
326
|
+
const getSharedConfigs = (child, parent) => {
|
|
327
|
+
const sharedConfigs = {};
|
|
328
|
+
if (parent && Array.isArray(parent.configs) && child.meta.did !== parent.meta.did) {
|
|
329
|
+
const parentKeys = parent.configs.filter((x) => x.secure === false).map((x) => x.key);
|
|
330
|
+
const childKeys = child.configs.map((x) => x.key);
|
|
331
|
+
const sharedKeys = intersection(parentKeys, childKeys);
|
|
332
|
+
sharedKeys.forEach((key) => {
|
|
333
|
+
if (!child.configObj[key]) {
|
|
334
|
+
sharedConfigs[key] = parent.configObj[key];
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
return sharedConfigs;
|
|
339
|
+
};
|
|
340
|
+
|
|
316
341
|
const isUsefulError = (err) => err && err.message !== 'process or namespace not found';
|
|
317
342
|
|
|
318
343
|
const getHealthyCheckTimeout = (blocklet, { checkHealthImmediately } = {}) => {
|
|
@@ -16,4 +16,8 @@ const getIpDnsDomainForBlocklet = (blocklet, blockletInterface) => {
|
|
|
16
16
|
}${iName}-${SLOT_FOR_IP_DNS_SITE}.${DEFAULT_IP_DNS_DOMAIN_SUFFIX}`;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const getDidDomainForBlocklet = ({ appId, didDomain }) => {
|
|
20
|
+
return `${appId.toLowerCase()}.${didDomain}`;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
module.exports = { getIpDnsDomainForBlocklet, getDidDomainForBlocklet };
|
package/lib/util/index.js
CHANGED
|
@@ -315,7 +315,6 @@ const getHttpsCertInfo = (certificate) => {
|
|
|
315
315
|
validFrom,
|
|
316
316
|
validTo,
|
|
317
317
|
issuer,
|
|
318
|
-
serialNumber: info.serialNumber,
|
|
319
318
|
sans: info.dnsNames,
|
|
320
319
|
validityPeriod: info.validTo - info.validFrom,
|
|
321
320
|
fingerprintAlg: 'SHA256',
|
|
@@ -358,39 +357,53 @@ const formatEnvironments = (environments) => Object.keys(environments).map((x) =
|
|
|
358
357
|
const transformIPToDomain = (ip) => ip.split('.').join('-');
|
|
359
358
|
|
|
360
359
|
const getBaseUrls = async (node, ips) => {
|
|
361
|
-
const ipTypes = {
|
|
362
|
-
internal: 'private',
|
|
363
|
-
external: 'public',
|
|
364
|
-
};
|
|
365
360
|
const info = await node.getNodeInfo();
|
|
366
361
|
const { https, httpPort, httpsPort } = info.routing;
|
|
367
|
-
const ipKeys = Object.keys(ips).filter((x) => ips[x]);
|
|
368
362
|
const getPort = (port, defaultPort) => (port && port !== defaultPort ? `:${port}` : '');
|
|
363
|
+
const availableIps = ips.filter(Boolean);
|
|
364
|
+
|
|
365
|
+
const getHttpInfo = async (domain) => {
|
|
366
|
+
const certificate = https ? await node.certManager.getNormalByDomain(domain) : null;
|
|
367
|
+
const protocol = certificate ? 'https' : 'http';
|
|
368
|
+
const port = certificate ? getPort(httpsPort, DEFAULT_HTTPS_PORT) : getPort(httpPort, DEFAULT_HTTP_PORT);
|
|
369
|
+
|
|
370
|
+
return { protocol, port };
|
|
371
|
+
};
|
|
369
372
|
|
|
370
373
|
if (info.routing.provider !== ROUTER_PROVIDER_NONE && info.routing.snapshotHash && info.routing.adminPath) {
|
|
371
374
|
const sites = await node.getSitesFromSnapshot();
|
|
372
375
|
|
|
373
376
|
const { dashboardDomain } = info.routing;
|
|
374
377
|
const adminPath = normalizePathPrefix(info.routing.adminPath);
|
|
375
|
-
const
|
|
376
|
-
|
|
378
|
+
const tmpHttpPort = getPort(httpPort, DEFAULT_HTTP_PORT);
|
|
379
|
+
|
|
380
|
+
const httpUrls = availableIps.map((ip) => {
|
|
377
381
|
return {
|
|
378
|
-
url: `http://${
|
|
379
|
-
type: ipTypes[x],
|
|
382
|
+
url: `http://${ip}${tmpHttpPort}${adminPath}`,
|
|
380
383
|
};
|
|
381
384
|
});
|
|
382
385
|
|
|
383
386
|
if (dashboardDomain) {
|
|
384
387
|
const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value === dashboardDomain));
|
|
385
388
|
if (site) {
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
type: ipTypes[x],
|
|
389
|
+
const httpInfo = await getHttpInfo(dashboardDomain);
|
|
390
|
+
const httpsUrls = availableIps.map((ip) => ({
|
|
391
|
+
url: `${httpInfo.protocol}://${transformIPToDomain(ip)}.${dashboardDomain.substring(2)}${
|
|
392
|
+
httpInfo.port
|
|
393
|
+
}${adminPath}`,
|
|
392
394
|
}));
|
|
393
395
|
|
|
396
|
+
// add did domain access url
|
|
397
|
+
const didDomainAlias = site.domainAliases.find((item) => item.value.endsWith(info.didDomain));
|
|
398
|
+
if (didDomainAlias) {
|
|
399
|
+
const didDomain = didDomainAlias.value;
|
|
400
|
+
const didDomainHttpInfo = await getHttpInfo(didDomain);
|
|
401
|
+
|
|
402
|
+
httpsUrls.push({
|
|
403
|
+
url: `${didDomainHttpInfo.protocol}://${didDomain}${didDomainHttpInfo.port}${adminPath}`,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
394
407
|
return httpUrls.concat(httpsUrls);
|
|
395
408
|
}
|
|
396
409
|
}
|
|
@@ -399,9 +412,8 @@ const getBaseUrls = async (node, ips) => {
|
|
|
399
412
|
}
|
|
400
413
|
|
|
401
414
|
// port urls
|
|
402
|
-
return
|
|
403
|
-
url: `http://${
|
|
404
|
-
type: ipTypes[x],
|
|
415
|
+
return availableIps.map((ip) => ({
|
|
416
|
+
url: `http://${ip}:${info.port}`,
|
|
405
417
|
}));
|
|
406
418
|
};
|
|
407
419
|
|
package/lib/util/ready.js
CHANGED
|
@@ -33,7 +33,7 @@ const createStateReadyHandler =
|
|
|
33
33
|
console.error('Sharing data dir between Blocklet Server instances may break things!');
|
|
34
34
|
console.error('======================================================\x1b[0m');
|
|
35
35
|
console.log('\nIf you intend to use this dir:');
|
|
36
|
-
console.log(` 1. Stop Blocklet Server by ${chalk.cyan('
|
|
36
|
+
console.log(` 1. Stop Blocklet Server by ${chalk.cyan('blocklet server stop --force')}`);
|
|
37
37
|
console.log(` 2. Clear data dir by ${chalk.cyan(`rm -r ${options.dataDir}`)}`);
|
|
38
38
|
console.log(' 3. Reinitialize and start Blocklet Server');
|
|
39
39
|
process.exit(1);
|
package/lib/webhook/index.js
CHANGED
|
@@ -66,7 +66,7 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
66
66
|
const webhookList = await webhookState.list();
|
|
67
67
|
const nodeInfo = await nodeState.read();
|
|
68
68
|
const { internal, external } = await IP.get();
|
|
69
|
-
const baseUrls = await getBaseUrls(instance,
|
|
69
|
+
const baseUrls = await getBaseUrls(instance, [internal, external]);
|
|
70
70
|
const senderFns = {};
|
|
71
71
|
|
|
72
72
|
if (webhookList.length) {
|
|
@@ -76,8 +76,8 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
76
76
|
const senderInstance = WebHookSender.getMessageSender(item.type);
|
|
77
77
|
senderFns[item.type] = senderInstance.send.bind(senderInstance);
|
|
78
78
|
}
|
|
79
|
-
const {
|
|
80
|
-
const options = { ...message, nodeInfo: `*${
|
|
79
|
+
const { name } = nodeInfo;
|
|
80
|
+
const options = { ...message, nodeInfo: `*${name}*` };
|
|
81
81
|
if (item.type === 'slack') {
|
|
82
82
|
options.urlInfo = getSlackUrlInfo(message.action, baseUrls);
|
|
83
83
|
}
|
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.12",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,22 +19,22 @@
|
|
|
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.
|
|
22
|
+
"@abtnode/certificate-manager": "1.6.12",
|
|
23
|
+
"@abtnode/constant": "1.6.12",
|
|
24
|
+
"@abtnode/cron": "1.6.12",
|
|
25
|
+
"@abtnode/db": "1.6.12",
|
|
26
|
+
"@abtnode/logger": "1.6.12",
|
|
27
|
+
"@abtnode/queue": "1.6.12",
|
|
28
|
+
"@abtnode/rbac": "1.6.12",
|
|
29
|
+
"@abtnode/router-provider": "1.6.12",
|
|
30
|
+
"@abtnode/static-server": "1.6.12",
|
|
31
|
+
"@abtnode/timemachine": "1.6.12",
|
|
32
|
+
"@abtnode/util": "1.6.12",
|
|
33
33
|
"@arcblock/did": "^1.13.79",
|
|
34
34
|
"@arcblock/event-hub": "1.13.79",
|
|
35
35
|
"@arcblock/pm2-events": "^0.0.5",
|
|
36
36
|
"@arcblock/vc": "^1.13.79",
|
|
37
|
-
"@blocklet/meta": "1.6.
|
|
37
|
+
"@blocklet/meta": "1.6.12",
|
|
38
38
|
"@fidm/x509": "^1.2.1",
|
|
39
39
|
"@nedb/core": "^1.2.2",
|
|
40
40
|
"@nedb/multi": "^1.2.2",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"express": "^4.17.1",
|
|
76
76
|
"jest": "^27.4.5"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "dd79037978dc12f72330227a553a80a504f03fa7"
|
|
79
79
|
}
|