@abtnode/blocklet-services 1.16.16-beta-740ea329 → 1.16.16-beta-301539f6

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.
Files changed (69) hide show
  1. package/api/index.js +1 -1
  2. package/api/libs/auth/utils.js +2 -1
  3. package/api/libs/connect/session.js +131 -72
  4. package/api/libs/connect/shared.js +36 -16
  5. package/api/libs/connect/v1.js +7 -9
  6. package/api/libs/jwt.js +5 -3
  7. package/api/routes/federated.js +145 -19
  8. package/api/routes/oauth.js +214 -53
  9. package/api/routes/user.js +8 -2
  10. package/api/services/auth/connect/invite.js +10 -1
  11. package/api/services/auth/connect/login.js +0 -2
  12. package/api/services/auth/connect/receive-transfer-app-owner.js +2 -1
  13. package/api/services/auth/connect/switch-passport.js +5 -1
  14. package/api/services/auth/session.js +14 -2
  15. package/api/util/blocklet-utils.js +2 -3
  16. package/api/util/federated.js +84 -0
  17. package/build/asset-manifest.json +63 -63
  18. package/build/index.html +1 -1
  19. package/build/service-worker.js +1 -1
  20. package/build/service-worker.js.map +1 -1
  21. package/build/static/js/1480.88c590c2.chunk.js +2 -0
  22. package/build/static/js/{1565.a6f98c38.chunk.js → 1565.6df974b9.chunk.js} +2 -2
  23. package/build/static/js/{1760.95d0c320.chunk.js → 1760.70492184.chunk.js} +2 -2
  24. package/build/static/js/{2653.11a1ad57.chunk.js → 2653.5dc29ed5.chunk.js} +2 -2
  25. package/build/static/js/2686.7ae70bfd.chunk.js +2 -0
  26. package/build/static/js/2836.f4b10b64.chunk.js +2 -0
  27. package/build/static/js/{4042.3c8e0025.chunk.js → 2838.6fa46760.chunk.js} +3 -3
  28. package/build/static/js/{1660.5c8ade93.chunk.js → 3025.7dc2fe04.chunk.js} +2 -2
  29. package/build/static/js/4023.202dcd9a.chunk.js +2 -0
  30. package/build/static/js/{4706.df5b600d.chunk.js → 4706.212c92c8.chunk.js} +3 -3
  31. package/build/static/js/4716.88f32cf2.chunk.js +2 -0
  32. package/build/static/js/{4802.63425dd4.chunk.js → 4802.3b60e453.chunk.js} +2 -2
  33. package/build/static/js/50.cbaa5a4e.chunk.js +3 -0
  34. package/build/static/js/{5176.42904a22.chunk.js → 5176.7e91bc3b.chunk.js} +2 -2
  35. package/build/static/js/{5628.773a32da.chunk.js → 5628.e46ecc79.chunk.js} +2 -2
  36. package/build/static/js/{6380.2b96be29.chunk.js → 5673.ab67c509.chunk.js} +2 -2
  37. package/build/static/js/5683.7e5d47f1.chunk.js +2 -0
  38. package/build/static/js/6186.ebbdb4b8.chunk.js +2 -0
  39. package/build/static/js/{6452.b1899621.chunk.js → 6452.143af37a.chunk.js} +2 -2
  40. package/build/static/js/{6629.36e61c26.chunk.js → 6629.376863d2.chunk.js} +3 -3
  41. package/build/static/js/{6640.53cdcb95.chunk.js → 6640.a4431c82.chunk.js} +2 -2
  42. package/build/static/js/6737.7d135225.chunk.js +2 -0
  43. package/build/static/js/{6771.735ebd3f.chunk.js → 6771.1e778542.chunk.js} +3 -3
  44. package/build/static/js/{6856.e5c166e6.chunk.js → 6856.e185e317.chunk.js} +2 -2
  45. package/build/static/js/{7006.9a53f7ed.chunk.js → 7006.b72aff66.chunk.js} +2 -2
  46. package/build/static/js/{8706.3d16907a.chunk.js → 7367.60cb10e0.chunk.js} +2 -2
  47. package/build/static/js/{7465.ba1027a7.chunk.js → 7465.2bb961d7.chunk.js} +3 -3
  48. package/build/static/js/{9409.befe72b4.chunk.js → 9409.62a2aee0.chunk.js} +2 -2
  49. package/build/static/js/{9620.59bc85b8.chunk.js → 9620.301493bc.chunk.js} +2 -2
  50. package/build/static/js/{9899.c8ff588e.chunk.js → 9899.b8d8a5ca.chunk.js} +2 -2
  51. package/build/static/js/main.a58f939e.js +3 -0
  52. package/build/static/js/{main.3ba3901e.js.LICENSE.txt → main.a58f939e.js.LICENSE.txt} +1 -1
  53. package/package.json +34 -34
  54. package/build/static/js/1480.30b94380.chunk.js +0 -2
  55. package/build/static/js/2307.2e451912.chunk.js +0 -2
  56. package/build/static/js/2686.07687254.chunk.js +0 -2
  57. package/build/static/js/4023.0f348986.chunk.js +0 -2
  58. package/build/static/js/4716.47aa133c.chunk.js +0 -2
  59. package/build/static/js/5683.3bdd2338.chunk.js +0 -2
  60. package/build/static/js/6186.61596c22.chunk.js +0 -2
  61. package/build/static/js/6606.9f17eaa6.chunk.js +0 -3
  62. package/build/static/js/6737.5f735a29.chunk.js +0 -2
  63. package/build/static/js/main.3ba3901e.js +0 -3
  64. /package/build/static/js/{4042.3c8e0025.chunk.js.LICENSE.txt → 2838.6fa46760.chunk.js.LICENSE.txt} +0 -0
  65. /package/build/static/js/{4706.df5b600d.chunk.js.LICENSE.txt → 4706.212c92c8.chunk.js.LICENSE.txt} +0 -0
  66. /package/build/static/js/{6606.9f17eaa6.chunk.js.LICENSE.txt → 50.cbaa5a4e.chunk.js.LICENSE.txt} +0 -0
  67. /package/build/static/js/{6629.36e61c26.chunk.js.LICENSE.txt → 6629.376863d2.chunk.js.LICENSE.txt} +0 -0
  68. /package/build/static/js/{6771.735ebd3f.chunk.js.LICENSE.txt → 6771.1e778542.chunk.js.LICENSE.txt} +0 -0
  69. /package/build/static/js/{7465.ba1027a7.chunk.js.LICENSE.txt → 7465.2bb961d7.chunk.js.LICENSE.txt} +0 -0
