@abtnode/core 1.16.3 → 1.16.4-beta-8682e092

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 CHANGED
@@ -12,7 +12,6 @@ const {
12
12
  WELLKNOWN_SERVICE_PATH_PREFIX,
13
13
  MAX_USER_PAGE_SIZE,
14
14
  STORE_DETAIL_PAGE_PATH_PREFIX,
15
- USER_TYPE,
16
15
  } = require('@abtnode/constant');
17
16
  const { isValid: isValidDid } = require('@arcblock/did');
18
17
  const { BlockletEvents } = require('@blocklet/constant');
@@ -634,7 +633,9 @@ class TeamAPI extends EventEmitter {
634
633
  const state = await this.getSessionState(teamDid);
635
634
 
636
635
  const currentUser = await this.getUser({ teamDid, user: { did: ownerDid } });
637
- if (currentUser?.source === USER_TYPE.DERIVED) {
636
+ const isRawWalletAccount =
637
+ !currentUser?.extraConfigs?.sourceProvider || currentUser?.extraConfigs?.sourceProvider === 'wallet';
638
+ if (!isRawWalletAccount) {
638
639
  const userDid = currentUser.did;
639
640
  const blocklet = await getBlocklet({ did: teamDid, states: this.states, dataDirs: this.dataDirs });
640
641
  const nodeInfo = await this.node.read();
@@ -34,6 +34,8 @@ const {
34
34
  getComponentId,
35
35
  isPreferenceKey,
36
36
  getRolesFromAuthConfig,
37
+ isInProgress,
38
+ isBeforeInstalled,
37
39
  } = require('@blocklet/meta/lib/util');
38
40
  const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
39
41
  const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
@@ -124,14 +126,7 @@ const BlockletDownloader = require('../downloader/blocklet-downloader');
124
126
  const RollbackCache = require('./helper/rollback-cache');
125
127
  const { migrateApplicationToStructV2 } = require('./helper/migrate-application-to-struct-v2');
126
128
 
127
- const {
128
- isInProgress,
129
- isBeforeInstalled,
130
- formatEnvironments,
131
- shouldUpdateBlockletStatus,
132
- getBlockletMeta,
133
- validateOwner,
134
- } = util;
129
+ const { formatEnvironments, shouldUpdateBlockletStatus, getBlockletMeta, validateOwner } = util;
135
130
 
136
131
  const statusLock = new Lock('blocklet-status-lock');
137
132
 
@@ -237,6 +232,7 @@ class BlockletManager extends BaseBlockletManager {
237
232
  * description: string;
238
233
  * storeUrl: string;
239
234
  * appSk: string;
235
+ * skSource: string;
240
236
  * sync: boolean = false; // download synchronously, not use queue
241
237
  * delay: number; // push download task to queue after a delay
242
238
  * downloadTokenList: Array<{did: string, token: string}>;
@@ -1839,7 +1835,7 @@ class BlockletManager extends BaseBlockletManager {
1839
1835
  return children;
1840
1836
  }
1841
1837
 
1842
- async _addBlocklet({ component, mode = BLOCKLET_MODES.PRODUCTION, name, did, title, description }) {
1838
+ async _addBlocklet({ component, mode = BLOCKLET_MODES.PRODUCTION, name, did, title, description, skSource = '' }) {
1843
1839
  const meta = {
1844
1840
  name,
1845
1841
  did,
@@ -1898,6 +1894,7 @@ class BlockletManager extends BaseBlockletManager {
1898
1894
  source: BlockletSource.custom,
1899
1895
  children,
1900
1896
  mode,
1897
+ externalSkSource: skSource,
1901
1898
  };
1902
1899
 
1903
1900
  if (containerSourceUrl) {
@@ -20,6 +20,7 @@ const { getBlockletMetaFromUrl, ensureMeta, validateStore, validateInServerless
20
20
  const installApplicationFromGeneral = async ({
21
21
  type,
22
22
  appSk,
23
+ skSource,
23
24
  sync,
24
25
  delay,
25
26
  controller,
@@ -104,7 +105,7 @@ const installApplicationFromGeneral = async ({
104
105
  }
105
106
 
106
107
  // create app
107
- const blocklet = await manager._addBlocklet({ component, name, did, title, description });
108
+ const blocklet = await manager._addBlocklet({ component, name, did, title, description, skSource });
108
109
  logger.info('blocklet added to database', { did: blocklet.meta.did });
109
110
 
110
111
  // create config
@@ -2,9 +2,9 @@ const path = require('path');
2
2
 
3
3
  const logger = require('@abtnode/logger')('@abtnode/core:install-component-upload');
4
4
  const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
5
+ const { isInProgress } = require('@blocklet/meta/lib/util');
5
6
 
6
7
  const { BlockletSource, BlockletGroup, fromBlockletStatus } = require('@blocklet/constant');
7
- const { isInProgress } = require('../../../util');
8
8
  const {
9
9
  parseComponents,
10
10
  filterDuplicateComponents,
@@ -3,13 +3,18 @@ const fs = require('fs-extra');
3
3
  const pick = require('lodash/pick');
4
4
  const pRetry = require('p-retry');
5
5
  const Client = require('@ocap/client');
6
- const urlFriendly = require('@blocklet/meta/lib/url-friendly').default;
6
+ const urlPathFriendly = require('@blocklet/meta/lib/url-path-friendly').default;
7
7
  const { slugify } = require('transliteration');
8
8
  const Lock = require('@abtnode/util/lib/lock');
9
9
 
10
10
  const logger = require('@abtnode/logger')('@abtnode/core:migrate-application-to-struct-v2');
11
11
 
12
- const { forEachBlockletSync, getSharedConfigObj, getBlockletChainInfo } = require('@blocklet/meta/lib/util');
12
+ const {
13
+ forEachBlockletSync,
14
+ getSharedConfigObj,
15
+ getBlockletChainInfo,
16
+ isInProgress,
17
+ } = require('@blocklet/meta/lib/util');
13
18
  const { SLOT_FOR_IP_DNS_SITE, MAIN_CHAIN_ENDPOINT } = require('@abtnode/constant');
14
19
 
15
20
  const {
@@ -33,7 +38,6 @@ const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
33
38
  const getBlockletWallet = require('@blocklet/meta/lib/wallet');
34
39
  const { cloneDeep } = require('lodash');
35
40
 
36
- const { isInProgress } = require('../../../util');
37
41
  const { getBlockletDomainGroupName } = require('../../../util/router');
38
42
  const { getIpDnsDomainForBlocklet } = require('../../../util/get-domain-for-blocklet');
39
43
  const { getBundleDir } = require('../../../util/blocklet');
@@ -107,7 +111,7 @@ const ensureAccountOnMainChain = async (blocklet, newWallet) => {
107
111
  if (!newResultOnMainChain.state) {
108
112
  logger.info('declare account on main chain', { address: newWallet.address, did: blocklet.meta.did });
109
113
  const hash = await mainChainClient.declare({
110
- moniker: (urlFriendly(slugify(blocklet.meta.title || blocklet.meta.name)) || 'application').toLowerCase(),
114
+ moniker: (urlPathFriendly(slugify(blocklet.meta.title || blocklet.meta.name)) || 'application').toLowerCase(),
111
115
  wallet: newWallet,
112
116
  });
113
117
  logger.info('declare account on main chain done', { did: blocklet.meta.did, hash });
package/lib/event.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const get = require('lodash/get');
2
2
  const cloneDeep = require('lodash/cloneDeep');
3
3
  const { EventEmitter } = require('events');
4
- const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
4
+ const { wipeSensitiveData, isBeforeInstalled } = 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/constant');
7
7
  const { EVENTS } = require('@abtnode/constant');
@@ -12,7 +12,6 @@ const eventHub =
12
12
  process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
13
13
 
14
14
  const states = require('./states');
15
- const { isBeforeInstalled } = require('./util');
16
15
 
17
16
  const routingSnapshotPrefix = (blocklet) => (blocklet.mode === BLOCKLET_MODES.DEVELOPMENT ? '[DEV] ' : '');
18
17
 
@@ -104,7 +103,7 @@ module.exports = ({
104
103
  notificationState.create({
105
104
  title: 'Blocklet URL Mapping Error',
106
105
  // eslint-disable-next-line max-len
107
- description: `Failed to create URL mapping for blocklet ${blocklet.meta.name}@${blocklet.meta.version}, due to: ${error.message}`,
106
+ description: `Failed to create URL mapping for blocklet ${blocklet.meta.title}, due to: ${error.message}`,
108
107
  entityType: 'blocklet',
109
108
  entityId: blocklet.meta.did,
110
109
  severity: 'error',
@@ -155,7 +154,7 @@ module.exports = ({
155
154
  notificationState.create({
156
155
  title: 'Blocklet URL Mapping Error',
157
156
  // eslint-disable-next-line max-len
158
- description: `Failed to upgrade URL mapping for blocklet ${blocklet.meta.name}@${blocklet.meta.version}, due to: ${error.message}`,
157
+ description: `Failed to upgrade URL mapping for blocklet ${blocklet.meta.title}, due to: ${error.message}`,
159
158
  entityType: 'blocklet',
160
159
  entityId: blocklet.meta.did,
161
160
  severity: 'error',
@@ -270,39 +270,50 @@ const ensureWellknownRule = async (sites) => {
270
270
  // 这里默认 pathPrefix 最短的是自己 ( 通常自己在 /, 其他 blocklet 在 /xxxx )
271
271
  // 挂载其他 blocklet 的使用方式不推荐, 将来可能会被废弃
272
272
  .sort((a, b) => (a.from.pathPrefix.length > b.from.pathPrefix.length ? 1 : -1));
273
- if (blockletRules.length) {
274
- // get pathPrefix for blocklet-service
275
- const rootBlockletRule = blockletRules.find((x) => x.to.did === x.to.componentId);
276
-
277
- const servicePathPrefix = joinUrl(
278
- // rootBlockletRule?.from?.pathPrefix is for backwards compatibility
279
- // rootBlockletRule?.from?.groupPathPrefix 在旧的场景中可能不为 '/' (blocklet 只能挂载在 relative prefix 下)
280
- rootBlockletRule?.from?.groupPathPrefix || rootBlockletRule?.from?.pathPrefix || '/',
281
- WELLKNOWN_SERVICE_PATH_PREFIX
282
- );
283
273
 
284
- // requests for /.well-known/service will stay in blocklet-service and never proxy back to blocklet
285
- // so any rule is ok to be cloned
286
- if (!site.rules.some((x) => x.from.pathPrefix === servicePathPrefix)) {
287
- const rule = cloneDeep(rootBlockletRule || blockletRules[0]);
288
- rule.from.pathPrefix = servicePathPrefix;
289
- rule.to.target = servicePathPrefix;
290
- rule.isProtected = true;
291
- rule.dynamic = true; // mark as dynamic to avoid redundant generated rules
292
- site.rules.push(rule);
293
- }
274
+ const rootRule = blockletRules[0];
294
275
 
295
- // Cache user avatar in nginx
296
- const avatarPathPrefix = joinUrl(servicePathPrefix, USER_AVATAR_PATH_PREFIX);
297
- if (!site.rules.some((x) => x.from.pathPrefix === avatarPathPrefix)) {
298
- const rule = cloneDeep(rootBlockletRule || blockletRules[0]);
299
- rule.from.pathPrefix = avatarPathPrefix;
300
- rule.to.cacheGroup = 'blockletProxy';
301
- rule.to.target = avatarPathPrefix;
302
- rule.isProtected = true;
303
- rule.dynamic = true; // mark as dynamic to avoid redundant generated rules
304
- site.rules.push(rule);
305
- }
276
+ // Serve blocklet service always
277
+ const servicePathPrefix = joinUrl(WELLKNOWN_SERVICE_PATH_PREFIX);
278
+ if (!site.rules.some((x) => x.from.pathPrefix === servicePathPrefix)) {
279
+ site.rules.push({
280
+ id: rootRule?.id || '',
281
+ groupId: rootRule?.groupId || '',
282
+ from: {
283
+ pathPrefix: servicePathPrefix,
284
+ groupPathPrefix: '/',
285
+ },
286
+ to: {
287
+ type: 'blocklet',
288
+ did: site.blockletDid,
289
+ componentId: site.blockletDid,
290
+ target: servicePathPrefix,
291
+ },
292
+ isProtected: true,
293
+ dynamic: true,
294
+ });
295
+ }
296
+
297
+ // Cache user avatar from gateway
298
+ const avatarPathPrefix = joinUrl(servicePathPrefix, USER_AVATAR_PATH_PREFIX);
299
+ if (!site.rules.some((x) => x.from.pathPrefix === avatarPathPrefix)) {
300
+ site.rules.push({
301
+ id: rootRule?.id || '',
302
+ groupId: rootRule?.groupId || '',
303
+ from: {
304
+ pathPrefix: avatarPathPrefix,
305
+ groupPathPrefix: '/',
306
+ },
307
+ to: {
308
+ type: 'blocklet',
309
+ did: site.blockletDid,
310
+ componentId: site.blockletDid,
311
+ cacheGroup: 'blockletProxy',
312
+ target: avatarPathPrefix,
313
+ },
314
+ isProtected: true,
315
+ dynamic: true,
316
+ });
306
317
  }
307
318
  }
308
319
  }
@@ -901,7 +912,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
901
912
  };
902
913
 
903
914
  if (!existedRule) {
904
- await routerManager.addRoutingRule({ id: wellknownSite.id, rule, skipCheckDynamicBlacklist: true }, context);
915
+ await routerManager.addRoutingRule(
916
+ { id: wellknownSite.id, rule, skipCheckDynamicBlacklist: true, formatPathPrefix: false },
917
+ context
918
+ );
905
919
  return true;
906
920
  }
907
921
 
@@ -910,7 +924,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
910
924
  existedRule.to = rule.to;
911
925
 
912
926
  await routerManager.updateRoutingRule(
913
- { id: wellknownSite.id, rule: existedRule, skipProtectedRuleChecking: true },
927
+ { id: wellknownSite.id, rule: existedRule, skipProtectedRuleChecking: true, formatPathPrefix: false },
914
928
  context
915
929
  );
916
930
 
@@ -1,5 +1,6 @@
1
1
  const get = require('lodash/get');
2
2
  const pick = require('lodash/pick');
3
+ const isEqual = require('lodash/isEqual');
3
4
  const cloneDeep = require('lodash/cloneDeep');
4
5
  const {
5
6
  DOMAIN_FOR_DEFAULT_SITE,
@@ -188,9 +189,6 @@ Router.formatSites = (sites = []) => {
188
189
  if (Array.isArray(site.rules) && site.rules.length > 0) {
189
190
  const rules = cloneDeep(site.rules);
190
191
 
191
- let hasRootPathBlockletRule = false;
192
- let tmpBlockletRule;
193
-
194
192
  rules.forEach((rule) => {
195
193
  if ([ROUTING_RULE_TYPES.BLOCKLET].includes(rule.to.type) === false) {
196
194
  return;
@@ -205,11 +203,6 @@ Router.formatSites = (sites = []) => {
205
203
  }
206
204
 
207
205
  if (daemonRule) {
208
- if (rule.from.pathPrefix === '/') {
209
- hasRootPathBlockletRule = true;
210
- }
211
- tmpBlockletRule = rule;
212
-
213
206
  // Serve meta js: both prefix and suffix do not contain trailing slash
214
207
  // NOTICE: 这里隐含了一个约定
215
208
  // 如果安装的 blockletA 和 blockletB 都需要 __blocklet__.js
@@ -242,38 +235,43 @@ Router.formatSites = (sites = []) => {
242
235
  cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletJs' : '',
243
236
  },
244
237
  });
238
+ }
239
+ });
245
240
 
241
+ if (daemonRule) {
242
+ const rootFrom = {
243
+ pathPrefix: '/',
244
+ groupPathPrefix: '/',
245
+ pathSuffix: '/__blocklet__.js',
246
+ };
247
+ // ensure /__blocklet__.js should be proxy to daemon
248
+ if (!site.rules.find((x) => isEqual(x.from, rootFrom))) {
249
+ site.rules.push({
250
+ from: rootFrom,
251
+ to: {
252
+ type: ROUTING_RULE_TYPES.DAEMON,
253
+ port: daemonRule.to.port,
254
+ cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletJs' : '',
255
+ did: site.blockletDid,
256
+ },
257
+ });
258
+ }
259
+
260
+ // ensure /.blocklet/proxy should be proxy to daemon
261
+ if (!site.rules.find((x) => x.from.pathPrefix === BLOCKLET_PROXY_PATH_PREFIX)) {
246
262
  site.rules.push({
247
263
  from: {
248
264
  pathPrefix: BLOCKLET_PROXY_PATH_PREFIX,
249
265
  },
250
266
  to: {
251
267
  port: daemonRule.to.port,
252
- did: rule.to.did,
253
268
  type: ROUTING_RULE_TYPES.DAEMON,
254
269
  target: BLOCKLET_PROXY_PATH_PREFIX,
255
270
  cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletProxy' : '',
271
+ did: site.blockletDid,
256
272
  },
257
273
  });
258
274
  }
259
- });
260
-
261
- // ensure /__blocklet__.js should be proxy to daemon
262
- if (daemonRule && !hasRootPathBlockletRule && tmpBlockletRule) {
263
- site.rules.push({
264
- from: {
265
- pathPrefix: '/',
266
- groupPathPrefix: '/',
267
- pathSuffix: '/__blocklet__.js',
268
- },
269
- to: {
270
- type: ROUTING_RULE_TYPES.DAEMON,
271
- port: daemonRule.to.port,
272
- did: tmpBlockletRule.to.did,
273
- componentId: tmpBlockletRule.to.did,
274
- cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletJs' : '',
275
- },
276
- });
277
275
  }
278
276
  }
279
277
  });
@@ -258,8 +258,16 @@ class RouterManager extends EventEmitter {
258
258
  return dbSite;
259
259
  }
260
260
 
261
- async addRoutingRule({ id, rule: tempRule, skipCheckDynamicBlacklist = false }, context = {}) {
261
+ async addRoutingRule(
262
+ { id, rule: tempRule, skipCheckDynamicBlacklist = false, formatPathPrefix = true },
263
+ context = {}
264
+ ) {
262
265
  const { rule } = await validateAddRule({ id, rule: tempRule }, context);
266
+
267
+ if (!formatPathPrefix) {
268
+ rule.from.pathPrefix = tempRule.from.pathPrefix;
269
+ }
270
+
263
271
  const dbSite = await states.site.findOne({ _id: id });
264
272
  if (!dbSite) {
265
273
  throw new Error(`site ${id} does not exist`);
@@ -275,7 +283,7 @@ class RouterManager extends EventEmitter {
275
283
  const existedRule = dbSite.rules.find((x) => x.from.pathPrefix === rule.from.pathPrefix);
276
284
 
277
285
  if (existedRule) {
278
- throw new Error(`path prefix '${originalPathPrefix}' already exists`);
286
+ throw new Error(`addRoutingRule: path prefix '${originalPathPrefix}' already exists`);
279
287
  }
280
288
  }
281
289
 
@@ -294,8 +302,16 @@ class RouterManager extends EventEmitter {
294
302
  return newSite;
295
303
  }
296
304
 
297
- async updateRoutingRule({ id, rule: tmpRule, skipProtectedRuleChecking = false }, context = {}) {
305
+ async updateRoutingRule(
306
+ { id, rule: tmpRule, skipProtectedRuleChecking = false, formatPathPrefix = true },
307
+ context = {}
308
+ ) {
298
309
  const { rule } = await validateEditRule({ id, rule: tmpRule }, context);
310
+
311
+ if (!formatPathPrefix) {
312
+ rule.from.pathPrefix = tmpRule.from.pathPrefix;
313
+ }
314
+
299
315
  const dbSite = await states.site.findOne({ _id: id, 'rules.id': rule.id });
300
316
  if (!dbSite) {
301
317
  throw new Error(`site ${id}, rule ${rule.id} does not exist`);
@@ -310,7 +326,7 @@ class RouterManager extends EventEmitter {
310
326
  // Ensure path prefix is unique across the site
311
327
  const existedRule = dbSite.rules.find((x) => x.id !== rule.id && x.from.pathPrefix === rule.from.pathPrefix);
312
328
  if (existedRule) {
313
- throw new Error(`path prefix '${originalPathPrefix}' already exists`);
329
+ throw new Error(`updateRoutingRule: path prefix '${originalPathPrefix}' already exists`);
314
330
  }
315
331
 
316
332
  // Ensure we are not updating protected rules
@@ -9,14 +9,14 @@ const detectPort = require('detect-port');
9
9
  const Lock = require('@abtnode/util/lib/lock');
10
10
  const security = require('@abtnode/util/lib/security');
11
11
  const { fixPerson, fixInterfaces } = require('@blocklet/meta/lib/fix');
12
- const { getDisplayName, forEachBlocklet, forEachBlockletSync, forEachChildSync } = require('@blocklet/meta/lib/util');
13
12
  const {
14
- BlockletStatus,
15
- BlockletSource,
16
- BLOCKLET_MODES,
17
- BLOCKLET_DEFAULT_PORT_NAME,
18
- BLOCKLET_INTERFACE_TYPE_SERVICE,
19
- } = require('@blocklet/constant');
13
+ getDisplayName,
14
+ forEachBlocklet,
15
+ forEachBlockletSync,
16
+ forEachChildSync,
17
+ getBlockletServices,
18
+ } = require('@blocklet/meta/lib/util');
19
+ const { BlockletStatus, BlockletSource, BLOCKLET_MODES, BLOCKLET_DEFAULT_PORT_NAME } = require('@blocklet/constant');
20
20
  const { APP_STRUCT_VERSION } = require('@abtnode/constant');
21
21
 
22
22
  const logger = require('@abtnode/logger')('state-blocklet');
@@ -259,6 +259,7 @@ class BlockletState extends BaseState {
259
259
  // whether sk is managed by some party beside server, such as did-wallet
260
260
  // externalSk is always true in struct V2 blocklet
261
261
  externalSk = true,
262
+ externalSkSource = '',
262
263
  } = {}) {
263
264
  return this.getBlocklet(meta.did).then(
264
265
  (exist) =>
@@ -300,6 +301,7 @@ class BlockletState extends BaseState {
300
301
  children,
301
302
  migratedFrom,
302
303
  externalSk,
304
+ externalSkSource,
303
305
  structVersion: APP_STRUCT_VERSION,
304
306
  };
305
307
 
@@ -489,16 +491,34 @@ class BlockletState extends BaseState {
489
491
  }
490
492
 
491
493
  async getServices() {
492
- const blocklets = await this.getBlocklets({}, { ports: 1, 'meta.interfaces': 1 });
494
+ const blocklets = await this.getBlocklets({}, { meta: 1, children: 1, ports: 1 });
493
495
  const services = [];
496
+
494
497
  blocklets.forEach((blocklet) => {
495
- const interfaces = (blocklet.meta.interfaces || []).filter((x) => x.type === BLOCKLET_INTERFACE_TYPE_SERVICE);
496
- interfaces.forEach((x) => {
497
- services.push({
498
- protocol: x.protocol,
499
- port: Number(x.port.external),
500
- upstreamPort: Number(blocklet.ports[x.port.internal]),
501
- });
498
+ const list = getBlockletServices(blocklet);
499
+ list.forEach((x) => {
500
+ if (!x.port) {
501
+ logger.error('Missing service port', { appId: blocklet.meta.did, x });
502
+ return;
503
+ }
504
+
505
+ if (!x.protocol) {
506
+ logger.error('Missing service protocol', { appId: blocklet.meta.did, x });
507
+ return;
508
+ }
509
+
510
+ if (!x.upstreamPort) {
511
+ logger.error('Missing service upstreamPort', { appId: blocklet.meta.did, x });
512
+ return;
513
+ }
514
+
515
+ if (services.find((s) => s.port === x.port)) {
516
+ // should not be here
517
+ logger.error('Duplicate service port', { appId: blocklet.meta.did, x });
518
+ return;
519
+ }
520
+
521
+ services.push(x);
502
522
  });
503
523
  });
504
524
 
@@ -24,6 +24,32 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
24
24
  * @property {string} role - passport's role
25
25
  */
26
26
 
27
+ /**
28
+ * Auth0Account
29
+ * @typedef {Object} Auth0Account
30
+ * @property {'auth0'} provider
31
+ * @property {string} id - id from auth0
32
+ * @property {string} did - did for auth0 account
33
+ * @property {string} pk - pk for auth0 account
34
+ * @property {string} lastLoginAt - Last login time new Date().toISOString()
35
+ * @property {string} firstLoginAt - First login time new Date().toISOString()
36
+ */
37
+
38
+ /**
39
+ * WalletAccount
40
+ * @typedef {Object} WalletAccount
41
+ * @property {'wallet'} provider
42
+ * @property {string} did - did for auth0 account
43
+ * @property {string} pk - pk for auth0 account
44
+ * @property {string} lastLoginAt - Last login time new Date().toISOString()
45
+ * @property {string} firstLoginAt - First login time new Date().toISOString()
46
+ */
47
+
48
+ /**
49
+ * ConnectedAccount
50
+ * @typedef {(Auth0Account|WalletAccount)} ConnectedAccount
51
+ */
52
+
27
53
  /**
28
54
  * The Data structure of blocklet-service user
29
55
  * @typedef {Object} BlockletUser - Blocklet Service User Table
@@ -31,13 +57,16 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
31
57
  * @property {('profile')} type - type of user
32
58
  * @property {string} fullName - user profile's name
33
59
  * @property {string} avatar - url of user's avatar, eg: bn://avatar/7f8848569405f8cdf8b1b2788ebf7d0f.jpg
34
- * @property {string} did - user's did
60
+ * @property {string} did - user's did -> 实际上变为 uid, 是不可变的;真正的 wallet-did 转移到 extraConfigs 中去了
61
+ * @property {string} pk - user's publicKey
35
62
  * @property {('owner'|'admin'|'member'|'guest'|string)} role - user's role
36
63
  * @property {UserPassport[]} passports - user's passport list
37
- * @property {string} pk - user's publicKey
38
64
  * @property {boolean} approved - enable user to login
39
65
  * @property {string} locale - locale
40
- * @property {Object} extra - extra data of user
66
+ * @property {Object} [extra] - extra data of user
67
+ * @property {Object} [extraConfigs] - extra data of user
68
+ * @property {ConnectedAccount[]} [extraConfigs.connectedAccounts] - connectedAccounts
69
+ * @property {('wallet'|'auth0')} [extraConfigs.sourceProvider] - sourceProvider, the main account provider
41
70
  * @property {Date} firstLoginAt - firstLoginAt
42
71
  * @property {Date} lastLoginAt - lastLoginAt
43
72
  * @property {string} lastLoginIp - lastLoginIp
@@ -139,7 +168,7 @@ class User extends BaseState {
139
168
  /**
140
169
  * update user's role
141
170
  * @param {string} did user's did
142
- * @param {BlockletUser.role} role user's rolel
171
+ * @param {BlockletUser.role} role user's role
143
172
  * @returns {BlockletUser}
144
173
  */
145
174
  async updateRole({ did, role }) {
@@ -160,7 +189,7 @@ class User extends BaseState {
160
189
  * @returns {{list: BlockletUser[]; paging: any;}}
161
190
  */
162
191
  async getUsers({ query, sort, paging: inputPaging } = {}) {
163
- const { approved, role, search, derivedDid } = query || {};
192
+ const { approved, role, search, connectedDid } = query || {};
164
193
 
165
194
  // make query param
166
195
  const queryParam = {};
@@ -191,9 +220,9 @@ class User extends BaseState {
191
220
  }
192
221
  }
193
222
 
194
- // 根据 derivedDid 查询 user 信息(wallet 账户绑定 oauth 账户后,会有该字段)
195
- if (derivedDid) {
196
- queryParam['extraConfigs.derivedAccount.did'] = derivedDid;
223
+ // 根据 connectedDid 查询 user 信息(wallet 账户绑定 oauth 账户后,会有该字段)
224
+ if (connectedDid) {
225
+ queryParam['extraConfigs.connectedAccounts.did'] = connectedDid;
197
226
  }
198
227
 
199
228
  const sortParam = pickBy(sort, (x) => !isNullOrUndefined(x));
@@ -77,6 +77,7 @@ const {
77
77
  getComponentName,
78
78
  isEnvShareable,
79
79
  getBlockletAppIdList,
80
+ isBeforeInstalled,
80
81
  } = require('@blocklet/meta/lib/util');
81
82
  const toBlockletDid = require('@blocklet/meta/lib/did');
82
83
  const { titleSchema, descriptionSchema, logoSchema } = require('@blocklet/meta/lib/schema');
@@ -91,14 +92,7 @@ const { validate: validateEngine, get: getEngine } = require('../blocklet/manage
91
92
 
92
93
  const isRequirementsSatisfied = require('./requirement');
93
94
  const { getDidDomainForBlocklet } = require('./get-domain-for-blocklet');
94
- const {
95
- isBeforeInstalled,
96
- expandBundle,
97
- findInterfacePortByName,
98
- prettyURL,
99
- getNFTState,
100
- templateReplace,
101
- } = require('./index');
95
+ const { expandBundle, findInterfacePortByName, prettyURL, getNFTState, templateReplace } = require('./index');
102
96
 
103
97
  const getComponentConfig = (meta) => {
104
98
  const components = meta.components || meta.children || [];
package/lib/util/index.js CHANGED
@@ -17,7 +17,7 @@ const axios = require('@abtnode/util/lib/axios');
17
17
  const { encode: encodeBase32 } = require('@abtnode/util/lib/base32');
18
18
  const parseBlockletMeta = require('@blocklet/meta/lib/parse');
19
19
  const { BlockletStatus } = require('@blocklet/constant');
20
- const { replaceSlotToIp } = require('@blocklet/meta/lib/util');
20
+ const { replaceSlotToIp, isInProgress } = require('@blocklet/meta/lib/util');
21
21
  const {
22
22
  StatusCode,
23
23
  DOMAIN_FOR_DEFAULT_SITE,
@@ -93,21 +93,6 @@ const getBlockletHost = ({ domain, context, nodeIp }) => {
93
93
 
94
94
  const isRoutingEnabled = (routing) => !!routing && !!routing.provider;
95
95
 
96
- const isInProgress = (status) =>
97
- [
98
- BlockletStatus.downloading,
99
- BlockletStatus.waiting,
100
- BlockletStatus.starting,
101
- BlockletStatus.installing,
102
- BlockletStatus.stopping,
103
- BlockletStatus.upgrading,
104
- ].includes(status);
105
-
106
- const isBeforeInstalled = (status) =>
107
- [BlockletStatus.added, BlockletStatus.waiting, BlockletStatus.downloading, BlockletStatus.installing].includes(
108
- status
109
- );
110
-
111
96
  // Check whether a domain is setup
112
97
  const checkDomainDNS = (domain) =>
113
98
  new Promise((resolve) => {
@@ -479,8 +464,6 @@ const lib = {
479
464
  toStatus,
480
465
  fromStatus,
481
466
  formatEnvironments,
482
- isInProgress,
483
- isBeforeInstalled,
484
467
  replaceDomainSlot,
485
468
  getBlockletHost,
486
469
  isRoutingEnabled,
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable newline-per-chained-call */
2
2
  const Joi = require('joi');
3
3
  const { DOMAIN_FOR_DEFAULT_SITE, ROUTING_RULE_TYPES, ROUTER_CACHE_GROUPS } = require('@abtnode/constant');
4
- const urlFriendly = require('@blocklet/meta/lib/url-friendly').default;
4
+ const urlPathFriendly = require('@blocklet/meta/lib/url-path-friendly').default;
5
5
  const { getMultipleLangParams } = require('./util');
6
6
 
7
7
  const WILDCARD_DOMAIN_REGEX = /^\*.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/;
@@ -29,7 +29,7 @@ const ruleSchema = {
29
29
  zh: { 'string.empty': 'URL 前缀不能为空', 'string.max': 'URL 前缀的最大长度是 150' },
30
30
  en: { 'string.empty': 'URL prefix cannot be empty', 'string.max': 'The maximum length of URL prefix is 150' },
31
31
  })
32
- .custom((value) => urlFriendly(value)),
32
+ .custom((value) => urlPathFriendly(value)),
33
33
  groupPathPrefix: Joi.string().trim().min(1).max(150), // path prefix of interface of root blocklet
34
34
  header: Joi.any(), // TODO: header does not take effect
35
35
  }),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.3",
6
+ "version": "1.16.4-beta-8682e092",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,34 +19,34 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.16.3",
23
- "@abtnode/certificate-manager": "1.16.3",
24
- "@abtnode/constant": "1.16.3",
25
- "@abtnode/cron": "1.16.3",
26
- "@abtnode/db": "1.16.3",
27
- "@abtnode/logger": "1.16.3",
28
- "@abtnode/queue": "1.16.3",
29
- "@abtnode/rbac": "1.16.3",
30
- "@abtnode/router-provider": "1.16.3",
31
- "@abtnode/static-server": "1.16.3",
32
- "@abtnode/timemachine": "1.16.3",
33
- "@abtnode/util": "1.16.3",
34
- "@arcblock/did": "1.18.65",
22
+ "@abtnode/auth": "1.16.4-beta-8682e092",
23
+ "@abtnode/certificate-manager": "1.16.4-beta-8682e092",
24
+ "@abtnode/constant": "1.16.4-beta-8682e092",
25
+ "@abtnode/cron": "1.16.4-beta-8682e092",
26
+ "@abtnode/db": "1.16.4-beta-8682e092",
27
+ "@abtnode/logger": "1.16.4-beta-8682e092",
28
+ "@abtnode/queue": "1.16.4-beta-8682e092",
29
+ "@abtnode/rbac": "1.16.4-beta-8682e092",
30
+ "@abtnode/router-provider": "1.16.4-beta-8682e092",
31
+ "@abtnode/static-server": "1.16.4-beta-8682e092",
32
+ "@abtnode/timemachine": "1.16.4-beta-8682e092",
33
+ "@abtnode/util": "1.16.4-beta-8682e092",
34
+ "@arcblock/did": "1.18.67",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.65",
37
- "@arcblock/event-hub": "1.18.65",
38
- "@arcblock/jwt": "^1.18.65",
36
+ "@arcblock/did-util": "1.18.67",
37
+ "@arcblock/event-hub": "1.18.67",
38
+ "@arcblock/jwt": "^1.18.67",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.65",
41
- "@blocklet/constant": "1.16.3",
42
- "@blocklet/meta": "1.16.3",
43
- "@blocklet/sdk": "1.16.3",
44
- "@did-space/client": "^0.2.45",
40
+ "@arcblock/vc": "1.18.67",
41
+ "@blocklet/constant": "1.16.4-beta-8682e092",
42
+ "@blocklet/meta": "1.16.4-beta-8682e092",
43
+ "@blocklet/sdk": "1.16.4-beta-8682e092",
44
+ "@did-space/client": "^0.2.67",
45
45
  "@fidm/x509": "^1.2.1",
46
- "@ocap/client": "1.18.65",
47
- "@ocap/mcrypto": "1.18.65",
48
- "@ocap/util": "1.18.65",
49
- "@ocap/wallet": "1.18.65",
46
+ "@ocap/client": "1.18.67",
47
+ "@ocap/mcrypto": "1.18.67",
48
+ "@ocap/util": "1.18.67",
49
+ "@ocap/wallet": "1.18.67",
50
50
  "@slack/webhook": "^5.0.4",
51
51
  "archiver": "^5.3.1",
52
52
  "axios": "^0.27.2",
@@ -93,5 +93,5 @@
93
93
  "express": "^4.18.2",
94
94
  "jest": "^27.5.1"
95
95
  },
96
- "gitHead": "a21d48225c6f89963796871f404a2318a335701d"
96
+ "gitHead": "ab6fc7aeaec32f14ec2153976f2121aa893486b5"
97
97
  }