@abtnode/core 1.8.1 → 1.8.4
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 +131 -46
- package/lib/event.js +51 -3
- package/lib/index.js +17 -16
- package/lib/states/audit-log.js +22 -6
- package/lib/states/blocklet.js +32 -0
- package/lib/states/node.js +8 -0
- package/lib/util/blocklet.js +22 -1
- package/lib/util/public-to-store.js +85 -0
- package/lib/validators/router.js +1 -1
- package/lib/webhook/index.js +7 -2
- package/lib/webhook/sender/index.js +5 -0
- package/lib/webhook/sender/slack/index.js +1 -1
- package/lib/webhook/sender/wallet/index.js +45 -0
- package/package.json +25 -24
|
@@ -22,8 +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
|
|
26
|
-
const { VC_TYPE_BLOCKLET_PURCHASE } = require('@abtnode/constant');
|
|
25
|
+
const { VC_TYPE_BLOCKLET_PURCHASE, WHO_CAN_ACCESS } = require('@abtnode/constant');
|
|
27
26
|
|
|
28
27
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
29
28
|
const {
|
|
@@ -116,6 +115,7 @@ const { getFactoryState } = require('../../util/chain');
|
|
|
116
115
|
const runMigrationScripts = require('../migration');
|
|
117
116
|
const hooks = require('../hooks');
|
|
118
117
|
const { formatName } = require('../../util/get-domain-for-blocklet');
|
|
118
|
+
const handleInstanceInStore = require('../../util/public-to-store');
|
|
119
119
|
|
|
120
120
|
const {
|
|
121
121
|
isInProgress,
|
|
@@ -128,7 +128,7 @@ const {
|
|
|
128
128
|
validateOwner,
|
|
129
129
|
} = util;
|
|
130
130
|
|
|
131
|
-
const
|
|
131
|
+
const statusLock = new Lock('blocklet-status-lock');
|
|
132
132
|
|
|
133
133
|
const asyncFs = fs.promises;
|
|
134
134
|
|
|
@@ -234,7 +234,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
234
234
|
context.headers = Object.assign(context?.headers || {}, {
|
|
235
235
|
'x-server-did': info.did,
|
|
236
236
|
'x-download-token': params.downloadToken,
|
|
237
|
+
// FIXME: 先保证兼容性,后续删除
|
|
237
238
|
'x-server-publick-key': info.pk,
|
|
239
|
+
'x-server-public-key': info.pk,
|
|
238
240
|
'x-server-signature': sign(info.did, info.sk, {
|
|
239
241
|
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
240
242
|
}),
|
|
@@ -427,6 +429,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
427
429
|
|
|
428
430
|
return blocklet;
|
|
429
431
|
} catch (err) {
|
|
432
|
+
const status = await states.blocklet.getBlockletStatus(did);
|
|
433
|
+
if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
|
|
434
|
+
logger.info('Failed to start blocklet maybe due to manually stopped');
|
|
435
|
+
return states.blocklet.getBlocklet(did);
|
|
436
|
+
}
|
|
437
|
+
|
|
430
438
|
const error = Array.isArray(err) ? err[0] : err;
|
|
431
439
|
logger.error('Failed to start blocklet', { error, did, name: blocklet.meta.name });
|
|
432
440
|
const description = `Start blocklet ${blocklet.meta.name} failed with error: ${error.message}`;
|
|
@@ -677,26 +685,38 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
677
685
|
return newBlocklet;
|
|
678
686
|
}
|
|
679
687
|
|
|
680
|
-
async cancelDownload({ did }, context) {
|
|
681
|
-
await preDownloadLock.acquire();
|
|
688
|
+
async cancelDownload({ did: inputDid }, context) {
|
|
682
689
|
try {
|
|
683
|
-
|
|
690
|
+
await statusLock.acquire();
|
|
691
|
+
const blocklet = await states.blocklet.getBlocklet(inputDid);
|
|
684
692
|
if (!blocklet) {
|
|
685
|
-
throw new Error('Can not cancel download for non-exist blocklet in database.', {
|
|
693
|
+
throw new Error('Can not cancel download for non-exist blocklet in database.', { inputDid });
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const { name, did, version } = blocklet.meta;
|
|
697
|
+
|
|
698
|
+
if (![BlockletStatus.downloading, BlockletStatus.waiting].includes(blocklet.status)) {
|
|
699
|
+
throw new Error(`Can not cancel blocklet that status is ${fromBlockletStatus(blocklet.status)}`);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const job = await this.installQueue.get(did);
|
|
703
|
+
if (job) {
|
|
704
|
+
const { postAction, oldBlocklet } = job;
|
|
705
|
+
await this._rollback(postAction, did, oldBlocklet);
|
|
686
706
|
}
|
|
687
707
|
|
|
688
708
|
if (blocklet.status === BlockletStatus.downloading) {
|
|
689
709
|
await this._cancelDownload(blocklet.meta, context);
|
|
690
710
|
} else if (blocklet.status === BlockletStatus.waiting) {
|
|
691
711
|
await this._cancelWaiting(blocklet.meta, context);
|
|
692
|
-
} else {
|
|
693
|
-
throw new Error(`Can not cancel blocklet that status is ${fromBlockletStatus(blocklet.status)}`);
|
|
694
712
|
}
|
|
695
713
|
|
|
696
|
-
|
|
714
|
+
logger.info('cancel download blocklet', { did, name, version, status: fromBlockletStatus(blocklet.status) });
|
|
715
|
+
|
|
716
|
+
statusLock.release();
|
|
697
717
|
return blocklet;
|
|
698
718
|
} catch (error) {
|
|
699
|
-
|
|
719
|
+
statusLock.release();
|
|
700
720
|
throw error;
|
|
701
721
|
}
|
|
702
722
|
}
|
|
@@ -870,7 +890,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
870
890
|
|
|
871
891
|
async configPublicToStore({ did, publicToStore = false }) {
|
|
872
892
|
const blocklet = await this.ensureBlocklet(did);
|
|
873
|
-
|
|
893
|
+
// publicToStore 由用户传入
|
|
894
|
+
// handleInstanceInStore 方法写在前面,保证向 store 操作成功后才会更改 blocklet 中的 publicToStore值
|
|
895
|
+
// handleInstanceInStore 中会校验修改 publicToStore字段 的条件,不符合则会抛错,就不会执行下面更新 publicToStore 的逻辑
|
|
874
896
|
await handleInstanceInStore(blocklet, { publicToStore });
|
|
875
897
|
await states.blockletExtras.setSettings(did, { publicToStore });
|
|
876
898
|
|
|
@@ -878,6 +900,25 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
878
900
|
return newState;
|
|
879
901
|
}
|
|
880
902
|
|
|
903
|
+
async updateWhoCanAccess({ did, whoCanAccess }) {
|
|
904
|
+
if (!(await this.hasBlocklet({ did }))) {
|
|
905
|
+
throw new Error('The blocklet does not exist');
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
if (!Object.values(WHO_CAN_ACCESS).includes(whoCanAccess)) {
|
|
909
|
+
logger.error(`The value of whoCanAccess is invalid: ${whoCanAccess}`);
|
|
910
|
+
throw new Error('the value is invalid');
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
await states.blockletExtras.setSettings(did, { whoCanAccess });
|
|
914
|
+
|
|
915
|
+
const blocklet = await this.ensureBlocklet(did);
|
|
916
|
+
|
|
917
|
+
this.emit(BlockletEvents.updated, { meta: { did: blocklet.meta.did } });
|
|
918
|
+
|
|
919
|
+
return blocklet;
|
|
920
|
+
}
|
|
921
|
+
|
|
881
922
|
/**
|
|
882
923
|
* upgrade blocklet from registry
|
|
883
924
|
*/
|
|
@@ -1302,6 +1343,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1302
1343
|
return blocklet;
|
|
1303
1344
|
}
|
|
1304
1345
|
|
|
1346
|
+
async hasBlocklet({ did }) {
|
|
1347
|
+
return states.blocklet.hasBlocklet(did);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1305
1350
|
async setInitialized({ did, owner }) {
|
|
1306
1351
|
if (!validateOwner(owner)) {
|
|
1307
1352
|
throw new Error('Blocklet owner is invalid');
|
|
@@ -1489,39 +1534,45 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1489
1534
|
const { meta } = blocklet;
|
|
1490
1535
|
const { name, did, version } = meta;
|
|
1491
1536
|
|
|
1537
|
+
// check status
|
|
1492
1538
|
try {
|
|
1493
|
-
await
|
|
1539
|
+
await statusLock.acquire();
|
|
1494
1540
|
|
|
1495
1541
|
const b0 = await states.blocklet.getBlocklet(did);
|
|
1496
|
-
if (!b0 || ![BlockletStatus.waiting
|
|
1542
|
+
if (!b0 || ![BlockletStatus.waiting].includes(b0.status)) {
|
|
1497
1543
|
if (!b0) {
|
|
1498
|
-
|
|
1544
|
+
throw new Error('blocklet does not exist before downloading');
|
|
1499
1545
|
} else {
|
|
1500
|
-
|
|
1501
|
-
name,
|
|
1502
|
-
did,
|
|
1503
|
-
status: fromBlockletStatus(b0.status),
|
|
1504
|
-
});
|
|
1546
|
+
throw new Error(`blocklet status is invalid before downloading: ${fromBlockletStatus(b0.status)}`);
|
|
1505
1547
|
}
|
|
1506
|
-
preDownloadLock.release();
|
|
1507
|
-
await this._rollback(postAction, did, oldBlocklet);
|
|
1508
|
-
return;
|
|
1509
1548
|
}
|
|
1549
|
+
statusLock.release();
|
|
1550
|
+
} catch (error) {
|
|
1551
|
+
statusLock.release();
|
|
1552
|
+
logger.error('Check blocklet status failed before downloading', {
|
|
1553
|
+
name,
|
|
1554
|
+
did,
|
|
1555
|
+
error,
|
|
1556
|
+
});
|
|
1557
|
+
await this._rollback(postAction, did, oldBlocklet);
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1510
1560
|
|
|
1511
|
-
|
|
1512
|
-
|
|
1561
|
+
// download bundle
|
|
1562
|
+
try {
|
|
1513
1563
|
const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet, context);
|
|
1514
1564
|
|
|
1515
1565
|
if (isCancelled) {
|
|
1516
|
-
logger.info('Download was canceled
|
|
1517
|
-
|
|
1566
|
+
logger.info('Download was canceled', { name, did, version });
|
|
1567
|
+
|
|
1568
|
+
if ((await states.blocklet.getBlockletStatus(did)) === BlockletStatus.downloading) {
|
|
1569
|
+
await this._rollback(postAction, did, oldBlocklet);
|
|
1570
|
+
}
|
|
1518
1571
|
return;
|
|
1519
1572
|
}
|
|
1520
1573
|
} catch (err) {
|
|
1521
1574
|
logger.error('Download blocklet tarball failed', { name, did, version });
|
|
1522
1575
|
|
|
1523
|
-
preDownloadLock.release();
|
|
1524
|
-
|
|
1525
1576
|
this.emit(BlockletEvents.downloadFailed, {
|
|
1526
1577
|
meta: { did },
|
|
1527
1578
|
error: {
|
|
@@ -1549,6 +1600,31 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1549
1600
|
return;
|
|
1550
1601
|
}
|
|
1551
1602
|
|
|
1603
|
+
// update status
|
|
1604
|
+
try {
|
|
1605
|
+
await statusLock.acquire();
|
|
1606
|
+
|
|
1607
|
+
if ((await states.blocklet.getBlockletStatus(did)) !== BlockletStatus.downloading) {
|
|
1608
|
+
throw new Error('blocklet status changed durning download');
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
if (postAction === 'install') {
|
|
1612
|
+
const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
|
|
1613
|
+
this.emit(BlockletEvents.statusChange, state);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
if (['upgrade', 'downgrade'].includes(postAction)) {
|
|
1617
|
+
const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
|
|
1618
|
+
this.emit(BlockletEvents.statusChange, state);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
statusLock.release();
|
|
1622
|
+
} catch (error) {
|
|
1623
|
+
logger.error(error.message);
|
|
1624
|
+
statusLock.release();
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// install
|
|
1552
1628
|
try {
|
|
1553
1629
|
// install blocklet
|
|
1554
1630
|
if (postAction === 'install') {
|
|
@@ -1572,9 +1648,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1572
1648
|
const { did, version } = meta;
|
|
1573
1649
|
logger.info('do install blocklet', { did, version });
|
|
1574
1650
|
|
|
1575
|
-
const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
|
|
1576
|
-
this.emit(BlockletEvents.statusChange, state);
|
|
1577
|
-
|
|
1578
1651
|
try {
|
|
1579
1652
|
const installedBlocklet = await this._installBlocklet({
|
|
1580
1653
|
did,
|
|
@@ -1602,9 +1675,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1602
1675
|
const { version, did } = newBlocklet.meta;
|
|
1603
1676
|
logger.info(`do ${action} blocklet`, { did, version });
|
|
1604
1677
|
|
|
1605
|
-
const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
|
|
1606
|
-
this.emit(BlockletEvents.statusChange, state);
|
|
1607
|
-
|
|
1608
1678
|
try {
|
|
1609
1679
|
await this._upgradeBlocklet({
|
|
1610
1680
|
newBlocklet,
|
|
@@ -1636,6 +1706,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1636
1706
|
const res = await this.status(did, { forceSync: true });
|
|
1637
1707
|
this.emit(BlockletEvents.started, res);
|
|
1638
1708
|
} catch (error) {
|
|
1709
|
+
const status = await states.blocklet.getBlockletStatus(did);
|
|
1710
|
+
if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
|
|
1711
|
+
logger.info(`Check blocklet healthy failing because blocklet is ${fromBlockletStatus(status)}`);
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1639
1715
|
logger.error('check blocklet if started failed', { did, name, context, timeout, error });
|
|
1640
1716
|
|
|
1641
1717
|
await this.deleteProcess({ did }, context);
|
|
@@ -1832,7 +1908,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1832
1908
|
headers: {
|
|
1833
1909
|
'x-server-did': info.did,
|
|
1834
1910
|
'x-download-token': downloadToken,
|
|
1911
|
+
// FIXME: 先保证兼容性,后续删除
|
|
1835
1912
|
'x-server-publick-key': info.pk,
|
|
1913
|
+
'x-server-public-key': info.pk,
|
|
1836
1914
|
'x-server-signature': sign(info.did, info.sk, {
|
|
1837
1915
|
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
1838
1916
|
}),
|
|
@@ -2400,7 +2478,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2400
2478
|
headers: {
|
|
2401
2479
|
'x-server-did': info.did,
|
|
2402
2480
|
'x-download-token': blocklet?.tokens?.paidBlockletDownloadToken,
|
|
2481
|
+
// FIXME: 先保证兼容性,后续删除
|
|
2403
2482
|
'x-server-publick-key': info.pk,
|
|
2483
|
+
'x-server-public-key': info.pk,
|
|
2404
2484
|
'x-server-signature': sign(info.did, info.sk, {
|
|
2405
2485
|
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
2406
2486
|
}),
|
|
@@ -2434,7 +2514,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2434
2514
|
ticket.on('failed', async (err) => {
|
|
2435
2515
|
logger.error('queue failed', { entity: 'blocklet', action, did, version, name, error: err });
|
|
2436
2516
|
await this._rollback(action, did, oldBlocklet);
|
|
2437
|
-
|
|
2517
|
+
const eventNames = {
|
|
2518
|
+
upgrade: BlockletEvents.upgradeFailed,
|
|
2519
|
+
downgrade: BlockletEvents.downgradeFailed,
|
|
2520
|
+
};
|
|
2521
|
+
this.emit(eventNames[action], { blocklet: oldBlocklet, context });
|
|
2438
2522
|
states.notification.create({
|
|
2439
2523
|
title: `Blocklet ${capitalize(action)} Failed`,
|
|
2440
2524
|
description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message || 'queue exception'}`,
|
|
@@ -2805,7 +2889,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2805
2889
|
} catch (err) {
|
|
2806
2890
|
const b = await this._rollback(action, did, oldBlocklet);
|
|
2807
2891
|
logger.error(`failed to ${action} blocklet`, { did, version, name, error: err });
|
|
2892
|
+
|
|
2808
2893
|
this.emit(BlockletEvents.updated, b);
|
|
2894
|
+
|
|
2895
|
+
const eventNames = {
|
|
2896
|
+
upgrade: BlockletEvents.upgradeFailed,
|
|
2897
|
+
downgrade: BlockletEvents.downgradeFailed,
|
|
2898
|
+
};
|
|
2899
|
+
this.emit(eventNames[action], { blocklet: oldBlocklet, context });
|
|
2900
|
+
|
|
2809
2901
|
states.notification.create({
|
|
2810
2902
|
title: `Blocklet ${capitalize(action)} Failed`,
|
|
2811
2903
|
description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message}`,
|
|
@@ -3114,26 +3206,19 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3114
3206
|
|
|
3115
3207
|
// eslint-disable-next-line no-unused-vars
|
|
3116
3208
|
async _cancelDownload(blockletMeta, context) {
|
|
3117
|
-
const { did
|
|
3209
|
+
const { did } = blockletMeta;
|
|
3118
3210
|
|
|
3119
3211
|
if (this.downloadCtrls[did]) {
|
|
3120
3212
|
for (const cancelCtrl of this.downloadCtrls[did].values()) {
|
|
3121
3213
|
cancelCtrl.cancel();
|
|
3122
3214
|
}
|
|
3123
|
-
logger.info('cancel download blocklet', { did, name, version });
|
|
3124
3215
|
}
|
|
3125
3216
|
}
|
|
3126
3217
|
|
|
3127
3218
|
// eslint-disable-next-line no-unused-vars
|
|
3128
3219
|
async _cancelWaiting(blockletMeta, context) {
|
|
3129
|
-
const { did
|
|
3130
|
-
|
|
3131
|
-
const {
|
|
3132
|
-
job: { postAction, oldBlocklet },
|
|
3133
|
-
} = await this.installQueue.cancel(did);
|
|
3134
|
-
await this._rollback(postAction, did, oldBlocklet);
|
|
3135
|
-
|
|
3136
|
-
logger.info('cancel waiting blocklet', { did, name, version });
|
|
3220
|
+
const { did } = blockletMeta;
|
|
3221
|
+
return this.installQueue.cancel(did);
|
|
3137
3222
|
}
|
|
3138
3223
|
|
|
3139
3224
|
/**
|
package/lib/event.js
CHANGED
|
@@ -5,7 +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('
|
|
8
|
+
const handleInstanceInStore = require('./util/public-to-store');
|
|
9
9
|
|
|
10
10
|
const eventHub =
|
|
11
11
|
process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
|
|
@@ -27,6 +27,7 @@ module.exports = ({
|
|
|
27
27
|
domainStatus,
|
|
28
28
|
teamAPI,
|
|
29
29
|
certManager,
|
|
30
|
+
node,
|
|
30
31
|
}) => {
|
|
31
32
|
const notificationState = states.notification;
|
|
32
33
|
const nodeState = states.node;
|
|
@@ -155,19 +156,66 @@ module.exports = ({
|
|
|
155
156
|
};
|
|
156
157
|
|
|
157
158
|
const handleBlockletEvent = async (eventName, payload) => {
|
|
159
|
+
const blocklet = payload.blocklet || payload;
|
|
160
|
+
|
|
158
161
|
if ([BlockletEvents.deployed, BlockletEvents.installed].includes(eventName)) {
|
|
159
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
|
+
}
|
|
160
176
|
} else if ([BlockletEvents.upgraded, BlockletEvents.downgraded].includes(eventName)) {
|
|
161
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
|
+
}
|
|
162
191
|
} else if ([BlockletEvents.removed].includes(eventName)) {
|
|
163
192
|
await handleBlockletRemove(eventName, payload);
|
|
164
193
|
} else if ([BlockletEvents.started].includes(eventName)) {
|
|
165
194
|
try {
|
|
166
|
-
const
|
|
167
|
-
|
|
195
|
+
const { publicToStore } = blocklet.settings || {};
|
|
196
|
+
// 如果一个 blocklet 没有设置 publicToStore,启动成功后不应给 store 发请求
|
|
197
|
+
if (publicToStore) {
|
|
198
|
+
await handleInstanceInStore(blocklet, { publicToStore });
|
|
199
|
+
}
|
|
168
200
|
} catch (error) {
|
|
169
201
|
logger.error('handleInstanceInStore failed', { error });
|
|
170
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
|
+
}
|
|
171
219
|
}
|
|
172
220
|
|
|
173
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,9 +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
|
-
configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
|
|
230
|
-
|
|
231
216
|
deleteBlockletProcess: blockletManager.deleteProcess.bind(blockletManager),
|
|
217
|
+
configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
|
|
218
|
+
updateWhoCanAccess: blockletManager.updateWhoCanAccess.bind(blockletManager),
|
|
232
219
|
|
|
233
220
|
// For diagnose purpose
|
|
234
221
|
syncBlockletStatus: blockletManager.status.bind(blockletManager),
|
|
@@ -238,6 +225,7 @@ function ABTNode(options) {
|
|
|
238
225
|
getBlocklets: blockletManager.list.bind(blockletManager),
|
|
239
226
|
getBlocklet: blockletManager.detail.bind(blockletManager),
|
|
240
227
|
getBlockletDiff: blockletManager.diff.bind(blockletManager),
|
|
228
|
+
hasBlocklet: blockletManager.hasBlocklet.bind(blockletManager),
|
|
241
229
|
updateAllBlockletEnvironment: blockletManager.updateAllBlockletEnvironment.bind(blockletManager),
|
|
242
230
|
setBlockletInitialized: blockletManager.setInitialized.bind(blockletManager),
|
|
243
231
|
|
|
@@ -318,7 +306,6 @@ function ABTNode(options) {
|
|
|
318
306
|
processPassportIssuance: teamAPI.processPassportIssuance.bind(teamAPI),
|
|
319
307
|
configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
|
|
320
308
|
configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
|
|
321
|
-
configWhoCanAccess: teamAPI.configWhoCanAccess.bind(teamAPI),
|
|
322
309
|
|
|
323
310
|
// Challenge
|
|
324
311
|
generateChallenge: states.challenge.generate.bind(states.challenge),
|
|
@@ -404,6 +391,20 @@ function ABTNode(options) {
|
|
|
404
391
|
getRouterProvider,
|
|
405
392
|
};
|
|
406
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
|
+
|
|
407
408
|
const webhook = WebHook({ events, dataDirs, instance });
|
|
408
409
|
|
|
409
410
|
const initCron = () => {
|
package/lib/states/audit-log.js
CHANGED
|
@@ -111,6 +111,9 @@ 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)}`;
|
|
@@ -141,7 +144,7 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
141
144
|
return `switched passport to ${args.passport.name} for ${team}`;
|
|
142
145
|
case 'login':
|
|
143
146
|
return `${user} logged in to ${team} with passport ${args.passport.name}`;
|
|
144
|
-
case '
|
|
147
|
+
case 'updateWhoCanAccess':
|
|
145
148
|
return `updated access control policy to **${args.value}** for ${team} when ${args.reason}`;
|
|
146
149
|
case 'configPassportIssuance':
|
|
147
150
|
return `${args.enabled ? 'enabled' : 'disabled'} passport issuance for ${team}`;
|
|
@@ -214,6 +217,14 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
214
217
|
return `added extra domain **${args.domainAlias}** to ${site}`; // prettier-ignore
|
|
215
218
|
case 'deleteDomainAlias':
|
|
216
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
|
|
217
228
|
case 'updateGateway': {
|
|
218
229
|
let message = args.requestLimit.enabled ? `status: enabled, rate: ${args.requestLimit.rate}` : 'status: disabled';
|
|
219
230
|
message = `update gateway. ${message}`;
|
|
@@ -312,16 +323,21 @@ const getScope = (args = {}) => {
|
|
|
312
323
|
return args.teamDid;
|
|
313
324
|
}
|
|
314
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
|
+
|
|
315
336
|
// this param usually means mutating a child component
|
|
316
337
|
if (args.rootDid) {
|
|
317
338
|
return args.rootDid;
|
|
318
339
|
}
|
|
319
340
|
|
|
320
|
-
// this param usually means mutating a nested child component
|
|
321
|
-
if (Array.isArray(args.did)) {
|
|
322
|
-
return args.did[0];
|
|
323
|
-
}
|
|
324
|
-
|
|
325
341
|
return null;
|
|
326
342
|
};
|
|
327
343
|
|
package/lib/states/blocklet.js
CHANGED
|
@@ -102,6 +102,38 @@ class BlockletState extends BaseState {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
async getBlockletStatus(did) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
if (!did) {
|
|
108
|
+
resolve(null);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.db.findOne({ $or: [{ 'meta.did': did }, { appDid: did }] }, { status: 1 }, (err, doc) => {
|
|
112
|
+
if (err) {
|
|
113
|
+
return reject(err);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return resolve(doc ? doc.status : null);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
hasBlocklet(did) {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
if (!did) {
|
|
124
|
+
resolve(false);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.db.count({ $or: [{ 'meta.did': did }, { appDid: did }] }, (err, count) => {
|
|
128
|
+
if (err) {
|
|
129
|
+
return reject(err);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return resolve(!!count);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
105
137
|
getBlocklets(query = {}, projection) {
|
|
106
138
|
return new Promise((resolve, reject) => {
|
|
107
139
|
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/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
|
};
|
|
@@ -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/lib/webhook/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const { evaluateURLs } = require('@abtnode/util/lib/url-evaluation');
|
|
|
4
4
|
const checkURLAccessible = require('@abtnode/util/lib/url-evaluation/check-accessible-node');
|
|
5
5
|
const { EVENTS } = require('@abtnode/constant');
|
|
6
6
|
const WebHookSender = require('./sender');
|
|
7
|
+
const WalletSender = require('./sender/wallet');
|
|
7
8
|
const createQueue = require('../queue');
|
|
8
9
|
const IP = require('../util/ip');
|
|
9
10
|
const states = require('../states');
|
|
@@ -72,6 +73,11 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
72
73
|
const baseUrls = await getBaseUrls(instance, [external, internal]);
|
|
73
74
|
const senderFns = {};
|
|
74
75
|
|
|
76
|
+
// Always send message to wallet
|
|
77
|
+
webhookList.push({
|
|
78
|
+
type: WalletSender.type,
|
|
79
|
+
});
|
|
80
|
+
|
|
75
81
|
if (webhookList.length) {
|
|
76
82
|
for (let i = 0; i < webhookList.length; i++) {
|
|
77
83
|
const item = webhookList[i];
|
|
@@ -79,8 +85,7 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
79
85
|
const senderInstance = WebHookSender.getMessageSender(item.type);
|
|
80
86
|
senderFns[item.type] = senderInstance.send.bind(senderInstance);
|
|
81
87
|
}
|
|
82
|
-
const {
|
|
83
|
-
const options = { ...message, nodeInfo: `*${name}*` };
|
|
88
|
+
const options = { ...message, nodeInfo, node: instance };
|
|
84
89
|
if (item.type === 'slack') {
|
|
85
90
|
// eslint-disable-next-line
|
|
86
91
|
options.urlInfo = await getSlackUrlInfo(message.action, baseUrls);
|
|
@@ -3,6 +3,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:sender');
|
|
|
3
3
|
|
|
4
4
|
const Slack = require('./slack');
|
|
5
5
|
const Api = require('./api');
|
|
6
|
+
const Wallet = require('./wallet');
|
|
6
7
|
|
|
7
8
|
const SenderMap = new Map([
|
|
8
9
|
[Slack.type, Slack],
|
|
@@ -12,6 +13,10 @@ const SenderMap = new Map([
|
|
|
12
13
|
const getSenderNames = () => [...SenderMap.keys()];
|
|
13
14
|
|
|
14
15
|
const getSender = (name) => {
|
|
16
|
+
if (name === Wallet.type) {
|
|
17
|
+
return Wallet;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
if (!SenderMap.has(name)) {
|
|
16
21
|
logger.error(`getSender:sender name [${name}] does not exist`);
|
|
17
22
|
return null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const logger = require('@abtnode/logger')('@abtnode/core:sender:api');
|
|
2
|
+
const { sendToUser } = require('@blocklet/sdk/lib/util/send-notification');
|
|
3
|
+
const { ROLES, PASSPORT_STATUS } = require('@abtnode/constant');
|
|
4
|
+
const BaseSender = require('../base');
|
|
5
|
+
|
|
6
|
+
class WalletSender extends BaseSender {
|
|
7
|
+
async send(params, data = {}) {
|
|
8
|
+
const { title, description, nodeInfo, node } = data;
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const sender = {
|
|
12
|
+
appDid: nodeInfo.did,
|
|
13
|
+
appSk: nodeInfo.sk,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const message = {
|
|
17
|
+
title,
|
|
18
|
+
body: description,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { users } = await node.getUsers({ teamDid: nodeInfo.did, paging: { pageSize: 100 } });
|
|
22
|
+
const adminUsers = users
|
|
23
|
+
.filter(
|
|
24
|
+
(x) =>
|
|
25
|
+
x.approved &&
|
|
26
|
+
(x.passports || []).some(
|
|
27
|
+
(y) => [ROLES.OWNER, ROLES.ADMIN].includes(y.name) && y.status === PASSPORT_STATUS.VALID
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
.map((x) => x.did);
|
|
31
|
+
|
|
32
|
+
if (!adminUsers.length) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await sendToUser(adminUsers, message, sender, process.env.ABT_NODE_SERVICE_PORT);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error('failed to push notification to wallet', { error });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
WalletSender.type = 'wallet';
|
|
44
|
+
|
|
45
|
+
module.exports = WalletSender;
|
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.4",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,31 +19,32 @@
|
|
|
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.4",
|
|
23
|
+
"@abtnode/constant": "1.8.4",
|
|
24
|
+
"@abtnode/cron": "1.8.4",
|
|
25
|
+
"@abtnode/db": "1.8.4",
|
|
26
|
+
"@abtnode/logger": "1.8.4",
|
|
27
|
+
"@abtnode/queue": "1.8.4",
|
|
28
|
+
"@abtnode/rbac": "1.8.4",
|
|
29
|
+
"@abtnode/router-provider": "1.8.4",
|
|
30
|
+
"@abtnode/static-server": "1.8.4",
|
|
31
|
+
"@abtnode/timemachine": "1.8.4",
|
|
32
|
+
"@abtnode/util": "1.8.4",
|
|
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.4",
|
|
41
|
+
"@blocklet/sdk": "1.8.4",
|
|
41
42
|
"@fidm/x509": "^1.2.1",
|
|
42
|
-
"@nedb/core": "^1.3.
|
|
43
|
-
"@nedb/multi": "^1.3.
|
|
44
|
-
"@ocap/mcrypto": "1.17.
|
|
45
|
-
"@ocap/util": "1.17.
|
|
46
|
-
"@ocap/wallet": "1.17.
|
|
43
|
+
"@nedb/core": "^1.3.2",
|
|
44
|
+
"@nedb/multi": "^1.3.2",
|
|
45
|
+
"@ocap/mcrypto": "1.17.5",
|
|
46
|
+
"@ocap/util": "1.17.5",
|
|
47
|
+
"@ocap/wallet": "1.17.5",
|
|
47
48
|
"@slack/webhook": "^5.0.3",
|
|
48
49
|
"axios": "^0.27.2",
|
|
49
50
|
"axon": "^2.0.3",
|
|
@@ -81,5 +82,5 @@
|
|
|
81
82
|
"express": "^4.17.1",
|
|
82
83
|
"jest": "^27.4.5"
|
|
83
84
|
},
|
|
84
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "c42fb1bb84c5eef0f753fd5397d8007c7a6eee19"
|
|
85
86
|
}
|