@abtnode/core 1.6.12 → 1.6.16
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 +24 -6
- package/lib/event.js +1 -1
- package/lib/index.js +1 -10
- package/lib/router/helper.js +72 -37
- package/lib/router/manager.js +24 -6
- package/lib/states/blocklet.js +14 -12
- package/lib/states/node.js +1 -0
- package/lib/util/blocklet.js +10 -1
- package/lib/util/default-node-config.js +1 -1
- package/lib/util/router.js +13 -0
- package/lib/validators/node.js +11 -12
- package/lib/validators/permission.js +16 -1
- package/package.json +20 -20
|
@@ -12,7 +12,7 @@ const LRU = require('lru-cache');
|
|
|
12
12
|
|
|
13
13
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
14
14
|
const { verifyPresentation } = require('@arcblock/vc');
|
|
15
|
-
const { toBase58 } = require('@ocap/util');
|
|
15
|
+
const { toBase58, isHex } = require('@ocap/util');
|
|
16
16
|
const { fromSecretKey } = require('@ocap/wallet');
|
|
17
17
|
|
|
18
18
|
const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
|
|
@@ -189,9 +189,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
const blocklet = await states.blocklet.getBlocklet(meta.did);
|
|
193
193
|
|
|
194
|
-
return meta;
|
|
194
|
+
return { meta, isFree, isInstalled: !!blocklet };
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
async installBlockletFromVc({ vcPresentation, challenge }, context) {
|
|
@@ -549,6 +549,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
549
549
|
}
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
+
if (x.key === 'BLOCKLET_PASSPORT_COLOR') {
|
|
553
|
+
if (x.value && x.value !== 'auto') {
|
|
554
|
+
if (x.value.length !== 7 || !isHex(x.value.slice(-6))) {
|
|
555
|
+
throw new Error('BLOCKLET_PASSPORT_COLOR must be a hex encoded color, eg. #ffeeaa');
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
552
560
|
blocklet.configObj[x.key] = x.value;
|
|
553
561
|
}
|
|
554
562
|
|
|
@@ -558,7 +566,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
558
566
|
hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
|
|
559
567
|
exitOnError: true,
|
|
560
568
|
env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments), ...blocklet.configObj },
|
|
561
|
-
notification: states.notification,
|
|
562
569
|
did,
|
|
563
570
|
context,
|
|
564
571
|
progress: blocklet.mode === BLOCKLET_MODES.DEVELOPMENT,
|
|
@@ -2332,7 +2339,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2332
2339
|
async _rollback(action, did, oldBlocklet) {
|
|
2333
2340
|
if (action === 'install') {
|
|
2334
2341
|
// remove blocklet
|
|
2335
|
-
return this._deleteBlocklet({ did, keepData:
|
|
2342
|
+
return this._deleteBlocklet({ did, keepData: true });
|
|
2336
2343
|
}
|
|
2337
2344
|
|
|
2338
2345
|
if (['upgrade', 'downgrade'].includes(action)) {
|
|
@@ -2374,7 +2381,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2374
2381
|
const result = await states.blocklet.deleteBlocklet(did);
|
|
2375
2382
|
logger.info('blocklet removed successfully', { did });
|
|
2376
2383
|
|
|
2377
|
-
|
|
2384
|
+
let keepRouting = true;
|
|
2385
|
+
if (keepData === false || keepConfigs === false) {
|
|
2386
|
+
keepRouting = false;
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
this.emit(BlockletEvents.removed, {
|
|
2390
|
+
blocklet: result,
|
|
2391
|
+
context: {
|
|
2392
|
+
...context,
|
|
2393
|
+
keepRouting,
|
|
2394
|
+
},
|
|
2395
|
+
});
|
|
2378
2396
|
return blocklet;
|
|
2379
2397
|
}
|
|
2380
2398
|
|
package/lib/event.js
CHANGED
|
@@ -182,7 +182,7 @@ module.exports = ({
|
|
|
182
182
|
.catch((error) => logger.error('refresh blocklets failed on initialize the registry', { error }));
|
|
183
183
|
|
|
184
184
|
// We need update router on some fields change
|
|
185
|
-
const fields = ['enableWelcomePage', 'webWalletUrl'];
|
|
185
|
+
const fields = ['enableWelcomePage', 'webWalletUrl', 'registerUrl'];
|
|
186
186
|
const shouldUpdateRouter = fields.some((x) => nodeInfo[x] !== oldInfo[x]);
|
|
187
187
|
if (shouldUpdateRouter) {
|
|
188
188
|
handleRouting(nodeInfo).catch((err) => {
|
package/lib/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const { toStatus, fromStatus, ensureDataDirs, getQueueConcurrencyByMem } = requi
|
|
|
50
50
|
* version
|
|
51
51
|
* runtimeConfig: {}
|
|
52
52
|
* autoUpgrade
|
|
53
|
+
* registerUrl
|
|
53
54
|
* webWalletUrl
|
|
54
55
|
*/
|
|
55
56
|
function ABTNode(options) {
|
|
@@ -400,16 +401,6 @@ function ABTNode(options) {
|
|
|
400
401
|
} else {
|
|
401
402
|
// We should only respond to pm2 events when node is alive
|
|
402
403
|
events.on('node.started', async () => {
|
|
403
|
-
const info = await states.node.read();
|
|
404
|
-
certManager
|
|
405
|
-
.issue({ domain: `${info.did.toLowerCase()}.${info.didDomain}` })
|
|
406
|
-
.then(() => {
|
|
407
|
-
logger.info('add issue daemon certificate job');
|
|
408
|
-
})
|
|
409
|
-
.catch((error) => {
|
|
410
|
-
logger.error('issue daemon certificate job failed', { error });
|
|
411
|
-
});
|
|
412
|
-
|
|
413
404
|
pm2Events.resume();
|
|
414
405
|
initCron();
|
|
415
406
|
});
|
package/lib/router/helper.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const tar = require('tar');
|
|
6
6
|
const get = require('lodash/get');
|
|
7
7
|
const cloneDeep = require('lodash/cloneDeep');
|
|
8
|
+
const isEqual = require('lodash/isEqual');
|
|
8
9
|
const joinUrl = require('url-join');
|
|
9
10
|
const { getProvider } = require('@abtnode/router-provider');
|
|
10
11
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
@@ -28,6 +29,7 @@ const {
|
|
|
28
29
|
SLOT_FOR_IP_DNS_SITE,
|
|
29
30
|
BLOCKLET_SITE_GROUP_SUFFIX,
|
|
30
31
|
WELLKNOWN_ACME_CHALLENGE_PREFIX,
|
|
32
|
+
WELLKNOWN_DID_RESOLVER_PREFIX,
|
|
31
33
|
} = require('@abtnode/constant');
|
|
32
34
|
const {
|
|
33
35
|
BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
@@ -53,6 +55,7 @@ const { getFromCache: getAccessibleExternalNodeIp } = require('../util/get-acces
|
|
|
53
55
|
|
|
54
56
|
const Router = require('./index');
|
|
55
57
|
const states = require('../states');
|
|
58
|
+
const { getBlockletDomainGroupName, getDidFromDomainGroupName } = require('../util/router');
|
|
56
59
|
|
|
57
60
|
/**
|
|
58
61
|
* replace 888-888-888-888 with accessible ip for domain
|
|
@@ -241,6 +244,9 @@ const ensureLatestNodeInfo = async (sites = [], { withDefaultCors = true } = {})
|
|
|
241
244
|
site.domain = DOMAIN_FOR_IP_SITE_REGEXP;
|
|
242
245
|
|
|
243
246
|
if (withDefaultCors) {
|
|
247
|
+
// Allow CORS from "Install on ABT Node"
|
|
248
|
+
addCorsToSite(site, info.registerUrl);
|
|
249
|
+
|
|
244
250
|
// Allow CORS from "Web Wallet"
|
|
245
251
|
addCorsToSite(site, info.webWalletUrl);
|
|
246
252
|
}
|
|
@@ -351,6 +357,18 @@ const ensureCorsForWebWallet = async (sites) => {
|
|
|
351
357
|
return sites;
|
|
352
358
|
};
|
|
353
359
|
|
|
360
|
+
const filterSitesForRemovedBlocklets = async (sites = []) => {
|
|
361
|
+
const blocklets = await states.blocklet.getBlocklets();
|
|
362
|
+
return sites.filter((site) => {
|
|
363
|
+
if (!site.domain.endsWith(BLOCKLET_SITE_GROUP_SUFFIX)) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const did = getDidFromDomainGroupName(site.domain);
|
|
368
|
+
return blocklets.some((x) => x.meta.did === did);
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
|
|
354
372
|
const ensureLatestInfo = async (sites = [], { withDefaultCors = true } = {}) => {
|
|
355
373
|
let result = await ensureLatestNodeInfo(sites, { withDefaultCors });
|
|
356
374
|
result = await ensureWellknownRule(result);
|
|
@@ -419,7 +437,8 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
419
437
|
|
|
420
438
|
const https = get(info, 'routing.https', true);
|
|
421
439
|
const dashboardDomain = get(info, 'routing.dashboardDomain', '');
|
|
422
|
-
const certDownloadAddress =
|
|
440
|
+
const certDownloadAddress =
|
|
441
|
+
process.env.ABT_NODE_DASHBOARD_CERT_DOWN_URL || get(info, 'routing.dashboardCertDownloadAddress', '');
|
|
423
442
|
if (!https || !dashboardDomain || !certDownloadAddress) {
|
|
424
443
|
return;
|
|
425
444
|
}
|
|
@@ -493,12 +512,36 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
493
512
|
return { status: 'existed' };
|
|
494
513
|
}
|
|
495
514
|
|
|
496
|
-
logger.debug('downloading certificate', { url: downloadUrl, dashboardDomain });
|
|
515
|
+
logger.debug('downloading dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
|
|
497
516
|
await updateDashboardCertificate({ checkExpire: false });
|
|
498
|
-
logger.debug('
|
|
517
|
+
logger.debug('downloaded dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
|
|
499
518
|
return { status: 'downloaded' };
|
|
500
519
|
};
|
|
501
520
|
|
|
521
|
+
const upsertSiteRule = async ({ site, rule }, context) => {
|
|
522
|
+
const findExistingRule = (prefix) => site.rules.find((r) => r.from.pathPrefix === normalizePathPrefix(prefix));
|
|
523
|
+
|
|
524
|
+
const newSiteRule = {
|
|
525
|
+
id: site.id,
|
|
526
|
+
rule,
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
const existingRule = findExistingRule(get(rule, 'from.pathPrefix'));
|
|
530
|
+
if (!existingRule) {
|
|
531
|
+
await routerManager.addRoutingRule(newSiteRule, context);
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (!isEqual(existingRule.to, rule.to)) {
|
|
536
|
+
newSiteRule.rule.id = existingRule.id;
|
|
537
|
+
newSiteRule.skipProtectedRuleChecking = true;
|
|
538
|
+
await routerManager.updateRoutingRule(newSiteRule, context);
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return false;
|
|
543
|
+
};
|
|
544
|
+
|
|
502
545
|
const addWellknownSite = async (sites, context) => {
|
|
503
546
|
const site = (sites || []).find((x) => x.name === NAME_FOR_WELLKNOWN_SITE);
|
|
504
547
|
|
|
@@ -511,42 +554,35 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
511
554
|
};
|
|
512
555
|
|
|
513
556
|
const didResolverWellknownRule = {
|
|
514
|
-
|
|
557
|
+
isProtected: true,
|
|
558
|
+
from: { pathPrefix: WELLKNOWN_DID_RESOLVER_PREFIX },
|
|
515
559
|
to: proxyTarget,
|
|
516
560
|
};
|
|
517
561
|
|
|
518
562
|
const acmeChallengeWellknownRule = {
|
|
563
|
+
isProtected: true,
|
|
519
564
|
from: { pathPrefix: WELLKNOWN_ACME_CHALLENGE_PREFIX },
|
|
520
565
|
to: proxyTarget,
|
|
521
566
|
};
|
|
522
567
|
|
|
523
568
|
if (site) {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
rule: didResolverWellknownRule,
|
|
532
|
-
},
|
|
533
|
-
context
|
|
534
|
-
);
|
|
535
|
-
changed = true;
|
|
536
|
-
}
|
|
569
|
+
const didResolverRuleUpdateRes = await upsertSiteRule(
|
|
570
|
+
{
|
|
571
|
+
site,
|
|
572
|
+
rule: didResolverWellknownRule,
|
|
573
|
+
},
|
|
574
|
+
context
|
|
575
|
+
);
|
|
537
576
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
);
|
|
546
|
-
changed = true;
|
|
547
|
-
}
|
|
577
|
+
const acmeRuleUpdateRes = await upsertSiteRule(
|
|
578
|
+
{
|
|
579
|
+
site,
|
|
580
|
+
rule: acmeChallengeWellknownRule,
|
|
581
|
+
},
|
|
582
|
+
context
|
|
583
|
+
);
|
|
548
584
|
|
|
549
|
-
return
|
|
585
|
+
return didResolverRuleUpdateRes || acmeRuleUpdateRes;
|
|
550
586
|
}
|
|
551
587
|
|
|
552
588
|
await routerManager.addRoutingSite(
|
|
@@ -694,7 +730,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
694
730
|
return `/${str}`.replace(/^\/+/, '/');
|
|
695
731
|
};
|
|
696
732
|
|
|
697
|
-
const domainGroup =
|
|
733
|
+
const domainGroup = getBlockletDomainGroupName(blocklet.meta.did);
|
|
698
734
|
|
|
699
735
|
const pathPrefix = getPrefix(webInterface.prefix);
|
|
700
736
|
const rule = {
|
|
@@ -736,13 +772,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
736
772
|
context
|
|
737
773
|
);
|
|
738
774
|
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
|
-
}
|
|
746
775
|
|
|
747
776
|
return true;
|
|
748
777
|
}
|
|
@@ -1061,7 +1090,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1061
1090
|
const nodeInfo = await nodeState.read();
|
|
1062
1091
|
|
|
1063
1092
|
const ruleChanged = await routerManager.deleteRoutingRulesItemByDid({ did: blocklet.meta.did }, context);
|
|
1064
|
-
|
|
1093
|
+
let siteChanged;
|
|
1094
|
+
if (!context.keepRouting) {
|
|
1095
|
+
siteChanged = await _removeBlockletSites(blocklet, nodeInfo, context);
|
|
1096
|
+
}
|
|
1065
1097
|
|
|
1066
1098
|
return ruleChanged || siteChanged;
|
|
1067
1099
|
};
|
|
@@ -1121,6 +1153,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1121
1153
|
try {
|
|
1122
1154
|
const info = await nodeState.read();
|
|
1123
1155
|
let { sites } = await readRoutingSites();
|
|
1156
|
+
sites = await filterSitesForRemovedBlocklets(sites);
|
|
1124
1157
|
sites = await ensureLatestInfo(sites);
|
|
1125
1158
|
sites = await ensureAuthService(sites, blockletManager);
|
|
1126
1159
|
sites = await ensureServiceRule(sites);
|
|
@@ -1354,6 +1387,8 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1354
1387
|
getCertificates,
|
|
1355
1388
|
checkDomain,
|
|
1356
1389
|
ensureDashboardCertificate,
|
|
1390
|
+
addWellknownSite,
|
|
1391
|
+
upsertSiteRule,
|
|
1357
1392
|
|
|
1358
1393
|
getRoutingCrons: () => [
|
|
1359
1394
|
{
|
package/lib/router/manager.js
CHANGED
|
@@ -186,19 +186,37 @@ class RouterManager extends EventEmitter {
|
|
|
186
186
|
return dbSite;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
async addDomainAlias({ id, domainAlias }, context = {}) {
|
|
189
|
+
async addDomainAlias({ id, domainAlias, force }, context = {}) {
|
|
190
190
|
await validateAddDomainAlias(domainAlias, context);
|
|
191
191
|
const dbSite = await states.site.findOne({ _id: id });
|
|
192
192
|
if (!dbSite) {
|
|
193
193
|
throw new Error(`site ${id} does not exist`);
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
// check domain exists in site domain
|
|
197
|
+
const mainDomainSiteCount = await states.site.count({
|
|
198
|
+
domain: domainAlias,
|
|
198
199
|
});
|
|
199
200
|
|
|
200
|
-
if (
|
|
201
|
-
|
|
201
|
+
if (mainDomainSiteCount > 0) {
|
|
202
|
+
if (!force) {
|
|
203
|
+
throw new Error(`${domainAlias} already exists`);
|
|
204
|
+
} else {
|
|
205
|
+
throw new Error(`${domainAlias} cannot be forced-added`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// check domain exists in site alias domain
|
|
210
|
+
const aliasDomainSite = await states.site.findOne({
|
|
211
|
+
$or: [{ domainAliases: domainAlias }, { 'domainAliases.value': domainAlias }],
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (aliasDomainSite) {
|
|
215
|
+
if (!force) {
|
|
216
|
+
throw new Error(`${domainAlias} already exists`);
|
|
217
|
+
} else {
|
|
218
|
+
await this.deleteDomainAlias({ id: aliasDomainSite.id, domainAlias });
|
|
219
|
+
}
|
|
202
220
|
}
|
|
203
221
|
|
|
204
222
|
const updateResult = await states.site.update(
|
|
@@ -302,7 +320,7 @@ class RouterManager extends EventEmitter {
|
|
|
302
320
|
|
|
303
321
|
// update rules
|
|
304
322
|
const newRules = [
|
|
305
|
-
...dbSite.rules.filter((x) => x.groupId !== rule.id || x.id !== rule.id), // 有些路由没有 rule.groupId
|
|
323
|
+
...dbSite.rules.filter((x) => (x.groupId && x.groupId !== rule.id) || x.id !== rule.id), // 有些路由没有 rule.groupId
|
|
306
324
|
...(await this.getRules(rule)),
|
|
307
325
|
];
|
|
308
326
|
|
package/lib/states/blocklet.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
/* eslint-disable no-underscore-dangle */
|
|
5
5
|
const omit = require('lodash/omit');
|
|
6
6
|
const uniq = require('lodash/uniq');
|
|
7
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
7
8
|
const detectPort = require('detect-port');
|
|
8
9
|
const Lock = require('@abtnode/util/lib/lock');
|
|
9
10
|
const security = require('@abtnode/util/lib/security');
|
|
@@ -119,7 +120,7 @@ class BlockletState extends BaseState {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
this.emit('remove', doc);
|
|
122
|
-
return resolve(doc);
|
|
123
|
+
return resolve(formatBlocklet(doc, 'onRead', this.options.dek));
|
|
123
124
|
});
|
|
124
125
|
})
|
|
125
126
|
);
|
|
@@ -196,7 +197,7 @@ class BlockletState extends BaseState {
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
try {
|
|
199
|
-
const formatted = formatBlocklet(updates, 'onUpdate', this.options.dek);
|
|
200
|
+
const formatted = formatBlocklet(cloneDeep(updates), 'onUpdate', this.options.dek);
|
|
200
201
|
const newDoc = await this.updateById(doc._id, { $set: formatted });
|
|
201
202
|
resolve(newDoc);
|
|
202
203
|
} catch (err) {
|
|
@@ -247,8 +248,10 @@ class BlockletState extends BaseState {
|
|
|
247
248
|
},
|
|
248
249
|
});
|
|
249
250
|
lock.release();
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
|
|
252
|
+
const formatted = formatBlocklet(newDoc, 'onRead', this.options.dek);
|
|
253
|
+
this.emit('upgrade', formatted);
|
|
254
|
+
resolve(formatted);
|
|
252
255
|
} catch (err) {
|
|
253
256
|
lock.release();
|
|
254
257
|
reject(err);
|
|
@@ -392,11 +395,12 @@ class BlockletState extends BaseState {
|
|
|
392
395
|
if (typeof status === 'undefined') {
|
|
393
396
|
throw new Error('Unsupported blocklet status');
|
|
394
397
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (
|
|
398
|
-
return
|
|
398
|
+
|
|
399
|
+
const doc = await this.getBlocklet(did);
|
|
400
|
+
if (doc.status === status) {
|
|
401
|
+
return formatBlocklet(doc, 'onRead', this.options.dek);
|
|
399
402
|
}
|
|
403
|
+
|
|
400
404
|
const updates = { status, startedAt: undefined, stoppedAt: undefined };
|
|
401
405
|
if (status === BlockletStatus.running) {
|
|
402
406
|
updates.startedAt = new Date();
|
|
@@ -408,10 +412,8 @@ class BlockletState extends BaseState {
|
|
|
408
412
|
updates.stoppedAt = new Date();
|
|
409
413
|
}
|
|
410
414
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
});
|
|
414
|
-
return res;
|
|
415
|
+
await this.update(doc._id, { $set: updates });
|
|
416
|
+
return formatBlocklet({ ...doc, ...updates }, 'onRead', this.options.dek);
|
|
415
417
|
}
|
|
416
418
|
|
|
417
419
|
getChildrenFromMetas(childrenMeta) {
|
package/lib/states/node.js
CHANGED
package/lib/util/blocklet.js
CHANGED
|
@@ -41,6 +41,7 @@ const { forEachBlocklet } = require('@blocklet/meta/lib/util');
|
|
|
41
41
|
const { validate: validateEngine, get: getEngine } = require('../blocklet/manager/engine');
|
|
42
42
|
|
|
43
43
|
const isRequirementsSatisfied = require('./requirement');
|
|
44
|
+
const { getDidDomainForBlocklet } = require('./get-domain-for-blocklet');
|
|
44
45
|
const { getServices } = require('./service');
|
|
45
46
|
const {
|
|
46
47
|
isBeforeInstalled,
|
|
@@ -74,7 +75,6 @@ const PRIVATE_NODE_ENVS = [
|
|
|
74
75
|
// 'NEDB_MULTI_PORT', // FIXME: 排查 abtnode 对外提供的 SDK(比如 @abtnode/queue), SDK 中不要自动使用 NEDB_MULTI_PORT 环境变量
|
|
75
76
|
'ABT_NODE_UPDATER_PORT',
|
|
76
77
|
'ABT_NODE_SESSION_TTL',
|
|
77
|
-
'ABT_NODE_MODE',
|
|
78
78
|
'ABT_NODE_ROUTER_PROVIDER',
|
|
79
79
|
'ABT_NODE_DATA_DIR',
|
|
80
80
|
'ABT_NODE_TOKEN_SECRET',
|
|
@@ -85,6 +85,11 @@ const PRIVATE_NODE_ENVS = [
|
|
|
85
85
|
'ABT_NODE_BASE_URL',
|
|
86
86
|
'ABT_NODE_LOG_LEVEL',
|
|
87
87
|
'ABT_NODE_LOG_DIR',
|
|
88
|
+
// in /core/cli/bin/blocklet.js
|
|
89
|
+
'CLI_MODE',
|
|
90
|
+
'ABT_NODE_HOME',
|
|
91
|
+
'PM2_HOME',
|
|
92
|
+
'ABT_NODE_CONFIG_FILE',
|
|
88
93
|
];
|
|
89
94
|
|
|
90
95
|
/**
|
|
@@ -243,12 +248,16 @@ const getRootSystemEnvironments = (blocklet, nodeInfo) => {
|
|
|
243
248
|
const appName = title || name || result.name;
|
|
244
249
|
const appDescription = description || result.description;
|
|
245
250
|
|
|
251
|
+
// FIXME: we should use https here when possible, eg, when did-gateway is available
|
|
252
|
+
const appUrl = `http://${getDidDomainForBlocklet({ appId, didDomain: nodeInfo.didDomain })}`;
|
|
253
|
+
|
|
246
254
|
return {
|
|
247
255
|
BLOCKLET_DID: did,
|
|
248
256
|
BLOCKLET_APP_SK: appSk,
|
|
249
257
|
BLOCKLET_APP_ID: appId,
|
|
250
258
|
BLOCKLET_APP_NAME: appName,
|
|
251
259
|
BLOCKLET_APP_DESCRIPTION: appDescription,
|
|
260
|
+
BLOCKLET_APP_URL: appUrl,
|
|
252
261
|
};
|
|
253
262
|
};
|
|
254
263
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { BLOCKLET_SITE_GROUP_SUFFIX } = require('@abtnode/constant');
|
|
2
|
+
|
|
3
|
+
const getBlockletDomainGroupName = (did) => `${did}${BLOCKLET_SITE_GROUP_SUFFIX}`;
|
|
4
|
+
|
|
5
|
+
const getDidFromDomainGroupName = (name) => {
|
|
6
|
+
const did = name.replace(BLOCKLET_SITE_GROUP_SUFFIX, '');
|
|
7
|
+
return did;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
getBlockletDomainGroupName,
|
|
12
|
+
getDidFromDomainGroupName,
|
|
13
|
+
};
|
package/lib/validators/node.js
CHANGED
|
@@ -9,14 +9,23 @@ const nodeInfoSchema = Joi.object({
|
|
|
9
9
|
description: Joi.string()
|
|
10
10
|
.required()
|
|
11
11
|
.messages({ zh: { 'string.empty': '描述不能为空' }, en: { 'string.empty': 'Description cannot be empty' } }),
|
|
12
|
+
registerUrl: Joi.string()
|
|
13
|
+
.uri({ scheme: [/https?/] })
|
|
14
|
+
.label('register url')
|
|
15
|
+
.allow('')
|
|
16
|
+
.optional()
|
|
17
|
+
.messages({
|
|
18
|
+
zh: { 'string.uriCustomScheme': '应用启动器必须是合法的 URL' },
|
|
19
|
+
en: { 'string.uriCustomScheme': 'Blocklet Launcher must be a valid URL' },
|
|
20
|
+
}),
|
|
12
21
|
webWalletUrl: Joi.string()
|
|
13
22
|
.uri({ scheme: [/https?/] })
|
|
14
23
|
.label('web wallet url')
|
|
15
24
|
.allow('')
|
|
16
25
|
.optional()
|
|
17
26
|
.messages({
|
|
18
|
-
zh: { 'string.uriCustomScheme': 'Web
|
|
19
|
-
en: { 'string.uriCustomScheme': 'Web
|
|
27
|
+
zh: { 'string.uriCustomScheme': 'Web Wallet 必须是合法的 URL' },
|
|
28
|
+
en: { 'string.uriCustomScheme': 'Web Wallet must be a valid URL' },
|
|
20
29
|
}),
|
|
21
30
|
autoUpgrade: Joi.boolean(),
|
|
22
31
|
enableWelcomePage: Joi.boolean(),
|
|
@@ -31,16 +40,6 @@ const nodeInfoSchema = Joi.object({
|
|
|
31
40
|
'number.max': 'Disk usage alert threshold cannot be higher than 99%',
|
|
32
41
|
},
|
|
33
42
|
}),
|
|
34
|
-
// removed in 1.5.1
|
|
35
|
-
registerUrl: Joi.string()
|
|
36
|
-
.uri({ scheme: [/https?/] })
|
|
37
|
-
.label('register url')
|
|
38
|
-
.allow('')
|
|
39
|
-
.optional()
|
|
40
|
-
.messages({
|
|
41
|
-
zh: { 'string.uriCustomScheme': '注册地址必须是合法的 URL' },
|
|
42
|
-
en: { 'string.uriCustomScheme': 'Registry URL must be a valid URL' },
|
|
43
|
-
}),
|
|
44
43
|
}).options({ stripUnknown: true });
|
|
45
44
|
|
|
46
45
|
module.exports = {
|
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
const JOI = require('joi');
|
|
3
3
|
const { getMultipleLangParams } = require('./util');
|
|
4
4
|
|
|
5
|
-
const nameSchema = JOI.string()
|
|
5
|
+
const nameSchema = JOI.string()
|
|
6
|
+
.trim()
|
|
7
|
+
.max(64)
|
|
8
|
+
.custom((name) => {
|
|
9
|
+
const arr = name.split('_');
|
|
10
|
+
const formatTip = 'The format of permission name should be "{action}_{resource}", e.g. query_data';
|
|
11
|
+
if (arr.length > 2) {
|
|
12
|
+
throw new Error(`Too much "_". ${formatTip}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (arr.length < 2) {
|
|
16
|
+
throw new Error(formatTip);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return name;
|
|
20
|
+
});
|
|
6
21
|
const descriptionSchema = JOI.string().trim().max(600);
|
|
7
22
|
|
|
8
23
|
const createPermissionSchema = JOI.object({
|
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.16",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,28 +19,28 @@
|
|
|
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.
|
|
34
|
-
"@arcblock/event-hub": "1.
|
|
22
|
+
"@abtnode/certificate-manager": "1.6.16",
|
|
23
|
+
"@abtnode/constant": "1.6.16",
|
|
24
|
+
"@abtnode/cron": "1.6.16",
|
|
25
|
+
"@abtnode/db": "1.6.16",
|
|
26
|
+
"@abtnode/logger": "1.6.16",
|
|
27
|
+
"@abtnode/queue": "1.6.16",
|
|
28
|
+
"@abtnode/rbac": "1.6.16",
|
|
29
|
+
"@abtnode/router-provider": "1.6.16",
|
|
30
|
+
"@abtnode/static-server": "1.6.16",
|
|
31
|
+
"@abtnode/timemachine": "1.6.16",
|
|
32
|
+
"@abtnode/util": "1.6.16",
|
|
33
|
+
"@arcblock/did": "^1.14.3",
|
|
34
|
+
"@arcblock/event-hub": "1.14.3",
|
|
35
35
|
"@arcblock/pm2-events": "^0.0.5",
|
|
36
|
-
"@arcblock/vc": "^1.
|
|
37
|
-
"@blocklet/meta": "1.6.
|
|
36
|
+
"@arcblock/vc": "^1.14.3",
|
|
37
|
+
"@blocklet/meta": "1.6.16",
|
|
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.
|
|
42
|
-
"@ocap/util": "^1.
|
|
43
|
-
"@ocap/wallet": "^1.
|
|
41
|
+
"@ocap/mcrypto": "^1.14.3",
|
|
42
|
+
"@ocap/util": "^1.14.3",
|
|
43
|
+
"@ocap/wallet": "^1.14.3",
|
|
44
44
|
"@slack/webhook": "^5.0.3",
|
|
45
45
|
"axios": "^0.21.4",
|
|
46
46
|
"axon": "^2.0.3",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"express": "^4.17.1",
|
|
76
76
|
"jest": "^27.4.5"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "69b08db16aeb75ce23b0e6bb5b9fa396adba2d4b"
|
|
79
79
|
}
|