package/api/index.js CHANGED
@@ -182,7 +182,7 @@ module.exports = function createServer(node, serverOptions = {}) {
182
182
  server.use(
183
183
  bodyParser.json({
184
184
  // We have to set a larger hard limit since
185
- limit: '2mb',
185
+ limit: '8mb',
186
186
 
187
187
  // https://flaviocopes.com/express-get-raw-body/
188
188
  // Side effects: this will double the memory consumption
@@ -6,6 +6,7 @@ const { getBlockletAppIdList } = require('@blocklet/meta/lib/util');
6
6
  const pick = require('lodash/pick');
7
7
  const uniq = require('lodash/uniq');
8
8
  const uniqBy = require('lodash/uniqBy');
9
+ const { LOGIN_PROVIDER } = require('@blocklet/constant');
9
10
 
10
11
  const { sendToUser } = require('../notification');
11
12
 
@@ -125,7 +126,7 @@ async function transferPassport(fromUser, toUser, { req, teamDid, node, nodeInfo
125
126
  const revokePendingList = waitPassportList
126
127
  .filter((item) => item.id)
127
128
  .map((item) => {
128
- if (fromUser.sourceProvider === 'auth0') {
129
+ if (fromUser.sourceProvider === LOGIN_PROVIDER.AUTH0) {
129
130
  return node.removeUserPassport({ teamDid, userDid: fromUser.did, passportId: item.id });
130
131
  }
131
132
  return node.revokeUserPassport({ teamDid, userDid: fromUser.did, passportId: item.id });
@@ -36,12 +36,11 @@ const { getKeyPairClaim, getAuthPrincipalForMigrateAppToV2 } = require('@abtnode
36
36
  const merge = require('lodash/merge');
37
37
  const { fromAppDid } = require('@arcblock/did-ext');
38
38
  const { LOGIN_PROVIDER } = require('@blocklet/constant');
39
- const { signV2 } = require('@arcblock/jwt');
40
39
  const pick = require('lodash/pick');
41
40
  const createTranslator = require('@abtnode/util/lib/translate');
42
41
 
43
42
  const { getRolesFromAuthConfig, getBlockletAppIdList } = require('@blocklet/meta/lib/util');
44
- const { getLoginProvider } = require('@blocklet/sdk/lib/util/login');
43
+ const { getSourceAppPid, getLoginProvider } = require('@blocklet/sdk/lib/util/login');
45
44
 
46
45
  const logger = require('@abtnode/logger')(require('../../../package.json').name);
47
46
 
@@ -49,13 +48,12 @@ const { isInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../.
49
48
  const { transferPassport } = require('../auth/utils');
50
49
  const { migrateAccount, declareAccount } = require('../../services/oauth');
51
50
  const { getTrustedIssuers, getFederatedTrustedIssuers } = require('../../util/blocklet-utils');
52
- const { getFederatedMaster, getUserAvatarUrl } = require('../../util/federated');
53
- const { api } = require('../api');
51
+ const { getUserAvatarUrl, migrateAuth0, getFederatedMaster } = require('../../util/federated');
54
52
 
55
53
  const vcTypes = [VC_TYPE_GENERAL_PASSPORT, VC_TYPE_NODE_PASSPORT];
56
54
 
57
- const getPassportVc = async ({ blocklet, claims, challenge, locale, provider }) => {
58
- const trustedIssuers = await getTrustedIssuers(blocklet, { provider });
55
+ const getPassportVc = async ({ blocklet, claims, challenge, locale, sourceAppPid }) => {
56
+ const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
59
57
  const { vc } = await getVCFromClaims({
60
58
  claims,
61
59
  challenge,
@@ -67,7 +65,7 @@ const getPassportVc = async ({ blocklet, claims, challenge, locale, provider })
67
65
  return vc;
68
66
  };
69
67
 
70
- const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid, provider }) => {
68
+ const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid, sourceAppPid }) => {
71
69
  let role = ROLES.GUEST;
72
70
  if (vc) {
73
71
  await validatePassport(get(vc, 'credentialSubject.passport'));
@@ -77,8 +75,7 @@ const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid, provider })
77
75
  role = getRoleFromLocalPassport(get(vc, 'credentialSubject.passport'));
78
76
  } else {
79
77
  // MEMO: 如果是 federated,需要将 actualIssuer 做一个转换
80
- const actualIssuerList =
81
- provider === LOGIN_PROVIDER.FEDERATED ? await getFederatedTrustedIssuers(blocklet) : [actualIssuer];
78
+ const actualIssuerList = sourceAppPid ? await getFederatedTrustedIssuers(blocklet) : [actualIssuer];
82
79
  // map external passport to local role
83
80
  const { mappings = [] } =
84
81
  (blocklet.trustedPassports || []).find((x) => actualIssuerList.includes(x.issuerDid)) || {};
@@ -146,7 +143,7 @@ module.exports = {
146
143
  const blocklet = await request.getBlocklet();
147
144
  const config = await request.getServiceConfig(NODE_SERVICES.AUTH, { componentId });
148
145
  const { did: teamDid, wallet: blockletWallet } = await request.getBlockletInfo();
149
- const provider = getLoginProvider(request);
146
+ const sourceAppPid = getSourceAppPid(request);
150
147
 
151
148
  const profileFields = get(config, 'profileFields');
152
149
 
@@ -160,7 +157,7 @@ module.exports = {
160
157
  if (action === 'login') {
161
158
  const [invitedUserOnly] = config ? await isInvitedUserOnly(config, node, teamDid) : [false];
162
159
 
163
- const trustedIssuers = await getTrustedIssuers(blocklet, { provider });
160
+ const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
164
161
  claims.verifiableCredential = {
165
162
  type: 'verifiableCredential',
166
163
  description: messages.requestPassport[locale],
@@ -246,11 +243,13 @@ module.exports = {
246
243
  let defaultTtlPolicy = 'never';
247
244
  let issuePassport = false;
248
245
 
246
+ const sourceAppPid = getSourceAppPid(request);
249
247
  const provider = getLoginProvider(request);
248
+ const masterSite = getFederatedMaster(blocklet);
250
249
 
251
250
  // Get passport vc
252
251
  if (action === 'login') {
253
- vc = await getPassportVc({ blocklet, claims, challenge, locale, provider });
252
+ vc = await getPassportVc({ blocklet, claims, challenge, locale, sourceAppPid });
254
253
  [invitedUserOnly, defaultRole, issuePassport] = await isInvitedUserOnly(authConfig, node, teamDid);
255
254
  if (invitedUserOnly && !vc) {
256
255
  throw new Error(messages.missingCredentialClaim[locale]);
@@ -323,7 +322,7 @@ module.exports = {
323
322
  }
324
323
 
325
324
  // Get role
326
- const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, provider });
325
+ const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, sourceAppPid });
327
326
  await validateRole({ role, authConfig, locale, node, teamDid });
328
327
 
329
328
  checkAppOwner({ role, blocklet, userDid, locale });
@@ -346,15 +345,10 @@ module.exports = {
346
345
  // Update profile
347
346
  const passportForLog = passport || { name: 'Guest', role: 'guest' };
348
347
 
349
- const masterSite = getFederatedMaster(blocklet);
350
- let connectAccount = { provider, did: userDid, pk: userPk };
348
+ const connectAccount = { provider, did: userDid, pk: userPk };
351
349
 
352
350
  let updatedUser;
353
351
  if (user) {
354
- // Update user
355
- if (masterSite && provider === LOGIN_PROVIDER.FEDERATED) {
356
- connectAccount = { provider, did: userDid, pk: userPk, id: masterSite.appPid };
357
- }
358
352
  updatedUser = await node.loginUser({
359
353
  teamDid,
360
354
  user: {
@@ -362,6 +356,7 @@ module.exports = {
362
356
  pk: user.pk,
363
357
  locale,
364
358
  passport,
359
+ sourceAppPid,
365
360
  lastLoginIp: get(request, 'headers[x-real-ip]') || '',
366
361
  connectedAccount: [connectAccount, connectedNft],
367
362
  },
@@ -369,7 +364,7 @@ module.exports = {
369
364
  await node.createAuditLog(
370
365
  {
371
366
  action,
372
- args: { teamDid, userDid: realDid, passport: passportForLog, provider },
367
+ args: { teamDid, userDid: realDid, passport: passportForLog, provider, sourceAppPid },
373
368
  context: formatContext(Object.assign(request, { user: updatedUser })),
374
369
  result: updatedUser,
375
370
  },
@@ -380,10 +375,6 @@ module.exports = {
380
375
  const profile = claims.find((x) => x.type === 'profile');
381
376
  fullName = profile.fullName;
382
377
 
383
- if (masterSite && provider === LOGIN_PROVIDER.FEDERATED) {
384
- connectAccount = { provider, did: userDid, pk: userPk, id: masterSite.appPid };
385
- }
386
-
387
378
  updatedUser = await node.loginUser({
388
379
  teamDid,
389
380
  user: {
@@ -395,6 +386,7 @@ module.exports = {
395
386
  pk: realPk,
396
387
  locale,
397
388
  passport,
389
+ sourceAppPid,
398
390
  lastLoginIp: get(request, 'headers[x-real-ip]') || '',
399
391
  connectedAccount: [connectAccount, connectedNft],
400
392
  },
@@ -402,7 +394,13 @@ module.exports = {
402
394
  await node.createAuditLog(
403
395
  {
404
396
  action: 'addUser',
405
- args: { teamDid, userDid: realDid, reason: `first login as ${passportForLog.role}` },
397
+ args: {
398
+ teamDid,
399
+ userDid: realDid,
400
+ sourceAppPid,
401
+ provider,
402
+ reason: `first login as ${passportForLog.role}`,
403
+ },
406
404
  context: formatContext(Object.assign(request, { user: updatedUser })),
407
405
  result: updatedUser,
408
406
  },
@@ -410,9 +408,33 @@ module.exports = {
410
408
  );
411
409
  }
412
410
 
411
+ // NOTICE: 采用异步来更新,不阻塞接口的正常响应
412
+ if (sourceAppPid || masterSite.appPid === blocklet.appPid) {
413
+ node.syncFederated({
414
+ did: teamDid,
415
+ data: {
416
+ users: [
417
+ {
418
+ did: updatedUser.did,
419
+ pk: updatedUser.pk,
420
+ fullName: updatedUser.fullName,
421
+ email: updatedUser.email || '',
422
+ avatar: getUserAvatarUrl(updatedUser.avatar, blocklet),
423
+ connectedAccount: [connectAccount, connectedNft],
424
+ action: 'connectAccount',
425
+ sourceAppPid: sourceAppPid || masterSite.appPid,
426
+ },
427
+ ],
428
+ },
429
+ });
430
+ }
431
+
413
432
  // Generate new session token that client can save to localStorage
414
433
  const createToken = createTokenFn(createSessionToken);
415
434
  const sessionConfig = blocklet.settings?.session || {};
435
+
436
+ // request.context.store.connectedWallet
437
+ const walletOS = request.context.didwallet.os;
416
438
  const { sessionToken, refreshToken } = createToken(
417
439
  realDid,
418
440
  {
@@ -422,6 +444,7 @@ module.exports = {
422
444
  fullName,
423
445
  // NOTE: token 中存储当前的 login provider
424
446
  provider,
447
+ walletOS,
425
448
  },
426
449
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(request) }
427
450
  );
@@ -437,36 +460,6 @@ module.exports = {
437
460
  await node.setBlockletInitialized({ did: teamDid, owner: { did: realDid, pk: realPk } });
438
461
  }
439
462
 
440
- const { permanentWallet } = blockletInfo;
441
-
442
- let federatedSessionToken;
443
- let federatedRefreshToken;
444
- // member 使用 deferated login 时,总是会让 Master 自动登录
445
- if (masterSite && provider === LOGIN_PROVIDER.FEDERATED) {
446
- const postUser = pick(updatedUser, ['did', 'pk', 'fullName', 'locale']);
447
- postUser.lastLoginAt = get(request, 'headers[x-real-ip]') || '';
448
-
449
- if (updatedUser.email) {
450
- postUser.email = updatedUser.email;
451
- }
452
- if (updatedUser.avatar) {
453
- postUser.avatar = getUserAvatarUrl(updatedUser.avatar, blocklet);
454
- }
455
-
456
- const { data } = await api.post(
457
- joinUrl(masterSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/federated/loginByMember'),
458
- {
459
- signer: permanentWallet.address,
460
- data: signV2(permanentWallet.address, permanentWallet.secretKey, {
461
- user: postUser,
462
- passport,
463
- }),
464
- }
465
- );
466
- federatedSessionToken = data.sessionToken;
467
- federatedRefreshToken = data.refreshToken;
468
- }
469
-
470
463
  // issue passport for the first login user in a invite-only team
471
464
  if (issuePassport) {
472
465
  return {
@@ -475,8 +468,6 @@ module.exports = {
475
468
  data: vc,
476
469
  sessionToken,
477
470
  refreshToken,
478
- federatedSessionToken,
479
- federatedRefreshToken,
480
471
  nextWorkflowData: {
481
472
  userDid: realDid,
482
473
  },
@@ -486,8 +477,6 @@ module.exports = {
486
477
  return {
487
478
  sessionToken,
488
479
  refreshToken,
489
- federatedSessionToken,
490
- federatedRefreshToken,
491
480
  nextWorkflowData: {
492
481
  userDid: realDid,
493
482
  },
@@ -574,6 +563,28 @@ module.exports = {
574
563
  },
575
564
  node
576
565
  );
566
+
567
+ const syncUserData = pick(doc, ['did', 'pk', 'fullName', 'avatar', 'email']);
568
+ if (syncUserData.avatar) {
569
+ syncUserData.avatar = getUserAvatarUrl(syncUserData.avatar, blocklet);
570
+ }
571
+ const sourceAppPid = getSourceAppPid(request);
572
+ const masterSite = getFederatedMaster(blocklet);
573
+ // NOTICE: 采用异步来更新,不阻塞接口的正常响应
574
+ if (sourceAppPid || masterSite.appPid === blocklet.appPid) {
575
+ node.syncFederated({
576
+ did: teamDid,
577
+ data: {
578
+ users: [
579
+ {
580
+ ...syncUserData,
581
+ action: 'switchProfile',
582
+ sourceAppPid: sourceAppPid || masterSite.appPid,
583
+ },
584
+ ],
585
+ },
586
+ });
587
+ }
577
588
  },
578
589
  },
579
590
 
@@ -606,8 +617,8 @@ module.exports = {
606
617
  const [invitedUserOnly] = await isInvitedUserOnly(config, node, teamDid);
607
618
 
608
619
  const blocklet = await request.getBlocklet();
609
- const provider = getLoginProvider(request);
610
- const trustedIssuers = await getTrustedIssuers(blocklet, { provider });
620
+ const sourceAppPid = getSourceAppPid(request);
621
+ const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
611
622
 
612
623
  return {
613
624
  verifiableCredential: {
@@ -629,6 +640,7 @@ module.exports = {
629
640
  userDid,
630
641
  createSessionToken,
631
642
  componentId,
643
+ sourceAppPid,
632
644
  provider,
633
645
  }) => {
634
646
  const blocklet = await request.getBlocklet();
@@ -660,7 +672,7 @@ module.exports = {
660
672
  claims: [verifiableCredential],
661
673
  challenge,
662
674
  locale,
663
- provider,
675
+ sourceAppPid,
664
676
  });
665
677
 
666
678
  // Validate passport required
@@ -676,7 +688,7 @@ module.exports = {
676
688
  }
677
689
 
678
690
  // Get role
679
- const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, provider });
691
+ const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, sourceAppPid });
680
692
  await validateRole({ role, authConfig, locale, node, teamDid });
681
693
 
682
694
  checkAppOwner({ role, blocklet, userDid, locale });
@@ -701,7 +713,7 @@ module.exports = {
701
713
  await node.createAuditLog(
702
714
  {
703
715
  action: 'switchPassport',
704
- args: { teamDid, userDid, passport: passportForLog, provider },
716
+ args: { teamDid, userDid, passport: passportForLog, sourceAppPid },
705
717
  context: formatContext(Object.assign(request, { user })),
706
718
  result: {},
707
719
  },
@@ -713,7 +725,15 @@ module.exports = {
713
725
  const sessionConfig = blocklet.settings?.session || {};
714
726
  const { sessionToken, refreshToken } = createToken(
715
727
  userDid,
716
- { secret, passport, role, fullName: user.fullName, provider },
728
+ {
729
+ secret,
730
+ passport,
731
+ role,
732
+ fullName: user.fullName,
733
+ provider,
734
+ // request.context.store.connectedWallet
735
+ walletOS: request.context.didwallet.os,
736
+ },
717
737
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(request) }
718
738
  );
719
739
  return { sessionToken, refreshToken };
@@ -815,7 +835,9 @@ module.exports = {
815
835
  },
816
836
  onApprove: async ({ node, request, locale, userDid, userPk, claims, previousUserDid, baseUrl }) => {
817
837
  const blocklet = await request.getBlocklet();
818
- const { did: teamDid, wallet: blockletWallet } = await request.getBlockletInfo();
838
+ const sourceAppPid = getSourceAppPid(request);
839
+ const blockletInfo = await request.getBlockletInfo();
840
+ const { did: teamDid, wallet: blockletWallet } = blockletInfo;
819
841
 
820
842
  const oauthUser = await node.getUser({ teamDid, user: { did: previousUserDid } });
821
843
  const nodeInfo = await request.getNodeInfo();
@@ -875,6 +897,31 @@ module.exports = {
875
897
  passports: mergePassport,
876
898
  },
877
899
  });
900
+ const masterSite = getFederatedMaster(blocklet);
901
+ // NOTICE: 采用异步来更新,不阻塞接口的正常响应
902
+ if (sourceAppPid || masterSite.appPid === blocklet.appPid) {
903
+ const syncUserData = {
904
+ did: oauthUser.did,
905
+ pk: oauthUser.pk,
906
+ ...mergeProfile,
907
+ connectedAccount: [connectedAccount],
908
+ };
909
+ if (syncUserData.avatar) {
910
+ syncUserData.avatar = getUserAvatarUrl(syncUserData.avatar, blocklet);
911
+ }
912
+ node.syncFederated({
913
+ did: teamDid,
914
+ data: {
915
+ users: [
916
+ {
917
+ ...syncUserData,
918
+ action: 'connectAccount',
919
+ sourceAppPid: sourceAppPid || masterSite.appPid,
920
+ },
921
+ ],
922
+ },
923
+ });
924
+ }
878
925
 
879
926
  if (!bindUser) {
880
927
  bindUser = {
@@ -885,6 +932,7 @@ module.exports = {
885
932
  };
886
933
  }
887
934
 
935
+ // FIXME:@zhanghan 统一登录的 passport 相关问题后续统一处理
888
936
  await transferPassport(oauthUser, bindUser, {
889
937
  req: request,
890
938
  node,
@@ -894,12 +942,23 @@ module.exports = {
894
942
  revokePassport: true,
895
943
  });
896
944
 
897
- const connectedAccounts = oauthUser?.connectedAccounts || [];
898
- const sourceProvider = oauthUser?.sourceProvider;
899
- const oauthAccount = connectedAccounts.find((item) => item.provider === sourceProvider);
900
- const userWallet = fromAppDid(oauthAccount.id, blockletWallet.secretKey);
901
- await declareAccount({ wallet: userWallet, blocklet });
902
- await migrateAccount({ wallet: userWallet, blocklet, user: bindUser });
945
+ if (sourceAppPid) {
946
+ await migrateAuth0({
947
+ // 目前只允许未注册过的钱包绑定 auth0,所以直接传入钱包生成的 userDid userPk
948
+ toUserDid: userDid,
949
+ toUserPk: userPk,
950
+ fromUserDid: previousUserDid,
951
+ blockletInfo,
952
+ blocklet,
953
+ });
954
+ } else {
955
+ const connectedAccounts = oauthUser?.connectedAccounts || [];
956
+ const sourceProvider = oauthUser?.sourceProvider;
957
+ const oauthAccount = connectedAccounts.find((item) => item.provider === sourceProvider);
958
+ const userWallet = fromAppDid(oauthAccount.id, blockletWallet.secretKey);
959
+ await declareAccount({ wallet: userWallet, blocklet });
960
+ await migrateAccount({ wallet: userWallet, blocklet, user: bindUser });
961
+ }
903
962
 
904
963
  await node.createAuditLog(
905
964
  {
@@ -2,28 +2,49 @@ const get = require('lodash/get');
2
2
  const joinUrl = require('url-join');
3
3
  const { getConnectAppUrl, getChainInfo } = require('@blocklet/meta/lib/util');
4
4
  const { WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
5
- const { LOGIN_PROVIDER } = require('@blocklet/constant');
6
- const { getLoginProvider } = require('@blocklet/sdk/lib/util/login');
5
+ const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
6
+
7
+ function getFederatedMasterAppInfo({ blocklet, sourceAppPid, baseUrl, version, request, groupPathPrefix, nodeInfo }) {
8
+ const { federated } = blocklet.settings;
9
+ const master = federated.sites.find((x) => x.appPid === sourceAppPid);
10
+ // 对于 ux 来说,要展示的始终是 pid,所以这个给 agentDid 的赋值也需要是 pid
11
+ // federated 登录模式下,需要告知原有的 blocklet-did
12
+ const agentDid = blocklet.appPid;
13
+
14
+ return {
15
+ name: master.appName,
16
+ description: master.appescription || `Connect to ${master.appName}`,
17
+ icon: joinUrl(master.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, `/blocklet/logo?v=${version}`),
18
+ link: getConnectAppUrl({ request, baseUrl }),
19
+ updateSubEndpoint: true,
20
+ subscriptionEndpoint: joinUrl(groupPathPrefix, WELLKNOWN_SERVICE_PATH_PREFIX, 'websocket'),
21
+ nodeDid: nodeInfo.did,
22
+ agentDid,
23
+ };
24
+ }
7
25
 
8
26
  module.exports = {
9
- appInfo: async ({ request, baseUrl, extraParams }) => {
27
+ appInfo: async ({ request, baseUrl }) => {
10
28
  const groupPathPrefix = request.headers['x-group-path-prefix'] || '/';
11
29
 
12
- const [blocklet, meta, info] = await Promise.all([
13
- request.getBlocklet(),
14
- request.getBlockletInfo(),
15
- request.getNodeInfo(),
16
- ]);
17
- // 对于 ux 来说, 要展示的始终是 pid,所以这个给 agentDid 的赋值也需要是 pid
18
- let agentDid;
19
- const provider = getLoginProvider(request, extraParams);
20
- // federated 登录模式下,需要告知原有的 blocklet-did
21
- if (provider === LOGIN_PROVIDER.FEDERATED) {
22
- agentDid = blocklet.appPid;
23
- }
30
+ const [blocklet, info] = await Promise.all([request.getBlocklet(), request.getNodeInfo()]);
31
+
32
+ const sourceAppPid = getSourceAppPid(request);
24
33
 
25
34
  const version = get(blocklet, 'meta.version', '');
26
35
 
36
+ if (sourceAppPid) {
37
+ return getFederatedMasterAppInfo({
38
+ blocklet,
39
+ sourceAppPid,
40
+ baseUrl,
41
+ version,
42
+ groupPathPrefix,
43
+ request,
44
+ nodeInfo: info,
45
+ });
46
+ }
47
+ const meta = await request.getBlockletInfo();
27
48
  return {
28
49
  name: meta.name,
29
50
  description: meta.description || `Connect to ${meta.name}`,
@@ -33,7 +54,6 @@ module.exports = {
33
54
  subscriptionEndpoint: joinUrl(groupPathPrefix, WELLKNOWN_SERVICE_PATH_PREFIX, 'websocket'),
34
55
  nodeDid: info.did,
35
56
  // NOTE: publisher 是 WalletAuthenticator 中自动添加的
36
- agentDid,
37
57
  };
38
58
  },
39
59
 
@@ -10,8 +10,7 @@ const { sendToUser, sendToRelay } = require('@blocklet/sdk/lib/util/send-notific
10
10
  const { WELLKNOWN_SERVICE_PATH_PREFIX, NODE_SERVICES_PREFIX } = require('@abtnode/constant');
11
11
  const DynamicStorage = require('@abtnode/connect-storage');
12
12
  const { fromPublicKey } = require('@ocap/wallet');
13
- const { LOGIN_PROVIDER } = require('@blocklet/constant');
14
- const { getLoginProvider } = require('@blocklet/sdk/lib/util/login');
13
+ const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
15
14
 
16
15
  const cache = require('../../cache');
17
16
  const { appInfo, chainInfo } = require('./shared');
@@ -24,11 +23,11 @@ module.exports = (node, opts) => {
24
23
  const { wallet } = await request.getBlockletInfo();
25
24
  return wallet.toJSON();
26
25
  },
27
- delegator: async ({ request, extraParams }) => {
28
- const provider = getLoginProvider(request, extraParams);
26
+ delegator: async ({ request }) => {
27
+ const sourceAppPid = getSourceAppPid(request);
29
28
 
30
29
  const blocklet = await request.getBlocklet();
31
- if (provider === LOGIN_PROVIDER.FEDERATED) {
30
+ if (sourceAppPid) {
32
31
  const pk = get(blocklet, 'settings.federated.sites[0].pk');
33
32
 
34
33
  // NOTE: 这里的 type 参数必须保持跟生成 blocklet 时使用的是一致的
@@ -39,7 +38,6 @@ module.exports = (node, opts) => {
39
38
  address: types.EncodingType.BASE58,
40
39
  };
41
40
  const delegator = fromPublicKey(pk, type);
42
- delegator.provider = LOGIN_PROVIDER.FEDERATED;
43
41
  return delegator;
44
42
  }
45
43
 
@@ -49,10 +47,10 @@ module.exports = (node, opts) => {
49
47
  }
50
48
  return null;
51
49
  },
52
- delegation: async ({ request, extraParams }) => {
50
+ delegation: async ({ request }) => {
53
51
  const { wallet: delegatee, permanentWallet: delegator } = await request.getBlockletInfo();
54
- const provider = getLoginProvider(request, extraParams);
55
- if (provider === LOGIN_PROVIDER.FEDERATED) {
52
+ const sourceAppPid = getSourceAppPid(request);
53
+ if (sourceAppPid) {
56
54
  const blocklet = await request.getBlocklet();
57
55
  const delegation = get(blocklet, 'settings.federated.config.delegation');
58
56
  return delegation;
package/api/libs/jwt.js CHANGED
@@ -18,7 +18,7 @@ const initJwt = (node, options) => {
18
18
 
19
19
  const createSessionToken = (
20
20
  did,
21
- { role, secret, passport, expiresIn, tokenType, fullName, provider = LOGIN_PROVIDER.WALLET }
21
+ { role, secret, passport, expiresIn, tokenType, fullName, provider = LOGIN_PROVIDER.WALLET, walletOS }
22
22
  ) =>
23
23
  createAuthToken({
24
24
  did,
@@ -29,6 +29,7 @@ const initJwt = (node, options) => {
29
29
  tokenType,
30
30
  fullName,
31
31
  provider,
32
+ walletOS,
32
33
  });
33
34
 
34
35
  const verifySessionToken = (token, secret, { checkFromDb, teamDid, checkToken } = {}) =>
@@ -47,7 +48,7 @@ const initJwt = (node, options) => {
47
48
  }
48
49
  }
49
50
 
50
- const { did, role, passport, fullName, provider = LOGIN_PROVIDER.WALLET } = decoded;
51
+ const { did, role, passport, fullName, provider = LOGIN_PROVIDER.WALLET, walletOS } = decoded;
51
52
  let user;
52
53
  if (!did) {
53
54
  return reject(new Error('Invalid jwt token: invalid did'));
@@ -75,8 +76,9 @@ const initJwt = (node, options) => {
75
76
  user.role = role;
76
77
  user.passport = passport;
77
78
  user.provider = provider;
79
+ user.walletOS = walletOS;
78
80
  } else {
79
- user = { did, role, passport, fullName, provider };
81
+ user = { did, role, passport, fullName, provider, walletOS };
80
82
  }
81
83
 
82
84
  return resolve(user);