@abtnode/core 1.16.6-beta-4ea1eb90 → 1.16.6-beta-7c9b42cc

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
@@ -110,6 +110,42 @@ class TeamAPI extends EventEmitter {
110
110
 
111
111
  // User && Invitation
112
112
 
113
+ async loginUser({ teamDid, user }) {
114
+ const state = await this.getUserState(teamDid);
115
+ const nodeInfo = await this.node.read();
116
+
117
+ if (user.role === ROLES.OWNER) {
118
+ if (teamDid !== nodeInfo.did) {
119
+ throw new Error('Cannot add user of owner role');
120
+ }
121
+
122
+ if (await state.count({ role: ROLES.OWNER })) {
123
+ throw new Error('The owner already exists');
124
+ }
125
+ }
126
+
127
+ const { _action, ...doc } = await state.login(user);
128
+ if (_action === 'update') {
129
+ logger.info('user updated successfully', { teamDid, userDid: user.did });
130
+ this.emit(EVENTS.USER_UPDATED, { teamDid, user: doc });
131
+ } else if (_action === 'add') {
132
+ if (teamDid === nodeInfo.did && nodeInfo.nodeOwner && user.did !== nodeInfo.nodeOwner.did) {
133
+ await this.notification.create({
134
+ title: 'New member join',
135
+ description: `User with Name (${user.fullName}) and DID (${user.did}) has joined this server`,
136
+ entityType: 'node',
137
+ action: '/team/members',
138
+ entityId: user.did,
139
+ severity: 'success',
140
+ });
141
+ }
142
+
143
+ logger.info('user added successfully', { teamDid, userDid: user.did, userPk: user.pk, userName: user.fullName });
144
+ this.emit(EVENTS.USER_ADDED, { teamDid, user: doc });
145
+ }
146
+ return doc;
147
+ }
148
+
113
149
  async addUser({ teamDid, user }) {
114
150
  const state = await this.getUserState(teamDid);
115
151
 
@@ -239,10 +275,10 @@ class TeamAPI extends EventEmitter {
239
275
  return res;
240
276
  }
241
277
 
242
- async getUser({ teamDid, user }) {
278
+ async getUser({ teamDid, user, options = {} }) {
243
279
  const state = await this.getUserState(teamDid);
244
280
 
245
- return state.getUser(user.did);
281
+ return state.getUser(user.did, options);
246
282
  }
247
283
 
248
284
  async getOwner({ teamDid }) {
@@ -103,6 +103,7 @@ const {
103
103
  getBlockletKnownAs,
104
104
  updateBlockletFallbackLogo,
105
105
  ensureAppLogo,
106
+ getBlockletDidDomainList,
106
107
  } = require('../../util/blocklet');
107
108
  const states = require('../../states');
108
109
  const BaseBlockletManager = require('./base');
@@ -110,7 +111,6 @@ const { get: getEngine } = require('./engine');
110
111
  const blockletPm2Events = require('./pm2-events');
111
112
  const runMigrationScripts = require('../migration');
112
113
  const hooks = require('../hooks');
113
- const { getDidDomainForBlocklet } = require('../../util/get-domain-for-blocklet');
114
114
  const handleInstanceInStore = require('../../util/public-to-store');
115
115
  const { BlockletRuntimeMonitor } = require('../../monitor/blocklet-runtime-monitor');
116
116
  const getHistoryList = require('../../monitor/get-history-list');
@@ -1095,10 +1095,6 @@ class BlockletManager extends BaseBlockletManager {
1095
1095
  this.emit(BlockletEvents.spaceConnected, blocklet);
1096
1096
  }
1097
1097
 
1098
- if (willAppDidChange && !skipDidDocument) {
1099
- await this._updateDidDocument(blocklet);
1100
- }
1101
-
1102
1098
  // update blocklet meta
1103
1099
  if (blocklet.structVersion && !childDids.length) {
1104
1100
  const changedTitle = newConfigs.find((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_NAME)?.value;
@@ -1124,7 +1120,13 @@ class BlockletManager extends BaseBlockletManager {
1124
1120
 
1125
1121
  // response
1126
1122
  const newState = await this.getBlocklet(rootDid);
1123
+
1124
+ if (willAppDidChange && !skipDidDocument) {
1125
+ await this._updateDidDocument(newState);
1126
+ }
1127
+
1127
1128
  this.emit(BlockletEvents.updated, newState);
1129
+
1128
1130
  return newState;
1129
1131
  }
1130
1132
 
@@ -2276,12 +2278,12 @@ class BlockletManager extends BaseBlockletManager {
2276
2278
  const nodeInfo = await states.node.read();
2277
2279
  const { wallet } = getBlockletInfo(blocklet, nodeInfo.sk);
2278
2280
  didDocument
2279
- .disableDNS({ wallet, didRegistryUrl: nodeInfo.didRegistry })
2281
+ .disableBlockletDNS({ appPid: blocklet.appPid, wallet, didRegistryUrl: nodeInfo.didRegistry })
2280
2282
  .then(() => {
2281
- logger.info(`disabled blocklet ${blocklet.appDid} dns`);
2283
+ logger.info(`disabled blocklet ${blocklet.appPid} dns`);
2282
2284
  })
2283
2285
  .catch((err) => {
2284
- logger.error(`disable blocklet ${blocklet.appDid} dns failed`, { error: err });
2286
+ logger.error(`disable blocklet ${blocklet.appPid} dns failed`, { error: err });
2285
2287
  });
2286
2288
  }
2287
2289
 
@@ -2547,32 +2549,24 @@ class BlockletManager extends BaseBlockletManager {
2547
2549
  async _updateDidDocument(blocklet) {
2548
2550
  const nodeInfo = await states.node.read();
2549
2551
 
2550
- const { wallet } = getBlockletInfo(
2551
- {
2552
- meta: blocklet.meta,
2553
- environments: [BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK, BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_WALLET_TYPE]
2554
- .map((key) => ({ key, value: blocklet.configObj[key] }))
2555
- .filter((x) => x.value),
2556
- },
2557
- nodeInfo.sk
2558
- );
2559
- const didDomain = getDidDomainForBlocklet({ appPid: blocklet.appPid, didDomain: nodeInfo.didDomain });
2560
-
2561
2552
  const domainAliases = (get(blocklet, 'site.domainAliases') || []).filter(
2562
2553
  (item) => !item.value.endsWith(nodeInfo.didDomain) && !item.value.endsWith('did.staging.arcblock.io') // did.staging.arcblock.io 是旧 did domain, 但主要存在于比较旧的节点中, 需要做兼容
2563
2554
  );
2564
2555
 
2565
- domainAliases.push({ value: didDomain, isProtected: true });
2556
+ const didDomainList = getBlockletDidDomainList(blocklet, nodeInfo);
2557
+ domainAliases.push(...didDomainList);
2566
2558
 
2567
2559
  // 先更新 routing rule db 中的 domain aliases, 这一步的目的是为了后面用
2568
2560
  await states.site.updateDomainAliasList(blocklet.site.id, domainAliases);
2569
2561
 
2570
2562
  this.emit(BlockletEvents.appDidChanged, blocklet);
2571
2563
 
2564
+ const { wallet } = getBlockletInfo(blocklet, nodeInfo.sk);
2565
+ const alsoKnownAs = getBlockletKnownAs(blocklet);
2572
2566
  await didDocument.updateBlockletDocument({
2573
2567
  wallet,
2574
2568
  appPid: blocklet.appPid,
2575
- alsoKnownAs: getBlockletKnownAs(blocklet),
2569
+ alsoKnownAs,
2576
2570
  daemonDidDomain: util.getServerDidDomain(nodeInfo),
2577
2571
  didRegistryUrl: nodeInfo.didRegistry,
2578
2572
  domain: nodeInfo.didDomain,
package/lib/index.js CHANGED
@@ -303,6 +303,7 @@ function ABTNode(options) {
303
303
  getNodeUsers: () => teamAPI.getUsers({ teamDid: options.nodeDid }),
304
304
  getNodeUser: (user) => teamAPI.getUser({ teamDid: options.nodeDid, user }),
305
305
  addUser: teamAPI.addUser.bind(teamAPI),
306
+ loginUser: teamAPI.loginUser.bind(teamAPI),
306
307
  removeUser: teamAPI.removeUser.bind(teamAPI),
307
308
  updateUser: teamAPI.updateUser.bind(teamAPI),
308
309
  updateUserApproval: teamAPI.updateUserApproval.bind(teamAPI),
@@ -61,13 +61,13 @@ const {
61
61
  isGatewayCacheEnabled,
62
62
  isBlockletSite,
63
63
  } = require('../util');
64
- const { getIpDnsDomainForBlocklet, getDidDomainForBlocklet } = require('../util/get-domain-for-blocklet');
64
+ const { getIpDnsDomainForBlocklet } = require('../util/get-domain-for-blocklet');
65
65
  const { getFromCache: getAccessibleExternalNodeIp } = require('../util/get-accessible-external-node-ip');
66
66
 
67
67
  const Router = require('./index');
68
68
  const states = require('../states');
69
69
  const { getBlockletDomainGroupName, getDidFromDomainGroupName } = require('../util/router');
70
- const { getBlockletKnownAs } = require('../util/blocklet');
70
+ const { getBlockletKnownAs, getBlockletDidDomainList } = require('../util/blocklet');
71
71
 
72
72
  const isServiceFeDevelopment = process.env.ABT_NODE_SERVICE_FE_PORT;
73
73
 
@@ -839,13 +839,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
839
839
  });
840
840
 
841
841
  if (!existSite) {
842
- const domainAliases = [];
843
-
844
- const didDomain = getDidDomainForBlocklet({ appPid: blocklet.appPid, didDomain: nodeInfo.didDomain });
845
- const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet);
842
+ const domainAliases = getBlockletDidDomainList(blocklet, nodeInfo);
846
843
 
847
844
  // let didDomain in front of ipEchoDnsDomain
848
- domainAliases.push({ value: didDomain, isProtected: true }, { value: ipEchoDnsDomain, isProtected: true });
845
+ domainAliases.push({ value: getIpDnsDomainForBlocklet(blocklet), isProtected: true });
849
846
 
850
847
  await routerManager.addRoutingSite(
851
848
  {
@@ -1,11 +1,17 @@
1
1
  const pickBy = require('lodash/pickBy');
2
2
  const escapeStringRegexp = require('escape-string-regexp');
3
-
3
+ const pick = require('lodash/pick');
4
+ const cloneDeep = require('lodash/cloneDeep');
4
5
  const logger = require('@abtnode/logger')('@abtnode/core:states:user');
5
6
  const { isValid } = require('@arcblock/did');
6
7
  const { PASSPORT_STATUS } = require('@abtnode/constant');
8
+ const { upsertToPassports } = require('@abtnode/auth/lib/passport');
9
+ const { fromAppDid } = require('@arcblock/did-ext');
10
+ const { types } = require('@arcblock/did');
11
+
7
12
  const BaseState = require('./base');
8
13
  const { validateOwner } = require('../util');
14
+ const { loginSchema } = require('../validators/user');
9
15
 
10
16
  const isNullOrUndefined = (x) => x === undefined || x === null;
11
17
 
@@ -39,15 +45,25 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
39
45
  * WalletAccount
40
46
  * @typedef {Object} WalletAccount
41
47
  * @property {'wallet'} provider
42
- * @property {string} did - did for auth0 account
43
- * @property {string} pk - pk for auth0 account
48
+ * @property {string} did - did for wallet account
49
+ * @property {string} pk - pk for wallet account
50
+ * @property {string} lastLoginAt - Last login time new Date().toISOString()
51
+ * @property {string} firstLoginAt - First login time new Date().toISOString()
52
+ */
53
+
54
+ /**
55
+ * NFTAccount
56
+ * @typedef {Object} NFTAccount
57
+ * @property {'nft'} provider
58
+ * @property {string} did - did for nft account
59
+ * @property {string} owner - owner for nft account
44
60
  * @property {string} lastLoginAt - Last login time new Date().toISOString()
45
61
  * @property {string} firstLoginAt - First login time new Date().toISOString()
46
62
  */
47
63
 
48
64
  /**
49
65
  * ConnectedAccount
50
- * @typedef {(Auth0Account|WalletAccount)} ConnectedAccount
66
+ * @typedef {(Auth0Account|WalletAccount|NFTAccount)} ConnectedAccount
51
67
  */
52
68
 
53
69
  /**
@@ -59,7 +75,6 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
59
75
  * @property {string} avatar - url of user's avatar, eg: bn://avatar/7f8848569405f8cdf8b1b2788ebf7d0f.jpg
60
76
  * @property {string} did - user's did -> 实际上变为 uid, 是不可变的;真正的 wallet-did 转移到 extraConfigs 中去了
61
77
  * @property {string} pk - user's publicKey
62
- * @property {('owner'|'admin'|'member'|'guest'|string)} role - user's role
63
78
  * @property {UserPassport[]} passports - user's passport list
64
79
  * @property {boolean} approved - enable user to login
65
80
  * @property {string} locale - locale
@@ -72,8 +87,36 @@ const isNullOrUndefined = (x) => x === undefined || x === null;
72
87
  * @property {string} lastLoginIp - lastLoginIp
73
88
  * @property {Date} createdAt - createdAt
74
89
  * @property {Date} updatedAt - updatedAt
90
+ * @property {('owner'|'admin'|'member'|'guest'|string)} role - user's role deprecated
75
91
  */
76
92
 
93
+ function updateConnectedAccount(connectedAccounts = [], connectedAccount = {}) {
94
+ const now = new Date().toISOString();
95
+ const filterAccounts = connectedAccounts.filter(Boolean);
96
+ const updated = cloneDeep(filterAccounts);
97
+ const updates = Array.isArray(connectedAccount) ? connectedAccount : [connectedAccount];
98
+ updates.filter(Boolean).forEach((x) => {
99
+ if (x.provider && x.did) {
100
+ const findAccountIndex = updated.findIndex((item) => item.provider === x.provider && item.did === x.did);
101
+ if (findAccountIndex > -1) {
102
+ updated[findAccountIndex] = {
103
+ ...filterAccounts[findAccountIndex],
104
+ ...x,
105
+ lastLoginAt: now,
106
+ };
107
+ } else {
108
+ updated.push({
109
+ ...x,
110
+ firstLoginAt: now,
111
+ lastLoginAt: now,
112
+ });
113
+ }
114
+ }
115
+ });
116
+
117
+ return updated;
118
+ }
119
+
77
120
  class User extends BaseState {
78
121
  constructor(baseDir, config = {}) {
79
122
  super(baseDir, { filename: 'user.db', ...config });
@@ -296,14 +339,124 @@ class User extends BaseState {
296
339
  return this.find(queryParam);
297
340
  }
298
341
 
342
+ /**
343
+ * user 版本标准化,统一将 user 转换为最新的结构,结构参考 core/state/lib/states/user.js L12-L75
344
+ */
345
+ // 1: 没有 extraConfigs 字段
346
+ // 2: 有 source 和 extraConfigs 字段,oauth 账号的 extraConfigs 中包含 sourceId 和 sourceProvider 字段
347
+ // 3: 只有 extraConfigs 字段,且 extraConfigs.connectedAccounts 中包含 extraConfigs.sourceProvider 的 account
348
+ async normalize(user, { blockletSk }) {
349
+ if (!user) {
350
+ return user;
351
+ }
352
+ let version = 1;
353
+ if (user.extraConfigs) {
354
+ version = 2;
355
+
356
+ const connectedAccounts = user.extraConfigs?.connectedAccounts || [];
357
+ const sourceProvider = user.extraConfigs?.sourceProvider || '';
358
+ if (connectedAccounts.some((item) => item.provider === sourceProvider)) {
359
+ version = 3;
360
+ }
361
+ }
362
+
363
+ const versionMap = {
364
+ 1: async () => {
365
+ const connectedAccounts = [
366
+ {
367
+ provider: 'wallet',
368
+ did: user.did,
369
+ pk: user.pk,
370
+ firstLoginAt: user.firstLoginAt,
371
+ lastLoginAt: user.lastLoginAt,
372
+ },
373
+ ];
374
+ const sourceProvider = 'wallet';
375
+ const updatedUser = await this.update({
376
+ did: user.did,
377
+ pk: user.pk,
378
+ extraConfigs: {
379
+ sourceProvider,
380
+ connectedAccounts,
381
+ },
382
+ });
383
+ return updatedUser;
384
+ },
385
+ 2: async () => {
386
+ // eslint-disable-next-line prefer-const
387
+ let { sourceId, sourceProvider, connectedAccounts = [] } = user.extraConfigs || {};
388
+ if (sourceId && sourceProvider) {
389
+ connectedAccounts = [
390
+ {
391
+ provider: sourceProvider,
392
+ id: sourceId,
393
+ did: user.did,
394
+ pk: user.pk,
395
+ firstLoginAt: user.firstLoginAt,
396
+ lastLoginAt: user.lastLoginAt,
397
+ },
398
+ ];
399
+ } else {
400
+ sourceProvider = 'wallet';
401
+ connectedAccounts.forEach((account) => {
402
+ if (account.id && blockletSk) {
403
+ const accountWallet = fromAppDid(account.id, blockletSk, types.RoleType.ROLE_ACCOUNT);
404
+ account.did = accountWallet.address;
405
+ account.pk = accountWallet.publicKey;
406
+ account.firstLoginAt = account.firstLoginAt || new Date().toISOString();
407
+ account.lastLoginAt = account.lastLoginAt || new Date().toISOString();
408
+ }
409
+ });
410
+ connectedAccounts.unshift({
411
+ provider: 'wallet',
412
+ did: user.did,
413
+ pk: user.pk,
414
+ firstLoginAt: user.firstLoginAt,
415
+ lastLoginAt: user.lastLoginAt,
416
+ });
417
+ }
418
+ const updatedUser = await this.update({
419
+ did: user.did,
420
+ pk: user.pk,
421
+ extraConfigs: {
422
+ sourceProvider,
423
+ connectedAccounts,
424
+ },
425
+ source: undefined,
426
+ });
427
+ return updatedUser;
428
+ },
429
+ 3: () => {
430
+ return user;
431
+ },
432
+ };
433
+ return versionMap[version]();
434
+ }
435
+
299
436
  /**
300
437
  * get user by did
301
438
  * @param {string} did user's did
302
439
  * @returns {BlockletUser}
303
440
  */
304
- async getUser(did) {
305
- const doc = await this.findOne({ did });
306
- return doc;
441
+ async getUser(did, { enableConnectedAccout = false, enableNormalize = false, blockletSk } = {}) {
442
+ let user = await this.findOne({ did });
443
+ if (enableConnectedAccout) {
444
+ if (!user) {
445
+ user = await this.findOne({
446
+ 'extraConfigs.connectedAccounts.did': did,
447
+ });
448
+ } else if (user.extraConfig?.bindDid) {
449
+ // @deprecated 已经不存在 bindDid 字段
450
+ ({ user } = await this.findOne({ did: user.extraConfig.bindDid }));
451
+ }
452
+ }
453
+ if (enableNormalize) {
454
+ if (!blockletSk) {
455
+ throw new Error('Normalize user must provide blockletSk params');
456
+ }
457
+ return this.normalize(user, { blockletSk });
458
+ }
459
+ return user;
307
460
  }
308
461
 
309
462
  /**
@@ -335,6 +488,82 @@ class User extends BaseState {
335
488
 
336
489
  return doc;
337
490
  }
491
+
492
+ /**
493
+ * 用户登录
494
+ * @param {Object} user
495
+ * @param {string} user.did
496
+ * @param {string} user.pk
497
+ * @param {ConnectedAccount} user.connectedAccount
498
+ * @param {passport} user.passport
499
+ * @param {string} user.fullName - user profile's name
500
+ * @param {string} user.avatar - url of user's avatar, eg: bn://avatar/7f8848569405f8cdf8b1b2788ebf7d0f.jpg
501
+ * @param {string} user.locale - locale
502
+ * @param {Object} [user.extra] - extra data of user
503
+ * @param {string} user.lastLoginIp - lastLoginIp
504
+ * @param {('owner'|'admin'|'member'|'guest'|string)} user.role - deprecated user's role
505
+ */
506
+ async login(_user) {
507
+ const { error, value: user } = loginSchema.validate(_user);
508
+ if (error) {
509
+ throw new Error(error);
510
+ }
511
+
512
+ let updatedUser;
513
+ let action = '';
514
+ const now = new Date().toISOString();
515
+ const oldUser = await this.getUser(user.did, {
516
+ enableConnectedAccout: true,
517
+ });
518
+ const cloneData = cloneDeep(user);
519
+ const passports = upsertToPassports(
520
+ oldUser?.passports || [],
521
+ cloneData.passport && {
522
+ ...cloneData.passport,
523
+ lastLoginAt: now,
524
+ }
525
+ );
526
+ const mergeData = {
527
+ ...pick(cloneData, ['type', 'fullName', 'email', 'avatar', 'role', 'locale', 'extra', 'lastLoginIp', 'remark']),
528
+ did: user.did,
529
+ pk: user.pk,
530
+ passports,
531
+ lastLoginAt: now,
532
+ extraConfigs: {
533
+ sourceProvider: 'wallet',
534
+ connectedAccounts: [],
535
+ },
536
+ };
537
+
538
+ if (oldUser) {
539
+ // update
540
+ action = 'update';
541
+ const extraConfigs = {
542
+ sourceProvider: oldUser?.extraConfigs?.sourceProvider || 'wallet',
543
+ connectedAccounts: updateConnectedAccount(
544
+ oldUser?.extraConfigs?.connectedAccounts || [],
545
+ cloneData.connectedAccount
546
+ ),
547
+ };
548
+ mergeData.extraConfigs = extraConfigs;
549
+ updatedUser = await this.update(mergeData);
550
+ } else {
551
+ // insert
552
+ action = 'add';
553
+ mergeData.firstLoginAt = now;
554
+ mergeData.approved = true;
555
+ const connectedAccount = Array.isArray(cloneData.connectedAccount)
556
+ ? cloneData.connectedAccount.filter(Boolean)[0]
557
+ : cloneData.connectedAccount;
558
+
559
+ mergeData.extraConfigs = {
560
+ sourceProvider: connectedAccount.provider,
561
+ connectedAccounts: updateConnectedAccount([], cloneData.connectedAccount),
562
+ };
563
+ updatedUser = await this.add(mergeData);
564
+ }
565
+ return { ...updatedUser, _action: action };
566
+ }
338
567
  }
339
568
 
340
569
  module.exports = User;
@@ -8,6 +8,8 @@ const os = require('os');
8
8
  const pRetry = require('p-retry');
9
9
  const tar = require('tar');
10
10
  const get = require('lodash/get');
11
+ const uniq = require('lodash/uniq');
12
+ const toLower = require('lodash/toLower');
11
13
  const isEmpty = require('lodash/isEmpty');
12
14
  const streamToPromise = require('stream-to-promise');
13
15
  const { Throttle } = require('stream-throttle');
@@ -21,7 +23,7 @@ const { stableStringify } = require('@arcblock/vc');
21
23
  const { chainInfo: chainInfoSchema } = require('@arcblock/did-auth/lib/schema');
22
24
 
23
25
  const { fromSecretKey } = require('@ocap/wallet');
24
- const { toHex, toBase58, isHex, toDid } = require('@ocap/util');
26
+ const { toHex, toBase58, isHex, toDid, toAddress } = require('@ocap/util');
25
27
  const { isValid: isValidDid, isEthereumDid } = require('@arcblock/did');
26
28
  const logger = require('@abtnode/logger')('@abtnode/core:util:blocklet');
27
29
  const pm2 = require('@abtnode/util/lib/async-pm2');
@@ -296,19 +298,19 @@ const getAppSystemEnvironments = (blocklet, nodeInfo) => {
296
298
  * 2. 如果没有,再拼接
297
299
  */
298
300
 
299
- let appUrl = '';
300
-
301
+ const pidDomain = getDidDomainForBlocklet({ appPid, didDomain: nodeInfo.didDomain });
301
302
  const domainAliases = get(blocklet, 'site.domainAliases') || [];
302
- const didDomainAlias = domainAliases.find(
303
- (item) => item.value.endsWith(nodeInfo.didDomain) || item.value.endsWith('did.staging.arcblock.io') // did.staging.arcblock.io 是旧 did domain, 但主要存在于比较旧的节点中, 需要做兼容
304
- );
305
303
 
306
- if (didDomainAlias) {
307
- appUrl = prettyURL(didDomainAlias.value, true);
308
- } else {
309
- appUrl = `https://${getDidDomainForBlocklet({ appPid, didDomain: nodeInfo.didDomain })}`;
304
+ let didDomain = domainAliases.find((item) => toLower(item.value) === toLower(pidDomain));
305
+
306
+ if (!didDomain) {
307
+ didDomain = domainAliases.find(
308
+ (item) => item.value.endsWith(nodeInfo.didDomain) || item.value.endsWith('did.staging.arcblock.io') // did.staging.arcblock.io 是旧 did domain, 但主要存在于比较旧的节点中, 需要做兼容
309
+ );
310
310
  }
311
311
 
312
+ const appUrl = didDomain ? prettyURL(didDomain.value, true) : `https://${pidDomain}`;
313
+
312
314
  return {
313
315
  BLOCKLET_DID: did, // BLOCKLET_DID is always same as BLOCKLET_APP_PID in structV2 application
314
316
  BLOCKLET_APP_SK: appSk,
@@ -1922,6 +1924,21 @@ const ensureAppLogo = async (blocklet, blockletsDir) => {
1922
1924
  }
1923
1925
  };
1924
1926
 
1927
+ const getBlockletDidDomainList = (blocklet, nodeInfo) => {
1928
+ const domainAliases = [];
1929
+ const alsoKnownAs = getBlockletKnownAs(blocklet);
1930
+
1931
+ const dids = [blocklet.appPid, blocklet.appDid, ...alsoKnownAs].filter(Boolean).map((did) => toAddress(did));
1932
+
1933
+ uniq(dids).forEach((did) => {
1934
+ const domain = getDidDomainForBlocklet({ appPid: did, didDomain: nodeInfo.didDomain });
1935
+
1936
+ domainAliases.push({ value: domain, isProtected: true });
1937
+ });
1938
+
1939
+ return domainAliases;
1940
+ };
1941
+
1925
1942
  module.exports = {
1926
1943
  updateBlockletFallbackLogo,
1927
1944
  consumeServerlessNFT,
@@ -1980,4 +1997,5 @@ module.exports = {
1980
1997
  getBlockletKnownAs,
1981
1998
  getFixedBundleSource,
1982
1999
  ensureAppLogo,
2000
+ getBlockletDidDomainList,
1983
2001
  };
@@ -0,0 +1,44 @@
1
+ const JOI = require('joi');
2
+ const { didExtension } = require('@blocklet/meta/lib/extension');
3
+
4
+ const Joi = JOI.extend(didExtension);
5
+
6
+ // TODO: @zhanghan 这里目前仅包含必填的字段,后续需要增加其他字段
7
+ const passportSchema = Joi.object({
8
+ id: Joi.string().required(),
9
+ role: Joi.string().required(),
10
+ name: Joi.string().required(),
11
+ })
12
+ .unknown()
13
+ .empty(null);
14
+
15
+ // TODO: @zhanghan 这里目前仅包含必填的字段,后续需要增加其他字段
16
+ const connectedAccountSchema = Joi.object({
17
+ provider: Joi.string().required(),
18
+ did: Joi.DID().trim().required(),
19
+ pk: Joi.string().optional(),
20
+ id: Joi.string().optional(),
21
+ firstLoginAt: Joi.string().optional(),
22
+ lastLoginAt: Joi.string().optional(),
23
+ })
24
+ .unknown()
25
+ .empty(null);
26
+
27
+ const loginSchema = Joi.object({
28
+ did: Joi.DID().trim().required(),
29
+ pk: Joi.string().required(),
30
+ fullName: Joi.string().empty(''),
31
+ avatar: Joi.string().empty(''),
32
+ email: Joi.string().empty(''),
33
+ role: Joi.string().empty(''),
34
+ locale: Joi.string().empty(''),
35
+ extra: Joi.object(),
36
+ remark: Joi.string().empty(''),
37
+ lastLoginIp: Joi.string().empty(''),
38
+ passport: passportSchema.optional(),
39
+ connectedAccount: Joi.alternatives()
40
+ .try(connectedAccountSchema.required(), Joi.array().items(connectedAccountSchema).min(1).sparse(true))
41
+ .required(),
42
+ }).unknown();
43
+
44
+ exports.loginSchema = loginSchema;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.6-beta-4ea1eb90",
6
+ "version": "1.16.6-beta-7c9b42cc",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,35 +19,36 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.16.6-beta-4ea1eb90",
23
- "@abtnode/certificate-manager": "1.16.6-beta-4ea1eb90",
24
- "@abtnode/constant": "1.16.6-beta-4ea1eb90",
25
- "@abtnode/cron": "1.16.6-beta-4ea1eb90",
26
- "@abtnode/db": "1.16.6-beta-4ea1eb90",
27
- "@abtnode/logger": "1.16.6-beta-4ea1eb90",
28
- "@abtnode/queue": "1.16.6-beta-4ea1eb90",
29
- "@abtnode/rbac": "1.16.6-beta-4ea1eb90",
30
- "@abtnode/router-provider": "1.16.6-beta-4ea1eb90",
31
- "@abtnode/static-server": "1.16.6-beta-4ea1eb90",
32
- "@abtnode/timemachine": "1.16.6-beta-4ea1eb90",
33
- "@abtnode/util": "1.16.6-beta-4ea1eb90",
34
- "@arcblock/did": "1.18.72",
35
- "@arcblock/did-auth": "1.18.72",
22
+ "@abtnode/auth": "1.16.6-beta-7c9b42cc",
23
+ "@abtnode/certificate-manager": "1.16.6-beta-7c9b42cc",
24
+ "@abtnode/constant": "1.16.6-beta-7c9b42cc",
25
+ "@abtnode/cron": "1.16.6-beta-7c9b42cc",
26
+ "@abtnode/db": "1.16.6-beta-7c9b42cc",
27
+ "@abtnode/logger": "1.16.6-beta-7c9b42cc",
28
+ "@abtnode/queue": "1.16.6-beta-7c9b42cc",
29
+ "@abtnode/rbac": "1.16.6-beta-7c9b42cc",
30
+ "@abtnode/router-provider": "1.16.6-beta-7c9b42cc",
31
+ "@abtnode/static-server": "1.16.6-beta-7c9b42cc",
32
+ "@abtnode/timemachine": "1.16.6-beta-7c9b42cc",
33
+ "@abtnode/util": "1.16.6-beta-7c9b42cc",
34
+ "@arcblock/did": "1.18.75",
35
+ "@arcblock/did-auth": "1.18.75",
36
+ "@arcblock/did-ext": "^1.18.75",
36
37
  "@arcblock/did-motif": "^1.1.10",
37
- "@arcblock/did-util": "1.18.72",
38
- "@arcblock/event-hub": "1.18.72",
39
- "@arcblock/jwt": "^1.18.72",
38
+ "@arcblock/did-util": "1.18.75",
39
+ "@arcblock/event-hub": "1.18.75",
40
+ "@arcblock/jwt": "^1.18.75",
40
41
  "@arcblock/pm2-events": "^0.0.5",
41
- "@arcblock/vc": "1.18.72",
42
- "@blocklet/constant": "1.16.6-beta-4ea1eb90",
43
- "@blocklet/meta": "1.16.6-beta-4ea1eb90",
44
- "@blocklet/sdk": "1.16.6-beta-4ea1eb90",
42
+ "@arcblock/vc": "1.18.75",
43
+ "@blocklet/constant": "1.16.6-beta-7c9b42cc",
44
+ "@blocklet/meta": "1.16.6-beta-7c9b42cc",
45
+ "@blocklet/sdk": "1.16.6-beta-7c9b42cc",
45
46
  "@did-space/client": "^0.2.80",
46
47
  "@fidm/x509": "^1.2.1",
47
- "@ocap/client": "1.18.72",
48
- "@ocap/mcrypto": "1.18.72",
49
- "@ocap/util": "1.18.72",
50
- "@ocap/wallet": "1.18.72",
48
+ "@ocap/client": "1.18.75",
49
+ "@ocap/mcrypto": "1.18.75",
50
+ "@ocap/util": "1.18.75",
51
+ "@ocap/wallet": "1.18.75",
51
52
  "@slack/webhook": "^5.0.4",
52
53
  "archiver": "^5.3.1",
53
54
  "axios": "^0.27.2",
@@ -97,5 +98,5 @@
97
98
  "express": "^4.18.2",
98
99
  "jest": "^27.5.1"
99
100
  },
100
- "gitHead": "0f0f63b552a88343a3f8e0d434b47c3bca6a75b9"
101
+ "gitHead": "113a82e948a779a050f1b06f5667c43c96315054"
101
102
  }