@abtnode/core 1.8.36 → 1.8.37
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 +0 -73
- package/lib/api/team.js +59 -0
- package/lib/blocklet/manager/disk.js +29 -40
- package/lib/event.js +15 -11
- package/lib/index.js +4 -3
- package/lib/states/audit-log.js +1 -1
- package/lib/states/node.js +0 -4
- package/lib/team/manager.js +21 -0
- package/lib/util/blocklet.js +55 -3
- package/lib/util/default-node-config.js +3 -13
- package/lib/util/store.js +6 -6
- package/package.json +17 -17
package/lib/api/node.js
CHANGED
|
@@ -7,24 +7,14 @@ 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');
|
|
11
10
|
|
|
12
11
|
const logger = require('@abtnode/logger')('@abtnode/core:api:node');
|
|
13
12
|
|
|
14
13
|
const IP = require('../util/ip');
|
|
15
14
|
const { validateNodeInfo, validateUpdateGateway } = require('../validators/node');
|
|
16
15
|
const { getAll } = require('../blocklet/manager/engine');
|
|
17
|
-
const StoreUtil = require('../util/store');
|
|
18
16
|
const { getDelegateState } = require('../util');
|
|
19
17
|
|
|
20
|
-
const sanitizeUrl = (url) => {
|
|
21
|
-
if (!url) {
|
|
22
|
-
throw new Error('Registry URL should not be empty');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return url.trim();
|
|
26
|
-
};
|
|
27
|
-
|
|
28
18
|
class NodeAPI {
|
|
29
19
|
/**
|
|
30
20
|
*
|
|
@@ -37,69 +27,6 @@ class NodeAPI {
|
|
|
37
27
|
this.state = state;
|
|
38
28
|
}
|
|
39
29
|
|
|
40
|
-
// eslint-disable-next-line no-unused-vars
|
|
41
|
-
async addRegistry({ url }, context) {
|
|
42
|
-
logger.info('add registry', { url });
|
|
43
|
-
|
|
44
|
-
const urlObj = new URL(url);
|
|
45
|
-
let newUrl = urlObj.origin;
|
|
46
|
-
|
|
47
|
-
// if the pathname is store blocklet list or blocklet detail
|
|
48
|
-
if (urlObj.pathname?.includes(STORE_DETAIL_PAGE_PATH_PREFIX)) {
|
|
49
|
-
const lastIndex = urlObj.pathname.lastIndexOf(STORE_DETAIL_PAGE_PATH_PREFIX);
|
|
50
|
-
const pathnamePrefix = urlObj.pathname.substring(0, lastIndex);
|
|
51
|
-
newUrl = `${newUrl}${pathnamePrefix || ''}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const sanitized = sanitizeUrl(newUrl);
|
|
55
|
-
|
|
56
|
-
const info = await this.state.read();
|
|
57
|
-
const exist = info.blockletRegistryList.find((x) => x.url === sanitized);
|
|
58
|
-
if (exist) {
|
|
59
|
-
throw new Error(`Blocklet registry already exist: ${sanitized}`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
await StoreUtil.validateRegistryURL(sanitized);
|
|
63
|
-
|
|
64
|
-
const newBlockletRegistry = await StoreUtil.getRegistryMeta(sanitized);
|
|
65
|
-
const newBlockletRegistryList = info.blockletRegistryList.map((x) => ({ ...x, selected: false }));
|
|
66
|
-
newBlockletRegistryList.push({ ...newBlockletRegistry, url: sanitized, selected: true, protected: false });
|
|
67
|
-
|
|
68
|
-
return this.state.updateNodeInfo({ blockletRegistryList: newBlockletRegistryList });
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// eslint-disable-next-line no-unused-vars
|
|
72
|
-
async deleteRegistry({ url }, context) {
|
|
73
|
-
logger.info('delete registry', { url });
|
|
74
|
-
const sanitized = sanitizeUrl(url);
|
|
75
|
-
const info = await this.state.read();
|
|
76
|
-
const exist = info.blockletRegistryList.find((x) => x.url === sanitized);
|
|
77
|
-
if (!exist) {
|
|
78
|
-
throw new Error(`Blocklet registry does not exist: ${sanitized}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const blockletRegistryList = info.blockletRegistryList.filter((x) => x.url !== sanitized);
|
|
82
|
-
if (!blockletRegistryList.find((x) => x.selected)) {
|
|
83
|
-
blockletRegistryList[0].selected = true;
|
|
84
|
-
}
|
|
85
|
-
return this.state.updateNodeInfo({ blockletRegistryList });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// eslint-disable-next-line no-unused-vars
|
|
89
|
-
async selectRegistry({ url }, context) {
|
|
90
|
-
logger.info('select registry', { url });
|
|
91
|
-
const sanitized = sanitizeUrl(url);
|
|
92
|
-
const info = await this.state.read();
|
|
93
|
-
const exist = info.blockletRegistryList.find((x) => x.url === sanitized);
|
|
94
|
-
if (!exist) {
|
|
95
|
-
throw new Error(`Blocklet registry does not exist: ${sanitized}`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return this.state.updateNodeInfo({
|
|
99
|
-
blockletRegistryList: info.blockletRegistryList.map((x) => ({ ...x, selected: x.url === sanitized })),
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
30
|
async updateNodeInfo(entity = {}, context) {
|
|
104
31
|
await validateNodeInfo(entity, context);
|
|
105
32
|
|
package/lib/api/team.js
CHANGED
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
PASSPORT_STATUS,
|
|
12
12
|
WELLKNOWN_SERVICE_PATH_PREFIX,
|
|
13
13
|
MAX_USER_PAGE_SIZE,
|
|
14
|
+
STORE_DETAIL_PAGE_PATH_PREFIX,
|
|
14
15
|
} = require('@abtnode/constant');
|
|
15
16
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
16
17
|
const { BlockletEvents } = require('@blocklet/constant');
|
|
@@ -30,6 +31,15 @@ const { validateCreateRole, validateUpdateRole } = require('../validators/role')
|
|
|
30
31
|
const { validateCreatePermission, validateUpdatePermission } = require('../validators/permission');
|
|
31
32
|
|
|
32
33
|
const { getBlocklet } = require('../util/blocklet');
|
|
34
|
+
const StoreUtil = require('../util/store');
|
|
35
|
+
|
|
36
|
+
const sanitizeUrl = (url) => {
|
|
37
|
+
if (!url) {
|
|
38
|
+
throw new Error('Registry URL should not be empty');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return url.trim();
|
|
42
|
+
};
|
|
33
43
|
|
|
34
44
|
const validateReservedRole = (role) => {
|
|
35
45
|
if (Object.values(ROLES).includes(role)) {
|
|
@@ -855,6 +865,55 @@ class TeamAPI extends EventEmitter {
|
|
|
855
865
|
);
|
|
856
866
|
}
|
|
857
867
|
|
|
868
|
+
// eslint-disable-next-line no-unused-vars
|
|
869
|
+
async addStore({ teamDid, url }, context) {
|
|
870
|
+
logger.info('add registry', { url });
|
|
871
|
+
|
|
872
|
+
const urlObj = new URL(url);
|
|
873
|
+
let newUrl = urlObj.origin;
|
|
874
|
+
|
|
875
|
+
// if the pathname is store blocklet list or blocklet detail
|
|
876
|
+
if (urlObj.pathname?.includes(STORE_DETAIL_PAGE_PATH_PREFIX)) {
|
|
877
|
+
const lastIndex = urlObj.pathname.lastIndexOf(STORE_DETAIL_PAGE_PATH_PREFIX);
|
|
878
|
+
const pathnamePrefix = urlObj.pathname.substring(0, lastIndex);
|
|
879
|
+
newUrl = `${newUrl}${pathnamePrefix || ''}`;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const sanitized = sanitizeUrl(newUrl);
|
|
883
|
+
|
|
884
|
+
const storeList = await this.teamManager.getStoreList(teamDid);
|
|
885
|
+
|
|
886
|
+
const exist = storeList.find((x) => x.url === sanitized);
|
|
887
|
+
if (exist) {
|
|
888
|
+
throw new Error(`Blocklet registry already exist: ${sanitized}`);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
await StoreUtil.validateRegistryURL(sanitized);
|
|
892
|
+
|
|
893
|
+
const store = await StoreUtil.getRegistryMeta(sanitized);
|
|
894
|
+
|
|
895
|
+
storeList.push({ ...store, url: sanitized, protected: false });
|
|
896
|
+
|
|
897
|
+
return this.teamManager.updateStoreList(teamDid, storeList);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// eslint-disable-next-line no-unused-vars
|
|
901
|
+
async deleteStore({ teamDid, url }, context) {
|
|
902
|
+
logger.info('delete registry', { url });
|
|
903
|
+
const sanitized = sanitizeUrl(url);
|
|
904
|
+
|
|
905
|
+
const storeList = await this.teamManager.getStoreList(teamDid);
|
|
906
|
+
const exist = storeList.find((x) => x.url === sanitized);
|
|
907
|
+
if (!exist) {
|
|
908
|
+
throw new Error(`Blocklet registry does not exist: ${sanitized}`);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
return this.teamManager.updateStoreList(
|
|
912
|
+
teamDid,
|
|
913
|
+
storeList.filter((x) => x.url !== sanitized)
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
|
|
858
917
|
// =======
|
|
859
918
|
// Private
|
|
860
919
|
// =======
|
|
@@ -109,6 +109,7 @@ const {
|
|
|
109
109
|
ensureMeta,
|
|
110
110
|
getBlocklet,
|
|
111
111
|
ensureEnvDefault,
|
|
112
|
+
getConfigFromPreferences,
|
|
112
113
|
} = require('../../util/blocklet');
|
|
113
114
|
const StoreUtil = require('../../util/store');
|
|
114
115
|
const states = require('../../states');
|
|
@@ -269,8 +270,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
269
270
|
}
|
|
270
271
|
|
|
271
272
|
if (source === BlockletSource.registry) {
|
|
272
|
-
const { did, controller, sync, delay } = params;
|
|
273
|
-
return this._installFromStore({ did, controller, sync, delay }, context);
|
|
273
|
+
const { did, controller, sync, delay, storeUrl } = params;
|
|
274
|
+
return this._installFromStore({ did, controller, sync, delay, storeUrl }, context);
|
|
274
275
|
}
|
|
275
276
|
|
|
276
277
|
if (source === BlockletSource.custom) {
|
|
@@ -836,6 +837,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
836
837
|
return result;
|
|
837
838
|
}
|
|
838
839
|
|
|
840
|
+
// Get blocklet by blockletDid or appDid
|
|
839
841
|
async detail({ did, attachConfig = true, attachRuntimeInfo = true }, context) {
|
|
840
842
|
if (!did) {
|
|
841
843
|
throw new Error('did should not be empty');
|
|
@@ -1130,23 +1132,23 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1130
1132
|
/**
|
|
1131
1133
|
* upgrade blocklet from registry
|
|
1132
1134
|
*/
|
|
1133
|
-
async upgrade({ did,
|
|
1135
|
+
async upgrade({ did, storeUrl, sync }, context) {
|
|
1134
1136
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
1135
1137
|
|
|
1136
|
-
if (!
|
|
1138
|
+
if (!storeUrl && blocklet.source === BlockletSource.url) {
|
|
1137
1139
|
return this._installFromUrl({ url: blocklet.deployedFrom }, context);
|
|
1138
1140
|
}
|
|
1139
1141
|
|
|
1140
|
-
// TODO: 查看了下目前页面中的升级按钮,都是会传
|
|
1141
|
-
if (!
|
|
1142
|
-
throw new Error('Wrong upgrade source, empty
|
|
1142
|
+
// TODO: 查看了下目前页面中的升级按钮,都是会传 storeUrl 过来的,这个函数里的逻辑感觉需要在以后做一个简化
|
|
1143
|
+
if (!storeUrl && blocklet.source !== BlockletSource.registry) {
|
|
1144
|
+
throw new Error('Wrong upgrade source, empty storeUrl or not installed from blocklet registry');
|
|
1143
1145
|
}
|
|
1144
1146
|
|
|
1145
|
-
const
|
|
1147
|
+
const upgradeFromStore = storeUrl || blocklet.deployedFrom;
|
|
1146
1148
|
|
|
1147
1149
|
let newVersionMeta = await StoreUtil.getBlockletMeta({
|
|
1148
1150
|
did: blocklet.meta.bundleDid,
|
|
1149
|
-
|
|
1151
|
+
storeUrl: upgradeFromStore,
|
|
1150
1152
|
});
|
|
1151
1153
|
newVersionMeta = ensureMeta(newVersionMeta, { name: blocklet.meta.name, did: blocklet.meta.did });
|
|
1152
1154
|
|
|
@@ -1197,7 +1199,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1197
1199
|
return this._upgrade({
|
|
1198
1200
|
meta: newVersionMeta,
|
|
1199
1201
|
source: BlockletSource.registry,
|
|
1200
|
-
deployedFrom:
|
|
1202
|
+
deployedFrom: upgradeFromStore,
|
|
1201
1203
|
context,
|
|
1202
1204
|
sync,
|
|
1203
1205
|
});
|
|
@@ -1382,7 +1384,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1382
1384
|
|
|
1383
1385
|
const meta = getBlockletMeta(folder);
|
|
1384
1386
|
if (meta.group !== 'static' && (!meta.scripts || !meta.scripts.dev)) {
|
|
1385
|
-
throw new Error('Incorrect blocklet
|
|
1387
|
+
throw new Error('Incorrect blocklet.yml: missing `scripts.dev` field');
|
|
1386
1388
|
}
|
|
1387
1389
|
|
|
1388
1390
|
if (rootDid) {
|
|
@@ -1975,16 +1977,19 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1975
1977
|
* @memberof BlockletManager
|
|
1976
1978
|
*/
|
|
1977
1979
|
async _installFromStore(params, context) {
|
|
1978
|
-
const { did,
|
|
1980
|
+
const { did, storeUrl, sync, delay, controller } = params;
|
|
1979
1981
|
|
|
1980
1982
|
logger.debug('start install blocklet', { did });
|
|
1981
1983
|
if (!isValidDid(did)) {
|
|
1982
1984
|
throw new Error('Blocklet did is invalid');
|
|
1983
1985
|
}
|
|
1984
1986
|
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1987
|
+
if (!storeUrl) {
|
|
1988
|
+
throw new Error('registry url should not be empty');
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
const info = await StoreUtil.getRegistryMeta(storeUrl);
|
|
1992
|
+
const meta = await StoreUtil.getBlockletMeta({ did, storeUrl });
|
|
1988
1993
|
if (!meta) {
|
|
1989
1994
|
throw new Error('Can not install blocklet that not found in registry');
|
|
1990
1995
|
}
|
|
@@ -2013,7 +2018,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2013
2018
|
return this._install({
|
|
2014
2019
|
meta: ensureMeta(meta, { did: blockletDid, name: blockletName }),
|
|
2015
2020
|
source: BlockletSource.registry,
|
|
2016
|
-
deployedFrom: info.cdnUrl ||
|
|
2021
|
+
deployedFrom: info.cdnUrl || storeUrl,
|
|
2017
2022
|
sync,
|
|
2018
2023
|
delay,
|
|
2019
2024
|
controller,
|
|
@@ -2056,10 +2061,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2056
2061
|
if (inStore) {
|
|
2057
2062
|
const exist = await states.blocklet.getBlocklet(blockletDid);
|
|
2058
2063
|
if (exist) {
|
|
2059
|
-
return this.upgrade({ did: blockletDid, registryUrl, sync, delay }, context);
|
|
2064
|
+
return this.upgrade({ did: blockletDid, storeUrl: registryUrl, sync, delay }, context);
|
|
2060
2065
|
}
|
|
2061
2066
|
|
|
2062
|
-
return this._installFromStore({ did: bundleDid,
|
|
2067
|
+
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay }, context);
|
|
2063
2068
|
}
|
|
2064
2069
|
|
|
2065
2070
|
const meta = ensureMeta(bundleMeta, { name: blockletName, did: blockletDid });
|
|
@@ -3490,11 +3495,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3490
3495
|
}
|
|
3491
3496
|
|
|
3492
3497
|
async _setConfigsFromMeta(did, childDid) {
|
|
3493
|
-
const blocklet = await states.
|
|
3498
|
+
const blocklet = await getBlocklet({ states, dataDirs: this.dataDirs, did, validateEnv: false, ensureDirs: false });
|
|
3494
3499
|
|
|
3495
3500
|
if (!childDid) {
|
|
3496
3501
|
await forEachBlocklet(blocklet, async (b, { ancestors }) => {
|
|
3497
|
-
const environments = get(b.meta, 'environments', []);
|
|
3502
|
+
const environments = [...get(b.meta, 'environments', []), ...getConfigFromPreferences(b)];
|
|
3498
3503
|
|
|
3499
3504
|
// remove default if ancestors has a value
|
|
3500
3505
|
ensureEnvDefault(environments, ancestors);
|
|
@@ -3507,7 +3512,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3507
3512
|
await forEachBlocklet(child, async (b, { ancestors }) => {
|
|
3508
3513
|
await states.blockletExtras.setConfigs(
|
|
3509
3514
|
[blocklet.meta.did, ...ancestors.map((x) => x.meta.did), b.meta.did],
|
|
3510
|
-
get(b.meta, 'environments', [])
|
|
3515
|
+
[...get(b.meta, 'environments', []), ...getConfigFromPreferences(child)]
|
|
3511
3516
|
);
|
|
3512
3517
|
});
|
|
3513
3518
|
}
|
|
@@ -3556,13 +3561,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3556
3561
|
}
|
|
3557
3562
|
|
|
3558
3563
|
async _getLatestBlockletVersionFromStore({ blocklet, version }) {
|
|
3559
|
-
const { deployedFrom:
|
|
3564
|
+
const { deployedFrom: storeUrl } = blocklet;
|
|
3560
3565
|
const { did, bundleDid } = blocklet.meta;
|
|
3561
3566
|
|
|
3562
3567
|
let versions = this.cachedBlockletVersions.get(did);
|
|
3563
3568
|
|
|
3564
3569
|
if (!versions) {
|
|
3565
|
-
const item = await StoreUtil.getBlockletMeta({ did: bundleDid,
|
|
3570
|
+
const item = await StoreUtil.getBlockletMeta({ did: bundleDid, storeUrl });
|
|
3566
3571
|
|
|
3567
3572
|
if (!item) {
|
|
3568
3573
|
return null;
|
|
@@ -3579,23 +3584,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3579
3584
|
return null;
|
|
3580
3585
|
}
|
|
3581
3586
|
|
|
3582
|
-
|
|
3583
|
-
if (blocklet.source === BlockletSource.registry && blocklet.deployedFrom) {
|
|
3584
|
-
const latestFromSameRegistry = versions.find((x) => x.registryUrl === blocklet.deployedFrom);
|
|
3585
|
-
if (latestFromSameRegistry) {
|
|
3586
|
-
return latestFromSameRegistry;
|
|
3587
|
-
}
|
|
3588
|
-
}
|
|
3589
|
-
|
|
3590
|
-
// Otherwise try upgrading from other store
|
|
3591
|
-
let latestBlockletVersion = versions[0];
|
|
3592
|
-
versions.forEach((item) => {
|
|
3593
|
-
if (semver.lt(latestBlockletVersion.version, item.version)) {
|
|
3594
|
-
latestBlockletVersion = item;
|
|
3595
|
-
}
|
|
3596
|
-
});
|
|
3597
|
-
|
|
3598
|
-
return latestBlockletVersion;
|
|
3587
|
+
return versions[0];
|
|
3599
3588
|
}
|
|
3600
3589
|
|
|
3601
3590
|
async _getLatestBlockletVersionFromUrl({ blocklet, version }) {
|
package/lib/event.js
CHANGED
|
@@ -249,6 +249,8 @@ module.exports = ({
|
|
|
249
249
|
}
|
|
250
250
|
};
|
|
251
251
|
|
|
252
|
+
const listen = (subject, event, handler) => subject.on(event, (data) => handler(event, data));
|
|
253
|
+
|
|
252
254
|
[
|
|
253
255
|
BlockletEvents.added,
|
|
254
256
|
BlockletEvents.downloadFailed,
|
|
@@ -265,12 +267,12 @@ module.exports = ({
|
|
|
265
267
|
BlockletEvents.startFailed,
|
|
266
268
|
BlockletEvents.stopped,
|
|
267
269
|
].forEach((eventName) => {
|
|
268
|
-
blockletManager
|
|
270
|
+
listen(blockletManager, eventName, handleBlockletEvent);
|
|
269
271
|
});
|
|
270
272
|
|
|
271
|
-
notificationState
|
|
273
|
+
listen(notificationState, EVENTS.NOTIFICATION_CREATE, onEvent);
|
|
272
274
|
|
|
273
|
-
nodeState
|
|
275
|
+
listen(nodeState, BlockletEvents.purchaseChange, onEvent);
|
|
274
276
|
nodeState.on(EVENTS.ROUTING_UPDATED, (nodeInfo) => onEvent(EVENTS.ROUTING_UPDATED, { routing: nodeInfo.routing }));
|
|
275
277
|
nodeState.once(EVENTS.NODE_ADDED_OWNER, () => downloadAddedBlocklet());
|
|
276
278
|
nodeState.on(EVENTS.NODE_UPDATED, (nodeInfo, oldInfo) => {
|
|
@@ -285,7 +287,8 @@ module.exports = ({
|
|
|
285
287
|
});
|
|
286
288
|
}
|
|
287
289
|
});
|
|
288
|
-
|
|
290
|
+
|
|
291
|
+
listen(nodeState, EVENTS.NODE_UPGRADE_PROGRESS, onEvent);
|
|
289
292
|
nodeState.on(EVENTS.RELOAD_GATEWAY, (nodeInfo) => {
|
|
290
293
|
handleRouting(nodeInfo).catch((err) => {
|
|
291
294
|
logger.error('Handle routing failed on node.updated', { error: err });
|
|
@@ -300,15 +303,16 @@ module.exports = ({
|
|
|
300
303
|
});
|
|
301
304
|
});
|
|
302
305
|
|
|
303
|
-
teamAPI
|
|
304
|
-
teamAPI
|
|
305
|
-
teamAPI
|
|
306
|
-
teamAPI
|
|
306
|
+
listen(teamAPI, EVENTS.USER_ADDED, onEvent);
|
|
307
|
+
listen(teamAPI, EVENTS.USER_REMOVED, onEvent);
|
|
308
|
+
listen(teamAPI, EVENTS.USER_UPDATED, onEvent);
|
|
309
|
+
listen(teamAPI, BlockletEvents.updated, onEvent);
|
|
310
|
+
listen(teamManager, BlockletEvents.storeChange, onEvent);
|
|
307
311
|
|
|
308
|
-
certManager
|
|
309
|
-
certManager
|
|
312
|
+
listen(certManager, EVENTS.CERT_ISSUED, onEvent);
|
|
313
|
+
listen(certManager, EVENTS.CERT_ERROR, onEvent);
|
|
310
314
|
|
|
311
|
-
routerManager
|
|
315
|
+
listen(routerManager, BlockletEvents.updated, onEvent);
|
|
312
316
|
|
|
313
317
|
events.setEventHandler = (handler) => {
|
|
314
318
|
if (typeof handler === 'function') {
|
package/lib/index.js
CHANGED
|
@@ -236,9 +236,6 @@ function ABTNode(options) {
|
|
|
236
236
|
getNodeInfo: nodeAPI.getInfo.bind(nodeAPI),
|
|
237
237
|
getNodeEnv: nodeAPI.getEnv.bind(nodeAPI),
|
|
238
238
|
updateNodeInfo: nodeAPI.updateNodeInfo.bind(nodeAPI),
|
|
239
|
-
addBlockletStore: nodeAPI.addRegistry.bind(nodeAPI),
|
|
240
|
-
deleteBlockletStore: nodeAPI.deleteRegistry.bind(nodeAPI),
|
|
241
|
-
selectBlockletStore: nodeAPI.selectRegistry.bind(nodeAPI),
|
|
242
239
|
getDelegationState: nodeAPI.getDelegationState.bind(nodeAPI),
|
|
243
240
|
cleanupDirtyUpgradeState: states.node.cleanupDirtyUpgradeState.bind(states.node),
|
|
244
241
|
updateNodeOwner: states.node.updateNodeOwner.bind(states.node),
|
|
@@ -307,6 +304,10 @@ function ABTNode(options) {
|
|
|
307
304
|
configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
|
|
308
305
|
configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
|
|
309
306
|
|
|
307
|
+
// Team Settings
|
|
308
|
+
addBlockletStore: teamAPI.addStore.bind(teamAPI),
|
|
309
|
+
deleteBlockletStore: teamAPI.deleteStore.bind(teamAPI),
|
|
310
|
+
|
|
310
311
|
// Challenge
|
|
311
312
|
generateChallenge: states.challenge.generate.bind(states.challenge),
|
|
312
313
|
verifyChallenge: states.challenge.verify.bind(states.challenge),
|
package/lib/states/audit-log.js
CHANGED
package/lib/states/node.js
CHANGED
|
@@ -302,10 +302,6 @@ class NodeState extends BaseState {
|
|
|
302
302
|
}));
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
getBlockletRegistry() {
|
|
306
|
-
return this.read().then((info) => info.blockletRegistryList.find((item) => item.selected).url);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
305
|
async increaseCustomBlockletNumber() {
|
|
310
306
|
const { _id, customBlockletNumber = 0 } = await this.read();
|
|
311
307
|
const num = customBlockletNumber + 1;
|
package/lib/team/manager.js
CHANGED
|
@@ -9,6 +9,7 @@ const get = require('lodash/get');
|
|
|
9
9
|
const { createRBAC, MemoryStorage, NedbStorage } = require('@abtnode/rbac');
|
|
10
10
|
const logger = require('@abtnode/logger')('@abtnode/core:team:manager');
|
|
11
11
|
const { ROLES, RBAC_CONFIG } = require('@abtnode/constant');
|
|
12
|
+
const { BlockletEvents } = require('@blocklet/constant');
|
|
12
13
|
const Lock = require('@abtnode/util/lib/lock');
|
|
13
14
|
const UserState = require('../states/user');
|
|
14
15
|
const SessionState = require('../states/session');
|
|
@@ -280,6 +281,26 @@ class TeamManager extends EventEmitter {
|
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
|
|
284
|
+
async getStoreList(did) {
|
|
285
|
+
if (this.isNodeTeam(did)) {
|
|
286
|
+
const nodeInfo = await this.states.node.read();
|
|
287
|
+
return nodeInfo.blockletRegistryList || [];
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const settings = await this.states.blockletExtras.getSettings(did);
|
|
291
|
+
return get(settings, 'storeList', []) || [];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async updateStoreList(did, list) {
|
|
295
|
+
if (this.isNodeTeam(did)) {
|
|
296
|
+
await this.states.node.updateNodeInfo({ blockletRegistryList: list });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
await this.states.blockletExtras.setSettings(did, { storeList: list });
|
|
301
|
+
this.emit(BlockletEvents.storeChange, { meta: { did } });
|
|
302
|
+
}
|
|
303
|
+
|
|
283
304
|
async getOwner(did) {
|
|
284
305
|
let owner;
|
|
285
306
|
if (this.isNodeTeam(did)) {
|
package/lib/util/blocklet.js
CHANGED
|
@@ -16,13 +16,15 @@ const { isValid: isValidDid } = require('@arcblock/did');
|
|
|
16
16
|
const logger = require('@abtnode/logger')('@abtnode/core:util:blocklet');
|
|
17
17
|
const pm2 = require('@abtnode/util/lib/async-pm2');
|
|
18
18
|
const sleep = require('@abtnode/util/lib/sleep');
|
|
19
|
+
const { formatEnv } = require('@abtnode/util/lib/security');
|
|
19
20
|
const ensureEndpointHealthy = require('@abtnode/util/lib/ensure-endpoint-healthy');
|
|
20
21
|
const CustomError = require('@abtnode/util/lib/custom-error');
|
|
21
22
|
const getFolderSize = require('@abtnode/util/lib/get-folder-size');
|
|
22
23
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
23
24
|
const hashFiles = require('@abtnode/util/lib/hash-files');
|
|
24
25
|
const isPathPrefixEqual = require('@abtnode/util/lib/is-path-prefix-equal');
|
|
25
|
-
const { BLOCKLET_MAX_MEM_LIMIT_IN_MB } = require('@abtnode/constant');
|
|
26
|
+
const { BLOCKLET_MAX_MEM_LIMIT_IN_MB, BLOCKLET_STORE } = require('@abtnode/constant');
|
|
27
|
+
const { BLOCKLET_PREFERENCE_FILE, BLOCKLET_PREFERENCE_PREFIX } = require('@blocklet/constant');
|
|
26
28
|
const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
|
|
27
29
|
|
|
28
30
|
const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
|
|
@@ -148,7 +150,7 @@ const getComponentDirs = (
|
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
if (validate && !main && !startFromDevEntry && group !== BlockletGroup.gateway) {
|
|
151
|
-
throw new Error('Incorrect blocklet
|
|
153
|
+
throw new Error('Incorrect blocklet.yml: missing `main` field');
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
let appDir = null;
|
|
@@ -380,7 +382,7 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
|
|
|
380
382
|
? getBlockletWallet(blocklet.meta.did, nodeEnvironments.ABT_NODE_SK, undefined, 1)
|
|
381
383
|
: null;
|
|
382
384
|
|
|
383
|
-
|
|
385
|
+
const env = {
|
|
384
386
|
...blocklet.configObj,
|
|
385
387
|
...getSharedConfigObj(blocklet, ancestors),
|
|
386
388
|
...blocklet.environmentObj,
|
|
@@ -392,6 +394,13 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
|
|
|
392
394
|
...nodeEnvironments,
|
|
393
395
|
...safeNodeEnvironments,
|
|
394
396
|
};
|
|
397
|
+
|
|
398
|
+
// ensure all envs are literals and do not contain line breaks
|
|
399
|
+
Object.keys(env).forEach((key) => {
|
|
400
|
+
env[key] = formatEnv(env[key]);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
return env;
|
|
395
404
|
};
|
|
396
405
|
|
|
397
406
|
const isUsefulError = (err) =>
|
|
@@ -1330,6 +1339,15 @@ const getBlocklet = async ({
|
|
|
1330
1339
|
blocklet.enablePassportIssuance = get(settings, 'enablePassportIssuance', true);
|
|
1331
1340
|
blocklet.settings = settings || {};
|
|
1332
1341
|
|
|
1342
|
+
blocklet.settings.storeList = blocklet.settings.storeList || [];
|
|
1343
|
+
|
|
1344
|
+
if (!blocklet.settings.storeList.find((x) => x.url === BLOCKLET_STORE.url)) {
|
|
1345
|
+
blocklet.settings.storeList.unshift({
|
|
1346
|
+
...BLOCKLET_STORE,
|
|
1347
|
+
protected: true,
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1333
1351
|
// app site
|
|
1334
1352
|
blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
|
|
1335
1353
|
|
|
@@ -1385,6 +1403,39 @@ const ensureEnvDefault = (environments, ancestors) => {
|
|
|
1385
1403
|
return environments;
|
|
1386
1404
|
};
|
|
1387
1405
|
|
|
1406
|
+
const fromProperty2Config = (properties = {}, result) => {
|
|
1407
|
+
Object.keys(properties).forEach((key) => {
|
|
1408
|
+
const prop = properties[key];
|
|
1409
|
+
if (prop.properties) {
|
|
1410
|
+
fromProperty2Config(prop.properties, result);
|
|
1411
|
+
} else if (prop['x-decorator'] === 'FormItem') {
|
|
1412
|
+
const secure = prop['x-component'] === 'Password';
|
|
1413
|
+
result.push({
|
|
1414
|
+
default: prop.default || '',
|
|
1415
|
+
description: prop.title || key,
|
|
1416
|
+
name: `${BLOCKLET_PREFERENCE_PREFIX}${key}`,
|
|
1417
|
+
required: prop.required || false,
|
|
1418
|
+
secure,
|
|
1419
|
+
shared: !secure,
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
};
|
|
1424
|
+
const getConfigFromPreferences = (blocklet) => {
|
|
1425
|
+
const result = [];
|
|
1426
|
+
const schemaFile = path.join(blocklet.env.appDir, BLOCKLET_PREFERENCE_FILE);
|
|
1427
|
+
if (fs.existsSync(schemaFile)) {
|
|
1428
|
+
try {
|
|
1429
|
+
const schema = JSON.parse(fs.readFileSync(schemaFile, 'utf8'));
|
|
1430
|
+
fromProperty2Config(schema.schema?.properties, result);
|
|
1431
|
+
} catch {
|
|
1432
|
+
// do nothing
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
return result;
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1388
1439
|
module.exports = {
|
|
1389
1440
|
forEachBlocklet,
|
|
1390
1441
|
getBlockletMetaFromUrl: (url) => getBlockletMetaFromUrl(url, { logger }),
|
|
@@ -1425,4 +1476,5 @@ module.exports = {
|
|
|
1425
1476
|
ensureMeta,
|
|
1426
1477
|
getBlocklet,
|
|
1427
1478
|
ensureEnvDefault,
|
|
1479
|
+
getConfigFromPreferences,
|
|
1428
1480
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { NODE_REGISTER_URL,
|
|
1
|
+
const { NODE_REGISTER_URL, BLOCKLET_STORE, BLOCKLET_STORE_DEV } = require('@abtnode/constant');
|
|
2
2
|
const canPackageReadWrite = require('@abtnode/util/lib/can-pkg-rw');
|
|
3
3
|
|
|
4
4
|
const getDefaultAutoUpgrade = () => {
|
|
@@ -16,21 +16,11 @@ const defaultNodeConfigs = {
|
|
|
16
16
|
blockletRegistryList: {
|
|
17
17
|
getDefaultValue: () => [
|
|
18
18
|
{
|
|
19
|
-
|
|
20
|
-
description: 'ArcBlock official blocklet registry',
|
|
21
|
-
url: BLOCKLET_STORE_URL,
|
|
22
|
-
logoUrl: '/logo.png',
|
|
23
|
-
maintainer: 'arcblock',
|
|
24
|
-
selected: true,
|
|
19
|
+
...BLOCKLET_STORE,
|
|
25
20
|
protected: true,
|
|
26
21
|
},
|
|
27
22
|
{
|
|
28
|
-
|
|
29
|
-
description: 'ArcBlock dev registry that contains demo and example blocklets',
|
|
30
|
-
url: BLOCKLET_STORE_URL_DEV,
|
|
31
|
-
maintainer: 'arcblock',
|
|
32
|
-
logoUrl: '/logo.png',
|
|
33
|
-
selected: false,
|
|
23
|
+
...BLOCKLET_STORE_DEV,
|
|
34
24
|
protected: false,
|
|
35
25
|
},
|
|
36
26
|
],
|
package/lib/util/store.js
CHANGED
|
@@ -84,7 +84,7 @@ const parseSourceUrl = async (url) => {
|
|
|
84
84
|
};
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const resolveTarballURL = async ({ did, tarball = '',
|
|
87
|
+
const resolveTarballURL = async ({ did, tarball = '', storeUrl = '' }) => {
|
|
88
88
|
if (!tarball) {
|
|
89
89
|
return '';
|
|
90
90
|
}
|
|
@@ -97,7 +97,7 @@ const resolveTarballURL = async ({ did, tarball = '', registryUrl = '' }) => {
|
|
|
97
97
|
return tarball;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
if (!
|
|
100
|
+
if (!storeUrl) {
|
|
101
101
|
return '';
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -105,11 +105,11 @@ const resolveTarballURL = async ({ did, tarball = '', registryUrl = '' }) => {
|
|
|
105
105
|
return '';
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
return joinURL(
|
|
108
|
+
return joinURL(storeUrl, 'api', 'blocklets', did, tarball);
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
const getBlockletMeta = async ({ did,
|
|
112
|
-
const url = joinURL(
|
|
111
|
+
const getBlockletMeta = async ({ did, storeUrl }) => {
|
|
112
|
+
const url = joinURL(storeUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json?__t__=${Date.now()}`);
|
|
113
113
|
|
|
114
114
|
const { data } = await request.get(url);
|
|
115
115
|
try {
|
|
@@ -122,7 +122,7 @@ const getBlockletMeta = async ({ did, registryUrl }) => {
|
|
|
122
122
|
meta.dist.tarball = await resolveTarballURL({
|
|
123
123
|
did,
|
|
124
124
|
tarball: meta.dist.tarball,
|
|
125
|
-
|
|
125
|
+
storeUrl,
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
return meta;
|
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.37",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,18 +19,18 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/auth": "1.8.
|
|
23
|
-
"@abtnode/certificate-manager": "1.8.
|
|
24
|
-
"@abtnode/constant": "1.8.
|
|
25
|
-
"@abtnode/cron": "1.8.
|
|
26
|
-
"@abtnode/db": "1.8.
|
|
27
|
-
"@abtnode/logger": "1.8.
|
|
28
|
-
"@abtnode/queue": "1.8.
|
|
29
|
-
"@abtnode/rbac": "1.8.
|
|
30
|
-
"@abtnode/router-provider": "1.8.
|
|
31
|
-
"@abtnode/static-server": "1.8.
|
|
32
|
-
"@abtnode/timemachine": "1.8.
|
|
33
|
-
"@abtnode/util": "1.8.
|
|
22
|
+
"@abtnode/auth": "1.8.37",
|
|
23
|
+
"@abtnode/certificate-manager": "1.8.37",
|
|
24
|
+
"@abtnode/constant": "1.8.37",
|
|
25
|
+
"@abtnode/cron": "1.8.37",
|
|
26
|
+
"@abtnode/db": "1.8.37",
|
|
27
|
+
"@abtnode/logger": "1.8.37",
|
|
28
|
+
"@abtnode/queue": "1.8.37",
|
|
29
|
+
"@abtnode/rbac": "1.8.37",
|
|
30
|
+
"@abtnode/router-provider": "1.8.37",
|
|
31
|
+
"@abtnode/static-server": "1.8.37",
|
|
32
|
+
"@abtnode/timemachine": "1.8.37",
|
|
33
|
+
"@abtnode/util": "1.8.37",
|
|
34
34
|
"@arcblock/did": "1.18.15",
|
|
35
35
|
"@arcblock/did-motif": "^1.1.10",
|
|
36
36
|
"@arcblock/did-util": "1.18.15",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"@arcblock/jwt": "^1.18.15",
|
|
39
39
|
"@arcblock/pm2-events": "^0.0.5",
|
|
40
40
|
"@arcblock/vc": "1.18.15",
|
|
41
|
-
"@blocklet/constant": "1.8.
|
|
42
|
-
"@blocklet/meta": "1.8.
|
|
43
|
-
"@blocklet/sdk": "1.8.
|
|
41
|
+
"@blocklet/constant": "1.8.37",
|
|
42
|
+
"@blocklet/meta": "1.8.37",
|
|
43
|
+
"@blocklet/sdk": "1.8.37",
|
|
44
44
|
"@fidm/x509": "^1.2.1",
|
|
45
45
|
"@ocap/mcrypto": "1.18.15",
|
|
46
46
|
"@ocap/util": "1.18.15",
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"express": "^4.18.2",
|
|
83
83
|
"jest": "^27.5.1"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "f26f451c6e2b1168b36f78269eafdf3f671236bf"
|
|
86
86
|
}
|