@abtnode/core 1.8.66-beta-7f4224af → 1.8.66

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.
@@ -15,18 +15,20 @@ const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
15
15
  const didDocument = require('@abtnode/util/lib/did-document');
16
16
  const { sign } = require('@arcblock/jwt');
17
17
  const { isValid: isValidDid } = require('@arcblock/did');
18
+ const { verifyPresentation } = require('@arcblock/vc');
18
19
  const { toSvg: createDidLogo } =
19
20
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
20
21
  const getBlockletInfo = require('@blocklet/meta/lib/info');
21
22
  const sleep = require('@abtnode/util/lib/sleep');
22
23
 
23
24
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
25
+ const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
24
26
  const {
27
+ VC_TYPE_BLOCKLET_PURCHASE,
25
28
  WHO_CAN_ACCESS,
26
29
  SERVER_ROLES,
27
30
  WHO_CAN_ACCESS_PREFIX_ROLES,
28
31
  BLOCKLET_INSTALL_TYPE,
29
- NODE_MODES,
30
32
  } = require('@abtnode/constant');
31
33
 
32
34
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
@@ -109,8 +111,6 @@ const {
109
111
  validateAppConfig,
110
112
  checkDuplicateAppSk,
111
113
  checkDuplicateMountPoint,
112
- validateStore,
113
- validateInServerless,
114
114
  } = require('../../util/blocklet');
115
115
  const StoreUtil = require('../../util/store');
116
116
  const states = require('../../states');
