@abtnode/core 1.6.6 → 1.6.10
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 +124 -0
- package/lib/event.js +9 -2
- package/lib/index.js +30 -10
- package/lib/migrations/1.6.7-certificate.js +30 -0
- package/lib/migrations/1.6.9-update-node-info-and-certificate.js +38 -0
- package/lib/router/helper.js +132 -115
- package/lib/router/manager.js +9 -8
- package/lib/states/base.js +3 -220
- package/lib/states/index.js +4 -21
- package/lib/states/node.js +10 -1
- 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 +33 -19
- package/lib/util/ready.js +1 -1
- package/lib/webhook/index.js +3 -3
- package/package.json +22 -20
package/lib/states/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const stateFactory = require('@abtnode/db/lib/factory');
|
|
2
2
|
const NodeState = require('./node');
|
|
3
3
|
const ChallengeState = require('./challenge');
|
|
4
4
|
const BlockletState = require('./blocklet');
|
|
@@ -12,8 +12,6 @@ const SessionState = require('./session');
|
|
|
12
12
|
const ExtrasState = require('./blocklet-extras');
|
|
13
13
|
const CacheState = require('./cache');
|
|
14
14
|
|
|
15
|
-
const states = {};
|
|
16
|
-
|
|
17
15
|
const init = (dataDirs, options) => {
|
|
18
16
|
const notificationState = new NotificationState(dataDirs.core, options);
|
|
19
17
|
const nodeState = new NodeState(dataDirs.core, options, dataDirs, notificationState);
|
|
@@ -28,7 +26,7 @@ const init = (dataDirs, options) => {
|
|
|
28
26
|
const extrasState = new ExtrasState(dataDirs.core, options);
|
|
29
27
|
const cacheState = new CacheState(dataDirs.core, options);
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
return {
|
|
32
30
|
node: nodeState,
|
|
33
31
|
blocklet: blockletState,
|
|
34
32
|
notification: notificationState,
|
|
@@ -41,22 +39,7 @@ const init = (dataDirs, options) => {
|
|
|
41
39
|
session: sessionState,
|
|
42
40
|
blockletExtras: extrasState,
|
|
43
41
|
cache: cacheState,
|
|
44
|
-
}
|
|
42
|
+
};
|
|
45
43
|
};
|
|
46
44
|
|
|
47
|
-
module.exports =
|
|
48
|
-
{},
|
|
49
|
-
{
|
|
50
|
-
get(target, prop) {
|
|
51
|
-
if (prop === 'init') {
|
|
52
|
-
return init;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (states[prop] instanceof BaseState) {
|
|
56
|
-
return states[prop];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
throw new Error(`State ${String(prop)} may not be initialized`);
|
|
60
|
-
},
|
|
61
|
-
}
|
|
62
|
-
);
|
|
45
|
+
module.exports = stateFactory(init);
|
package/lib/states/node.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
const semver = require('semver');
|
|
2
3
|
const omit = require('lodash/omit');
|
|
3
4
|
const isEqual = require('lodash/isEqual');
|
|
4
5
|
const isEmpty = require('lodash/isEmpty');
|
|
@@ -89,6 +90,8 @@ class NodeState extends BaseState {
|
|
|
89
90
|
runtimeConfig,
|
|
90
91
|
ownerNft,
|
|
91
92
|
launcherInfo,
|
|
93
|
+
didRegistry,
|
|
94
|
+
didDomain,
|
|
92
95
|
} = this.options;
|
|
93
96
|
|
|
94
97
|
if (nodeOwner && !validateOwner(nodeOwner)) {
|
|
@@ -121,6 +124,8 @@ class NodeState extends BaseState {
|
|
|
121
124
|
ownerNft,
|
|
122
125
|
diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
|
|
123
126
|
launcherInfo: launcherInfo || undefined,
|
|
127
|
+
didRegistry,
|
|
128
|
+
didDomain,
|
|
124
129
|
},
|
|
125
130
|
async (e, data) => {
|
|
126
131
|
if (e) {
|
|
@@ -133,6 +138,10 @@ class NodeState extends BaseState {
|
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
logger.info('create', { data });
|
|
141
|
+
if (dek) {
|
|
142
|
+
data.sk = security.decrypt(data.sk, data.did, dek);
|
|
143
|
+
}
|
|
144
|
+
|
|
136
145
|
return resolve(data);
|
|
137
146
|
}
|
|
138
147
|
)
|
|
@@ -163,7 +172,7 @@ class NodeState extends BaseState {
|
|
|
163
172
|
|
|
164
173
|
cleanupDirtyUpgradeState() {
|
|
165
174
|
return this.read().then((doc) => {
|
|
166
|
-
if (doc.nextVersion
|
|
175
|
+
if (doc.nextVersion && semver.lte(doc.nextVersion, doc.version)) {
|
|
167
176
|
const updates = { nextVersion: '', upgradeSessionId: '' };
|
|
168
177
|
|
|
169
178
|
// FIXME: this may cause the node exit some mode unexpectedly if it is not being upgraded
|
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',
|
|
@@ -332,6 +331,8 @@ const getDataDirs = (dataDir) => ({
|
|
|
332
331
|
tmp: path.join(dataDir, 'tmp'),
|
|
333
332
|
blocklets: path.join(dataDir, 'blocklets'),
|
|
334
333
|
services: path.join(dataDir, 'services'),
|
|
334
|
+
modules: path.join(dataDir, 'modules'),
|
|
335
|
+
certManagerModule: path.join(dataDir, 'modules', 'certificate-manager'),
|
|
335
336
|
});
|
|
336
337
|
|
|
337
338
|
// Ensure data dir for Blocklet Server exists
|
|
@@ -356,39 +357,53 @@ const formatEnvironments = (environments) => Object.keys(environments).map((x) =
|
|
|
356
357
|
const transformIPToDomain = (ip) => ip.split('.').join('-');
|
|
357
358
|
|
|
358
359
|
const getBaseUrls = async (node, ips) => {
|
|
359
|
-
const ipTypes = {
|
|
360
|
-
internal: 'private',
|
|
361
|
-
external: 'public',
|
|
362
|
-
};
|
|
363
360
|
const info = await node.getNodeInfo();
|
|
364
361
|
const { https, httpPort, httpsPort } = info.routing;
|
|
365
|
-
const ipKeys = Object.keys(ips).filter((x) => ips[x]);
|
|
366
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
|
+
};
|
|
367
372
|
|
|
368
373
|
if (info.routing.provider !== ROUTER_PROVIDER_NONE && info.routing.snapshotHash && info.routing.adminPath) {
|
|
369
374
|
const sites = await node.getSitesFromSnapshot();
|
|
370
375
|
|
|
371
376
|
const { dashboardDomain } = info.routing;
|
|
372
377
|
const adminPath = normalizePathPrefix(info.routing.adminPath);
|
|
373
|
-
const
|
|
374
|
-
|
|
378
|
+
const tmpHttpPort = getPort(httpPort, DEFAULT_HTTP_PORT);
|
|
379
|
+
|
|
380
|
+
const httpUrls = availableIps.map((ip) => {
|
|
375
381
|
return {
|
|
376
|
-
url: `http://${
|
|
377
|
-
type: ipTypes[x],
|
|
382
|
+
url: `http://${ip}${tmpHttpPort}${adminPath}`,
|
|
378
383
|
};
|
|
379
384
|
});
|
|
380
385
|
|
|
381
386
|
if (dashboardDomain) {
|
|
382
387
|
const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value === dashboardDomain));
|
|
383
388
|
if (site) {
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
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}`,
|
|
390
394
|
}));
|
|
391
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
|
+
|
|
392
407
|
return httpUrls.concat(httpsUrls);
|
|
393
408
|
}
|
|
394
409
|
}
|
|
@@ -397,9 +412,8 @@ const getBaseUrls = async (node, ips) => {
|
|
|
397
412
|
}
|
|
398
413
|
|
|
399
414
|
// port urls
|
|
400
|
-
return
|
|
401
|
-
url: `http://${
|
|
402
|
-
type: ipTypes[x],
|
|
415
|
+
return availableIps.map((ip) => ({
|
|
416
|
+
url: `http://${ip}:${info.port}`,
|
|
403
417
|
}));
|
|
404
418
|
};
|
|
405
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.10",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,26 +19,28 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/
|
|
23
|
-
"@abtnode/
|
|
24
|
-
"@abtnode/
|
|
25
|
-
"@abtnode/
|
|
26
|
-
"@abtnode/
|
|
27
|
-
"@abtnode/
|
|
28
|
-
"@abtnode/
|
|
29
|
-
"@abtnode/
|
|
30
|
-
"@abtnode/
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
22
|
+
"@abtnode/certificate-manager": "1.6.10",
|
|
23
|
+
"@abtnode/constant": "1.6.10",
|
|
24
|
+
"@abtnode/cron": "1.6.10",
|
|
25
|
+
"@abtnode/db": "1.6.10",
|
|
26
|
+
"@abtnode/logger": "1.6.10",
|
|
27
|
+
"@abtnode/queue": "1.6.10",
|
|
28
|
+
"@abtnode/rbac": "1.6.10",
|
|
29
|
+
"@abtnode/router-provider": "1.6.10",
|
|
30
|
+
"@abtnode/static-server": "1.6.10",
|
|
31
|
+
"@abtnode/timemachine": "1.6.10",
|
|
32
|
+
"@abtnode/util": "1.6.10",
|
|
33
|
+
"@arcblock/did": "^1.13.79",
|
|
34
|
+
"@arcblock/event-hub": "1.13.79",
|
|
33
35
|
"@arcblock/pm2-events": "^0.0.5",
|
|
34
|
-
"@arcblock/vc": "^1.13.
|
|
35
|
-
"@blocklet/meta": "1.6.
|
|
36
|
+
"@arcblock/vc": "^1.13.79",
|
|
37
|
+
"@blocklet/meta": "1.6.10",
|
|
36
38
|
"@fidm/x509": "^1.2.1",
|
|
37
39
|
"@nedb/core": "^1.2.2",
|
|
38
40
|
"@nedb/multi": "^1.2.2",
|
|
39
|
-
"@ocap/mcrypto": "^1.13.
|
|
40
|
-
"@ocap/util": "^1.13.
|
|
41
|
-
"@ocap/wallet": "^1.13.
|
|
41
|
+
"@ocap/mcrypto": "^1.13.79",
|
|
42
|
+
"@ocap/util": "^1.13.79",
|
|
43
|
+
"@ocap/wallet": "^1.13.79",
|
|
42
44
|
"@slack/webhook": "^5.0.3",
|
|
43
45
|
"axios": "^0.21.4",
|
|
44
46
|
"axon": "^2.0.3",
|
|
@@ -51,7 +53,7 @@
|
|
|
51
53
|
"is-base64": "^1.1.0",
|
|
52
54
|
"is-ip": "^3.1.0",
|
|
53
55
|
"is-url": "^1.2.4",
|
|
54
|
-
"joi": "^17.
|
|
56
|
+
"joi": "^17.5.0",
|
|
55
57
|
"js-yaml": "^3.14.0",
|
|
56
58
|
"lodash": "^4.17.21",
|
|
57
59
|
"lru-cache": "^6.0.0",
|
|
@@ -71,7 +73,7 @@
|
|
|
71
73
|
"compression": "^1.7.4",
|
|
72
74
|
"expand-tilde": "^2.0.2",
|
|
73
75
|
"express": "^4.17.1",
|
|
74
|
-
"jest": "^27.
|
|
76
|
+
"jest": "^27.4.5"
|
|
75
77
|
},
|
|
76
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "90aa29d892f9f54c87faa3041daec042997fffcc"
|
|
77
79
|
}
|