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

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,20 +15,18 @@ 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');
19
18
  const { toSvg: createDidLogo } =
20
19
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
21
20
  const getBlockletInfo = require('@blocklet/meta/lib/info');
22
21
  const sleep = require('@abtnode/util/lib/sleep');
23
22
 
24
23
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
25
- const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
26
24
  const {
27
- VC_TYPE_BLOCKLET_PURCHASE,
28
25
  WHO_CAN_ACCESS,
29
26
  SERVER_ROLES,
30
27
  WHO_CAN_ACCESS_PREFIX_ROLES,
31
28
  BLOCKLET_INSTALL_TYPE,
29
+ NODE_MODES,
32
30
  } = require('@abtnode/constant');
33
31
 
34
32
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
@@ -111,6 +109,8 @@ const {
111
109
  validateAppConfig,
112
110
  checkDuplicateAppSk,
113
111
  checkDuplicateMountPoint,
112
+ validateStore,
113
+ validateInServerless,
114
114
  } = require('../../util/blocklet');
115
115
  const StoreUtil = require('../../util/store');
116
116
  const states = require('../../states');
@@ -242,6 +242,8 @@ class BlockletManager extends BaseBlockletManager {
242
242
  * did: string;
243
243
  * title: string;
244
244
  * description: string;
245
+ * storeUrl: string;
246
+ * blockletSecretKey: string;
245
247
  * sync: boolean = false; // download synchronously, not use queue
246
248
  * delay: number; // push download task to queue after a delay
247
249
  * downloadTokenList: Array<{did: string, token: string}>;
@@ -346,6 +348,12 @@ class BlockletManager extends BaseBlockletManager {
346
348
  logger.debug('start install component', { rootDid, mountPoint, url });
347
349
 
348
350
  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
+
349
357
  return this._installComponentFromUpload({
350
358
  rootDid,
351
359
  mountPoint,
@@ -359,6 +367,11 @@ class BlockletManager extends BaseBlockletManager {
359
367
  }
360
368
 
361
369
  if (url) {
370
+ const info = await states.node.read();
371
+ if (info.mode === NODE_MODES.SERVERLESS) {
372
+ validateStore(info, url);
373
+ }
374
+
362
375
  return this._installComponentFromUrl({
363
376
  rootDid,
364
377
  mountPoint,
@@ -430,25 +443,6 @@ class BlockletManager extends BaseBlockletManager {
430
443
  return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
431
444
  }
432
445
 
433
- async installBlockletFromVc({ vcPresentation, challenge }, context) {
434
- logger.info('Install from vc');
435
- const vc = getVcFromPresentation(vcPresentation);
436
-
437
- // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
438
- verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
439
-
440
- if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
441
- throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
442
- }
443
-
444
- const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
445
- const urlObject = new URL(blockletUrl);
446
- const did = get(vc, 'credentialSubject.purchased.blocklet.id');
447
- const registry = urlObject.origin;
448
-
449
- return this._installFromStore({ did, registry }, context);
450
- }
451
-
452
446
  async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
453
447
  logger.info('start blocklet', { did });
454
448
  // should check blocklet integrity
@@ -2173,6 +2167,11 @@ class BlockletManager extends BaseBlockletManager {
2173
2167
 
2174
2168
  // install from store if url is a store url
2175
2169
  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
+
2176
2175
  if (inStore) {
2177
2176
  const exist = await states.blocklet.getBlocklet(blockletDid);
2178
2177
  if (exist) {
@@ -2788,6 +2787,11 @@ class BlockletManager extends BaseBlockletManager {
2788
2787
 
2789
2788
  validateBlockletMeta(meta, { ensureDist: true });
2790
2789
 
2790
+ const info = await states.node.read();
2791
+ if (info.mode === NODE_MODES.SERVERLESS) {
2792
+ validateInServerless({ blockletMeta: meta });
2793
+ }
2794
+
2791
2795
  const { name, did, version } = meta;
2792
2796
 
2793
2797
  const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
@@ -3410,6 +3414,7 @@ class BlockletManager extends BaseBlockletManager {
3410
3414
  }
3411
3415
  const number = await states.node.increaseCustomBlockletNumber();
3412
3416
  const name = `custom-${number}`;
3417
+ // MEMO: 空壳 APP可以保留原有的 did 生成逻辑
3413
3418
  const did = toBlockletDid(name);
3414
3419
  const blocklet = await states.blocklet.getBlocklet(did);
3415
3420
  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: 64,
155
+ concurrency: 32,
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: 64,
120
+ concurrency: 32,
121
121
  retryCount: 100,
122
122
  })
123
123
  );
package/lib/index.js CHANGED
@@ -192,7 +192,6 @@ function ABTNode(options) {
192
192
 
193
193
  // Blocklet manager
194
194
  installBlocklet: blockletManager.install.bind(blockletManager),
195
- installBlockletFromVc: blockletManager.installBlockletFromVc.bind(blockletManager),
196
195
  installComponent: blockletManager.installComponent.bind(blockletManager),
197
196
  startBlocklet: blockletManager.start.bind(blockletManager),
198
197
  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) {
521
+ if (!cert || get(cert, 'meta.validTo') <= Date.now()) {
522
522
  await downloadCert({
523
523
  domain,
524
524
  url,
@@ -124,7 +124,7 @@ class NodeState extends BaseState {
124
124
  routing,
125
125
  docker,
126
126
  mode,
127
- enableWelcomePage: true,
127
+ enableWelcomePage: mode !== NODE_MODES.SERVERLESS,
128
128
  runtimeConfig,
129
129
  ownerNft,
130
130
  diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
@@ -31,7 +31,12 @@ 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 { BLOCKLET_MAX_MEM_LIMIT_IN_MB, BLOCKLET_STORE, BLOCKLET_INSTALL_TYPE } = require('@abtnode/constant');
34
+ const {
35
+ BLOCKLET_MAX_MEM_LIMIT_IN_MB,
36
+ BLOCKLET_STORE,
37
+ BLOCKLET_INSTALL_TYPE,
38
+ BLOCKLET_STORE_DEV,
39
+ } = require('@abtnode/constant');
35
40
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
36
41
 
37
42
  const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
@@ -835,7 +840,7 @@ const parseChildrenFromMeta = async (src, context = {}) => {
835
840
  };
836
841
 
837
842
  const validateBlocklet = (blocklet) =>
838
- forEachBlocklet(blocklet, (b) => {
843
+ forEachBlocklet(blocklet, async (b) => {
839
844
  isRequirementsSatisfied(b.meta.requirements);
840
845
  validateEngine(getBlockletEngineNameByPlatform(b.meta));
841
846
  });
@@ -1400,12 +1405,14 @@ const getBlocklet = async ({
1400
1405
 
1401
1406
  blocklet.settings.storeList = blocklet.settings.storeList || [];
1402
1407
 
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
- }
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
+ });
1409
1416
 
1410
1417
  // app site
1411
1418
  blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
@@ -1690,6 +1697,32 @@ const checkDuplicateMountPoint = (blocklet, mountPoint) => {
1690
1697
  }
1691
1698
  };
1692
1699
 
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
+
1693
1726
  module.exports = {
1694
1727
  consumeServerlessNFT,
1695
1728
  forEachBlocklet,
@@ -1737,4 +1770,6 @@ module.exports = {
1737
1770
  validateAppConfig,
1738
1771
  checkDuplicateAppSk,
1739
1772
  checkDuplicateMountPoint,
1773
+ validateStore,
1774
+ validateInServerless,
1740
1775
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.65",
6
+ "version": "1.8.66-beta-7f4224af",
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.65",
23
- "@abtnode/certificate-manager": "1.8.65",
24
- "@abtnode/constant": "1.8.65",
25
- "@abtnode/cron": "1.8.65",
26
- "@abtnode/db": "1.8.65",
27
- "@abtnode/logger": "1.8.65",
28
- "@abtnode/queue": "1.8.65",
29
- "@abtnode/rbac": "1.8.65",
30
- "@abtnode/router-provider": "1.8.65",
31
- "@abtnode/static-server": "1.8.65",
32
- "@abtnode/timemachine": "1.8.65",
33
- "@abtnode/util": "1.8.65",
34
- "@arcblock/did": "1.18.42",
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",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.42",
37
- "@arcblock/event-hub": "1.18.42",
38
- "@arcblock/jwt": "^1.18.42",
36
+ "@arcblock/did-util": "1.18.47",
37
+ "@arcblock/event-hub": "1.18.47",
38
+ "@arcblock/jwt": "^1.18.47",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.42",
41
- "@blocklet/constant": "1.8.65",
42
- "@blocklet/meta": "1.8.65",
43
- "@blocklet/sdk": "1.8.65",
44
- "@did-space/client": "^0.1.66",
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",
45
45
  "@fidm/x509": "^1.2.1",
46
- "@ocap/mcrypto": "1.18.42",
47
- "@ocap/util": "1.18.42",
48
- "@ocap/wallet": "1.18.42",
46
+ "@ocap/mcrypto": "1.18.47",
47
+ "@ocap/util": "1.18.47",
48
+ "@ocap/wallet": "1.18.47",
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": "69b608353fbbdb7c61f9ccb10965a1d0c55c45f2"
93
+ "gitHead": "72d418f63ecb76b1d5d62edbcc5f336cb62bf308"
94
94
  }