@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.
- package/lib/blocklet/manager/disk.js +26 -30
- package/lib/blocklet/storage/backup/spaces.js +1 -1
- package/lib/blocklet/storage/restore/spaces.js +1 -1
- package/lib/index.js +1 -0
- package/lib/router/helper.js +1 -1
- package/lib/router/manager.js +4 -4
- package/lib/states/node.js +1 -1
- package/lib/util/blocklet.js +8 -43
- package/lib/validators/router.js +3 -1
- package/package.json +26 -26
|
@@ -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(
|
|
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:
|
|
155
|
+
concurrency: 64,
|
|
156
156
|
retryCount: 100,
|
|
157
157
|
filter: (object) => {
|
|
158
158
|
return object.name !== '.DS_Store';
|
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),
|
package/lib/router/helper.js
CHANGED
|
@@ -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) {
|
|
522
522
|
await downloadCert({
|
|
523
523
|
domain,
|
|
524
524
|
url,
|
package/lib/router/manager.js
CHANGED
|
@@ -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`);
|
package/lib/states/node.js
CHANGED
package/lib/util/blocklet.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
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
|
};
|
package/lib/validators/router.js
CHANGED
|
@@ -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
|
|
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
|
|
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.
|
|
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.
|
|
37
|
-
"@arcblock/event-hub": "1.18.
|
|
38
|
-
"@arcblock/jwt": "^1.18.
|
|
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.
|
|
41
|
-
"@blocklet/constant": "1.8.66
|
|
42
|
-
"@blocklet/meta": "1.8.66
|
|
43
|
-
"@blocklet/sdk": "1.8.66
|
|
44
|
-
"@did-space/client": "^0.1.
|
|
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
|
-
"@ocap/util": "1.18.
|
|
48
|
-
"@ocap/wallet": "1.18.
|
|
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": "
|
|
93
|
+
"gitHead": "282247fd0ce6702e1d6920e90e2b3be0408cf879"
|
|
94
94
|
}
|