@abtnode/core 1.8.0 → 1.8.3
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/api/node.js +14 -1
- package/lib/blocklet/manager/disk.js +92 -10
- package/lib/cert.js +10 -5
- package/lib/event.js +56 -0
- package/lib/index.js +17 -15
- package/lib/router/helper.js +2 -1
- package/lib/router/manager.js +0 -34
- package/lib/states/audit-log.js +28 -7
- package/lib/states/blocklet.js +16 -0
- package/lib/states/node.js +8 -0
- package/lib/states/session.js +7 -1
- package/lib/util/blocklet.js +22 -6
- package/lib/util/index.js +4 -1
- package/lib/util/public-to-store.js +85 -0
- package/lib/validators/router.js +1 -1
- package/package.json +24 -24
package/lib/api/node.js
CHANGED
|
@@ -7,6 +7,7 @@ const isGitpod = require('@abtnode/util/lib/is-gitpod');
|
|
|
7
7
|
const getFolderSize = require('@abtnode/util/lib/get-folder-size');
|
|
8
8
|
const canPackageReadWrite = require('@abtnode/util/lib/can-pkg-rw');
|
|
9
9
|
const { toDelegateAddress } = require('@arcblock/did-util');
|
|
10
|
+
const { STORE_DETAIL_PAGE_PATH_PREFIX } = require('@abtnode/constant');
|
|
10
11
|
|
|
11
12
|
const logger = require('@abtnode/logger')('@abtnode/core:api:node');
|
|
12
13
|
|
|
@@ -40,7 +41,19 @@ class NodeAPI {
|
|
|
40
41
|
// eslint-disable-next-line no-unused-vars
|
|
41
42
|
async addRegistry({ url }, context) {
|
|
42
43
|
logger.info('add registry', { url });
|
|
43
|
-
|
|
44
|
+
|
|
45
|
+
const urlObj = new URL(url);
|
|
46
|
+
let newUrl = urlObj.origin;
|
|
47
|
+
|
|
48
|
+
// if the pathname is store blocklet list or blocklet detail
|
|
49
|
+
if (urlObj.pathname?.includes(STORE_DETAIL_PAGE_PATH_PREFIX)) {
|
|
50
|
+
const lastIndex = urlObj.pathname.lastIndexOf(STORE_DETAIL_PAGE_PATH_PREFIX);
|
|
51
|
+
const pathnamePrefix = urlObj.pathname.substring(0, lastIndex);
|
|
52
|
+
newUrl = `${newUrl}${pathnamePrefix || ''}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const sanitized = sanitizeUrl(newUrl);
|
|
56
|
+
|
|
44
57
|
const info = await this.state.read();
|
|
45
58
|
const exist = info.blockletRegistryList.find((x) => x.url === sanitized);
|
|
46
59
|
if (exist) {
|
|
@@ -22,7 +22,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
|
|
|
22
22
|
const downloadFile = require('@abtnode/util/lib/download-file');
|
|
23
23
|
const Lock = require('@abtnode/util/lib/lock');
|
|
24
24
|
const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
|
|
25
|
-
const { VC_TYPE_BLOCKLET_PURCHASE } = require('@abtnode/constant');
|
|
25
|
+
const { VC_TYPE_BLOCKLET_PURCHASE, WHO_CAN_ACCESS } = require('@abtnode/constant');
|
|
26
26
|
|
|
27
27
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
28
28
|
const {
|
|
@@ -115,6 +115,7 @@ const { getFactoryState } = require('../../util/chain');
|
|
|
115
115
|
const runMigrationScripts = require('../migration');
|
|
116
116
|
const hooks = require('../hooks');
|
|
117
117
|
const { formatName } = require('../../util/get-domain-for-blocklet');
|
|
118
|
+
const handleInstanceInStore = require('../../util/public-to-store');
|
|
118
119
|
|
|
119
120
|
const {
|
|
120
121
|
isInProgress,
|
|
@@ -216,6 +217,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
216
217
|
* @param {{
|
|
217
218
|
* url: string;
|
|
218
219
|
* sync: boolean = false;
|
|
220
|
+
* downloadToken: string;
|
|
219
221
|
* }} params
|
|
220
222
|
* @param {{
|
|
221
223
|
* [key: string]: any
|
|
@@ -223,9 +225,24 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
223
225
|
* @return {*}
|
|
224
226
|
* @memberof BlockletManager
|
|
225
227
|
*/
|
|
226
|
-
async install(params, context) {
|
|
228
|
+
async install(params, context = {}) {
|
|
227
229
|
logger.debug('install blocklet', { params, context });
|
|
228
230
|
|
|
231
|
+
if (params.downloadToken) {
|
|
232
|
+
const info = await states.node.read();
|
|
233
|
+
|
|
234
|
+
context.headers = Object.assign(context?.headers || {}, {
|
|
235
|
+
'x-server-did': info.did,
|
|
236
|
+
'x-download-token': params.downloadToken,
|
|
237
|
+
// FIXME: 先保证兼容性,后续删除
|
|
238
|
+
'x-server-publick-key': info.pk,
|
|
239
|
+
'x-server-public-key': info.pk,
|
|
240
|
+
'x-server-signature': sign(info.did, info.sk, {
|
|
241
|
+
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
242
|
+
}),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
229
246
|
const source = getSourceFromInstallParams(params);
|
|
230
247
|
if (typeof context.startImmediately === 'undefined') {
|
|
231
248
|
context.startImmediately = !!params.startImmediately;
|
|
@@ -319,10 +336,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
319
336
|
}
|
|
320
337
|
}
|
|
321
338
|
|
|
339
|
+
const { inStore, registryUrl } = await parseSourceUrl(url);
|
|
340
|
+
|
|
322
341
|
const blocklet = await states.blocklet.getBlocklet(meta.did);
|
|
323
342
|
const isRunning = blocklet ? blocklet.status === BlockletStatus.running : false;
|
|
324
343
|
|
|
325
|
-
return { meta, isFree, isInstalled: !!blocklet, isRunning };
|
|
344
|
+
return { meta, isFree, isInstalled: !!blocklet, isRunning, inStore, registryUrl };
|
|
326
345
|
}
|
|
327
346
|
|
|
328
347
|
async installBlockletFromVc({ vcPresentation, challenge }, context) {
|
|
@@ -423,7 +442,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
423
442
|
|
|
424
443
|
await this.deleteProcess({ did });
|
|
425
444
|
const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
|
|
426
|
-
this.emit(BlockletEvents.startFailed, res);
|
|
445
|
+
this.emit(BlockletEvents.startFailed, { ...res, error: { message: error.message } });
|
|
427
446
|
|
|
428
447
|
if (throwOnError) {
|
|
429
448
|
throw new Error(description);
|
|
@@ -601,7 +620,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
601
620
|
async deleteComponent({ did, rootDid, keepData, keepState }, context) {
|
|
602
621
|
logger.info('delete blocklet component', { did, rootDid, keepData });
|
|
603
622
|
|
|
604
|
-
const blocklet = await this.ensureBlocklet(rootDid);
|
|
623
|
+
const blocklet = await this.ensureBlocklet(rootDid, { validateEnv: false });
|
|
605
624
|
const child = blocklet.children.find((x) => x.meta.did === did);
|
|
606
625
|
if (!child) {
|
|
607
626
|
throw new Error('Component does not exist');
|
|
@@ -851,6 +870,37 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
851
870
|
return newState;
|
|
852
871
|
}
|
|
853
872
|
|
|
873
|
+
async configPublicToStore({ did, publicToStore = false }) {
|
|
874
|
+
const blocklet = await this.ensureBlocklet(did);
|
|
875
|
+
// publicToStore 由用户传入
|
|
876
|
+
// handleInstanceInStore 方法写在前面,保证向 store 操作成功后才会更改 blocklet 中的 publicToStore值
|
|
877
|
+
// handleInstanceInStore 中会校验修改 publicToStore字段 的条件,不符合则会抛错,就不会执行下面更新 publicToStore 的逻辑
|
|
878
|
+
await handleInstanceInStore(blocklet, { publicToStore });
|
|
879
|
+
await states.blockletExtras.setSettings(did, { publicToStore });
|
|
880
|
+
|
|
881
|
+
const newState = await this.ensureBlocklet(did);
|
|
882
|
+
return newState;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
async updateWhoCanAccess({ did, whoCanAccess }) {
|
|
886
|
+
if (!(await this.hasBlocklet({ did }))) {
|
|
887
|
+
throw new Error('The blocklet does not exist');
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (!Object.values(WHO_CAN_ACCESS).includes(whoCanAccess)) {
|
|
891
|
+
logger.error(`The value of whoCanAccess is invalid: ${whoCanAccess}`);
|
|
892
|
+
throw new Error('the value is invalid');
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
await states.blockletExtras.setSettings(did, { whoCanAccess });
|
|
896
|
+
|
|
897
|
+
const blocklet = await this.ensureBlocklet(did);
|
|
898
|
+
|
|
899
|
+
this.emit(BlockletEvents.updated, { meta: { did: blocklet.meta.did } });
|
|
900
|
+
|
|
901
|
+
return blocklet;
|
|
902
|
+
}
|
|
903
|
+
|
|
854
904
|
/**
|
|
855
905
|
* upgrade blocklet from registry
|
|
856
906
|
*/
|
|
@@ -1275,6 +1325,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1275
1325
|
return blocklet;
|
|
1276
1326
|
}
|
|
1277
1327
|
|
|
1328
|
+
async hasBlocklet({ did }) {
|
|
1329
|
+
return states.blocklet.hasBlocklet(did);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1278
1332
|
async setInitialized({ did, owner }) {
|
|
1279
1333
|
if (!validateOwner(owner)) {
|
|
1280
1334
|
throw new Error('Blocklet owner is invalid');
|
|
@@ -1495,7 +1549,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1495
1549
|
|
|
1496
1550
|
preDownloadLock.release();
|
|
1497
1551
|
|
|
1498
|
-
this.emit(BlockletEvents.downloadFailed, {
|
|
1552
|
+
this.emit(BlockletEvents.downloadFailed, {
|
|
1553
|
+
meta: { did },
|
|
1554
|
+
error: {
|
|
1555
|
+
message: err.message,
|
|
1556
|
+
},
|
|
1557
|
+
});
|
|
1499
1558
|
states.notification.create({
|
|
1500
1559
|
title: 'Blocklet Download Failed',
|
|
1501
1560
|
description: `Blocklet ${name}@${version} download failed with error: ${err.message}`,
|
|
@@ -1786,10 +1845,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1786
1845
|
throw new Error('Root blocklet does not exist');
|
|
1787
1846
|
}
|
|
1788
1847
|
|
|
1848
|
+
const { inStore } = await parseSourceUrl(url);
|
|
1849
|
+
|
|
1789
1850
|
const meta = await getBlockletMetaFromUrl(url);
|
|
1790
1851
|
|
|
1791
|
-
// 如果是一个付费的blocklet
|
|
1792
|
-
if (!isFreeBlocklet(meta)) {
|
|
1852
|
+
// 如果是一个付费的blocklet,并且url来源为Store, 需要携带token才能下载成功
|
|
1853
|
+
if (!isFreeBlocklet(meta) && inStore) {
|
|
1793
1854
|
const info = await states.node.read();
|
|
1794
1855
|
|
|
1795
1856
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -1798,7 +1859,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1798
1859
|
headers: {
|
|
1799
1860
|
'x-server-did': info.did,
|
|
1800
1861
|
'x-download-token': downloadToken,
|
|
1862
|
+
// FIXME: 先保证兼容性,后续删除
|
|
1801
1863
|
'x-server-publick-key': info.pk,
|
|
1864
|
+
'x-server-public-key': info.pk,
|
|
1802
1865
|
'x-server-signature': sign(info.did, info.sk, {
|
|
1803
1866
|
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
1804
1867
|
}),
|
|
@@ -2366,7 +2429,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2366
2429
|
headers: {
|
|
2367
2430
|
'x-server-did': info.did,
|
|
2368
2431
|
'x-download-token': blocklet?.tokens?.paidBlockletDownloadToken,
|
|
2432
|
+
// FIXME: 先保证兼容性,后续删除
|
|
2369
2433
|
'x-server-publick-key': info.pk,
|
|
2434
|
+
'x-server-public-key': info.pk,
|
|
2370
2435
|
'x-server-signature': sign(info.did, info.sk, {
|
|
2371
2436
|
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
2372
2437
|
}),
|
|
@@ -2400,7 +2465,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2400
2465
|
ticket.on('failed', async (err) => {
|
|
2401
2466
|
logger.error('queue failed', { entity: 'blocklet', action, did, version, name, error: err });
|
|
2402
2467
|
await this._rollback(action, did, oldBlocklet);
|
|
2403
|
-
|
|
2468
|
+
const eventNames = {
|
|
2469
|
+
upgrade: BlockletEvents.upgradeFailed,
|
|
2470
|
+
downgrade: BlockletEvents.downgradeFailed,
|
|
2471
|
+
};
|
|
2472
|
+
this.emit(eventNames[action], { blocklet: oldBlocklet, context });
|
|
2404
2473
|
states.notification.create({
|
|
2405
2474
|
title: `Blocklet ${capitalize(action)} Failed`,
|
|
2406
2475
|
description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message || 'queue exception'}`,
|
|
@@ -2625,7 +2694,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2625
2694
|
logger.error('failed to install blocklet', { name, did, version, error: err });
|
|
2626
2695
|
try {
|
|
2627
2696
|
await this._rollback('install', did, oldBlocklet);
|
|
2628
|
-
this.emit(BlockletEvents.installFailed, {
|
|
2697
|
+
this.emit(BlockletEvents.installFailed, {
|
|
2698
|
+
meta: { did },
|
|
2699
|
+
error: {
|
|
2700
|
+
message: err.message,
|
|
2701
|
+
},
|
|
2702
|
+
});
|
|
2629
2703
|
states.notification.create({
|
|
2630
2704
|
title: 'Blocklet Install Failed',
|
|
2631
2705
|
description: `Blocklet ${meta.name}@${meta.version} install failed with error: ${err.message}`,
|
|
@@ -2766,7 +2840,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2766
2840
|
} catch (err) {
|
|
2767
2841
|
const b = await this._rollback(action, did, oldBlocklet);
|
|
2768
2842
|
logger.error(`failed to ${action} blocklet`, { did, version, name, error: err });
|
|
2843
|
+
|
|
2769
2844
|
this.emit(BlockletEvents.updated, b);
|
|
2845
|
+
|
|
2846
|
+
const eventNames = {
|
|
2847
|
+
upgrade: BlockletEvents.upgradeFailed,
|
|
2848
|
+
downgrade: BlockletEvents.downgradeFailed,
|
|
2849
|
+
};
|
|
2850
|
+
this.emit(eventNames[action], { blocklet: oldBlocklet, context });
|
|
2851
|
+
|
|
2770
2852
|
states.notification.create({
|
|
2771
2853
|
title: `Blocklet ${capitalize(action)} Failed`,
|
|
2772
2854
|
description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message}`,
|
package/lib/cert.js
CHANGED
|
@@ -103,14 +103,16 @@ class Cert extends EventEmitter {
|
|
|
103
103
|
|
|
104
104
|
async add(data) {
|
|
105
105
|
if (!data.certificate || !data.privateKey) {
|
|
106
|
-
throw new Error('certificate and privateKey
|
|
106
|
+
throw new Error('certificate and privateKey are required');
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
Cert.fixCertificate(data);
|
|
110
110
|
|
|
111
|
-
await this.manager.add(data);
|
|
112
|
-
logger.info('add certificate result', { name:
|
|
113
|
-
this.emit('cert.added',
|
|
111
|
+
const result = await this.manager.add(data);
|
|
112
|
+
logger.info('add certificate result', { name: result.name });
|
|
113
|
+
this.emit('cert.added', result);
|
|
114
|
+
|
|
115
|
+
return result;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
async issue({ domain }) {
|
|
@@ -120,7 +122,10 @@ class Cert extends EventEmitter {
|
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
async upsertByDomain(data) {
|
|
123
|
-
|
|
125
|
+
const result = await this.manager.upsertByDomain(data);
|
|
126
|
+
this.emit('cert.updated', result);
|
|
127
|
+
|
|
128
|
+
return result;
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
async update(data) {
|
package/lib/event.js
CHANGED
|
@@ -5,6 +5,7 @@ const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
|
|
|
5
5
|
const logger = require('@abtnode/logger')('@abtnode/core:event');
|
|
6
6
|
const { BLOCKLET_MODES, BlockletStatus, BlockletSource, BlockletEvents } = require('@blocklet/meta/lib/constants');
|
|
7
7
|
const { EVENTS } = require('@abtnode/constant');
|
|
8
|
+
const handleInstanceInStore = require('./util/public-to-store');
|
|
8
9
|
|
|
9
10
|
const eventHub =
|
|
10
11
|
process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
|
|
@@ -26,6 +27,7 @@ module.exports = ({
|
|
|
26
27
|
domainStatus,
|
|
27
28
|
teamAPI,
|
|
28
29
|
certManager,
|
|
30
|
+
node,
|
|
29
31
|
}) => {
|
|
30
32
|
const notificationState = states.notification;
|
|
31
33
|
const nodeState = states.node;
|
|
@@ -154,12 +156,66 @@ module.exports = ({
|
|
|
154
156
|
};
|
|
155
157
|
|
|
156
158
|
const handleBlockletEvent = async (eventName, payload) => {
|
|
159
|
+
const blocklet = payload.blocklet || payload;
|
|
160
|
+
|
|
157
161
|
if ([BlockletEvents.deployed, BlockletEvents.installed].includes(eventName)) {
|
|
158
162
|
await handleBlockletAdd(eventName, payload);
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
await node.createAuditLog({
|
|
166
|
+
action: 'installBlocklet',
|
|
167
|
+
args: {
|
|
168
|
+
did: blocklet.meta.did,
|
|
169
|
+
},
|
|
170
|
+
context: payload.context || {},
|
|
171
|
+
result: blocklet,
|
|
172
|
+
});
|
|
173
|
+
} catch (error) {
|
|
174
|
+
logger.error('Failed to createAuditLog for installBlocklet', { error });
|
|
175
|
+
}
|
|
159
176
|
} else if ([BlockletEvents.upgraded, BlockletEvents.downgraded].includes(eventName)) {
|
|
160
177
|
await handleBlockletUpgrade(eventName, payload);
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
await node.createAuditLog({
|
|
181
|
+
action: 'upgradeBlocklet',
|
|
182
|
+
args: {
|
|
183
|
+
did: blocklet.meta.did,
|
|
184
|
+
},
|
|
185
|
+
context: payload.context || {},
|
|
186
|
+
result: blocklet,
|
|
187
|
+
});
|
|
188
|
+
} catch (error) {
|
|
189
|
+
logger.error('Failed to createAuditLog for upgradeBlocklet', { error });
|
|
190
|
+
}
|
|
161
191
|
} else if ([BlockletEvents.removed].includes(eventName)) {
|
|
162
192
|
await handleBlockletRemove(eventName, payload);
|
|
193
|
+
} else if ([BlockletEvents.started].includes(eventName)) {
|
|
194
|
+
try {
|
|
195
|
+
const { publicToStore } = blocklet.settings || {};
|
|
196
|
+
// 如果一个 blocklet 没有设置 publicToStore,启动成功后不应给 store 发请求
|
|
197
|
+
if (publicToStore) {
|
|
198
|
+
await handleInstanceInStore(blocklet, { publicToStore });
|
|
199
|
+
}
|
|
200
|
+
} catch (error) {
|
|
201
|
+
logger.error('handleInstanceInStore failed', { error });
|
|
202
|
+
}
|
|
203
|
+
} else if ([BlockletEvents.upgradeFailed, BlockletEvents.downgradeFailed].includes(eventName)) {
|
|
204
|
+
try {
|
|
205
|
+
await node.createAuditLog({
|
|
206
|
+
action: 'upgradeBlocklet',
|
|
207
|
+
args: {
|
|
208
|
+
did: blocklet.meta.did,
|
|
209
|
+
},
|
|
210
|
+
context: payload.context || {},
|
|
211
|
+
result: {
|
|
212
|
+
...blocklet,
|
|
213
|
+
resultStatus: 'failed',
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
} catch (error) {
|
|
217
|
+
logger.error('Failed to createAuditLog for upgradeBlocklet failed', { error });
|
|
218
|
+
}
|
|
163
219
|
}
|
|
164
220
|
|
|
165
221
|
if (payload.blocklet && !payload.meta) {
|
package/lib/index.js
CHANGED
|
@@ -174,19 +174,6 @@ function ABTNode(options) {
|
|
|
174
174
|
onStatesReady(createStateReadyHandler(routingSnapshot));
|
|
175
175
|
const domainStatus = new DomainStatus(routerManager);
|
|
176
176
|
|
|
177
|
-
const events = createEvents({
|
|
178
|
-
blockletManager,
|
|
179
|
-
blockletRegistry,
|
|
180
|
-
ensureBlockletRouting,
|
|
181
|
-
ensureBlockletRoutingForUpgrade,
|
|
182
|
-
removeBlockletRouting,
|
|
183
|
-
takeRoutingSnapshot,
|
|
184
|
-
handleRouting,
|
|
185
|
-
domainStatus,
|
|
186
|
-
teamAPI,
|
|
187
|
-
certManager,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
177
|
const isInitialized = async () => {
|
|
191
178
|
const state = await states.node.read();
|
|
192
179
|
return states.node.isInitialized(state);
|
|
@@ -226,8 +213,9 @@ function ABTNode(options) {
|
|
|
226
213
|
getLatestBlockletVersion: blockletManager.getLatestBlockletVersion.bind(blockletManager),
|
|
227
214
|
getBlockletMetaFromUrl: blockletManager.getMetaFromUrl.bind(blockletManager),
|
|
228
215
|
resetBlocklet: blockletManager.reset.bind(blockletManager),
|
|
229
|
-
|
|
230
216
|
deleteBlockletProcess: blockletManager.deleteProcess.bind(blockletManager),
|
|
217
|
+
configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
|
|
218
|
+
updateWhoCanAccess: blockletManager.updateWhoCanAccess.bind(blockletManager),
|
|
231
219
|
|
|
232
220
|
// For diagnose purpose
|
|
233
221
|
syncBlockletStatus: blockletManager.status.bind(blockletManager),
|
|
@@ -237,6 +225,7 @@ function ABTNode(options) {
|
|
|
237
225
|
getBlocklets: blockletManager.list.bind(blockletManager),
|
|
238
226
|
getBlocklet: blockletManager.detail.bind(blockletManager),
|
|
239
227
|
getBlockletDiff: blockletManager.diff.bind(blockletManager),
|
|
228
|
+
hasBlocklet: blockletManager.hasBlocklet.bind(blockletManager),
|
|
240
229
|
updateAllBlockletEnvironment: blockletManager.updateAllBlockletEnvironment.bind(blockletManager),
|
|
241
230
|
setBlockletInitialized: blockletManager.setInitialized.bind(blockletManager),
|
|
242
231
|
|
|
@@ -317,7 +306,6 @@ function ABTNode(options) {
|
|
|
317
306
|
processPassportIssuance: teamAPI.processPassportIssuance.bind(teamAPI),
|
|
318
307
|
configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
|
|
319
308
|
configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
|
|
320
|
-
configWhoCanAccess: teamAPI.configWhoCanAccess.bind(teamAPI),
|
|
321
309
|
|
|
322
310
|
// Challenge
|
|
323
311
|
generateChallenge: states.challenge.generate.bind(states.challenge),
|
|
@@ -403,6 +391,20 @@ function ABTNode(options) {
|
|
|
403
391
|
getRouterProvider,
|
|
404
392
|
};
|
|
405
393
|
|
|
394
|
+
const events = createEvents({
|
|
395
|
+
blockletManager,
|
|
396
|
+
blockletRegistry,
|
|
397
|
+
ensureBlockletRouting,
|
|
398
|
+
ensureBlockletRoutingForUpgrade,
|
|
399
|
+
removeBlockletRouting,
|
|
400
|
+
takeRoutingSnapshot,
|
|
401
|
+
handleRouting,
|
|
402
|
+
domainStatus,
|
|
403
|
+
teamAPI,
|
|
404
|
+
certManager,
|
|
405
|
+
node: instance,
|
|
406
|
+
});
|
|
407
|
+
|
|
406
408
|
const webhook = WebHook({ events, dataDirs, instance });
|
|
407
409
|
|
|
408
410
|
const initCron = () => {
|
package/lib/router/helper.js
CHANGED
|
@@ -434,7 +434,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
434
434
|
isProtected: true,
|
|
435
435
|
});
|
|
436
436
|
|
|
437
|
-
logger.info('dashboard certificate updated');
|
|
437
|
+
logger.info('dashboard certificate updated', { domain });
|
|
438
438
|
} catch (error) {
|
|
439
439
|
logger.error('update dashboard certificate failed', { error });
|
|
440
440
|
throw error;
|
|
@@ -1103,6 +1103,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1103
1103
|
certManager.on('cert.added', () => providers[providerName].reload());
|
|
1104
1104
|
certManager.on('cert.removed', () => providers[providerName].reload());
|
|
1105
1105
|
certManager.on('cert.issued', () => providers[providerName].reload());
|
|
1106
|
+
certManager.on('cert.updated', () => providers[providerName].reload());
|
|
1106
1107
|
|
|
1107
1108
|
await providers[providerName].start();
|
|
1108
1109
|
}
|
package/lib/router/manager.js
CHANGED
|
@@ -8,7 +8,6 @@ const path = require('path');
|
|
|
8
8
|
const os = require('os');
|
|
9
9
|
const fse = require('fs-extra');
|
|
10
10
|
const get = require('lodash/get');
|
|
11
|
-
const { Certificate, PrivateKey } = require('@fidm/x509');
|
|
12
11
|
const { EventEmitter } = require('events');
|
|
13
12
|
const uuid = require('uuid');
|
|
14
13
|
const isUrl = require('is-url');
|
|
@@ -564,39 +563,6 @@ class RouterManager extends EventEmitter {
|
|
|
564
563
|
}
|
|
565
564
|
}
|
|
566
565
|
|
|
567
|
-
validateCertificate(cert, domain) {
|
|
568
|
-
const certificate = Certificate.fromPEM(cert.certificate);
|
|
569
|
-
const privateKey = PrivateKey.fromPEM(cert.privateKey);
|
|
570
|
-
|
|
571
|
-
const data = Buffer.allocUnsafe(100);
|
|
572
|
-
const signature = privateKey.sign(data, 'sha512');
|
|
573
|
-
if (!certificate.publicKey.verify(data, signature, 'sha512')) {
|
|
574
|
-
throw new Error('Invalid certificate: signature verify failed');
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
const certDomain = get(certificate, 'subject.commonName', '');
|
|
578
|
-
if (domain && domain !== certDomain) {
|
|
579
|
-
throw new Error('Invalid certificate: domain does not match');
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const validFrom = get(certificate, 'validFrom', '');
|
|
583
|
-
if (!validFrom || new Date(validFrom).getTime() > Date.now()) {
|
|
584
|
-
throw new Error('Invalid certificate: not in valid period');
|
|
585
|
-
}
|
|
586
|
-
const validTo = get(certificate, 'validTo', '');
|
|
587
|
-
if (!validTo || new Date(validTo).getTime() < Date.now()) {
|
|
588
|
-
throw new Error('Invalid certificate: not in valid period');
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
return certificate;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
fixCertificate(entity) {
|
|
595
|
-
// Hack: this logic exists because gql does not allow line breaks in arg values
|
|
596
|
-
entity.privateKey = entity.privateKey.split('|').join('\n');
|
|
597
|
-
entity.certificate = entity.certificate.split('|').join('\n');
|
|
598
|
-
}
|
|
599
|
-
|
|
600
566
|
fixRootBlockletRule(rule) {
|
|
601
567
|
if (!rule.id) {
|
|
602
568
|
rule.id = uuid.v4();
|
package/lib/states/audit-log.js
CHANGED
|
@@ -111,10 +111,17 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
111
111
|
case 'configBlocklet':
|
|
112
112
|
return `updated following config for blocklet ${getBlockletInfo(result, info)}:\n${args.configs.map(x => `- ${x.key}: ${x.value}\n`)}`; // prettier-ignore
|
|
113
113
|
case 'upgradeBlocklet':
|
|
114
|
+
if (result.resultStatus === 'failed') {
|
|
115
|
+
return `upgrade blocklet failed: ${getBlockletInfo(result, info)}`;
|
|
116
|
+
}
|
|
114
117
|
return `upgraded blocklet ${getBlockletInfo(result, info)} to v${result.meta.version}`;
|
|
115
118
|
case 'updateChildBlocklets':
|
|
116
119
|
return `upgraded components for blocklet ${getBlockletInfo(result, info)}`;
|
|
117
|
-
|
|
120
|
+
case 'configPublicToStore':
|
|
121
|
+
if (args.publicToStore) {
|
|
122
|
+
return `set publicToStore to true for blocklet ${getBlockletInfo(result, info)}`;
|
|
123
|
+
}
|
|
124
|
+
return `set publicToStore to false for blocklet ${getBlockletInfo(result, info)}`;
|
|
118
125
|
// store
|
|
119
126
|
case 'addBlockletStore':
|
|
120
127
|
return `added blocklet store ${args.url}`;
|
|
@@ -137,7 +144,7 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
137
144
|
return `switched passport to ${args.passport.name} for ${team}`;
|
|
138
145
|
case 'login':
|
|
139
146
|
return `${user} logged in to ${team} with passport ${args.passport.name}`;
|
|
140
|
-
case '
|
|
147
|
+
case 'updateWhoCanAccess':
|
|
141
148
|
return `updated access control policy to **${args.value}** for ${team} when ${args.reason}`;
|
|
142
149
|
case 'configPassportIssuance':
|
|
143
150
|
return `${args.enabled ? 'enabled' : 'disabled'} passport issuance for ${team}`;
|
|
@@ -210,6 +217,14 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
210
217
|
return `added extra domain **${args.domainAlias}** to ${site}`; // prettier-ignore
|
|
211
218
|
case 'deleteDomainAlias':
|
|
212
219
|
return `removed extra domain **${args.domainAlias}** from ${site}`; // prettier-ignore
|
|
220
|
+
case 'updateRoutingSite':
|
|
221
|
+
return `updated site from ${site}`; // prettier-ignore
|
|
222
|
+
case 'addRoutingRule':
|
|
223
|
+
return `added routing rule **${args.rule?.from?.pathPrefix}** from ${site}`; // prettier-ignore
|
|
224
|
+
case 'updateRoutingRule':
|
|
225
|
+
return `updated routing rule **${args.rule?.from?.pathPrefix}** from ${site}`; // prettier-ignore
|
|
226
|
+
case 'deleteRoutingRule':
|
|
227
|
+
return `deleted routing rule from ${site}`; // prettier-ignore
|
|
213
228
|
case 'updateGateway': {
|
|
214
229
|
let message = args.requestLimit.enabled ? `status: enabled, rate: ${args.requestLimit.rate}` : 'status: disabled';
|
|
215
230
|
message = `update gateway. ${message}`;
|
|
@@ -237,6 +252,7 @@ const getLogCategory = (action) => {
|
|
|
237
252
|
case 'configBlocklet':
|
|
238
253
|
case 'upgradeBlocklet':
|
|
239
254
|
case 'updateChildBlocklets':
|
|
255
|
+
case 'configPublicToStore':
|
|
240
256
|
return 'blocklet';
|
|
241
257
|
|
|
242
258
|
// store
|
|
@@ -307,16 +323,21 @@ const getScope = (args = {}) => {
|
|
|
307
323
|
return args.teamDid;
|
|
308
324
|
}
|
|
309
325
|
|
|
326
|
+
// this param usually means mutating an blockle application
|
|
327
|
+
if (args.did) {
|
|
328
|
+
// this param usually means mutating a nested child component
|
|
329
|
+
if (Array.isArray(args.did)) {
|
|
330
|
+
return args.did[0];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return args.did;
|
|
334
|
+
}
|
|
335
|
+
|
|
310
336
|
// this param usually means mutating a child component
|
|
311
337
|
if (args.rootDid) {
|
|
312
338
|
return args.rootDid;
|
|
313
339
|
}
|
|
314
340
|
|
|
315
|
-
// this param usually means mutating a nested child component
|
|
316
|
-
if (Array.isArray(args.did)) {
|
|
317
|
-
return args.did[0];
|
|
318
|
-
}
|
|
319
|
-
|
|
320
341
|
return null;
|
|
321
342
|
};
|
|
322
343
|
|
package/lib/states/blocklet.js
CHANGED
|
@@ -102,6 +102,22 @@ class BlockletState extends BaseState {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
hasBlocklet(did) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
if (!did) {
|
|
108
|
+
resolve(false);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.db.count({ $or: [{ 'meta.did': did }, { appDid: did }] }, (err, count) => {
|
|
112
|
+
if (err) {
|
|
113
|
+
return reject(err);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return resolve(!!count);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
105
121
|
getBlocklets(query = {}, projection) {
|
|
106
122
|
return new Promise((resolve, reject) => {
|
|
107
123
|
this.db
|
package/lib/states/node.js
CHANGED
|
@@ -283,6 +283,14 @@ class NodeState extends BaseState {
|
|
|
283
283
|
return this.updateNodeInfo({ previousMode: '', mode: info.previousMode });
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
async setMode(mode) {
|
|
287
|
+
if (Object.values(NODE_MODES).includes(mode) === false) {
|
|
288
|
+
throw new Error(`Can not update server to unsupported mode: ${mode}`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return this.updateNodeInfo({ previousMode: '', mode });
|
|
292
|
+
}
|
|
293
|
+
|
|
286
294
|
async getEnvironments() {
|
|
287
295
|
return this.read().then((info) => ({
|
|
288
296
|
ABT_NODE: info.version,
|
package/lib/states/session.js
CHANGED
|
@@ -10,7 +10,13 @@ class SessionState extends BaseState {
|
|
|
10
10
|
|
|
11
11
|
this.db.ensureIndex({ fieldName: 'createdAt' }, (error) => {
|
|
12
12
|
if (error) {
|
|
13
|
-
logger.error('ensure index failed', { error });
|
|
13
|
+
logger.error('ensure createdAt index failed', { error });
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
this.db.ensureIndex({ fieldName: 'expireDate', expireAfterSeconds: 0 }, (error) => {
|
|
18
|
+
if (error) {
|
|
19
|
+
logger.error('ensure expireDate index failed', { error });
|
|
14
20
|
}
|
|
15
21
|
});
|
|
16
22
|
}
|
package/lib/util/blocklet.js
CHANGED
|
@@ -309,8 +309,10 @@ const getComponentSystemEnvironments = (blocklet) => {
|
|
|
309
309
|
if (ports) {
|
|
310
310
|
Object.assign(portEnvironments, ports);
|
|
311
311
|
}
|
|
312
|
+
|
|
312
313
|
return {
|
|
313
314
|
BLOCKLET_REAL_DID: blocklet.env.id,
|
|
315
|
+
BLOCKLET_REAL_NAME: blocklet.env.name,
|
|
314
316
|
BLOCKLET_DATA_DIR: blocklet.env.dataDir,
|
|
315
317
|
BLOCKLET_LOG_DIR: blocklet.env.logsDir,
|
|
316
318
|
BLOCKLET_CACHE_DIR: blocklet.env.cacheDir,
|
|
@@ -328,10 +330,29 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
|
|
|
328
330
|
return o;
|
|
329
331
|
}, {});
|
|
330
332
|
|
|
333
|
+
// get devEnvironments, when blocklet is in dev mode
|
|
334
|
+
const devEnvironments =
|
|
335
|
+
blocklet.mode === BLOCKLET_MODES.DEVELOPMENT
|
|
336
|
+
? {
|
|
337
|
+
BLOCKLET_DEV_MOUNT_POINT: blocklet?.mountPoint || '',
|
|
338
|
+
}
|
|
339
|
+
: {};
|
|
340
|
+
|
|
341
|
+
const root = (ancestors || [])[0] || blocklet;
|
|
342
|
+
const ports = {};
|
|
343
|
+
forEachBlockletSync(root, (x) => {
|
|
344
|
+
const webInterface = findWebInterface(x);
|
|
345
|
+
if (webInterface && x.environmentObj[webInterface.port]) {
|
|
346
|
+
ports[x.environmentObj.BLOCKLET_REAL_NAME] = x.environmentObj[webInterface.port];
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
331
350
|
return {
|
|
332
351
|
...blocklet.configObj,
|
|
333
352
|
...getSharedConfigObj(blocklet, ancestors),
|
|
334
353
|
...blocklet.environmentObj,
|
|
354
|
+
...devEnvironments,
|
|
355
|
+
BLOCKLET_WEB_PORTS: JSON.stringify(ports),
|
|
335
356
|
...nodeEnvironments,
|
|
336
357
|
...safeNodeEnvironments,
|
|
337
358
|
};
|
|
@@ -405,7 +426,7 @@ const getBlockletMetaFromUrls = async (urls) => {
|
|
|
405
426
|
const meta = await any(urls.map(getBlockletMetaFromUrl));
|
|
406
427
|
return meta;
|
|
407
428
|
} catch (err) {
|
|
408
|
-
logger.error('failed get blocklet meta', { urls });
|
|
429
|
+
logger.error('failed get blocklet meta', { urls, error: err });
|
|
409
430
|
throw new Error('Failed get blocklet meta');
|
|
410
431
|
}
|
|
411
432
|
};
|
|
@@ -934,11 +955,6 @@ const pruneBlockletBundle = async ({ blocklets, installDir, blockletSettings })
|
|
|
934
955
|
|
|
935
956
|
const fillAppDirs = async (dir, level = 'root') => {
|
|
936
957
|
if (level === 'version') {
|
|
937
|
-
if (!fs.existsSync(path.join(dir, 'blocklet.yml'))) {
|
|
938
|
-
logger.error('blocklet.yml does not exist in blocklet bundle dir', { dir });
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
958
|
appDirs.push({
|
|
943
959
|
key: path.relative(installDir, dir),
|
|
944
960
|
dir,
|
package/lib/util/index.js
CHANGED
|
@@ -398,7 +398,10 @@ const validateUrl = async (url, expectedHttpResTypes = ['application/json', 'tex
|
|
|
398
398
|
throw new Error(`Cannot get content-type from ${url}: ${err.message}`);
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
-
if (
|
|
401
|
+
if (
|
|
402
|
+
res.headers['content-type'] &&
|
|
403
|
+
expectedHttpResTypes.some((x) => res.headers['content-type'].includes(x)) === false
|
|
404
|
+
) {
|
|
402
405
|
throw new Error(`Unexpected content-type from ${url}: ${res.headers['content-type']}`);
|
|
403
406
|
}
|
|
404
407
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const { sign } = require('@arcblock/jwt');
|
|
2
|
+
const { BlockletSource } = require('@blocklet/meta/lib/constants');
|
|
3
|
+
const { WHO_CAN_ACCESS } = require('@abtnode/constant');
|
|
4
|
+
const logger = require('@abtnode/logger')('@abtnode/util:public-to-store');
|
|
5
|
+
|
|
6
|
+
const getWallet = require('@abtnode/util/lib/get-app-wallet');
|
|
7
|
+
const axios = require('@abtnode/util/lib/axios');
|
|
8
|
+
|
|
9
|
+
const getAppToken = (blocklet) =>
|
|
10
|
+
sign(blocklet.environmentObj?.BLOCKLET_APP_ID, blocklet.environmentObj?.BLOCKLET_APP_SK);
|
|
11
|
+
|
|
12
|
+
const getAppId = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_ID;
|
|
13
|
+
|
|
14
|
+
const getAppSK = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_SK;
|
|
15
|
+
|
|
16
|
+
const getBlockletDid = (blocklet) => blocklet.meta?.bundleDid;
|
|
17
|
+
|
|
18
|
+
const getAppUrl = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_URL;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* verify manages the permissions of blocklet public instance
|
|
22
|
+
* @param {*} blocklet
|
|
23
|
+
* @returns bool
|
|
24
|
+
*/
|
|
25
|
+
const verifyPublicInstance = (blocklet) => {
|
|
26
|
+
const { whoCanAccess = WHO_CAN_ACCESS.ALL } = blocklet.settings;
|
|
27
|
+
return blocklet.source === BlockletSource.registry && whoCanAccess === WHO_CAN_ACCESS.ALL;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {*} blocklet
|
|
33
|
+
* @param {*} {userDid publicToStore}
|
|
34
|
+
* @returns bool
|
|
35
|
+
*/
|
|
36
|
+
async function handleInstanceInStore(blocklet, { userDid = null, publicToStore = false } = {}) {
|
|
37
|
+
if (!blocklet) {
|
|
38
|
+
logger.error('blocklet argument is required');
|
|
39
|
+
throw new Error('blocklet argument is required');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const ownerDid = userDid || blocklet.settings?.owner?.did;
|
|
43
|
+
if (!ownerDid) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!verifyPublicInstance(blocklet)) {
|
|
48
|
+
logger.error('no permission to set publicInstance');
|
|
49
|
+
throw new Error('no permission to set publicInstance');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const appToken = getAppToken(blocklet);
|
|
53
|
+
const blockletDid = getBlockletDid(blocklet);
|
|
54
|
+
const appId = getAppId(blocklet);
|
|
55
|
+
const appSK = getAppSK(blocklet);
|
|
56
|
+
const wallet = getWallet(appSK);
|
|
57
|
+
const body = {
|
|
58
|
+
appToken,
|
|
59
|
+
appId,
|
|
60
|
+
appPK: wallet.publicKey,
|
|
61
|
+
ownerDid,
|
|
62
|
+
appUrl: getAppUrl(blocklet),
|
|
63
|
+
blockletDid,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const api = axios.create({ baseURL: blocklet.deployedFrom, timeout: 1000 * 10 });
|
|
67
|
+
if (!publicToStore) {
|
|
68
|
+
try {
|
|
69
|
+
await api.delete(`/api/blocklet-instances/${appId}`, { data: body });
|
|
70
|
+
} catch (error) {
|
|
71
|
+
logger.error('failed to delete blocklet instance', { error });
|
|
72
|
+
throw new Error('failed to delete blocklet instance');
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
try {
|
|
76
|
+
await api.put(`/api/blocklet-instances/${appId}`, body);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
logger.error('failed to update blocklet instance', { error });
|
|
79
|
+
throw new Error('failed to delete blocklet instance');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = handleInstanceInStore;
|
package/lib/validators/router.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.8.
|
|
6
|
+
"version": "1.8.3",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,31 +19,31 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/certificate-manager": "1.8.
|
|
23
|
-
"@abtnode/constant": "1.8.
|
|
24
|
-
"@abtnode/cron": "1.8.
|
|
25
|
-
"@abtnode/db": "1.8.
|
|
26
|
-
"@abtnode/logger": "1.8.
|
|
27
|
-
"@abtnode/queue": "1.8.
|
|
28
|
-
"@abtnode/rbac": "1.8.
|
|
29
|
-
"@abtnode/router-provider": "1.8.
|
|
30
|
-
"@abtnode/static-server": "1.8.
|
|
31
|
-
"@abtnode/timemachine": "1.8.
|
|
32
|
-
"@abtnode/util": "1.8.
|
|
33
|
-
"@arcblock/did": "1.17.
|
|
22
|
+
"@abtnode/certificate-manager": "1.8.3",
|
|
23
|
+
"@abtnode/constant": "1.8.3",
|
|
24
|
+
"@abtnode/cron": "1.8.3",
|
|
25
|
+
"@abtnode/db": "1.8.3",
|
|
26
|
+
"@abtnode/logger": "1.8.3",
|
|
27
|
+
"@abtnode/queue": "1.8.3",
|
|
28
|
+
"@abtnode/rbac": "1.8.3",
|
|
29
|
+
"@abtnode/router-provider": "1.8.3",
|
|
30
|
+
"@abtnode/static-server": "1.8.3",
|
|
31
|
+
"@abtnode/timemachine": "1.8.3",
|
|
32
|
+
"@abtnode/util": "1.8.3",
|
|
33
|
+
"@arcblock/did": "1.17.5",
|
|
34
34
|
"@arcblock/did-motif": "^1.1.10",
|
|
35
|
-
"@arcblock/did-util": "1.17.
|
|
36
|
-
"@arcblock/event-hub": "1.17.
|
|
37
|
-
"@arcblock/jwt": "^1.17.
|
|
35
|
+
"@arcblock/did-util": "1.17.5",
|
|
36
|
+
"@arcblock/event-hub": "1.17.5",
|
|
37
|
+
"@arcblock/jwt": "^1.17.5",
|
|
38
38
|
"@arcblock/pm2-events": "^0.0.5",
|
|
39
|
-
"@arcblock/vc": "1.17.
|
|
40
|
-
"@blocklet/meta": "1.8.
|
|
39
|
+
"@arcblock/vc": "1.17.5",
|
|
40
|
+
"@blocklet/meta": "1.8.3",
|
|
41
41
|
"@fidm/x509": "^1.2.1",
|
|
42
|
-
"@nedb/core": "^1.
|
|
43
|
-
"@nedb/multi": "^1.
|
|
44
|
-
"@ocap/mcrypto": "1.17.
|
|
45
|
-
"@ocap/util": "1.17.
|
|
46
|
-
"@ocap/wallet": "1.17.
|
|
42
|
+
"@nedb/core": "^1.3.1",
|
|
43
|
+
"@nedb/multi": "^1.3.1",
|
|
44
|
+
"@ocap/mcrypto": "1.17.5",
|
|
45
|
+
"@ocap/util": "1.17.5",
|
|
46
|
+
"@ocap/wallet": "1.17.5",
|
|
47
47
|
"@slack/webhook": "^5.0.3",
|
|
48
48
|
"axios": "^0.27.2",
|
|
49
49
|
"axon": "^2.0.3",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"express": "^4.17.1",
|
|
82
82
|
"jest": "^27.4.5"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "c734aca7bf1fc03378c3b082d0622b6a540a8bd3"
|
|
85
85
|
}
|