@abtnode/core 1.7.24 → 1.7.27
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/team.js +54 -22
- package/lib/blocklet/manager/disk.js +321 -89
- package/lib/index.js +7 -1
- package/lib/router/index.js +2 -5
- package/lib/states/user.js +41 -5
- package/lib/team/manager.js +34 -4
- package/lib/util/blocklet.js +2 -17
- package/lib/util/index.js +1 -1
- package/package.json +22 -21
package/lib/api/team.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const { EventEmitter } = require('events');
|
|
2
2
|
const pick = require('lodash/pick');
|
|
3
3
|
const logger = require('@abtnode/logger')('@abtnode/core:api:team');
|
|
4
|
-
const { ROLES, genPermissionName, EVENTS, WHO_CAN_ACCESS } = require('@abtnode/constant');
|
|
4
|
+
const { ROLES, genPermissionName, EVENTS, WHO_CAN_ACCESS, PASSPORT_STATUS } = require('@abtnode/constant');
|
|
5
5
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
6
6
|
const { BlockletEvents } = require('@blocklet/meta/lib/constants');
|
|
7
7
|
const { validateTrustedPassportIssuers } = require('../validators/trusted-passport');
|
|
8
8
|
const { validateCreateRole, validateUpdateRole } = require('../validators/role');
|
|
9
9
|
const { validateCreatePermission, validateUpdatePermission } = require('../validators/permission');
|
|
10
10
|
|
|
11
|
+
const MAX_USER_PAGE_SIZE = 100;
|
|
12
|
+
|
|
11
13
|
const validateReservedRole = (role) => {
|
|
12
14
|
if (Object.values(ROLES).includes(role)) {
|
|
13
15
|
throw new Error(`The role ${role} is reserved`);
|
|
@@ -68,29 +70,37 @@ class TeamAPI extends EventEmitter {
|
|
|
68
70
|
return doc;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
async getUsers({ teamDid }) {
|
|
73
|
+
async getUsers({ teamDid, query, paging: inputPaging, sort }) {
|
|
72
74
|
const state = await this.getUserState(teamDid);
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
if (inputPaging?.pageSize > MAX_USER_PAGE_SIZE) {
|
|
77
|
+
throw new Error(`Length of users should not exceed ${MAX_USER_PAGE_SIZE} per page`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const { list, paging } = await state.getUsers({ query, sort, paging: { pageSize: 20, ...inputPaging } });
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
users: list.map(
|
|
84
|
+
(d) =>
|
|
85
|
+
pick(d, [
|
|
86
|
+
'did',
|
|
87
|
+
'pk',
|
|
88
|
+
'role',
|
|
89
|
+
'email',
|
|
90
|
+
'fullName',
|
|
91
|
+
'approved',
|
|
92
|
+
'createdAt',
|
|
93
|
+
'updatedAt',
|
|
94
|
+
'passports',
|
|
95
|
+
'firstLoginAt',
|
|
96
|
+
'lastLoginAt',
|
|
97
|
+
'remark',
|
|
98
|
+
'avatar',
|
|
99
|
+
])
|
|
100
|
+
// eslint-disable-next-line function-paren-newline
|
|
101
|
+
),
|
|
102
|
+
paging,
|
|
103
|
+
};
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
async getUsersCount({ teamDid }) {
|
|
@@ -99,6 +109,28 @@ class TeamAPI extends EventEmitter {
|
|
|
99
109
|
return state.count();
|
|
100
110
|
}
|
|
101
111
|
|
|
112
|
+
async getUsersCountPerRole({ teamDid }) {
|
|
113
|
+
const roles = await this.getRoles({ teamDid });
|
|
114
|
+
|
|
115
|
+
const state = await this.getUserState(teamDid);
|
|
116
|
+
|
|
117
|
+
const res = [];
|
|
118
|
+
|
|
119
|
+
const all = await state.count();
|
|
120
|
+
res.push({ key: '$all', value: all });
|
|
121
|
+
|
|
122
|
+
for (const { name } of roles) {
|
|
123
|
+
// eslint-disable-next-line no-await-in-loop
|
|
124
|
+
const count = await state.count({ passports: { $elemMatch: { name, status: PASSPORT_STATUS.VALID } } });
|
|
125
|
+
res.push({ key: name, value: count });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const none = await state.count({ passports: { $size: 0 } });
|
|
129
|
+
res.push({ key: '$none', value: none });
|
|
130
|
+
|
|
131
|
+
return res;
|
|
132
|
+
}
|
|
133
|
+
|
|
102
134
|
async getUser({ teamDid, user }) {
|
|
103
135
|
const state = await this.getUserState(teamDid);
|
|
104
136
|
|
|
@@ -10,7 +10,7 @@ const capitalize = require('lodash/capitalize');
|
|
|
10
10
|
const { Throttle } = require('stream-throttle');
|
|
11
11
|
const LRU = require('lru-cache');
|
|
12
12
|
const joi = require('joi');
|
|
13
|
-
|
|
13
|
+
const { sign } = require('@arcblock/jwt');
|
|
14
14
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
15
15
|
const { verifyPresentation } = require('@arcblock/vc');
|
|
16
16
|
const { toBase58, isHex } = require('@ocap/util');
|
|
@@ -45,6 +45,7 @@ const toBlockletDid = require('@blocklet/meta/lib/did');
|
|
|
45
45
|
const { validateMeta } = require('@blocklet/meta/lib/validate');
|
|
46
46
|
const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
47
47
|
const { titleSchema, descriptionSchema } = require('@blocklet/meta/lib/schema');
|
|
48
|
+
const hasReservedKey = require('@blocklet/meta/lib/has-reserved-key');
|
|
48
49
|
|
|
49
50
|
const {
|
|
50
51
|
BlockletStatus,
|
|
@@ -101,7 +102,6 @@ const {
|
|
|
101
102
|
getDiffFiles,
|
|
102
103
|
getBundleDir,
|
|
103
104
|
needBlockletDownload,
|
|
104
|
-
verifyPurchase,
|
|
105
105
|
findAvailableDid,
|
|
106
106
|
ensureMeta,
|
|
107
107
|
} = require('../../util/blocklet');
|
|
@@ -172,13 +172,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
172
172
|
/**
|
|
173
173
|
* @param {*} dataDirs generate by ../../util:getDataDirs
|
|
174
174
|
*/
|
|
175
|
-
constructor({ dataDirs, registry, startQueue, installQueue, daemon = false }) {
|
|
175
|
+
constructor({ dataDirs, registry, startQueue, installQueue, daemon = false, teamManager }) {
|
|
176
176
|
super();
|
|
177
177
|
|
|
178
178
|
this.dataDirs = dataDirs;
|
|
179
179
|
this.installDir = dataDirs.blocklets;
|
|
180
180
|
this.startQueue = startQueue;
|
|
181
181
|
this.installQueue = installQueue;
|
|
182
|
+
this.teamManager = teamManager;
|
|
183
|
+
|
|
182
184
|
/**
|
|
183
185
|
* { did: Map({ <childDid>: <downloadFile.cancelCtrl> }) }
|
|
184
186
|
*/
|
|
@@ -209,9 +211,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
209
211
|
// ============================================================================================
|
|
210
212
|
|
|
211
213
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* @param {
|
|
214
|
+
*
|
|
215
|
+
*
|
|
216
|
+
* @param {{
|
|
217
|
+
* url: string;
|
|
218
|
+
* sync: boolean = false;
|
|
219
|
+
* }} params
|
|
220
|
+
* @param {{
|
|
221
|
+
* [key: string]: any
|
|
222
|
+
* }} context
|
|
223
|
+
* @return {*}
|
|
224
|
+
* @memberof BlockletManager
|
|
215
225
|
*/
|
|
216
226
|
async install(params, context) {
|
|
217
227
|
logger.debug('install blocklet', { params, context });
|
|
@@ -245,7 +255,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
245
255
|
/**
|
|
246
256
|
* @param {String} rootDid
|
|
247
257
|
* @param {String} mountPoint
|
|
248
|
-
* @param {Boolean} context.blockletPurchaseVerified
|
|
249
258
|
*
|
|
250
259
|
* installFromUrl
|
|
251
260
|
* @param {String} url
|
|
@@ -259,8 +268,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
259
268
|
* Custom info
|
|
260
269
|
* @param {String} title custom component title
|
|
261
270
|
* @param {String} name custom component name
|
|
271
|
+
*
|
|
272
|
+
* @param {ConfigEntry} configs pre configs
|
|
262
273
|
*/
|
|
263
|
-
async installComponent(
|
|
274
|
+
async installComponent(
|
|
275
|
+
{ rootDid, mountPoint, url, file, did, diffVersion, deleteSet, title, name, configs, downloadToken },
|
|
276
|
+
context = {}
|
|
277
|
+
) {
|
|
264
278
|
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
265
279
|
|
|
266
280
|
if (file) {
|
|
@@ -268,7 +282,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
268
282
|
}
|
|
269
283
|
|
|
270
284
|
if (url) {
|
|
271
|
-
return this._installComponentFromUrl({
|
|
285
|
+
return this._installComponentFromUrl({
|
|
286
|
+
rootDid,
|
|
287
|
+
mountPoint,
|
|
288
|
+
url,
|
|
289
|
+
context,
|
|
290
|
+
title,
|
|
291
|
+
did,
|
|
292
|
+
name,
|
|
293
|
+
configs,
|
|
294
|
+
downloadToken,
|
|
295
|
+
});
|
|
272
296
|
}
|
|
273
297
|
|
|
274
298
|
// should not be here
|
|
@@ -317,7 +341,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
317
341
|
const did = get(vc, 'credentialSubject.purchased.blocklet.id');
|
|
318
342
|
const registry = urlObject.origin;
|
|
319
343
|
|
|
320
|
-
return this._installFromStore({ did, registry },
|
|
344
|
+
return this._installFromStore({ did, registry }, context);
|
|
321
345
|
}
|
|
322
346
|
|
|
323
347
|
async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
|
|
@@ -833,6 +857,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
833
857
|
async upgrade({ did, registryUrl, sync }, context) {
|
|
834
858
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
835
859
|
|
|
860
|
+
if (!registryUrl && blocklet.source === BlockletSource.url) {
|
|
861
|
+
return this._installFromUrl({ url: blocklet.deployedFrom }, context);
|
|
862
|
+
}
|
|
863
|
+
|
|
836
864
|
// TODO: 查看了下目前页面中的升级按钮,都是会传 registryUrl 过来的,这个函数里的逻辑感觉需要在以后做一个简化
|
|
837
865
|
if (!registryUrl && blocklet.source !== BlockletSource.registry) {
|
|
838
866
|
throw new Error('Wrong upgrade source, empty registryUrl or not installed from blocklet registry');
|
|
@@ -1408,7 +1436,21 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1408
1436
|
}
|
|
1409
1437
|
}
|
|
1410
1438
|
|
|
1411
|
-
|
|
1439
|
+
/**
|
|
1440
|
+
*
|
|
1441
|
+
*
|
|
1442
|
+
* @param {{
|
|
1443
|
+
* blocklet: {},
|
|
1444
|
+
* context: {},
|
|
1445
|
+
* postAction: 'install' | 'upgrade' | 'downgrade',
|
|
1446
|
+
* oldBlocklet: {},
|
|
1447
|
+
* throwOnError: Error
|
|
1448
|
+
* }} params
|
|
1449
|
+
* @return {*}
|
|
1450
|
+
* @memberof BlockletManager
|
|
1451
|
+
*/
|
|
1452
|
+
async onDownload(params) {
|
|
1453
|
+
const { blocklet, context, postAction, oldBlocklet, throwOnError } = params;
|
|
1412
1454
|
const { meta } = blocklet;
|
|
1413
1455
|
const { name, did, version } = meta;
|
|
1414
1456
|
|
|
@@ -1433,7 +1475,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1433
1475
|
|
|
1434
1476
|
preDownloadLock.release();
|
|
1435
1477
|
|
|
1436
|
-
const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet);
|
|
1478
|
+
const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet, context);
|
|
1437
1479
|
|
|
1438
1480
|
if (isCancelled) {
|
|
1439
1481
|
logger.info('Download was canceled manually', { name, did, version });
|
|
@@ -1624,7 +1666,21 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1624
1666
|
}
|
|
1625
1667
|
}
|
|
1626
1668
|
|
|
1627
|
-
|
|
1669
|
+
/**
|
|
1670
|
+
***
|
|
1671
|
+
*
|
|
1672
|
+
* @param {{
|
|
1673
|
+
* did: string;
|
|
1674
|
+
* registry: string;
|
|
1675
|
+
* sync: boolean;
|
|
1676
|
+
* }} params
|
|
1677
|
+
* @param {*} context
|
|
1678
|
+
* @return {*}
|
|
1679
|
+
* @memberof BlockletManager
|
|
1680
|
+
*/
|
|
1681
|
+
async _installFromStore(params, context) {
|
|
1682
|
+
const { did, registry, sync } = params;
|
|
1683
|
+
|
|
1628
1684
|
logger.debug('start install blocklet', { did });
|
|
1629
1685
|
if (!isValidDid(did)) {
|
|
1630
1686
|
throw new Error('Blocklet did is invalid');
|
|
@@ -1642,8 +1698,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1642
1698
|
throw new Error('Can not install an already installed blocklet');
|
|
1643
1699
|
}
|
|
1644
1700
|
|
|
1645
|
-
verifyPurchase(meta, context);
|
|
1646
|
-
|
|
1647
1701
|
// install
|
|
1648
1702
|
return this._install({
|
|
1649
1703
|
meta,
|
|
@@ -1654,7 +1708,20 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1654
1708
|
});
|
|
1655
1709
|
}
|
|
1656
1710
|
|
|
1657
|
-
|
|
1711
|
+
/**
|
|
1712
|
+
*
|
|
1713
|
+
*
|
|
1714
|
+
* @param {{
|
|
1715
|
+
* url: string;
|
|
1716
|
+
* sync: boolean;
|
|
1717
|
+
* }} params
|
|
1718
|
+
* @param {{}} context
|
|
1719
|
+
* @return {*}
|
|
1720
|
+
* @memberof BlockletManager
|
|
1721
|
+
*/
|
|
1722
|
+
async _installFromUrl(params, context) {
|
|
1723
|
+
const { url, sync } = params;
|
|
1724
|
+
|
|
1658
1725
|
logger.debug('start install blocklet', { url });
|
|
1659
1726
|
|
|
1660
1727
|
const { inStore, registryUrl, blockletDid } = await parseSourceUrl(url);
|
|
@@ -1695,7 +1762,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1695
1762
|
});
|
|
1696
1763
|
}
|
|
1697
1764
|
|
|
1698
|
-
async _installComponentFromUrl({
|
|
1765
|
+
async _installComponentFromUrl({
|
|
1766
|
+
rootDid,
|
|
1767
|
+
mountPoint,
|
|
1768
|
+
url,
|
|
1769
|
+
context,
|
|
1770
|
+
title,
|
|
1771
|
+
name: inputName,
|
|
1772
|
+
did: inputDid,
|
|
1773
|
+
configs,
|
|
1774
|
+
downloadToken,
|
|
1775
|
+
}) {
|
|
1699
1776
|
const blocklet = await this._getBlockletForInstallation(rootDid);
|
|
1700
1777
|
if (!blocklet) {
|
|
1701
1778
|
throw new Error('Root blocklet does not exist');
|
|
@@ -1703,12 +1780,28 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1703
1780
|
|
|
1704
1781
|
const meta = await getBlockletMetaFromUrl(url);
|
|
1705
1782
|
|
|
1783
|
+
// 如果是一个付费的blocklet,需要携带token才能下载成功
|
|
1784
|
+
if (!isFreeBlocklet(meta)) {
|
|
1785
|
+
const info = await states.node.read();
|
|
1786
|
+
|
|
1787
|
+
// eslint-disable-next-line no-param-reassign
|
|
1788
|
+
context = {
|
|
1789
|
+
...context,
|
|
1790
|
+
headers: {
|
|
1791
|
+
'x-server-did': info.did,
|
|
1792
|
+
'x-download-token': downloadToken,
|
|
1793
|
+
'x-server-publick-key': info.pk,
|
|
1794
|
+
'x-server-signature': sign(info.did, info.sk, {
|
|
1795
|
+
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
1796
|
+
}),
|
|
1797
|
+
},
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1706
1801
|
if (!isComponentBlocklet(meta)) {
|
|
1707
1802
|
throw new Error('The blocklet cannot be a component');
|
|
1708
1803
|
}
|
|
1709
1804
|
|
|
1710
|
-
verifyPurchase(meta, context);
|
|
1711
|
-
|
|
1712
1805
|
if (title) {
|
|
1713
1806
|
meta.title = await titleSchema.validateAsync(title);
|
|
1714
1807
|
}
|
|
@@ -1724,26 +1817,41 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1724
1817
|
did = found.did;
|
|
1725
1818
|
}
|
|
1726
1819
|
|
|
1727
|
-
const
|
|
1728
|
-
{
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
];
|
|
1820
|
+
const newChild = {
|
|
1821
|
+
meta: ensureMeta(meta, { did, name }),
|
|
1822
|
+
mountPoint,
|
|
1823
|
+
bundleSource: { url },
|
|
1824
|
+
dynamic: true,
|
|
1825
|
+
children: await parseChildrenFromMeta(meta, { ...context, ancestors: [{ mountPoint }] }),
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
checkDuplicateComponents([...blocklet.children, newChild]);
|
|
1829
|
+
|
|
1830
|
+
try {
|
|
1831
|
+
// add component to db
|
|
1832
|
+
await states.blocklet.addChildren(rootDid, [newChild]);
|
|
1736
1833
|
|
|
1737
|
-
|
|
1834
|
+
// update navigation
|
|
1835
|
+
await this._upsertDynamicNavigation(blocklet.meta.did, newChild);
|
|
1738
1836
|
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1837
|
+
// update configs
|
|
1838
|
+
if (Array.isArray(configs)) {
|
|
1839
|
+
if (hasReservedKey(configs)) {
|
|
1840
|
+
throw new Error('Component key of environments can not start with `ABT_NODE_` or `BLOCKLET_`');
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
await states.blockletExtras.setConfigs([blocklet.meta.did, newChild.meta.did], configs);
|
|
1844
|
+
}
|
|
1845
|
+
} catch (err) {
|
|
1846
|
+
logger.error('Add component failed', err);
|
|
1847
|
+
await this._rollback('upgrade', rootDid, blocklet);
|
|
1848
|
+
throw err;
|
|
1849
|
+
}
|
|
1742
1850
|
|
|
1743
1851
|
return this.updateChildren(
|
|
1744
1852
|
{
|
|
1745
1853
|
did: rootDid,
|
|
1746
|
-
children: [...blocklet.children,
|
|
1854
|
+
children: [...blocklet.children, newChild],
|
|
1747
1855
|
oldBlocklet: blocklet,
|
|
1748
1856
|
},
|
|
1749
1857
|
context
|
|
@@ -2033,50 +2141,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2033
2141
|
throw new Error('the blocklet is not installed');
|
|
2034
2142
|
}
|
|
2035
2143
|
|
|
2036
|
-
const { bundleDid } = blocklet.meta;
|
|
2037
|
-
|
|
2038
|
-
let versions = this.cachedBlockletVersions.get(did);
|
|
2039
|
-
|
|
2040
|
-
if (!versions) {
|
|
2041
|
-
const { blockletRegistryList } = await states.node.read();
|
|
2042
|
-
const tasks = blockletRegistryList.map((registry) =>
|
|
2043
|
-
this.registry
|
|
2044
|
-
.getBlockletMeta({ did: bundleDid, registryUrl: registry.url })
|
|
2045
|
-
.then((item) => ({ did, version: item.version, registryUrl: registry.url }))
|
|
2046
|
-
.catch((error) => {
|
|
2047
|
-
if (error.response && error.response.status === 404) {
|
|
2048
|
-
return;
|
|
2049
|
-
}
|
|
2050
|
-
logger.error('get blocklet meta from registry failed', { did, error });
|
|
2051
|
-
})); // prettier-ignore
|
|
2052
|
-
|
|
2053
|
-
versions = await Promise.all(tasks);
|
|
2054
|
-
this.cachedBlockletVersions.set(did, versions);
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
versions = versions.filter((item) => item && semver.gt(item.version, version));
|
|
2058
|
-
|
|
2059
|
-
if (versions.length === 0) {
|
|
2060
|
-
return null;
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
// When new version found from the store where the blocklet was installed from, we should use that store first
|
|
2064
2144
|
if (blocklet.source === BlockletSource.registry && blocklet.deployedFrom) {
|
|
2065
|
-
|
|
2066
|
-
if (latestFromSameRegistry) {
|
|
2067
|
-
return latestFromSameRegistry;
|
|
2068
|
-
}
|
|
2145
|
+
return this._getLatestBlockletVersionFromStore({ blocklet, version });
|
|
2069
2146
|
}
|
|
2070
2147
|
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
if (semver.lt(latestBlockletVersion.version, item.version)) {
|
|
2075
|
-
latestBlockletVersion = item;
|
|
2076
|
-
}
|
|
2077
|
-
});
|
|
2148
|
+
if (blocklet.source === BlockletSource.url && blocklet.deployedFrom) {
|
|
2149
|
+
return this._getLatestBlockletVersionFromUrl({ blocklet, version });
|
|
2150
|
+
}
|
|
2078
2151
|
|
|
2079
|
-
return
|
|
2152
|
+
return null;
|
|
2080
2153
|
}
|
|
2081
2154
|
|
|
2082
2155
|
getCrons() {
|
|
@@ -2132,7 +2205,22 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2132
2205
|
.filter((x) => (skipDeleted ? x.status !== BlockletStatus.deleted : true));
|
|
2133
2206
|
}
|
|
2134
2207
|
|
|
2135
|
-
|
|
2208
|
+
/**
|
|
2209
|
+
*
|
|
2210
|
+
*
|
|
2211
|
+
* @param {{
|
|
2212
|
+
* meta: {}; // blocklet meta
|
|
2213
|
+
* source: number; // example: BlockletSource.registry,
|
|
2214
|
+
* deployedFrom: string;
|
|
2215
|
+
* context: {}
|
|
2216
|
+
* sync: boolean = false;
|
|
2217
|
+
* }} params
|
|
2218
|
+
* @return {*}
|
|
2219
|
+
* @memberof BlockletManager
|
|
2220
|
+
*/
|
|
2221
|
+
async _install(params) {
|
|
2222
|
+
const { meta, source, deployedFrom, context, sync } = params;
|
|
2223
|
+
|
|
2136
2224
|
validateBlockletMeta(meta, { ensureDist: true });
|
|
2137
2225
|
|
|
2138
2226
|
const { name, did, version } = meta;
|
|
@@ -2141,6 +2229,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2141
2229
|
|
|
2142
2230
|
const children = await this._getChildrenForInstallation(meta);
|
|
2143
2231
|
try {
|
|
2232
|
+
// 创建一个blocklet到database
|
|
2144
2233
|
const blocklet = await states.blocklet.addBlocklet({
|
|
2145
2234
|
meta,
|
|
2146
2235
|
source,
|
|
@@ -2157,7 +2246,15 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2157
2246
|
const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
|
|
2158
2247
|
this.emit(BlockletEvents.added, blocklet1);
|
|
2159
2248
|
|
|
2160
|
-
|
|
2249
|
+
/** @type {{
|
|
2250
|
+
* blocklet: any;
|
|
2251
|
+
* oldBlocklet: {
|
|
2252
|
+
* children: any[];
|
|
2253
|
+
* extraState: any;
|
|
2254
|
+
* };
|
|
2255
|
+
* context: {};
|
|
2256
|
+
* postAction: string
|
|
2257
|
+
* }} */
|
|
2161
2258
|
const downloadParams = {
|
|
2162
2259
|
blocklet: { ...blocklet1 },
|
|
2163
2260
|
oldBlocklet: {
|
|
@@ -2220,6 +2317,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2220
2317
|
}
|
|
2221
2318
|
}
|
|
2222
2319
|
|
|
2320
|
+
/**
|
|
2321
|
+
*
|
|
2322
|
+
*
|
|
2323
|
+
* @param {{}} { meta, source, deployedFrom, context, sync }
|
|
2324
|
+
* @return {*}
|
|
2325
|
+
* @memberof BlockletManager
|
|
2326
|
+
*/
|
|
2223
2327
|
async _upgrade({ meta, source, deployedFrom, context, sync }) {
|
|
2224
2328
|
validateBlockletMeta(meta, { ensureDist: meta.group !== BlockletGroup.gateway });
|
|
2225
2329
|
|
|
@@ -2242,6 +2346,26 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2242
2346
|
|
|
2243
2347
|
this.emit(BlockletEvents.statusChange, newBlocklet);
|
|
2244
2348
|
|
|
2349
|
+
// 如果是一个付费的blocklet,需要携带token才能下载成功
|
|
2350
|
+
if (!isFreeBlocklet(meta)) {
|
|
2351
|
+
const blocklet = await states.blocklet.getBlocklet(did);
|
|
2352
|
+
|
|
2353
|
+
const info = await states.node.read();
|
|
2354
|
+
|
|
2355
|
+
// eslint-disable-next-line no-param-reassign
|
|
2356
|
+
context = {
|
|
2357
|
+
...context,
|
|
2358
|
+
headers: {
|
|
2359
|
+
'x-server-did': info.did,
|
|
2360
|
+
'x-download-token': blocklet?.tokens?.paidBlockletDownloadToken,
|
|
2361
|
+
'x-server-publick-key': info.pk,
|
|
2362
|
+
'x-server-signature': sign(info.did, info.sk, {
|
|
2363
|
+
exp: (Date.now() + 5 * 60 * 1000) / 1000,
|
|
2364
|
+
}),
|
|
2365
|
+
},
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2245
2369
|
// download
|
|
2246
2370
|
const downloadParams = {
|
|
2247
2371
|
oldBlocklet: { ...oldBlocklet },
|
|
@@ -2255,7 +2379,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2255
2379
|
await this.onDownload({ ...downloadParams, throwOnError: true });
|
|
2256
2380
|
return states.blocklet.getBlocklet(did);
|
|
2257
2381
|
}
|
|
2258
|
-
|
|
2259
2382
|
const ticket = this.installQueue.push(
|
|
2260
2383
|
{
|
|
2261
2384
|
entity: 'blocklet',
|
|
@@ -2469,6 +2592,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2469
2592
|
// Update dynamic component meta in blocklet settings
|
|
2470
2593
|
await this._ensureDynamicChildrenInSettings(blocklet);
|
|
2471
2594
|
|
|
2595
|
+
if (context?.headers?.['x-download-token']) {
|
|
2596
|
+
await states.blocklet.updateBlocklet(did, {
|
|
2597
|
+
tokens: {
|
|
2598
|
+
paidBlockletDownloadToken: context.headers['x-download-token'],
|
|
2599
|
+
},
|
|
2600
|
+
});
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2472
2603
|
states.notification.create({
|
|
2473
2604
|
title: 'Blocklet Installed',
|
|
2474
2605
|
description: `Blocklet ${meta.name}@${meta.version} is installed successfully. (Source: ${
|
|
@@ -2657,11 +2788,23 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2657
2788
|
}
|
|
2658
2789
|
|
|
2659
2790
|
/**
|
|
2660
|
-
*
|
|
2661
|
-
*
|
|
2662
|
-
*
|
|
2791
|
+
*
|
|
2792
|
+
*
|
|
2793
|
+
* @param {{
|
|
2794
|
+
* url: string,
|
|
2795
|
+
* cwd: string,
|
|
2796
|
+
* tarball: string,
|
|
2797
|
+
* did: string,
|
|
2798
|
+
* integrity: string,
|
|
2799
|
+
* verify: boolean = true,
|
|
2800
|
+
* ctrlStore: {},
|
|
2801
|
+
* rootDid: string,
|
|
2802
|
+
* context: {} = {},
|
|
2803
|
+
* }} { url, cwd, tarball, did, integrity, verify = true, ctrlStore = {}, rootDid, context = {} }
|
|
2804
|
+
* @return {*}
|
|
2805
|
+
* @memberof BlockletManager
|
|
2663
2806
|
*/
|
|
2664
|
-
async _downloadTarball({ url, cwd, tarball, did, integrity, verify = true, ctrlStore = {}, rootDid }) {
|
|
2807
|
+
async _downloadTarball({ url, cwd, tarball, did, integrity, verify = true, ctrlStore = {}, rootDid, context = {} }) {
|
|
2665
2808
|
fs.mkdirSync(cwd, { recursive: true });
|
|
2666
2809
|
|
|
2667
2810
|
const tarballName = url.split('/').slice(-1)[0];
|
|
@@ -2673,7 +2816,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2673
2816
|
const cachedTarFile = await this._getCachedTarFile(integrity);
|
|
2674
2817
|
if (cachedTarFile) {
|
|
2675
2818
|
logger.info('found cache tarFile', { did, tarballName, integrity });
|
|
2676
|
-
await fs.move(cachedTarFile, tarballPath);
|
|
2819
|
+
await fs.move(cachedTarFile, tarballPath, { overwrite: true });
|
|
2677
2820
|
} else if (protocol.startsWith('file')) {
|
|
2678
2821
|
await fs.copy(decodeURIComponent(pathname), tarballPath);
|
|
2679
2822
|
} else {
|
|
@@ -2684,7 +2827,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2684
2827
|
}
|
|
2685
2828
|
ctrlStore[rootDid].set(did, cancelCtrl);
|
|
2686
2829
|
|
|
2687
|
-
await downloadFile(url, path.join(cwd, tarballName), { cancelCtrl });
|
|
2830
|
+
await downloadFile(url, path.join(cwd, tarballName), { cancelCtrl }, context);
|
|
2688
2831
|
|
|
2689
2832
|
if (ctrlStore[rootDid]) {
|
|
2690
2833
|
ctrlStore[rootDid].delete(did);
|
|
@@ -2773,12 +2916,16 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2773
2916
|
}
|
|
2774
2917
|
|
|
2775
2918
|
/**
|
|
2776
|
-
*
|
|
2777
|
-
*
|
|
2778
|
-
* @param {
|
|
2779
|
-
* @
|
|
2919
|
+
*
|
|
2920
|
+
*
|
|
2921
|
+
* @param {*} meta
|
|
2922
|
+
* @param {*} rootDid
|
|
2923
|
+
* @param {*} url
|
|
2924
|
+
* @param {{}} [context={}]
|
|
2925
|
+
* @return {*}
|
|
2926
|
+
* @memberof BlockletManager
|
|
2780
2927
|
*/
|
|
2781
|
-
async _downloadBundle(meta, rootDid, url) {
|
|
2928
|
+
async _downloadBundle(meta, rootDid, url, context = {}) {
|
|
2782
2929
|
const { bundleName: name, bundleDid: did, version, dist = {} } = meta;
|
|
2783
2930
|
const { tarball, integrity } = dist;
|
|
2784
2931
|
|
|
@@ -2806,6 +2953,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2806
2953
|
ctrlStore: this.downloadCtrls,
|
|
2807
2954
|
rootDid,
|
|
2808
2955
|
url,
|
|
2956
|
+
context,
|
|
2809
2957
|
});
|
|
2810
2958
|
logger.info('downloaded blocklet tar file', { name, version, tarballPath });
|
|
2811
2959
|
if (tarballPath === downloadFile.CANCEL) {
|
|
@@ -2826,7 +2974,16 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2826
2974
|
}
|
|
2827
2975
|
}
|
|
2828
2976
|
|
|
2829
|
-
|
|
2977
|
+
/**
|
|
2978
|
+
*
|
|
2979
|
+
*
|
|
2980
|
+
* @param {{}} blocklet
|
|
2981
|
+
* @param {{}} [oldBlocklet={}]
|
|
2982
|
+
* @param {{}} [context={}]
|
|
2983
|
+
* @return {*}
|
|
2984
|
+
* @memberof BlockletManager
|
|
2985
|
+
*/
|
|
2986
|
+
async _downloadBlocklet(blocklet, oldBlocklet = {}, context = {}) {
|
|
2830
2987
|
const {
|
|
2831
2988
|
meta: { name, did },
|
|
2832
2989
|
} = blocklet;
|
|
@@ -2880,7 +3037,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2880
3037
|
tarball: get(meta, 'dist.tarball'),
|
|
2881
3038
|
registryUrl: blocklet.source === BlockletSource.registry ? blocklet.deployedFrom : undefined,
|
|
2882
3039
|
});
|
|
2883
|
-
tasks.push(this._downloadBundle(meta, did, url));
|
|
3040
|
+
tasks.push(this._downloadBundle(meta, did, url, context));
|
|
2884
3041
|
}
|
|
2885
3042
|
const results = await Promise.all(tasks);
|
|
2886
3043
|
if (results.find((x) => x.isCancelled)) {
|
|
@@ -2976,6 +3133,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2976
3133
|
const logsDir = path.join(this.dataDirs.logs, name);
|
|
2977
3134
|
const cacheDir = path.join(this.dataDirs.cache, name);
|
|
2978
3135
|
|
|
3136
|
+
// Cleanup db
|
|
3137
|
+
await this.teamManager.deleteTeam(blocklet.meta.did);
|
|
3138
|
+
|
|
2979
3139
|
// Cleanup disk storage
|
|
2980
3140
|
fs.removeSync(cacheDir);
|
|
2981
3141
|
if (keepData === false) {
|
|
@@ -3068,6 +3228,78 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3068
3228
|
|
|
3069
3229
|
return blocklet;
|
|
3070
3230
|
}
|
|
3231
|
+
|
|
3232
|
+
async _getLatestBlockletVersionFromStore({ blocklet, version }) {
|
|
3233
|
+
const { did, bundleDid } = blocklet.meta;
|
|
3234
|
+
|
|
3235
|
+
let versions = this.cachedBlockletVersions.get(did);
|
|
3236
|
+
|
|
3237
|
+
if (!versions) {
|
|
3238
|
+
const { blockletRegistryList } = await states.node.read();
|
|
3239
|
+
const tasks = blockletRegistryList.map((registry) =>
|
|
3240
|
+
this.registry
|
|
3241
|
+
.getBlockletMeta({ did: bundleDid, registryUrl: registry.url })
|
|
3242
|
+
.then((item) => ({ did, version: item.version, registryUrl: registry.url }))
|
|
3243
|
+
.catch((error) => {
|
|
3244
|
+
if (error.response && error.response.status === 404) {
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
logger.error('get blocklet meta from registry failed', { did, error });
|
|
3248
|
+
})); // prettier-ignore
|
|
3249
|
+
|
|
3250
|
+
versions = await Promise.all(tasks);
|
|
3251
|
+
this.cachedBlockletVersions.set(did, versions);
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
versions = versions.filter((item) => item && semver.gt(item.version, version));
|
|
3255
|
+
|
|
3256
|
+
if (versions.length === 0) {
|
|
3257
|
+
return null;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
// When new version found from the store where the blocklet was installed from, we should use that store first
|
|
3261
|
+
if (blocklet.source === BlockletSource.registry && blocklet.deployedFrom) {
|
|
3262
|
+
const latestFromSameRegistry = versions.find((x) => x.registryUrl === blocklet.deployedFrom);
|
|
3263
|
+
if (latestFromSameRegistry) {
|
|
3264
|
+
return latestFromSameRegistry;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
// Otherwise try upgrading from other store
|
|
3269
|
+
let latestBlockletVersion = versions[0];
|
|
3270
|
+
versions.forEach((item) => {
|
|
3271
|
+
if (semver.lt(latestBlockletVersion.version, item.version)) {
|
|
3272
|
+
latestBlockletVersion = item;
|
|
3273
|
+
}
|
|
3274
|
+
});
|
|
3275
|
+
|
|
3276
|
+
return latestBlockletVersion;
|
|
3277
|
+
}
|
|
3278
|
+
|
|
3279
|
+
async _getLatestBlockletVersionFromUrl({ blocklet, version }) {
|
|
3280
|
+
const { did } = blocklet.meta;
|
|
3281
|
+
|
|
3282
|
+
let versions = this.cachedBlockletVersions.get(did);
|
|
3283
|
+
|
|
3284
|
+
if (!versions) {
|
|
3285
|
+
try {
|
|
3286
|
+
const item = await getBlockletMetaFromUrl(blocklet.deployedFrom);
|
|
3287
|
+
versions = [{ did, version: item.version }];
|
|
3288
|
+
} catch (error) {
|
|
3289
|
+
logger.error('get blocklet meta from url failed when checking latest version', { did, error });
|
|
3290
|
+
versions = [];
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
this.cachedBlockletVersions.set(did, versions);
|
|
3295
|
+
versions = versions.filter((item) => item && semver.gt(item.version, version));
|
|
3296
|
+
|
|
3297
|
+
if (versions.length === 0) {
|
|
3298
|
+
return null;
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
return versions[0];
|
|
3302
|
+
}
|
|
3071
3303
|
}
|
|
3072
3304
|
|
|
3073
3305
|
module.exports = BlockletManager;
|
package/lib/index.js
CHANGED
|
@@ -117,6 +117,7 @@ function ABTNode(options) {
|
|
|
117
117
|
maintainerEmail: DEFAULT_CERTIFICATE_EMAIL,
|
|
118
118
|
dataDir: dataDirs.certManagerModule,
|
|
119
119
|
});
|
|
120
|
+
|
|
120
121
|
const routerManager = new RouterManager({ certManager });
|
|
121
122
|
const routingSnapshot = new RoutingSnapshot({
|
|
122
123
|
baseDir: dataDirs.core,
|
|
@@ -126,13 +127,18 @@ function ABTNode(options) {
|
|
|
126
127
|
return { sites };
|
|
127
128
|
},
|
|
128
129
|
});
|
|
130
|
+
|
|
129
131
|
const blockletRegistry = new BlockletRegistry();
|
|
132
|
+
|
|
133
|
+
const teamManager = new TeamManager({ nodeDid: options.nodeDid, dataDirs, states });
|
|
134
|
+
|
|
130
135
|
const blockletManager = new BlockletManager({
|
|
131
136
|
dataDirs,
|
|
132
137
|
startQueue,
|
|
133
138
|
installQueue,
|
|
134
139
|
registry: blockletRegistry,
|
|
135
140
|
daemon: options.daemon,
|
|
141
|
+
teamManager,
|
|
136
142
|
});
|
|
137
143
|
blockletManager.setMaxListeners(0);
|
|
138
144
|
|
|
@@ -156,7 +162,6 @@ function ABTNode(options) {
|
|
|
156
162
|
getRouterProvider,
|
|
157
163
|
} = getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager });
|
|
158
164
|
|
|
159
|
-
const teamManager = new TeamManager({ nodeDid: options.nodeDid, dataDirs, states });
|
|
160
165
|
const nodeAPI = new NodeAPI(states.node, blockletRegistry);
|
|
161
166
|
const teamAPI = new TeamAPI({ states, teamManager });
|
|
162
167
|
|
|
@@ -272,6 +277,7 @@ function ABTNode(options) {
|
|
|
272
277
|
// Account
|
|
273
278
|
getUsers: teamAPI.getUsers.bind(teamAPI),
|
|
274
279
|
getUsersCount: teamAPI.getUsersCount.bind(teamAPI),
|
|
280
|
+
getUsersCountPerRole: teamAPI.getUsersCountPerRole.bind(teamAPI),
|
|
275
281
|
getUser: teamAPI.getUser.bind(teamAPI),
|
|
276
282
|
getOwner: teamAPI.getOwner.bind(teamAPI),
|
|
277
283
|
getNodeUsers: () => teamAPI.getUsers({ teamDid: options.nodeDid }),
|
package/lib/router/index.js
CHANGED
|
@@ -95,19 +95,16 @@ class Router {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
async updateRoutingTable() {
|
|
98
|
+
logger.info('update routing table');
|
|
99
|
+
|
|
98
100
|
const { sites, certificates, headers = {}, services = [], nodeInfo = {} } = (await this.getRoutingParams()) || {};
|
|
99
101
|
if (!Array.isArray(sites)) {
|
|
100
102
|
logger.error('sites is not an array', { sites });
|
|
101
103
|
return;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
logger.info('updateRoutingTable sites:', { sites });
|
|
105
|
-
|
|
106
106
|
this.routingTable = getRoutingTable({ sites, nodeInfo });
|
|
107
107
|
|
|
108
|
-
logger.info('updateRoutingTable routingTable:', { routingTable: this.routingTable });
|
|
109
|
-
logger.info('updateRoutingTable certificates:', { certificates: certificates.map((item) => item.domain) });
|
|
110
|
-
|
|
111
108
|
const requestLimit = nodeInfo.routing.requestLimit || { enable: false, rate: GATEWAY_REQ_LIMIT.min };
|
|
112
109
|
if (requestLimit.enabled) {
|
|
113
110
|
requestLimit.maxInstantRate = requestLimit.rate >= 20 ? 20 : requestLimit.rate + 20;
|
package/lib/states/user.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const pickBy = require('lodash/pickBy');
|
|
2
|
+
|
|
1
3
|
const logger = require('@abtnode/logger')('@abtnode/core:states:user');
|
|
2
4
|
const { PASSPORT_STATUS } = require('@abtnode/constant');
|
|
3
5
|
const BaseState = require('./base');
|
|
@@ -7,6 +9,8 @@ const fixPassports = (doc) => {
|
|
|
7
9
|
doc.passports = (doc.passports || []).filter((x) => x.id);
|
|
8
10
|
};
|
|
9
11
|
|
|
12
|
+
const isNullOrUndefined = (x) => x === undefined || x === null;
|
|
13
|
+
|
|
10
14
|
class User extends BaseState {
|
|
11
15
|
constructor(baseDir, options = {}) {
|
|
12
16
|
super(baseDir, { filename: 'user.db', ...options });
|
|
@@ -85,13 +89,45 @@ class User extends BaseState {
|
|
|
85
89
|
return doc;
|
|
86
90
|
}
|
|
87
91
|
|
|
88
|
-
async getUsers() {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
async getUsers({ query, sort, paging: inputPaging } = {}) {
|
|
93
|
+
const { approved, role, search } = query || {};
|
|
94
|
+
|
|
95
|
+
// make query param
|
|
96
|
+
const queryParam = {};
|
|
97
|
+
|
|
98
|
+
if (!isNullOrUndefined(approved)) {
|
|
99
|
+
queryParam.approved = !!approved;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (search) {
|
|
103
|
+
queryParam.$or = [{ fullName: search }, { did: search }];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (role && role !== '$all') {
|
|
107
|
+
if (role === '$none') {
|
|
108
|
+
queryParam.passports = { $size: 0 };
|
|
109
|
+
} else {
|
|
110
|
+
queryParam.passports = { $elemMatch: { name: role, status: PASSPORT_STATUS.VALID } };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const sortParam = pickBy(sort, (x) => !isNullOrUndefined(x));
|
|
115
|
+
|
|
116
|
+
if (!Object.keys(sortParam).length) {
|
|
117
|
+
sortParam.createdAt = -1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// get data
|
|
121
|
+
const { list, paging } = await this.paginate(queryParam, sortParam, inputPaging);
|
|
122
|
+
|
|
123
|
+
if (list) {
|
|
124
|
+
list.forEach(fixPassports); // backward compatible
|
|
92
125
|
}
|
|
93
126
|
|
|
94
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
list,
|
|
129
|
+
paging,
|
|
130
|
+
};
|
|
95
131
|
}
|
|
96
132
|
|
|
97
133
|
async getUser(did) {
|
package/lib/team/manager.js
CHANGED
|
@@ -17,6 +17,18 @@ const { isCLI } = require('../util');
|
|
|
17
17
|
|
|
18
18
|
const rbacCreationLock = new Lock('rbac-creation-lock');
|
|
19
19
|
|
|
20
|
+
const closeDatabase = async (db) =>
|
|
21
|
+
new Promise((resolve, reject) => {
|
|
22
|
+
db.closeDatabase((err) => {
|
|
23
|
+
if (err) {
|
|
24
|
+
reject(err);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
resolve();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
20
32
|
class TeamManager extends EventEmitter {
|
|
21
33
|
constructor({ nodeDid, dataDirs, states }) {
|
|
22
34
|
super();
|
|
@@ -48,10 +60,6 @@ class TeamManager extends EventEmitter {
|
|
|
48
60
|
});
|
|
49
61
|
});
|
|
50
62
|
|
|
51
|
-
this.states.blocklet.on('remove', ({ meta: { did } }) => {
|
|
52
|
-
this.cache[did] = null;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
63
|
// init blocklet
|
|
56
64
|
this.states.blocklet
|
|
57
65
|
.getBlocklets()
|
|
@@ -280,6 +288,28 @@ class TeamManager extends EventEmitter {
|
|
|
280
288
|
return owner;
|
|
281
289
|
}
|
|
282
290
|
|
|
291
|
+
async deleteTeam(did) {
|
|
292
|
+
if (this.cache[did]) {
|
|
293
|
+
try {
|
|
294
|
+
if (this.cache[did].rbac) {
|
|
295
|
+
await closeDatabase(this.cache[did].rbac.storage.db);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (this.cache[did].user) {
|
|
299
|
+
await closeDatabase(this.cache[did].user.db);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (this.cache[did].session) {
|
|
303
|
+
await closeDatabase(this.cache[did].session.db);
|
|
304
|
+
}
|
|
305
|
+
} catch (err) {
|
|
306
|
+
logger.error('Failed to close database', { did, err });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
this.cache[did] = null;
|
|
311
|
+
}
|
|
312
|
+
|
|
283
313
|
// =======
|
|
284
314
|
// Private
|
|
285
315
|
// =======
|
package/lib/util/blocklet.js
CHANGED
|
@@ -44,7 +44,6 @@ const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
|
44
44
|
const { validateMeta, fixAndValidateService } = require('@blocklet/meta/lib/validate');
|
|
45
45
|
const {
|
|
46
46
|
forEachBlocklet,
|
|
47
|
-
isFreeBlocklet,
|
|
48
47
|
getDisplayName,
|
|
49
48
|
findWebInterface,
|
|
50
49
|
forEachBlockletSync,
|
|
@@ -338,7 +337,8 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
|
|
|
338
337
|
};
|
|
339
338
|
};
|
|
340
339
|
|
|
341
|
-
const isUsefulError = (err) =>
|
|
340
|
+
const isUsefulError = (err) =>
|
|
341
|
+
err && err.message !== 'process or namespace not found' && !/^Process \d+ not found$/.test(err.message);
|
|
342
342
|
|
|
343
343
|
const getHealthyCheckTimeout = (blocklet, { checkHealthImmediately } = {}) => {
|
|
344
344
|
let minConsecutiveTime = 5000;
|
|
@@ -724,8 +724,6 @@ const parseChildrenFromMeta = async (src, context = {}) => {
|
|
|
724
724
|
|
|
725
725
|
validateBlockletMeta(m, { ensureDist: true });
|
|
726
726
|
|
|
727
|
-
verifyPurchase(m, context);
|
|
728
|
-
|
|
729
727
|
if (!isComponentBlocklet(m)) {
|
|
730
728
|
throw new Error(`The blocklet cannot be a component: ${m.title}`);
|
|
731
729
|
}
|
|
@@ -1227,18 +1225,6 @@ const needBlockletDownload = (blocklet, oldBlocklet) => {
|
|
|
1227
1225
|
return !(get(oldBlocklet, 'meta.dist.integrity') === get(blocklet, 'meta.dist.integrity'));
|
|
1228
1226
|
};
|
|
1229
1227
|
|
|
1230
|
-
const verifyPurchase = (meta, opts = {}) => {
|
|
1231
|
-
if (opts.blockletPurchaseVerified) {
|
|
1232
|
-
return true;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
if (isFreeBlocklet(meta)) {
|
|
1236
|
-
return true;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
throw new Error('Can not install a non-free blocklet directly');
|
|
1240
|
-
};
|
|
1241
|
-
|
|
1242
1228
|
const findAvailableDid = (meta, siblings) => {
|
|
1243
1229
|
const reg = /-(\d+)$/;
|
|
1244
1230
|
const match = reg.exec(meta.name);
|
|
@@ -1316,7 +1302,6 @@ module.exports = {
|
|
|
1316
1302
|
getDiffFiles,
|
|
1317
1303
|
getBundleDir,
|
|
1318
1304
|
needBlockletDownload,
|
|
1319
|
-
verifyPurchase,
|
|
1320
1305
|
findAvailableDid,
|
|
1321
1306
|
ensureMeta,
|
|
1322
1307
|
getSourceUrlsFromConfig,
|
package/lib/util/index.js
CHANGED
|
@@ -68,7 +68,7 @@ const getInterfaceUrl = ({ baseUrl, url }) => {
|
|
|
68
68
|
|
|
69
69
|
const trimSlash = (str = '') => str.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
70
70
|
|
|
71
|
-
const replaceDomainSlot = ({ domain, context, nodeIp }) => {
|
|
71
|
+
const replaceDomainSlot = ({ domain, context = {}, nodeIp }) => {
|
|
72
72
|
let processed = domain;
|
|
73
73
|
if (processed.includes(SLOT_FOR_IP_DNS_SITE)) {
|
|
74
74
|
const ipRegex = /\d+[-.]\d+[-.]\d+[-.]\d+/;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.27",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,30 +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.7.
|
|
23
|
-
"@abtnode/constant": "1.7.
|
|
24
|
-
"@abtnode/cron": "1.7.
|
|
25
|
-
"@abtnode/db": "1.7.
|
|
26
|
-
"@abtnode/logger": "1.7.
|
|
27
|
-
"@abtnode/queue": "1.7.
|
|
28
|
-
"@abtnode/rbac": "1.7.
|
|
29
|
-
"@abtnode/router-provider": "1.7.
|
|
30
|
-
"@abtnode/static-server": "1.7.
|
|
31
|
-
"@abtnode/timemachine": "1.7.
|
|
32
|
-
"@abtnode/util": "1.7.
|
|
33
|
-
"@arcblock/did": "
|
|
22
|
+
"@abtnode/certificate-manager": "1.7.27",
|
|
23
|
+
"@abtnode/constant": "1.7.27",
|
|
24
|
+
"@abtnode/cron": "1.7.27",
|
|
25
|
+
"@abtnode/db": "1.7.27",
|
|
26
|
+
"@abtnode/logger": "1.7.27",
|
|
27
|
+
"@abtnode/queue": "1.7.27",
|
|
28
|
+
"@abtnode/rbac": "1.7.27",
|
|
29
|
+
"@abtnode/router-provider": "1.7.27",
|
|
30
|
+
"@abtnode/static-server": "1.7.27",
|
|
31
|
+
"@abtnode/timemachine": "1.7.27",
|
|
32
|
+
"@abtnode/util": "1.7.27",
|
|
33
|
+
"@arcblock/did": "1.17.0",
|
|
34
34
|
"@arcblock/did-motif": "^1.1.10",
|
|
35
|
-
"@arcblock/did-util": "
|
|
36
|
-
"@arcblock/event-hub": "1.
|
|
35
|
+
"@arcblock/did-util": "1.17.0",
|
|
36
|
+
"@arcblock/event-hub": "1.17.0",
|
|
37
|
+
"@arcblock/jwt": "^1.17.0",
|
|
37
38
|
"@arcblock/pm2-events": "^0.0.5",
|
|
38
|
-
"@arcblock/vc": "
|
|
39
|
-
"@blocklet/meta": "1.7.
|
|
39
|
+
"@arcblock/vc": "1.17.0",
|
|
40
|
+
"@blocklet/meta": "1.7.27",
|
|
40
41
|
"@fidm/x509": "^1.2.1",
|
|
41
42
|
"@nedb/core": "^1.2.2",
|
|
42
43
|
"@nedb/multi": "^1.2.2",
|
|
43
|
-
"@ocap/mcrypto": "
|
|
44
|
-
"@ocap/util": "
|
|
45
|
-
"@ocap/wallet": "
|
|
44
|
+
"@ocap/mcrypto": "1.17.0",
|
|
45
|
+
"@ocap/util": "1.17.0",
|
|
46
|
+
"@ocap/wallet": "1.17.0",
|
|
46
47
|
"@slack/webhook": "^5.0.3",
|
|
47
48
|
"axios": "^0.27.2",
|
|
48
49
|
"axon": "^2.0.3",
|
|
@@ -80,5 +81,5 @@
|
|
|
80
81
|
"express": "^4.17.1",
|
|
81
82
|
"jest": "^27.4.5"
|
|
82
83
|
},
|
|
83
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "81a5492df66389b0aede13f033d1e493450833bc"
|
|
84
85
|
}
|