@abtnode/core 1.8.66-beta-b56e3b54 → 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 +49 -79
- package/lib/blocklet/manager/helper/install-from-backup.js +4 -4
- package/lib/blocklet/storage/backup/spaces.js +3 -3
- package/lib/blocklet/storage/restore/blocklets.js +2 -5
- package/lib/blocklet/storage/restore/spaces.js +5 -5
- package/lib/event.js +2 -2
- 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 +27 -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
|
-
* appSk: 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}>;
|
|
@@ -280,31 +278,28 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
280
278
|
context.startImmediately = !!params.startImmediately;
|
|
281
279
|
}
|
|
282
280
|
|
|
283
|
-
const { appSk } = params;
|
|
284
|
-
|
|
285
281
|
if (type === BLOCKLET_INSTALL_TYPE.URL) {
|
|
286
282
|
const { url, controller, sync, delay } = params;
|
|
287
|
-
return this._installFromUrl({ url, controller, sync, delay
|
|
283
|
+
return this._installFromUrl({ url, controller, sync, delay }, context);
|
|
288
284
|
}
|
|
289
285
|
|
|
290
286
|
if (type === BLOCKLET_INSTALL_TYPE.UPLOAD) {
|
|
291
287
|
const { file, did, diffVersion, deleteSet } = params;
|
|
292
|
-
return this._installFromUpload({ file, did, diffVersion, deleteSet,
|
|
288
|
+
return this._installFromUpload({ file, did, diffVersion, deleteSet, context });
|
|
293
289
|
}
|
|
294
290
|
|
|
295
291
|
if (type === BLOCKLET_INSTALL_TYPE.STORE) {
|
|
296
292
|
const { did, controller, sync, delay, storeUrl } = params;
|
|
297
|
-
return this._installFromStore({ did, controller, sync, delay, storeUrl
|
|
293
|
+
return this._installFromStore({ did, controller, sync, delay, storeUrl }, context);
|
|
298
294
|
}
|
|
299
295
|
|
|
300
296
|
if (type === BLOCKLET_INSTALL_TYPE.CREATE) {
|
|
301
|
-
|
|
302
|
-
return this._installFromCreate({ title, description, appSk }, context);
|
|
297
|
+
return this._installFromCreate({ title: params.title, description: params.description }, context);
|
|
303
298
|
}
|
|
304
299
|
|
|
305
300
|
if (type === BLOCKLET_INSTALL_TYPE.RESTORE) {
|
|
306
|
-
const { url } = params;
|
|
307
|
-
return this._installFromBackup({ url,
|
|
301
|
+
const { url, blockletSecretKey } = params;
|
|
302
|
+
return this._installFromBackup({ url, blockletSecretKey }, context);
|
|
308
303
|
}
|
|
309
304
|
|
|
310
305
|
// should not be here
|
|
@@ -334,7 +329,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
334
329
|
async installComponent(
|
|
335
330
|
{
|
|
336
331
|
rootDid,
|
|
337
|
-
mountPoint,
|
|
332
|
+
mountPoint: tmpMountPoint,
|
|
338
333
|
url,
|
|
339
334
|
file,
|
|
340
335
|
did,
|
|
@@ -348,15 +343,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
348
343
|
},
|
|
349
344
|
context = {}
|
|
350
345
|
) {
|
|
346
|
+
const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
|
|
351
347
|
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
352
348
|
|
|
353
349
|
if (file) {
|
|
354
|
-
// TODO: 如何触发这种场景?
|
|
355
|
-
const info = await states.node.read();
|
|
356
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
357
|
-
throw new Error("Can't install component in serverless-mode server via upload");
|
|
358
|
-
}
|
|
359
|
-
|
|
360
350
|
return this._installComponentFromUpload({
|
|
361
351
|
rootDid,
|
|
362
352
|
mountPoint,
|
|
@@ -370,11 +360,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
370
360
|
}
|
|
371
361
|
|
|
372
362
|
if (url) {
|
|
373
|
-
const info = await states.node.read();
|
|
374
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
375
|
-
validateStore(info, url);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
363
|
return this._installComponentFromUrl({
|
|
379
364
|
rootDid,
|
|
380
365
|
mountPoint,
|
|
@@ -446,6 +431,25 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
446
431
|
return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
|
|
447
432
|
}
|
|
448
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
|
+
|
|
449
453
|
async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
|
|
450
454
|
logger.info('start blocklet', { did });
|
|
451
455
|
// should check blocklet integrity
|
|
@@ -627,7 +631,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
627
631
|
// FIXME: 需要改成队列执行,本次失败,下次还需要重试,页面刷新后也能知道最新的状态
|
|
628
632
|
await this._installFromBackup({
|
|
629
633
|
url: `file://${spacesRestore.blockletRestoreDir}`,
|
|
630
|
-
|
|
634
|
+
blockletSecretKey: spacesRestore.blockletWallet.secretKey,
|
|
631
635
|
moveDir: true,
|
|
632
636
|
});
|
|
633
637
|
}
|
|
@@ -1000,7 +1004,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1000
1004
|
}
|
|
1001
1005
|
|
|
1002
1006
|
// eslint-disable-next-line no-unused-vars
|
|
1003
|
-
async config({ did, configs: newConfigs, skipHook
|
|
1007
|
+
async config({ did, configs: newConfigs, skipHook }, context) {
|
|
1004
1008
|
if (!Array.isArray(newConfigs)) {
|
|
1005
1009
|
throw new Error('configs list is not an array');
|
|
1006
1010
|
}
|
|
@@ -1060,7 +1064,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1060
1064
|
[BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK, BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_WALLET_TYPE].includes(item.key)
|
|
1061
1065
|
);
|
|
1062
1066
|
|
|
1063
|
-
if (isSkOrWalletTypeChanged
|
|
1067
|
+
if (isSkOrWalletTypeChanged) {
|
|
1064
1068
|
await this._updateDidDocument(blocklet);
|
|
1065
1069
|
}
|
|
1066
1070
|
|
|
@@ -1193,8 +1197,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1193
1197
|
return this.getBlocklet(rootDid);
|
|
1194
1198
|
}
|
|
1195
1199
|
|
|
1196
|
-
async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint }, context) {
|
|
1197
|
-
await mountPointSchema.validateAsync(
|
|
1200
|
+
async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint: tmpMountPoint }, context) {
|
|
1201
|
+
const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
|
|
1198
1202
|
|
|
1199
1203
|
const blocklet = await states.blocklet.getBlocklet(inputRootDid);
|
|
1200
1204
|
|
|
@@ -1675,13 +1679,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1675
1679
|
* /blocklet.json
|
|
1676
1680
|
* /blocklet_extras.json
|
|
1677
1681
|
* @see Blocklet 端到端备份方案的设计与实现(一期) https://team.arcblock.io/comment/discussions/e62084d5-fafa-489e-91d5-defcd6e93223
|
|
1678
|
-
* @param {{ url: string,
|
|
1682
|
+
* @param {{ url: string, blockletSecretKey: string, moveDir: boolean}} [{ url }={}]
|
|
1679
1683
|
* @param {Record<string, string>} [context={}]
|
|
1680
1684
|
* @return {Promise<any>}
|
|
1681
1685
|
* @memberof BlockletManager
|
|
1682
1686
|
*/
|
|
1683
|
-
async _installFromBackup({ url,
|
|
1684
|
-
return installFromBackup({ url,
|
|
1687
|
+
async _installFromBackup({ url, blockletSecretKey, moveDir } = {}, context = {}) {
|
|
1688
|
+
return installFromBackup({ url, blockletSecretKey, moveDir, context, manager: this, states });
|
|
1685
1689
|
}
|
|
1686
1690
|
|
|
1687
1691
|
async ensureBlocklet(did, opts = {}) {
|
|
@@ -2080,18 +2084,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2080
2084
|
*
|
|
2081
2085
|
* @param {{
|
|
2082
2086
|
* did: string;
|
|
2087
|
+
* registry: string;
|
|
2083
2088
|
* sync: boolean;
|
|
2084
2089
|
* delay: number;
|
|
2085
2090
|
* controller: Controller;
|
|
2086
|
-
* appSk: string;
|
|
2087
|
-
* storeUrl: string;
|
|
2088
2091
|
* }} params
|
|
2089
2092
|
* @param {*} context
|
|
2090
2093
|
* @return {*}
|
|
2091
2094
|
* @memberof BlockletManager
|
|
2092
2095
|
*/
|
|
2093
2096
|
async _installFromStore(params, context) {
|
|
2094
|
-
const { did, storeUrl, sync, delay, controller
|
|
2097
|
+
const { did, storeUrl, sync, delay, controller } = params;
|
|
2095
2098
|
|
|
2096
2099
|
logger.debug('start install blocklet', { did });
|
|
2097
2100
|
if (!isValidDid(did)) {
|
|
@@ -2135,7 +2138,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2135
2138
|
sync,
|
|
2136
2139
|
delay,
|
|
2137
2140
|
controller,
|
|
2138
|
-
appSk,
|
|
2139
2141
|
context,
|
|
2140
2142
|
});
|
|
2141
2143
|
}
|
|
@@ -2152,14 +2154,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2152
2154
|
* sync: boolean;
|
|
2153
2155
|
* delay: number;
|
|
2154
2156
|
* controller: Controller;
|
|
2155
|
-
* appSk: string;
|
|
2156
2157
|
* }} params
|
|
2157
2158
|
* @param {{}} context
|
|
2158
2159
|
* @return {*}
|
|
2159
2160
|
* @memberof BlockletManager
|
|
2160
2161
|
*/
|
|
2161
2162
|
async _installFromUrl(params, context) {
|
|
2162
|
-
const { url, sync, delay, controller
|
|
2163
|
+
const { url, sync, delay, controller } = params;
|
|
2163
2164
|
|
|
2164
2165
|
logger.debug('start install blocklet', { url });
|
|
2165
2166
|
|
|
@@ -2173,18 +2174,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2173
2174
|
|
|
2174
2175
|
// install from store if url is a store url
|
|
2175
2176
|
const { inStore, registryUrl, blockletDid: bundleDid } = await StoreUtil.parseSourceUrl(url, controller);
|
|
2176
|
-
|
|
2177
|
-
const nodeInfo = await states.node.read();
|
|
2178
|
-
|
|
2179
|
-
await validateStore(nodeInfo, registryUrl);
|
|
2180
|
-
|
|
2181
2177
|
if (inStore) {
|
|
2182
2178
|
const exist = await states.blocklet.getBlocklet(blockletDid);
|
|
2183
2179
|
if (exist) {
|
|
2184
2180
|
return this.upgrade({ did: blockletDid, storeUrl: registryUrl, sync, delay }, context);
|
|
2185
2181
|
}
|
|
2186
2182
|
|
|
2187
|
-
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay
|
|
2183
|
+
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay }, context);
|
|
2188
2184
|
}
|
|
2189
2185
|
|
|
2190
2186
|
const meta = ensureMeta(bundleMeta, { name: blockletName, did: blockletDid });
|
|
@@ -2210,7 +2206,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2210
2206
|
sync,
|
|
2211
2207
|
delay,
|
|
2212
2208
|
controller,
|
|
2213
|
-
appSk,
|
|
2214
2209
|
context,
|
|
2215
2210
|
});
|
|
2216
2211
|
}
|
|
@@ -2315,7 +2310,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2315
2310
|
);
|
|
2316
2311
|
}
|
|
2317
2312
|
|
|
2318
|
-
async _installFromCreate({ title, description
|
|
2313
|
+
async _installFromCreate({ title, description }, context = {}) {
|
|
2319
2314
|
logger.debug('create blocklet', { title, description });
|
|
2320
2315
|
|
|
2321
2316
|
await joi.string().label('title').max(20).required().validateAsync(title);
|
|
@@ -2343,9 +2338,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2343
2338
|
};
|
|
2344
2339
|
const meta = validateMeta(rawMeta);
|
|
2345
2340
|
|
|
2346
|
-
await states.blocklet.addBlocklet({
|
|
2341
|
+
await states.blocklet.addBlocklet({
|
|
2342
|
+
meta,
|
|
2343
|
+
source: BlockletSource.custom,
|
|
2344
|
+
});
|
|
2347
2345
|
await this._setConfigsFromMeta(did);
|
|
2348
|
-
await this._setAppSk(did, appSk);
|
|
2349
2346
|
|
|
2350
2347
|
// check duplicate appSk
|
|
2351
2348
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -2385,7 +2382,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2385
2382
|
return { cwd, tarFile };
|
|
2386
2383
|
}
|
|
2387
2384
|
|
|
2388
|
-
async _installFromUpload({ file, did, diffVersion, deleteSet,
|
|
2385
|
+
async _installFromUpload({ file, did, diffVersion, deleteSet, context }) {
|
|
2389
2386
|
logger.info('install blocklet', { from: 'upload file' });
|
|
2390
2387
|
const { tarFile } = await this._downloadFromUpload(file);
|
|
2391
2388
|
|
|
@@ -2483,7 +2480,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2483
2480
|
const oldState = { extraState: oldExtraState };
|
|
2484
2481
|
try {
|
|
2485
2482
|
await this._setConfigsFromMeta(meta.did);
|
|
2486
|
-
await this._setAppSk(appSk);
|
|
2487
2483
|
await validateBlocklet(blocklet);
|
|
2488
2484
|
|
|
2489
2485
|
// check duplicate appSk
|
|
@@ -2780,7 +2776,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2780
2776
|
* meta: {}; // blocklet meta
|
|
2781
2777
|
* source: number; // example: BlockletSource.registry,
|
|
2782
2778
|
* deployedFrom: string;
|
|
2783
|
-
* appSk: string;
|
|
2784
2779
|
* context: {}
|
|
2785
2780
|
* sync: boolean = false;
|
|
2786
2781
|
* delay: number;
|
|
@@ -2790,15 +2785,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2790
2785
|
* @memberof BlockletManager
|
|
2791
2786
|
*/
|
|
2792
2787
|
async _install(params) {
|
|
2793
|
-
const { meta, source, deployedFrom, context, sync, delay, controller
|
|
2788
|
+
const { meta, source, deployedFrom, context, sync, delay, controller } = params;
|
|
2794
2789
|
|
|
2795
2790
|
validateBlockletMeta(meta, { ensureDist: true });
|
|
2796
2791
|
|
|
2797
|
-
const info = await states.node.read();
|
|
2798
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
2799
|
-
validateInServerless({ blockletMeta: meta });
|
|
2800
|
-
}
|
|
2801
|
-
|
|
2802
2792
|
const { name, did, version } = meta;
|
|
2803
2793
|
|
|
2804
2794
|
const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
|
|
@@ -2818,7 +2808,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2818
2808
|
await states.blockletExtras.addMeta({ did, meta: { did, name }, controller });
|
|
2819
2809
|
|
|
2820
2810
|
await this._setConfigsFromMeta(did);
|
|
2821
|
-
await this._setAppSk(did, appSk);
|
|
2822
2811
|
|
|
2823
2812
|
// check duplicate appSk
|
|
2824
2813
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -3416,31 +3405,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3416
3405
|
}
|
|
3417
3406
|
}
|
|
3418
3407
|
|
|
3419
|
-
async _setAppSk(did, appSk, context) {
|
|
3420
|
-
if (process.env.NODE_ENV === 'production' && !appSk) {
|
|
3421
|
-
throw new Error(`appSk for blocklet ${did} is required`);
|
|
3422
|
-
}
|
|
3423
|
-
|
|
3424
|
-
if (appSk) {
|
|
3425
|
-
await this.config(
|
|
3426
|
-
{
|
|
3427
|
-
did,
|
|
3428
|
-
configs: [{ key: 'BLOCKLET_APP_SK', value: appSk, secure: true }],
|
|
3429
|
-
skipHook: true,
|
|
3430
|
-
skipDidDocument: true,
|
|
3431
|
-
},
|
|
3432
|
-
context
|
|
3433
|
-
);
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
|
|
3437
3408
|
async _findNextCustomBlockletName(leftTimes = 10) {
|
|
3438
3409
|
if (leftTimes <= 0) {
|
|
3439
3410
|
throw new Error('Generate custom blocklet did too many times');
|
|
3440
3411
|
}
|
|
3441
3412
|
const number = await states.node.increaseCustomBlockletNumber();
|
|
3442
3413
|
const name = `custom-${number}`;
|
|
3443
|
-
// MEMO: 空壳 APP可以保留原有的 did 生成逻辑
|
|
3444
3414
|
const did = toBlockletDid(name);
|
|
3445
3415
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
3446
3416
|
if (blocklet) {
|
|
@@ -19,7 +19,7 @@ const { validateBlocklet, checkDuplicateAppSk, getAppDirs } = require('../../../
|
|
|
19
19
|
* }} param0
|
|
20
20
|
* @returns
|
|
21
21
|
*/
|
|
22
|
-
module.exports = async ({ url,
|
|
22
|
+
module.exports = async ({ url, blockletSecretKey, moveDir, context = {}, states, manager } = {}) => {
|
|
23
23
|
// TODO: support more url schema feature (http, did-spaces)
|
|
24
24
|
if (!url.startsWith('file://')) {
|
|
25
25
|
throw new Error('url must starts with file://');
|
|
@@ -71,17 +71,17 @@ module.exports = async ({ url, appSk, moveDir, context = {}, states, manager } =
|
|
|
71
71
|
throw new Error('blocklet is already exist');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
if (
|
|
74
|
+
if (blockletSecretKey) {
|
|
75
75
|
extra.configs = extra.configs || [];
|
|
76
76
|
const skConfig = extra.configs.find((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK);
|
|
77
77
|
if (skConfig) {
|
|
78
|
-
skConfig.value =
|
|
78
|
+
skConfig.value = blockletSecretKey;
|
|
79
79
|
skConfig.secure = true;
|
|
80
80
|
skConfig.shared = false;
|
|
81
81
|
} else {
|
|
82
82
|
extra.configs.push({
|
|
83
83
|
key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK,
|
|
84
|
-
value:
|
|
84
|
+
value: blockletSecretKey,
|
|
85
85
|
secure: true,
|
|
86
86
|
shared: false,
|
|
87
87
|
});
|
|
@@ -150,10 +150,10 @@ class SpacesBackup {
|
|
|
150
150
|
const { errorCount } = await spaceClient.send(
|
|
151
151
|
new SyncFolderPushCommand({
|
|
152
152
|
source: join(this.blockletBackupDir, '/'),
|
|
153
|
-
target: join('.did-objects', this.blocklet.appDid
|
|
153
|
+
target: join('.did-objects', this.blocklet.appDid),
|
|
154
154
|
debug: true,
|
|
155
|
-
concurrency:
|
|
156
|
-
retryCount:
|
|
155
|
+
concurrency: 64,
|
|
156
|
+
retryCount: 100,
|
|
157
157
|
filter: (object) => {
|
|
158
158
|
return object.name !== '.DS_Store';
|
|
159
159
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { existsSync, remove
|
|
1
|
+
const { existsSync, remove } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const fg = require('fast-glob');
|
|
4
4
|
const { BaseRestore } = require('./base');
|
|
@@ -10,11 +10,8 @@ class BlockletsRestore extends BaseRestore {
|
|
|
10
10
|
async import() {
|
|
11
11
|
const blockletsDir = join(this.blockletRestoreDir, this.filename);
|
|
12
12
|
|
|
13
|
-
// blockletsDir 可以不存在, 因为还原的 blocklet 可能所有的组件都是来自 store 的
|
|
14
13
|
if (!existsSync(blockletsDir)) {
|
|
15
|
-
|
|
16
|
-
ensureDirSync(blockletsDir);
|
|
17
|
-
return;
|
|
14
|
+
throw new Error(`dir not found: ${blockletsDir}`);
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
const paths = await fg('**/*.zip', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {{
|
|
3
3
|
* endpoint: string;
|
|
4
|
-
*
|
|
4
|
+
* blockletSecretKey: string;
|
|
5
5
|
* }} SpaceRestoreInput
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -98,7 +98,7 @@ class SpacesRestore {
|
|
|
98
98
|
|
|
99
99
|
async getBlockletWallet() {
|
|
100
100
|
// @FIXME: blocklet 钱包类型如何得知呢?
|
|
101
|
-
const wallet = fromSecretKey(this.input.
|
|
101
|
+
const wallet = fromSecretKey(this.input.blockletSecretKey, WalletType({ role: types.RoleType.ROLE_APPLICATION }));
|
|
102
102
|
|
|
103
103
|
return wallet;
|
|
104
104
|
}
|
|
@@ -115,10 +115,10 @@ class SpacesRestore {
|
|
|
115
115
|
const { errorCount } = await spaceClient.send(
|
|
116
116
|
new SyncFolderPullCommand({
|
|
117
117
|
source: join('.did-objects', this.blockletWallet.address, '/'),
|
|
118
|
-
target:
|
|
118
|
+
target: this.blockletRestoreDir,
|
|
119
119
|
debug: true,
|
|
120
|
-
concurrency:
|
|
121
|
-
retryCount:
|
|
120
|
+
concurrency: 64,
|
|
121
|
+
retryCount: 100,
|
|
122
122
|
})
|
|
123
123
|
);
|
|
124
124
|
|
package/lib/event.js
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = ({
|
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
const
|
|
84
|
+
const handleBlockletAdd = async (name, { blocklet, context }) => {
|
|
85
85
|
try {
|
|
86
86
|
const changed = await ensureBlockletRouting(blocklet, context);
|
|
87
87
|
if (changed) {
|
|
@@ -173,7 +173,7 @@ module.exports = ({
|
|
|
173
173
|
const blocklet = payload.blocklet || payload;
|
|
174
174
|
|
|
175
175
|
if ([BlockletEvents.installed].includes(eventName)) {
|
|
176
|
-
await
|
|
176
|
+
await handleBlockletAdd(eventName, payload);
|
|
177
177
|
|
|
178
178
|
try {
|
|
179
179
|
await node.createAuditLog({
|
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",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"pm2": "^5.2.0",
|
|
73
73
|
"semver": "^7.3.8",
|
|
74
74
|
"shelljs": "^0.8.5",
|
|
75
|
+
"slugify": "^1.6.5",
|
|
75
76
|
"ssri": "^8.0.1",
|
|
76
77
|
"stream-throttle": "^0.1.3",
|
|
77
78
|
"stream-to-promise": "^3.0.0",
|
|
@@ -89,5 +90,5 @@
|
|
|
89
90
|
"express": "^4.18.2",
|
|
90
91
|
"jest": "^27.5.1"
|
|
91
92
|
},
|
|
92
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "282247fd0ce6702e1d6920e90e2b3be0408cf879"
|
|
93
94
|
}
|