@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.
@@ -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
- meta.isFree = isFree;
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: false });
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
- this.emit(BlockletEvents.removed, { blocklet: result, context });
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
  });
@@ -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 = get(info, 'routing.dashboardCertDownloadAddress', '');
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('downloading certificate', { url: downloadUrl, dashboardDomain });
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
- from: { pathPrefix: joinUrl(WELLKNOWN_PATH_PREFIX, '/did.json') },
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
- let changed = false;
525
- const exists = (prefix) => !!site.rules.find((r) => r.from.pathPrefix === normalizePathPrefix(prefix));
526
-
527
- if (!exists(didResolverWellknownRule.from.pathPrefix)) {
528
- await routerManager.addRoutingRule(
529
- {
530
- id: site.id,
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
- if (!exists(acmeChallengeWellknownRule.from.pathPrefix)) {
539
- await routerManager.addRoutingRule(
540
- {
541
- id: site.id,
542
- rule: acmeChallengeWellknownRule,
543
- },
544
- context
545
- );
546
- changed = true;
547
- }
577
+ const acmeRuleUpdateRes = await upsertSiteRule(
578
+ {
579
+ site,
580
+ rule: acmeChallengeWellknownRule,
581
+ },
582
+ context
583
+ );
548
584
 
549
- return changed;
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 = `${blocklet.meta.did}${BLOCKLET_SITE_GROUP_SUFFIX}`;
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
- const siteChanged = await _removeBlockletSites(blocklet, nodeInfo, context);
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
  {
@@ -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
- const siteCount = await states.site.count({
197
- $or: [{ domain: domainAlias }, { domainAliases: domainAlias }, { 'domainAliases.value': domainAlias }],
196
+ // check domain exists in site domain
197
+ const mainDomainSiteCount = await states.site.count({
198
+ domain: domainAlias,
198
199
  });
199
200
 
200
- if (siteCount > 0) {
201
- throw new Error(`domain alias ${domainAlias} already exists`);
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
 
@@ -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
- this.emit('upgrade', newDoc);
251
- resolve(newDoc);
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
- const record = await this.getBlocklet(did);
396
- // when status change update record
397
- if (record.status === status) {
398
- return record;
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
- const res = await this.update(record._id, {
412
- $set: updates,
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) {
@@ -255,6 +255,7 @@ class NodeState extends BaseState {
255
255
  ABT_NODE_PK: info.pk,
256
256
  ABT_NODE_PORT: info.port,
257
257
  ABT_NODE_SERVICE_PORT: process.env.ABT_NODE_SERVICE_PORT,
258
+ ABT_NODE_MODE: info.mode,
258
259
  }));
259
260
  }
260
261
 
@@ -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
 
@@ -35,7 +35,7 @@ const defaultNodeConfigs = {
35
35
  },
36
36
  ],
37
37
  },
38
- registerUrl: { getDefaultValue: () => NODE_REGISTER_URL }, // removed in 1.5.1
38
+ registerUrl: { getDefaultValue: () => NODE_REGISTER_URL },
39
39
  webWalletUrl: { getDefaultValue: () => WEB_WALLET_URL },
40
40
  };
41
41
 
@@ -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
+ };
@@ -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 DID Wallet 必须是合法的 URL' },
19
- en: { 'string.uriCustomScheme': 'Web DID Wallet must be a valid URL' },
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().trim().max(64);
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.12",
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.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
- "@arcblock/did": "^1.13.79",
34
- "@arcblock/event-hub": "1.13.79",
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.13.79",
37
- "@blocklet/meta": "1.6.12",
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.13.79",
42
- "@ocap/util": "^1.13.79",
43
- "@ocap/wallet": "^1.13.79",
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": "dd79037978dc12f72330227a553a80a504f03fa7"
78
+ "gitHead": "69b08db16aeb75ce23b0e6bb5b9fa396adba2d4b"
79
79
  }