@@ -242,8 +242,6 @@ class BlockletManager extends BaseBlockletManager {
242
242
  * did: string;
243
243
  * title: string;
244
244
  * description: string;
245
- * storeUrl: string;
246
- * blockletSecretKey: string;
247
245
  * sync: boolean = false; // download synchronously, not use queue
248
246
  * delay: number; // push download task to queue after a delay
249
247
  * downloadTokenList: Array<{did: string, token: string}>;
@@ -331,7 +329,7 @@ class BlockletManager extends BaseBlockletManager {
331
329
  async installComponent(
332
330
  {
333
331
  rootDid,
334
- mountPoint,
332
+ mountPoint: tmpMountPoint,
335
333
  url,
336
334
  file,
337
335
  did,
@@ -345,15 +343,10 @@ class BlockletManager extends BaseBlockletManager {
345
343
  },
346
344
  context = {}
347
345
  ) {
346
+ const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
348
347
  logger.debug('start install component', { rootDid, mountPoint, url });
349
348
 
350
349
  if (file) {
351
- // TODO: 如何触发这种场景?
352
- const info = await states.node.read();
353
- if (info.mode === NODE_MODES.SERVERLESS) {
354
- throw new Error("Can't install component in serverless-mode server via upload");
355
- }
356
-
357
350
  return this._installComponentFromUpload({
358
351
  rootDid,
359
352
  mountPoint,
@@ -367,11 +360,6 @@ class BlockletManager extends BaseBlockletManager {
367
360
  }
368
361
 
369
362
  if (url) {
370
- const info = await states.node.read();
371
- if (info.mode === NODE_MODES.SERVERLESS) {
372
- validateStore(info, url);
373
- }
374
-
375
363
  return this._installComponentFromUrl({
376
364
  rootDid,
377
365
  mountPoint,
@@ -443,6 +431,25 @@ class BlockletManager extends BaseBlockletManager {
443
431
  return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
444
432
  }
445
433
 
434
+ async installBlockletFromVc({ vcPresentation, challenge }, context) {
435
+ logger.info('Install from vc');
436
+ const vc = getVcFromPresentation(vcPresentation);
437
+
438
+ // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
439
+ verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
440
+
441
+ if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
442
+ throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
443
+ }
444
+
445
+ const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
446
+ const urlObject = new URL(blockletUrl);
447
+ const did = get(vc, 'credentialSubject.purchased.blocklet.id');
448
+ const registry = urlObject.origin;
449
+
450
+ return this._installFromStore({ did, registry }, context);
451
+ }
452
+
446
453
  async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
447
454
  logger.info('start blocklet', { did });
448
455
  // should check blocklet integrity
@@ -1190,8 +1197,8 @@ class BlockletManager extends BaseBlockletManager {
1190
1197
  return this.getBlocklet(rootDid);
1191
1198
  }
1192
1199
 
1193
- async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint }, context) {
1194
- await mountPointSchema.validateAsync(mountPoint);
1200
+ async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint: tmpMountPoint }, context) {
1201
+ const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
1195
1202
 
1196
1203
  const blocklet = await states.blocklet.getBlocklet(inputRootDid);
1197
1204
 
@@ -2167,11 +2174,6 @@ class BlockletManager extends BaseBlockletManager {
2167
2174
 
2168
2175
  // install from store if url is a store url
2169
2176
  const { inStore, registryUrl, blockletDid: bundleDid } = await StoreUtil.parseSourceUrl(url, controller);
2170
-
2171
- const nodeInfo = await states.node.read();
2172
-
2173
- await validateStore(nodeInfo, registryUrl);
2174
-
2175
2177
  if (inStore) {
2176
2178
  const exist = await states.blocklet.getBlocklet(blockletDid);
2177
2179
  if (exist) {
@@ -2787,11 +2789,6 @@ class BlockletManager extends BaseBlockletManager {
2787
2789
 
2788
2790
  validateBlockletMeta(meta, { ensureDist: true });
2789
2791
 
2790
- const info = await states.node.read();
2791
- if (info.mode === NODE_MODES.SERVERLESS) {
2792
- validateInServerless({ blockletMeta: meta });
2793
- }
2794
-
2795
2792
  const { name, did, version } = meta;
2796
2793
 
2797
2794
  const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
@@ -3414,7 +3411,6 @@ class BlockletManager extends BaseBlockletManager {
3414
3411
  }
3415
3412
  const number = await states.node.increaseCustomBlockletNumber();
3416
3413
  const name = `custom-${number}`;
3417
- // MEMO: 空壳 APP可以保留原有的 did 生成逻辑
3418
3414
  const did = toBlockletDid(name);
3419
3415
  const blocklet = await states.blocklet.getBlocklet(did);
3420
3416
  if (blocklet) {
@@ -152,7 +152,7 @@ class SpacesBackup {
152
152
  source: join(this.blockletBackupDir, '/'),
153
153
  target: join('.did-objects', this.blocklet.appDid),
154
154
  debug: true,
155
- concurrency: 32,
155
+ concurrency: 64,
156
156
  retryCount: 100,
157
157
  filter: (object) => {
158
158
  return object.name !== '.DS_Store';
@@ -117,7 +117,7 @@ class SpacesRestore {
117
117
  source: join('.did-objects', this.blockletWallet.address, '/'),
118
118
  target: this.blockletRestoreDir,
119
119
  debug: true,
120
- concurrency: 32,
120
+ concurrency: 64,
121
121
  retryCount: 100,
122
122
  })
123
123
  );
package/lib/index.js CHANGED
@@ -192,6 +192,7 @@ function ABTNode(options) {
192
192
 
193
193
  // Blocklet manager
194
194
  installBlocklet: blockletManager.install.bind(blockletManager),
195
+ installBlockletFromVc: blockletManager.installBlockletFromVc.bind(blockletManager),
195
196
  installComponent: blockletManager.installComponent.bind(blockletManager),
196
197
  startBlocklet: blockletManager.start.bind(blockletManager),
197
198
  stopBlocklet: blockletManager.stop.bind(blockletManager),
@@ -518,7 +518,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
518
518
 
519
519
  const ensureDomainCert = async (domain, url) => {
520
520
  const cert = await certManager.getByDomain(domain);
521
- if (!cert || get(cert, 'meta.validTo') <= Date.now()) {
521
+ if (!cert) {
522
522
  await downloadCert({
523
523
  domain,
524
524
  url,
@@ -258,8 +258,8 @@ class RouterManager extends EventEmitter {
258
258
  return dbSite;
259
259
  }
260
260
 
261
- async addRoutingRule({ id, rule, skipCheckDynamicBlacklist = false }, context = {}) {
262
- await validateAddRule({ id, rule }, context);
261
+ async addRoutingRule({ id, rule: tempRule, skipCheckDynamicBlacklist = false }, context = {}) {
262
+ const { rule } = await validateAddRule({ id, rule: tempRule }, context);
263
263
  const dbSite = await states.site.findOne({ _id: id });
264
264
  if (!dbSite) {
265
265
  throw new Error(`site ${id} does not exist`);
@@ -294,8 +294,8 @@ class RouterManager extends EventEmitter {
294
294
  return newSite;
295
295
  }
296
296
 
297
- async updateRoutingRule({ id, rule, skipProtectedRuleChecking = false }, context = {}) {
298
- await validateEditRule({ id, rule }, context);
297
+ async updateRoutingRule({ id, rule: tmpRule, skipProtectedRuleChecking = false }, context = {}) {
298
+ const { rule } = await validateEditRule({ id, rule: tmpRule }, context);
299
299
  const dbSite = await states.site.findOne({ _id: id, 'rules.id': rule.id });
300
300
  if (!dbSite) {
301
301
  throw new Error(`site ${id}, rule ${rule.id} does not exist`);
@@ -124,7 +124,7 @@ class NodeState extends BaseState {
124
124
  routing,
125
125
  docker,
126
126
  mode,
127
- enableWelcomePage: mode !== NODE_MODES.SERVERLESS,
127
+ enableWelcomePage: true,
128
128
  runtimeConfig,
129
129
  ownerNft,
130
130
  diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
@@ -31,12 +31,7 @@ const getFolderSize = require('@abtnode/util/lib/get-folder-size');
31
31
  const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
32
32
  const hashFiles = require('@abtnode/util/lib/hash-files');
33
33
  const isPathPrefixEqual = require('@abtnode/util/lib/is-path-prefix-equal');
34
- const {
35
- BLOCKLET_MAX_MEM_LIMIT_IN_MB,
36
- BLOCKLET_STORE,
37
- BLOCKLET_INSTALL_TYPE,
38
- BLOCKLET_STORE_DEV,
39
- } = require('@abtnode/constant');
34
+ const { BLOCKLET_MAX_MEM_LIMIT_IN_MB, BLOCKLET_STORE, BLOCKLET_INSTALL_TYPE } = require('@abtnode/constant');
40
35
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
41
36
 
42
37
  const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
@@ -840,7 +835,7 @@ const parseChildrenFromMeta = async (src, context = {}) => {
840
835
  };
841
836
 
842
837
  const validateBlocklet = (blocklet) =>
843
- forEachBlocklet(blocklet, async (b) => {
838
+ forEachBlocklet(blocklet, (b) => {
844
839
  isRequirementsSatisfied(b.meta.requirements);
845
840
  validateEngine(getBlockletEngineNameByPlatform(b.meta));
846
841
  });
@@ -1405,14 +1400,12 @@ const getBlocklet = async ({
1405
1400
 
1406
1401
  blocklet.settings.storeList = blocklet.settings.storeList || [];
1407
1402
 
1408
- [BLOCKLET_STORE_DEV, BLOCKLET_STORE].forEach((store) => {
1409
- if (!blocklet.settings.storeList.find((x) => x.url === store.url)) {
1410
- blocklet.settings.storeList.unshift({
1411
- ...store,
1412
- protected: true,
1413
- });
1414
- }
1415
- });
1403
+ if (!blocklet.settings.storeList.find((x) => x.url === BLOCKLET_STORE.url)) {
1404
+ blocklet.settings.storeList.unshift({
1405
+ ...BLOCKLET_STORE,
1406
+ protected: true,
1407
+ });
1408
+ }
1416
1409
 
1417
1410
  // app site
1418
1411
  blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
@@ -1697,32 +1690,6 @@ const checkDuplicateMountPoint = (blocklet, mountPoint) => {
1697
1690
  }
1698
1691
  };
1699
1692
 
1700
- const validateStore = (nodeInfo, storeUrl) => {
1701
- if (nodeInfo.mode !== 'serverless') {
1702
- return;
1703
- }
1704
-
1705
- const inStoreList = nodeInfo.blockletRegistryList.find((item) => {
1706
- const itemURLObj = new URL(item.url);
1707
- const storeUrlObj = new URL(storeUrl);
1708
-
1709
- return itemURLObj.host === storeUrlObj.host;
1710
- });
1711
-
1712
- if (!inStoreList) {
1713
- throw new Error('Must be installed from the compliant blocklet store list');
1714
- }
1715
- };
1716
-
1717
- const validateInServerless = ({ blockletMeta }) => {
1718
- const { interfaces } = blockletMeta;
1719
- const externalPortInterfaces = (interfaces || []).filter((item) => !!item.port?.external);
1720
-
1721
- if (externalPortInterfaces.length > 0) {
1722
- throw new Error('Blocklets with exposed ports cannot be installed');
1723
- }
1724
- };
1725
-
1726
1693
  module.exports = {
1727
1694
  consumeServerlessNFT,
1728
1695
  forEachBlocklet,
@@ -1770,6 +1737,4 @@ module.exports = {
1770
1737
  validateAppConfig,
1771
1738
  checkDuplicateAppSk,
1772
1739
  checkDuplicateMountPoint,
1773
- validateStore,
1774
- validateInServerless,
1775
1740
  };
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable newline-per-chained-call */
2
2
  const Joi = require('joi');
3
3
  const { DOMAIN_FOR_DEFAULT_SITE, ROUTING_RULE_TYPES, ROUTER_CACHE_GROUPS } = require('@abtnode/constant');
4
+ const urlFriendly = require('@blocklet/meta/lib/url-friendly').default;
4
5
  const { getMultipleLangParams } = require('./util');
5
6
 
6
7
  const WILDCARD_DOMAIN_REGEX = /^\*.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/;
@@ -27,7 +28,8 @@ const ruleSchema = {
27
28
  .messages({
28
29
  zh: { 'string.empty': 'URL 前缀不能为空', 'string.max': 'URL 前缀的最大长度是 150' },
29
30
  en: { 'string.empty': 'URL prefix cannot be empty', 'string.max': 'The maximum length of URL prefix is 150' },
30
- }),
31
+ })
32
+ .custom((value) => urlFriendly(value)),
31
33
  groupPathPrefix: Joi.string().trim().min(1).max(150), // path prefix of interface of root blocklet
32
34
  header: Joi.any(), // TODO: header does not take effect
33
35
  }),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.66-beta-7f4224af",
6
+ "version": "1.8.66",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,33 +19,33 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.8.66-beta-7f4224af",
23
- "@abtnode/certificate-manager": "1.8.66-beta-7f4224af",
24
- "@abtnode/constant": "1.8.66-beta-7f4224af",
25
- "@abtnode/cron": "1.8.66-beta-7f4224af",
26
- "@abtnode/db": "1.8.66-beta-7f4224af",
27
- "@abtnode/logger": "1.8.66-beta-7f4224af",
28
- "@abtnode/queue": "1.8.66-beta-7f4224af",
29
- "@abtnode/rbac": "1.8.66-beta-7f4224af",
30
- "@abtnode/router-provider": "1.8.66-beta-7f4224af",
31
- "@abtnode/static-server": "1.8.66-beta-7f4224af",
32
- "@abtnode/timemachine": "1.8.66-beta-7f4224af",
33
- "@abtnode/util": "1.8.66-beta-7f4224af",
34
- "@arcblock/did": "1.18.47",
22
+ "@abtnode/auth": "1.8.66",
23
+ "@abtnode/certificate-manager": "1.8.66",
24
+ "@abtnode/constant": "1.8.66",
25
+ "@abtnode/cron": "1.8.66",
26
+ "@abtnode/db": "1.8.66",
27
+ "@abtnode/logger": "1.8.66",
28
+ "@abtnode/queue": "1.8.66",
29
+ "@abtnode/rbac": "1.8.66",
30
+ "@abtnode/router-provider": "1.8.66",
31
+ "@abtnode/static-server": "1.8.66",
32
+ "@abtnode/timemachine": "1.8.66",
33
+ "@abtnode/util": "1.8.66",
34
+ "@arcblock/did": "1.18.42",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.47",
37
- "@arcblock/event-hub": "1.18.47",
38
- "@arcblock/jwt": "^1.18.47",
36
+ "@arcblock/did-util": "1.18.42",
37
+ "@arcblock/event-hub": "1.18.42",
38
+ "@arcblock/jwt": "^1.18.42",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.47",
41
- "@blocklet/constant": "1.8.66-beta-7f4224af",
42
- "@blocklet/meta": "1.8.66-beta-7f4224af",
43
- "@blocklet/sdk": "1.8.66-beta-7f4224af",
44
- "@did-space/client": "^0.1.73",
40
+ "@arcblock/vc": "1.18.42",
41
+ "@blocklet/constant": "1.8.66",
42
+ "@blocklet/meta": "1.8.66",
43
+ "@blocklet/sdk": "1.8.66",
44
+ "@did-space/client": "^0.1.66",
45
45
  "@fidm/x509": "^1.2.1",
46
- "@ocap/mcrypto": "1.18.47",
47
- "@ocap/util": "1.18.47",
48
- "@ocap/wallet": "1.18.47",
46
+ "@ocap/mcrypto": "1.18.42",
47
+ "@ocap/util": "1.18.42",
48
+ "@ocap/wallet": "1.18.42",
49
49
  "@slack/webhook": "^5.0.4",
50
50
  "archiver": "^5.3.1",
51
51
  "axios": "^0.27.2",
@@ -90,5 +90,5 @@
90
90
  "express": "^4.18.2",
91
91
  "jest": "^27.5.1"
92
92
  },
93
- "gitHead": "72d418f63ecb76b1d5d62edbcc5f336cb62bf308"
93
+ "gitHead": "282247fd0ce6702e1d6920e90e2b3be0408cf879"
94
94
  }