@abtnode/core 1.8.66-beta-ff281dd5 → 1.8.66-beta-b56e3b54
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 +75 -45
- package/lib/blocklet/manager/helper/install-from-backup.js +4 -4
- package/lib/blocklet/storage/backup/spaces.js +2 -2
- package/lib/blocklet/storage/restore/blocklets.js +5 -2
- package/lib/blocklet/storage/restore/spaces.js +4 -4
- package/lib/event.js +2 -2
- package/lib/index.js +0 -1
- package/lib/router/helper.js +1 -1
- package/lib/states/node.js +1 -1
- package/lib/util/blocklet.js +43 -8
- package/package.json +26 -27
|
@@ -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
|
+
* appSk: 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}>;
|
|
@@ -278,28 +280,31 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
278
280
|
context.startImmediately = !!params.startImmediately;
|
|
279
281
|
}
|
|
280
282
|
|
|
283
|
+
const { appSk } = params;
|
|
284
|
+
|
|
281
285
|
if (type === BLOCKLET_INSTALL_TYPE.URL) {
|
|
282
286
|
const { url, controller, sync, delay } = params;
|
|
283
|
-
return this._installFromUrl({ url, controller, sync, delay }, context);
|
|
287
|
+
return this._installFromUrl({ url, controller, sync, delay, appSk }, context);
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
if (type === BLOCKLET_INSTALL_TYPE.UPLOAD) {
|
|
287
291
|
const { file, did, diffVersion, deleteSet } = params;
|
|
288
|
-
return this._installFromUpload({ file, did, diffVersion, deleteSet,
|
|
292
|
+
return this._installFromUpload({ file, did, diffVersion, deleteSet, appSk }, context);
|
|
289
293
|
}
|
|
290
294
|
|
|
291
295
|
if (type === BLOCKLET_INSTALL_TYPE.STORE) {
|
|
292
296
|
const { did, controller, sync, delay, storeUrl } = params;
|
|
293
|
-
return this._installFromStore({ did, controller, sync, delay, storeUrl }, context);
|
|
297
|
+
return this._installFromStore({ did, controller, sync, delay, storeUrl, appSk }, context);
|
|
294
298
|
}
|
|
295
299
|
|
|
296
300
|
if (type === BLOCKLET_INSTALL_TYPE.CREATE) {
|
|
297
|
-
|
|
301
|
+
const { title, description } = params;
|
|
302
|
+
return this._installFromCreate({ title, description, appSk }, context);
|
|
298
303
|
}
|
|
299
304
|
|
|
300
305
|
if (type === BLOCKLET_INSTALL_TYPE.RESTORE) {
|
|
301
|
-
const { url
|
|
302
|
-
return this._installFromBackup({ url,
|
|
306
|
+
const { url } = params;
|
|
307
|
+
return this._installFromBackup({ url, appSk }, context);
|
|
303
308
|
}
|
|
304
309
|
|
|
305
310
|
// should not be here
|
|
@@ -346,6 +351,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
346
351
|
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
347
352
|
|
|
348
353
|
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
|
+
|
|
349
360
|
return this._installComponentFromUpload({
|
|
350
361
|
rootDid,
|
|
351
362
|
mountPoint,
|
|
@@ -359,6 +370,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
359
370
|
}
|
|
360
371
|
|
|
361
372
|
if (url) {
|
|
373
|
+
const info = await states.node.read();
|
|
374
|
+
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
375
|
+
validateStore(info, url);
|
|
376
|
+
}
|
|
377
|
+
|
|
362
378
|
return this._installComponentFromUrl({
|
|
363
379
|
rootDid,
|
|
364
380
|
mountPoint,
|
|
@@ -430,25 +446,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
430
446
|
return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
|
|
431
447
|
}
|
|
432
448
|
|
|
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
449
|
async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
|
|
453
450
|
logger.info('start blocklet', { did });
|
|
454
451
|
// should check blocklet integrity
|
|
@@ -630,7 +627,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
630
627
|
// FIXME: 需要改成队列执行,本次失败,下次还需要重试,页面刷新后也能知道最新的状态
|
|
631
628
|
await this._installFromBackup({
|
|
632
629
|
url: `file://${spacesRestore.blockletRestoreDir}`,
|
|
633
|
-
|
|
630
|
+
appSk: spacesRestore.blockletWallet.secretKey,
|
|
634
631
|
moveDir: true,
|
|
635
632
|
});
|
|
636
633
|
}
|
|
@@ -1003,7 +1000,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1003
1000
|
}
|
|
1004
1001
|
|
|
1005
1002
|
// eslint-disable-next-line no-unused-vars
|
|
1006
|
-
async config({ did, configs: newConfigs, skipHook }, context) {
|
|
1003
|
+
async config({ did, configs: newConfigs, skipHook, skipDidDocument }, context) {
|
|
1007
1004
|
if (!Array.isArray(newConfigs)) {
|
|
1008
1005
|
throw new Error('configs list is not an array');
|
|
1009
1006
|
}
|
|
@@ -1063,7 +1060,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1063
1060
|
[BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK, BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_WALLET_TYPE].includes(item.key)
|
|
1064
1061
|
);
|
|
1065
1062
|
|
|
1066
|
-
if (isSkOrWalletTypeChanged) {
|
|
1063
|
+
if (isSkOrWalletTypeChanged && !skipDidDocument) {
|
|
1067
1064
|
await this._updateDidDocument(blocklet);
|
|
1068
1065
|
}
|
|
1069
1066
|
|
|
@@ -1678,13 +1675,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1678
1675
|
* /blocklet.json
|
|
1679
1676
|
* /blocklet_extras.json
|
|
1680
1677
|
* @see Blocklet 端到端备份方案的设计与实现(一期) https://team.arcblock.io/comment/discussions/e62084d5-fafa-489e-91d5-defcd6e93223
|
|
1681
|
-
* @param {{ url: string,
|
|
1678
|
+
* @param {{ url: string, appSk: string, moveDir: boolean}} [{ url }={}]
|
|
1682
1679
|
* @param {Record<string, string>} [context={}]
|
|
1683
1680
|
* @return {Promise<any>}
|
|
1684
1681
|
* @memberof BlockletManager
|
|
1685
1682
|
*/
|
|
1686
|
-
async _installFromBackup({ url,
|
|
1687
|
-
return installFromBackup({ url,
|
|
1683
|
+
async _installFromBackup({ url, appSk, moveDir } = {}, context = {}) {
|
|
1684
|
+
return installFromBackup({ url, appSk, moveDir, context, manager: this, states });
|
|
1688
1685
|
}
|
|
1689
1686
|
|
|
1690
1687
|
async ensureBlocklet(did, opts = {}) {
|
|
@@ -2083,17 +2080,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2083
2080
|
*
|
|
2084
2081
|
* @param {{
|
|
2085
2082
|
* did: string;
|
|
2086
|
-
* registry: string;
|
|
2087
2083
|
* sync: boolean;
|
|
2088
2084
|
* delay: number;
|
|
2089
2085
|
* controller: Controller;
|
|
2086
|
+
* appSk: string;
|
|
2087
|
+
* storeUrl: string;
|
|
2090
2088
|
* }} params
|
|
2091
2089
|
* @param {*} context
|
|
2092
2090
|
* @return {*}
|
|
2093
2091
|
* @memberof BlockletManager
|
|
2094
2092
|
*/
|
|
2095
2093
|
async _installFromStore(params, context) {
|
|
2096
|
-
const { did, storeUrl, sync, delay, controller } = params;
|
|
2094
|
+
const { did, storeUrl, sync, delay, controller, appSk } = params;
|
|
2097
2095
|
|
|
2098
2096
|
logger.debug('start install blocklet', { did });
|
|
2099
2097
|
if (!isValidDid(did)) {
|
|
@@ -2137,6 +2135,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2137
2135
|
sync,
|
|
2138
2136
|
delay,
|
|
2139
2137
|
controller,
|
|
2138
|
+
appSk,
|
|
2140
2139
|
context,
|
|
2141
2140
|
});
|
|
2142
2141
|
}
|
|
@@ -2153,13 +2152,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2153
2152
|
* sync: boolean;
|
|
2154
2153
|
* delay: number;
|
|
2155
2154
|
* controller: Controller;
|
|
2155
|
+
* appSk: string;
|
|
2156
2156
|
* }} params
|
|
2157
2157
|
* @param {{}} context
|
|
2158
2158
|
* @return {*}
|
|
2159
2159
|
* @memberof BlockletManager
|
|
2160
2160
|
*/
|
|
2161
2161
|
async _installFromUrl(params, context) {
|
|
2162
|
-
const { url, sync, delay, controller } = params;
|
|
2162
|
+
const { url, sync, delay, controller, appSk } = params;
|
|
2163
2163
|
|
|
2164
2164
|
logger.debug('start install blocklet', { url });
|
|
2165
2165
|
|
|
@@ -2173,13 +2173,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2173
2173
|
|
|
2174
2174
|
// install from store if url is a store url
|
|
2175
2175
|
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
|
+
|
|
2176
2181
|
if (inStore) {
|
|
2177
2182
|
const exist = await states.blocklet.getBlocklet(blockletDid);
|
|
2178
2183
|
if (exist) {
|
|
2179
2184
|
return this.upgrade({ did: blockletDid, storeUrl: registryUrl, sync, delay }, context);
|
|
2180
2185
|
}
|
|
2181
2186
|
|
|
2182
|
-
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay }, context);
|
|
2187
|
+
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay, appSk }, context);
|
|
2183
2188
|
}
|
|
2184
2189
|
|
|
2185
2190
|
const meta = ensureMeta(bundleMeta, { name: blockletName, did: blockletDid });
|
|
@@ -2205,6 +2210,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2205
2210
|
sync,
|
|
2206
2211
|
delay,
|
|
2207
2212
|
controller,
|
|
2213
|
+
appSk,
|
|
2208
2214
|
context,
|
|
2209
2215
|
});
|
|
2210
2216
|
}
|
|
@@ -2309,7 +2315,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2309
2315
|
);
|
|
2310
2316
|
}
|
|
2311
2317
|
|
|
2312
|
-
async _installFromCreate({ title, description }, context = {}) {
|
|
2318
|
+
async _installFromCreate({ title, description, appSk }, context = {}) {
|
|
2313
2319
|
logger.debug('create blocklet', { title, description });
|
|
2314
2320
|
|
|
2315
2321
|
await joi.string().label('title').max(20).required().validateAsync(title);
|
|
@@ -2337,11 +2343,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2337
2343
|
};
|
|
2338
2344
|
const meta = validateMeta(rawMeta);
|
|
2339
2345
|
|
|
2340
|
-
await states.blocklet.addBlocklet({
|
|
2341
|
-
meta,
|
|
2342
|
-
source: BlockletSource.custom,
|
|
2343
|
-
});
|
|
2346
|
+
await states.blocklet.addBlocklet({ meta, source: BlockletSource.custom });
|
|
2344
2347
|
await this._setConfigsFromMeta(did);
|
|
2348
|
+
await this._setAppSk(did, appSk);
|
|
2345
2349
|
|
|
2346
2350
|
// check duplicate appSk
|
|
2347
2351
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -2381,7 +2385,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2381
2385
|
return { cwd, tarFile };
|
|
2382
2386
|
}
|
|
2383
2387
|
|
|
2384
|
-
async _installFromUpload({ file, did, diffVersion, deleteSet,
|
|
2388
|
+
async _installFromUpload({ file, did, diffVersion, deleteSet, appSk }, context) {
|
|
2385
2389
|
logger.info('install blocklet', { from: 'upload file' });
|
|
2386
2390
|
const { tarFile } = await this._downloadFromUpload(file);
|
|
2387
2391
|
|
|
@@ -2479,6 +2483,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2479
2483
|
const oldState = { extraState: oldExtraState };
|
|
2480
2484
|
try {
|
|
2481
2485
|
await this._setConfigsFromMeta(meta.did);
|
|
2486
|
+
await this._setAppSk(appSk);
|
|
2482
2487
|
await validateBlocklet(blocklet);
|
|
2483
2488
|
|
|
2484
2489
|
// check duplicate appSk
|
|
@@ -2775,6 +2780,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2775
2780
|
* meta: {}; // blocklet meta
|
|
2776
2781
|
* source: number; // example: BlockletSource.registry,
|
|
2777
2782
|
* deployedFrom: string;
|
|
2783
|
+
* appSk: string;
|
|
2778
2784
|
* context: {}
|
|
2779
2785
|
* sync: boolean = false;
|
|
2780
2786
|
* delay: number;
|
|
@@ -2784,10 +2790,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2784
2790
|
* @memberof BlockletManager
|
|
2785
2791
|
*/
|
|
2786
2792
|
async _install(params) {
|
|
2787
|
-
const { meta, source, deployedFrom, context, sync, delay, controller } = params;
|
|
2793
|
+
const { meta, source, deployedFrom, context, sync, delay, controller, appSk } = params;
|
|
2788
2794
|
|
|
2789
2795
|
validateBlockletMeta(meta, { ensureDist: true });
|
|
2790
2796
|
|
|
2797
|
+
const info = await states.node.read();
|
|
2798
|
+
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
2799
|
+
validateInServerless({ blockletMeta: meta });
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2791
2802
|
const { name, did, version } = meta;
|
|
2792
2803
|
|
|
2793
2804
|
const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
|
|
@@ -2807,6 +2818,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2807
2818
|
await states.blockletExtras.addMeta({ did, meta: { did, name }, controller });
|
|
2808
2819
|
|
|
2809
2820
|
await this._setConfigsFromMeta(did);
|
|
2821
|
+
await this._setAppSk(did, appSk);
|
|
2810
2822
|
|
|
2811
2823
|
// check duplicate appSk
|
|
2812
2824
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -3404,6 +3416,24 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3404
3416
|
}
|
|
3405
3417
|
}
|
|
3406
3418
|
|
|
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
|
+
|
|
3407
3437
|
async _findNextCustomBlockletName(leftTimes = 10) {
|
|
3408
3438
|
if (leftTimes <= 0) {
|
|
3409
3439
|
throw new Error('Generate custom blocklet did too many times');
|
|
@@ -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, appSk, 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, blockletSecretKey, moveDir, context = {}, states,
|
|
|
71
71
|
throw new Error('blocklet is already exist');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
if (
|
|
74
|
+
if (appSk) {
|
|
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 = appSk;
|
|
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: appSk,
|
|
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
155
|
concurrency: 32,
|
|
156
|
-
retryCount:
|
|
156
|
+
retryCount: 10,
|
|
157
157
|
filter: (object) => {
|
|
158
158
|
return object.name !== '.DS_Store';
|
|
159
159
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { existsSync, remove } = require('fs-extra');
|
|
1
|
+
const { existsSync, remove, ensureDirSync } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const fg = require('fast-glob');
|
|
4
4
|
const { BaseRestore } = require('./base');
|
|
@@ -10,8 +10,11 @@ class BlockletsRestore extends BaseRestore {
|
|
|
10
10
|
async import() {
|
|
11
11
|
const blockletsDir = join(this.blockletRestoreDir, this.filename);
|
|
12
12
|
|
|
13
|
+
// blockletsDir 可以不存在, 因为还原的 blocklet 可能所有的组件都是来自 store 的
|
|
13
14
|
if (!existsSync(blockletsDir)) {
|
|
14
|
-
|
|
15
|
+
// FIXME: 如果文件夹不存在,需要创建文件夹,因为 installFromBackup 未做容错处理
|
|
16
|
+
ensureDirSync(blockletsDir);
|
|
17
|
+
return;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
const paths = await fg('**/*.zip', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {{
|
|
3
3
|
* endpoint: string;
|
|
4
|
-
*
|
|
4
|
+
* appSk: 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.appSk, 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: this.blockletRestoreDir,
|
|
118
|
+
target: join(this.blockletRestoreDir, '/'),
|
|
119
119
|
debug: true,
|
|
120
120
|
concurrency: 32,
|
|
121
|
-
retryCount:
|
|
121
|
+
retryCount: 10,
|
|
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 handleBlockletInstall = 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 handleBlockletInstall(eventName, payload);
|
|
177
177
|
|
|
178
178
|
try {
|
|
179
179
|
await node.createAuditLog({
|
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),
|
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 || get(cert, 'meta.validTo') <= Date.now()) {
|
|
522
522
|
await downloadCert({
|
|
523
523
|
domain,
|
|
524
524
|
url,
|
package/lib/states/node.js
CHANGED
package/lib/util/blocklet.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
1404
|
-
blocklet.settings.storeList.
|
|
1405
|
-
|
|
1406
|
-
|
|
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.66-beta-
|
|
6
|
+
"version": "1.8.66-beta-b56e3b54",
|
|
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-
|
|
23
|
-
"@abtnode/certificate-manager": "1.8.66-beta-
|
|
24
|
-
"@abtnode/constant": "1.8.66-beta-
|
|
25
|
-
"@abtnode/cron": "1.8.66-beta-
|
|
26
|
-
"@abtnode/db": "1.8.66-beta-
|
|
27
|
-
"@abtnode/logger": "1.8.66-beta-
|
|
28
|
-
"@abtnode/queue": "1.8.66-beta-
|
|
29
|
-
"@abtnode/rbac": "1.8.66-beta-
|
|
30
|
-
"@abtnode/router-provider": "1.8.66-beta-
|
|
31
|
-
"@abtnode/static-server": "1.8.66-beta-
|
|
32
|
-
"@abtnode/timemachine": "1.8.66-beta-
|
|
33
|
-
"@abtnode/util": "1.8.66-beta-
|
|
34
|
-
"@arcblock/did": "1.18.
|
|
22
|
+
"@abtnode/auth": "1.8.66-beta-b56e3b54",
|
|
23
|
+
"@abtnode/certificate-manager": "1.8.66-beta-b56e3b54",
|
|
24
|
+
"@abtnode/constant": "1.8.66-beta-b56e3b54",
|
|
25
|
+
"@abtnode/cron": "1.8.66-beta-b56e3b54",
|
|
26
|
+
"@abtnode/db": "1.8.66-beta-b56e3b54",
|
|
27
|
+
"@abtnode/logger": "1.8.66-beta-b56e3b54",
|
|
28
|
+
"@abtnode/queue": "1.8.66-beta-b56e3b54",
|
|
29
|
+
"@abtnode/rbac": "1.8.66-beta-b56e3b54",
|
|
30
|
+
"@abtnode/router-provider": "1.8.66-beta-b56e3b54",
|
|
31
|
+
"@abtnode/static-server": "1.8.66-beta-b56e3b54",
|
|
32
|
+
"@abtnode/timemachine": "1.8.66-beta-b56e3b54",
|
|
33
|
+
"@abtnode/util": "1.8.66-beta-b56e3b54",
|
|
34
|
+
"@arcblock/did": "1.18.52",
|
|
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.52",
|
|
37
|
+
"@arcblock/event-hub": "1.18.52",
|
|
38
|
+
"@arcblock/jwt": "^1.18.52",
|
|
39
39
|
"@arcblock/pm2-events": "^0.0.5",
|
|
40
|
-
"@arcblock/vc": "1.18.
|
|
41
|
-
"@blocklet/constant": "1.8.66-beta-
|
|
42
|
-
"@blocklet/meta": "1.8.66-beta-
|
|
43
|
-
"@blocklet/sdk": "1.8.66-beta-
|
|
44
|
-
"@did-space/client": "^0.1.
|
|
40
|
+
"@arcblock/vc": "1.18.52",
|
|
41
|
+
"@blocklet/constant": "1.8.66-beta-b56e3b54",
|
|
42
|
+
"@blocklet/meta": "1.8.66-beta-b56e3b54",
|
|
43
|
+
"@blocklet/sdk": "1.8.66-beta-b56e3b54",
|
|
44
|
+
"@did-space/client": "^0.1.76",
|
|
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.52",
|
|
47
|
+
"@ocap/util": "1.18.52",
|
|
48
|
+
"@ocap/wallet": "1.18.52",
|
|
49
49
|
"@slack/webhook": "^5.0.4",
|
|
50
50
|
"archiver": "^5.3.1",
|
|
51
51
|
"axios": "^0.27.2",
|
|
@@ -72,7 +72,6 @@
|
|
|
72
72
|
"pm2": "^5.2.0",
|
|
73
73
|
"semver": "^7.3.8",
|
|
74
74
|
"shelljs": "^0.8.5",
|
|
75
|
-
"slugify": "^1.6.5",
|
|
76
75
|
"ssri": "^8.0.1",
|
|
77
76
|
"stream-throttle": "^0.1.3",
|
|
78
77
|
"stream-to-promise": "^3.0.0",
|
|
@@ -90,5 +89,5 @@
|
|
|
90
89
|
"express": "^4.18.2",
|
|
91
90
|
"jest": "^27.5.1"
|
|
92
91
|
},
|
|
93
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "4d95b431526128c14cd04c0741cac423afce8f48"
|
|
94
93
|
}
|