@abtnode/blocklet-services 1.16.16-beta-d6c5ed65 → 1.16.16-beta-d11cb031

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 (51) hide show
  1. package/api/index.js +1 -1
  2. package/api/libs/connect/session.js +96 -82
  3. package/api/libs/connect/shared.js +33 -12
  4. package/api/libs/jwt.js +5 -3
  5. package/api/routes/federated.js +65 -12
  6. package/api/routes/oauth.js +134 -76
  7. package/api/routes/user.js +1 -0
  8. package/api/services/auth/connect/invite.js +10 -1
  9. package/api/services/auth/connect/login.js +0 -2
  10. package/api/services/auth/connect/receive-transfer-app-owner.js +2 -1
  11. package/api/services/auth/connect/switch-passport.js +5 -1
  12. package/api/services/auth/session.js +14 -2
  13. package/api/util/federated.js +97 -0
  14. package/build/asset-manifest.json +53 -53
  15. package/build/index.html +1 -1
  16. package/build/service-worker.js +1 -1
  17. package/build/static/js/{1480.36129849.chunk.js → 1480.88c590c2.chunk.js} +2 -2
  18. package/build/static/js/{1565.ad002b88.chunk.js → 1565.6df974b9.chunk.js} +2 -2
  19. package/build/static/js/{1760.71e0c151.chunk.js → 1760.70492184.chunk.js} +2 -2
  20. package/build/static/js/{2653.6f37e8a0.chunk.js → 2653.5dc29ed5.chunk.js} +2 -2
  21. package/build/static/js/2836.f4b10b64.chunk.js +2 -0
  22. package/build/static/js/{4042.3c8e0025.chunk.js → 2838.6fa46760.chunk.js} +3 -3
  23. package/build/static/js/{1660.9fb17942.chunk.js → 3025.7dc2fe04.chunk.js} +2 -2
  24. package/build/static/js/{4023.4be0c818.chunk.js → 4023.202dcd9a.chunk.js} +2 -2
  25. package/build/static/js/{4706.df5b600d.chunk.js → 4706.212c92c8.chunk.js} +3 -3
  26. package/build/static/js/4716.88f32cf2.chunk.js +2 -0
  27. package/build/static/js/{4802.b7fa8e82.chunk.js → 4802.3b60e453.chunk.js} +2 -2
  28. package/build/static/js/{5176.53f7f419.chunk.js → 5176.7e91bc3b.chunk.js} +2 -2
  29. package/build/static/js/{5628.aa14b1a7.chunk.js → 5628.e46ecc79.chunk.js} +2 -2
  30. package/build/static/js/{6380.2b96be29.chunk.js → 5673.ab67c509.chunk.js} +2 -2
  31. package/build/static/js/{6186.6462ea21.chunk.js → 6186.ebbdb4b8.chunk.js} +2 -2
  32. package/build/static/js/{6452.4226209b.chunk.js → 6452.143af37a.chunk.js} +2 -2
  33. package/build/static/js/{6629.785fe237.chunk.js → 6629.376863d2.chunk.js} +3 -3
  34. package/build/static/js/{6640.e453c619.chunk.js → 6640.a4431c82.chunk.js} +2 -2
  35. package/build/static/js/{6737.7fe9f13a.chunk.js → 6737.7d135225.chunk.js} +2 -2
  36. package/build/static/js/{6856.9aaf692c.chunk.js → 6856.e185e317.chunk.js} +2 -2
  37. package/build/static/js/{8706.3d16907a.chunk.js → 7367.60cb10e0.chunk.js} +2 -2
  38. package/build/static/js/{7465.999f0039.chunk.js → 7465.2bb961d7.chunk.js} +3 -3
  39. package/build/static/js/{9409.fe4a0af0.chunk.js → 9409.62a2aee0.chunk.js} +2 -2
  40. package/build/static/js/{9620.db1568ef.chunk.js → 9620.301493bc.chunk.js} +2 -2
  41. package/build/static/js/{9899.92626f0a.chunk.js → 9899.b8d8a5ca.chunk.js} +2 -2
  42. package/build/static/js/main.a58f939e.js +3 -0
  43. package/package.json +34 -34
  44. package/build/static/js/4716.17a45b6a.chunk.js +0 -2
  45. package/build/static/js/5662.522d3713.chunk.js +0 -2
  46. package/build/static/js/main.85d66eb2.js +0 -3
  47. /package/build/static/js/{4042.3c8e0025.chunk.js.LICENSE.txt → 2838.6fa46760.chunk.js.LICENSE.txt} +0 -0
  48. /package/build/static/js/{4706.df5b600d.chunk.js.LICENSE.txt → 4706.212c92c8.chunk.js.LICENSE.txt} +0 -0
  49. /package/build/static/js/{6629.785fe237.chunk.js.LICENSE.txt → 6629.376863d2.chunk.js.LICENSE.txt} +0 -0
  50. /package/build/static/js/{7465.999f0039.chunk.js.LICENSE.txt → 7465.2bb961d7.chunk.js.LICENSE.txt} +0 -0
  51. /package/build/static/js/{main.85d66eb2.js.LICENSE.txt → main.a58f939e.js.LICENSE.txt} +0 -0
@@ -19,11 +19,11 @@ const logger = require('@abtnode/logger')('blocklet-services:oauth');
19
19
 
20
20
  const { AuthenticationClient } = require('../libs/auth/adapters/auth0');
21
21
  const { getAvatarByEmail, transferPassport, getAvatarByUrl } = require('../libs/auth/utils');
22
- const { api } = require('../libs/api');
23
22
  const initJwt = require('../libs/jwt');
24
23
  const { sendToUser } = require('../libs/notification');
25
24
  const { isInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../util');
26
25
  const { ApiError } = require('../util/error');
26
+ const { loginAuth0, getFederatedMaster, getOAuthUserInfo, shouldSyncFederated } = require('../util/federated');
27
27
 
28
28
  const PREFIX = WELLKNOWN_SERVICE_PATH_PREFIX;
29
29
 
@@ -72,21 +72,18 @@ async function login(req, node, options) {
72
72
  const { did: teamDid, wallet: blockletWallet, secret, appUrl } = await req.getBlockletInfo();
73
73
  let userWallet;
74
74
  let oauthInfo;
75
- let federatedSessionToken;
76
- let federatedRefreshToken;
77
75
 
78
- // NOTICE: 如果是统一登录,则向 master 站点发起 oauth 登录请求,auth0 的账户信息必须由 master 来生成
76
+ // NOTICE: 如果是统一登录,则向 master 站点发起 oauth 用户信息查询请求,auth0 的账户信息必须由 master 来生成
79
77
  if (sourceAppPid) {
80
- const federatedSites = blocklet.settings?.federated?.sites || [];
81
- const loginSite = federatedSites.find((x) => x.appPid === sourceAppPid);
82
- const postData = { token, locale, provider, componentId };
83
- const url = joinUrl(loginSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/oauth/login');
84
- const { data } = await api.post(url, postData, {
85
- headers: {
86
- 'x-did-connect-version': getDidConnectVersion(req),
87
- },
78
+ const data = await getOAuthUserInfo({
79
+ request: req,
80
+ blocklet,
81
+ provider,
82
+ token,
83
+ sourceAppPid,
88
84
  });
89
- ({ sessionToken: federatedSessionToken, refreshToken: federatedRefreshToken, oauthInfo, userWallet } = data);
85
+ userWallet = data.wallet;
86
+ oauthInfo = data.info;
90
87
  } else {
91
88
  const authClient = getAuthClient(blocklet, provider);
92
89
  oauthInfo = await authClient.getProfile(token);
@@ -189,22 +186,29 @@ async function login(req, node, options) {
189
186
  node
190
187
  );
191
188
 
189
+ const masterSite = getFederatedMaster(blocklet);
192
190
  // NOTICE: 采用异步来更新,不阻塞接口的正常响应
193
- node.syncFederated({
194
- did: teamDid,
195
- data: {
196
- users: [
197
- {
198
- did: userDid,
199
- pk: userPk,
200
- ...profile,
201
- avatar: getUserAvatarUrl(appUrl, profile.avatar),
202
- connectedAccount: [connectedAccount],
203
- action: 'connectAccount',
204
- },
205
- ],
206
- },
207
- });
191
+ if (shouldSyncFederated(sourceAppPid, masterSite, blocklet)) {
192
+ const syncUserData = {
193
+ did: userDid,
194
+ pk: userPk,
195
+ ...profile,
196
+ avatar: getUserAvatarUrl(appUrl, profile.avatar),
197
+ connectedAccount: [connectedAccount],
198
+ };
199
+ node.syncFederated({
200
+ did: teamDid,
201
+ data: {
202
+ users: [
203
+ {
204
+ ...syncUserData,
205
+ action: 'connectAccount',
206
+ sourceAppPid: sourceAppPid || masterSite.appPid,
207
+ },
208
+ ],
209
+ },
210
+ });
211
+ }
208
212
 
209
213
  const { createSessionToken } = initJwt(node, options);
210
214
 
@@ -218,6 +222,7 @@ async function login(req, node, options) {
218
222
  role: passport.role,
219
223
  fullName,
220
224
  provider,
225
+ walletOS: 'web',
221
226
  },
222
227
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
223
228
  );
@@ -230,22 +235,33 @@ async function login(req, node, options) {
230
235
  return {
231
236
  sessionToken,
232
237
  refreshToken,
233
- federatedSessionToken,
234
- federatedRefreshToken,
235
- oauthInfo,
236
- userWallet: pick(userWallet, ['type', 'publicKey', 'address']),
237
238
  };
238
239
  }
239
240
 
240
241
  async function invite(req, node, options) {
241
- const { locale, inviteId, token, baseUrl, provider = LOGIN_PROVIDER.AUTH0 } = req.body;
242
+ const { locale, inviteId, token, baseUrl, provider = LOGIN_PROVIDER.AUTH0, sourceAppPid } = req.body;
242
243
  const blocklet = await req.getBlocklet();
243
- const authClient = getAuthClient(blocklet, provider);
244
+ let userWallet;
245
+ let oauthInfo;
244
246
 
247
+ // NOTICE: 如果是统一登录,则向 master 站点发起 oauth 登录请求,auth0 的账户信息必须由 master 来生成
248
+ if (sourceAppPid) {
249
+ const data = await loginAuth0({
250
+ request: req,
251
+ blocklet,
252
+ locale,
253
+ provider,
254
+ token,
255
+ sourceAppPid,
256
+ });
257
+ ({ oauthInfo, userWallet } = data);
258
+ } else {
259
+ const authClient = getAuthClient(blocklet, provider);
260
+ oauthInfo = await authClient.getProfile(token);
261
+ userWallet = fromAppDid(oauthInfo.sub, blockletWallet.secretKey);
262
+ }
245
263
  const { did: teamDid, wallet: blockletWallet, secret } = await req.getBlockletInfo();
246
264
  const nodeInfo = await req.getNodeInfo();
247
- const oauthInfo = await authClient.getProfile(token);
248
- const userWallet = fromAppDid(oauthInfo.sub, blockletWallet.secretKey);
249
265
  let userDid = userWallet.address;
250
266
  let userPk = userWallet.publicKey;
251
267
 
@@ -332,23 +348,31 @@ async function invite(req, node, options) {
332
348
  did: userDid,
333
349
  pk: userPk,
334
350
  connectedAccount,
351
+ sourceAppPid,
335
352
  },
336
353
  });
354
+ const masterSite = getFederatedMaster(blocklet);
337
355
  // NOTICE: 采用异步来更新,不阻塞接口的正常响应
338
- node.syncFederated({
339
- did: teamDid,
340
- data: {
341
- users: [
342
- {
343
- did: userDid,
344
- pk: userPk,
345
- ...profile,
346
- connectedAccount: [connectedAccount],
347
- action: 'connectAccount',
348
- },
349
- ],
350
- },
351
- });
356
+ if (shouldSyncFederated(sourceAppPid, masterSite, blocklet)) {
357
+ const syncUserData = {
358
+ did: userDid,
359
+ pk: userPk,
360
+ ...profile,
361
+ connectedAccount: [connectedAccount],
362
+ };
363
+ node.syncFederated({
364
+ did: teamDid,
365
+ data: {
366
+ users: [
367
+ {
368
+ ...syncUserData,
369
+ action: 'connectAccount',
370
+ sourceAppPid: sourceAppPid || masterSite.appPid,
371
+ },
372
+ ],
373
+ },
374
+ });
375
+ }
352
376
  }
353
377
 
354
378
  const { createSessionToken } = initJwt(node, options);
@@ -358,7 +382,7 @@ async function invite(req, node, options) {
358
382
 
359
383
  const { sessionToken, refreshToken } = createToken(
360
384
  userDid,
361
- { secret, passport, role, fullName: profile.fullName, provider },
385
+ { secret, passport, role, fullName: profile.fullName, provider, walletOS: 'web' },
362
386
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
363
387
  );
364
388
 
@@ -373,14 +397,22 @@ async function invite(req, node, options) {
373
397
  // 给 DID Wallet 绑定 Auth0 的流程
374
398
  // eslint-disable-next-line no-unused-vars
375
399
  async function bind(req, node, options) {
376
- const { token, locale = 'en', provider } = req.body;
400
+ const { token, locale = 'en', provider, sourceAppPid } = req.body;
377
401
  const blocklet = await req.getBlocklet();
378
- const authClient = getAuthClient(blocklet, provider);
379
-
402
+ const { did: teamDid, wallet: blockletWallet, appUrl } = await req.getBlockletInfo();
380
403
  const userDid = req.user.did;
381
- const userInfo = await authClient.getProfile(token);
382
- const { did: teamDid, wallet: blockletWallet } = await req.getBlockletInfo();
383
- const userWallet = fromAppDid(userInfo.sub, blockletWallet.secretKey);
404
+
405
+ let userWallet;
406
+ let userInfo;
407
+ if (sourceAppPid) {
408
+ const data = await getOAuthUserInfo({ blocklet, provider, token, request: req, sourceAppPid });
409
+ userWallet = data.wallet;
410
+ userInfo = data.info;
411
+ } else {
412
+ const authClient = getAuthClient(blocklet, provider);
413
+ userInfo = await authClient.getProfile(token);
414
+ userWallet = fromAppDid(userInfo.sub, blockletWallet.secretKey);
415
+ }
384
416
  let oauthUser = await node.getUser({
385
417
  teamDid,
386
418
  user: { did: userWallet.address },
@@ -443,21 +475,31 @@ async function bind(req, node, options) {
443
475
  },
444
476
  });
445
477
 
446
- // NOTICE: 采用异步来更新,不阻塞接口的正常响应
447
- node.syncFederated({
448
- did: teamDid,
449
- data: {
450
- users: [
451
- {
452
- did: bindUser.did,
453
- pk: bindUser.pk,
454
- ...mergeProfile,
455
- connectedAccount: [connectedAccount],
456
- action: 'connectAccount',
457
- },
458
- ],
459
- },
460
- });
478
+ const masterSite = getFederatedMaster(blocklet);
479
+ if (shouldSyncFederated(sourceAppPid, masterSite, blocklet)) {
480
+ // NOTICE: 采用异步来更新,不阻塞接口的正常响应
481
+ const syncUserData = {
482
+ did: bindUser.did,
483
+ pk: bindUser.pk,
484
+ ...mergeProfile,
485
+ connectedAccount: [connectedAccount],
486
+ };
487
+ if (syncUserData.avatar) {
488
+ syncUserData.avatar = getUserAvatarUrl(appUrl, syncUserData.avatar);
489
+ }
490
+ node.syncFederated({
491
+ did: teamDid,
492
+ data: {
493
+ users: [
494
+ {
495
+ ...syncUserData,
496
+ action: 'connectAccount',
497
+ sourceAppPid: sourceAppPid || masterSite.appPid,
498
+ },
499
+ ],
500
+ },
501
+ });
502
+ }
461
503
 
462
504
  if (!oauthUser) {
463
505
  oauthUser = {
@@ -493,11 +535,11 @@ module.exports = {
493
535
  res.status(401).send('Unauthorized');
494
536
  }
495
537
  const userDid = req.user.did;
496
- const blocklet = await req.getBlockletInfo();
538
+ const blockletInfo = await req.getBlockletInfo();
497
539
  const nodeInfo = await req.getNodeInfo();
498
- const { did: teamDid, wallet: blockletWallet, appUrl } = blocklet;
540
+ const { did: teamDid, wallet: blockletWallet, appUrl } = blockletInfo;
499
541
  const { passportColor } = await getApplicationInfo({ node, nodeInfo, teamDid });
500
- const issuerDidList = uniq([blockletWallet.address, ...getBlockletAppIdList(blocklet)]);
542
+ const issuerDidList = uniq([blockletWallet.address, ...getBlockletAppIdList(blockletInfo)]);
501
543
  // NOTICE: 这里获取的 did 是当前登录用户的永久 did,无需查询 connectedAccount
502
544
  const user = await node.getUser({ teamDid, user: { did: userDid } });
503
545
  let ownerAvatarUrl = getUserAvatarUrl(appUrl, user.avatar);
@@ -594,7 +636,7 @@ module.exports = {
594
636
  const sessionConfig = blocklet.settings?.session || {};
595
637
  const { sessionToken, refreshToken } = createToken(
596
638
  userDid,
597
- { secret, passport, role: passport.role, fullName: user?.fullName, provider },
639
+ { secret, passport, role: passport.role, fullName: user?.fullName, provider, walletOS: 'web' },
598
640
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
599
641
  );
600
642
 
@@ -634,5 +676,21 @@ module.exports = {
634
676
  }
635
677
  server.post(`${prefix}/login`, loginFn);
636
678
  server.post(`${prefixApi}/login`, loginFn);
679
+
680
+ async function getUserFn(req, res) {
681
+ const { token, provider } = req.body;
682
+ const blocklet = await req.getBlocklet();
683
+ const { wallet: blockletWallet } = await req.getBlockletInfo();
684
+ const authClient = getAuthClient(blocklet, provider);
685
+ const oauthInfo = await authClient.getProfile(token);
686
+ const userWallet = fromAppDid(oauthInfo.sub, blockletWallet.secretKey);
687
+
688
+ res.json({
689
+ info: oauthInfo,
690
+ wallet: pick(userWallet, ['type', 'publicKey', 'address']),
691
+ });
692
+ }
693
+ server.post(`${prefix}/getUser`, getUserFn);
694
+ server.post(`${prefixApi}/getUser`, getUserFn);
637
695
  },
638
696
  };
@@ -274,6 +274,7 @@ async function login(req, node, options) {
274
274
  role: passport.role,
275
275
  fullName: doc.fullName,
276
276
  provider,
277
+ walletOS: 'api',
277
278
  },
278
279
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
279
280
  );
@@ -77,12 +77,21 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
77
77
  endpoint,
78
78
  });
79
79
 
80
+ const walletOS = req.context.didwallet.os;
81
+
80
82
  // Generate new session token that client can save to localStorage
81
83
  const createToken = createTokenFn(createSessionToken);
82
84
  const sessionConfig = blocklet.settings?.session || {};
83
85
  const { sessionToken, refreshToken } = createToken(
84
86
  userDid,
85
- { secret, passport, role, fullName: profile.fullName, provider: LOGIN_PROVIDER.WALLET },
87
+ {
88
+ secret,
89
+ passport,
90
+ role,
91
+ fullName: profile.fullName,
92
+ provider: LOGIN_PROVIDER.WALLET,
93
+ walletOS,
94
+ },
86
95
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
87
96
  );
88
97
  await updateSession({ sessionToken, refreshToken }, true);
@@ -40,8 +40,6 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
40
40
  {
41
41
  sessionToken: result.sessionToken,
42
42
  refreshToken: result.refreshToken,
43
- federatedSessionToken: result.federatedSessionToken || '',
44
- federatedRefreshToken: result.federatedRefreshToken || '',
45
43
  },
46
44
  true
47
45
  );
@@ -367,9 +367,10 @@ module.exports = function createRoutes(node, _, createSessionToken) {
367
367
  // Generate new session token that client can save to localStorage
368
368
  const createToken = createTokenFn(createSessionToken);
369
369
  const sessionConfig = blocklet.settings?.session || {};
370
+ const walletOS = req.context?.didwallet?.os;
370
371
  const { sessionToken, refreshToken } = createToken(
371
372
  userDid,
372
- { secret, passport: vc, role, fullName: profile.fullName, provider: LOGIN_PROVIDER.WALLET },
373
+ { secret, passport: vc, role, fullName: profile.fullName, provider: LOGIN_PROVIDER.WALLET, walletOS },
373
374
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
374
375
  );
375
376
  await updateSession({ sessionToken, refreshToken }, true);
@@ -1,4 +1,4 @@
1
- const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
1
+ const { getSourceAppPid, getLoginProvider } = require('@blocklet/sdk/lib/util/login');
2
2
  const { switchPassport } = require('../../../libs/connect/session');
3
3
 
4
4
  const { onConnect, onApprove } = switchPassport;
@@ -8,6 +8,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
8
8
  action: 'switch-passport',
9
9
  onConnect: ({ userDid, baseUrl, extraParams: { locale, connectedDid }, req, request }) => {
10
10
  const sourceAppPid = getSourceAppPid(request);
11
+ const provider = getLoginProvider(request);
11
12
  return onConnect({
12
13
  node,
13
14
  request: req,
@@ -16,11 +17,13 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
16
17
  previousUserDid: connectedDid,
17
18
  baseUrl,
18
19
  sourceAppPid,
20
+ provider,
19
21
  });
20
22
  },
21
23
 
22
24
  onAuth: async ({ claims, challenge, userDid, updateSession, extraParams, req, request }) => {
23
25
  const sourceAppPid = getSourceAppPid(request);
26
+ const provider = getLoginProvider(request);
24
27
  const { sessionToken, refreshToken } = await onApprove({
25
28
  node,
26
29
  request: req,
@@ -30,6 +33,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
30
33
  userDid,
31
34
  createSessionToken,
32
35
  sourceAppPid,
36
+ provider,
33
37
  });
34
38
 
35
39
  await updateSession({ sessionToken, refreshToken }, true);
@@ -56,7 +56,11 @@ module.exports = {
56
56
  .filter((x) => x.status === PASSPORT_STATUS.VALID)
57
57
  .map((x) => pick(x, ['id', 'name', 'title', 'role']));
58
58
 
59
- res.json({ user, provider: req.user.provider || LOGIN_PROVIDER.WALLET });
59
+ res.json({
60
+ user,
61
+ provider: req.user.provider || LOGIN_PROVIDER.WALLET,
62
+ walletOS: req.user.walletOS,
63
+ });
60
64
  };
61
65
 
62
66
  const sessionApi = `${prefix}/api/did/session`;
@@ -78,6 +82,7 @@ module.exports = {
78
82
  role,
79
83
  passport,
80
84
  provider = LOGIN_PROVIDER.WALLET,
85
+ walletOS,
81
86
  } = await verifySessionToken(token, secret, {
82
87
  checkFromDb: true,
83
88
  teamDid,
@@ -116,11 +121,18 @@ module.exports = {
116
121
  role,
117
122
  fullName: user.fullName,
118
123
  provider,
124
+ walletOS,
119
125
  },
120
126
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
121
127
  );
122
128
 
123
- res.json({ user, nextToken: sessionToken, nextRefreshToken: refreshToken, provider });
129
+ res.json({
130
+ user,
131
+ nextToken: sessionToken,
132
+ nextRefreshToken: refreshToken,
133
+ provider,
134
+ walletOS,
135
+ });
124
136
  } catch (err) {
125
137
  res.status(400).send(err.message);
126
138
  }
@@ -1,5 +1,22 @@
1
1
  const joinUrl = require('url-join');
2
2
  const { USER_AVATAR_URL_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX, USER_AVATAR_PATH_PREFIX } = require('@abtnode/constant');
3
+ const { pick, get } = require('lodash');
4
+ const { signV2 } = require('@arcblock/jwt');
5
+
6
+ const { api } = require('../libs/api');
7
+ const { getDidConnectVersion } = require('./index');
8
+
9
+ function shouldSyncFederated(sourceAppPid, master, blocklet) {
10
+ if (sourceAppPid) {
11
+ return true;
12
+ }
13
+
14
+ if (master && blocklet && master.appPid === blocklet.appPid) {
15
+ return true;
16
+ }
17
+
18
+ return false;
19
+ }
3
20
 
4
21
  function getFederatedMaster(blocklet) {
5
22
  const { sites } = blocklet?.settings?.federated || {};
@@ -22,8 +39,88 @@ function getUserAvatarUrl(avatar, blocklet) {
22
39
  return avatarUrl;
23
40
  }
24
41
 
42
+ async function loginAuth0({ blocklet, sourceAppPid, request, token, locale, provider, componentId }) {
43
+ const federatedSites = blocklet.settings?.federated?.sites || [];
44
+ const loginSite = federatedSites.find((x) => x.appPid === sourceAppPid);
45
+ const postData = { token, locale, provider };
46
+ if (componentId) {
47
+ postData.componentId = componentId;
48
+ }
49
+ const url = joinUrl(loginSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/oauth/login');
50
+ const { data } = await api.post(url, postData, {
51
+ headers: {
52
+ 'x-did-connect-version': getDidConnectVersion(request),
53
+ },
54
+ });
55
+ return data;
56
+ }
57
+
58
+ async function getOAuthUserInfo({ blocklet, sourceAppPid, request, token, provider }) {
59
+ const federatedSites = blocklet.settings?.federated?.sites || [];
60
+ const loginSite = federatedSites.find((x) => x.appPid === sourceAppPid);
61
+ const postData = { token, provider };
62
+ const url = joinUrl(loginSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/oauth/getUser');
63
+ const { data } = await api.post(url, postData, {
64
+ headers: {
65
+ 'x-did-connect-version': getDidConnectVersion(request),
66
+ },
67
+ });
68
+ return data;
69
+ }
70
+
71
+ async function migrateAuth0({ blocklet, blockletInfo, fromUserDid, toUserDid, toUserPk }) {
72
+ const masterSite = getFederatedMaster(blocklet);
73
+ const { permanentWallet } = blockletInfo;
74
+ const url = joinUrl(masterSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/federated/migrateAuth0');
75
+ const { data } = await api.post(url, {
76
+ signer: permanentWallet.address,
77
+ data: signV2(permanentWallet.address, permanentWallet.secretKey, {
78
+ fromUserDid,
79
+ toUserDid,
80
+ toUserPk,
81
+ }),
82
+ });
83
+ return data;
84
+ }
85
+
86
+ async function loginByMember({ blockletInfo, blocklet, request, user, passport }) {
87
+ const masterSite = getFederatedMaster(blocklet);
88
+ if (masterSite) {
89
+ const walletOS = request.context.didwallet.os;
90
+ const { permanentWallet } = blockletInfo;
91
+ const postUser = pick(user, ['did', 'pk', 'fullName', 'locale']);
92
+ postUser.lastLoginAt = get(request, 'headers[x-real-ip]') || '';
93
+
94
+ if (user.email) {
95
+ postUser.email = user.email;
96
+ }
97
+ if (user.avatar) {
98
+ postUser.avatar = getUserAvatarUrl(user.avatar, blocklet);
99
+ }
100
+
101
+ const { data } = await api.post(
102
+ joinUrl(masterSite.appUrl, WELLKNOWN_SERVICE_PATH_PREFIX, '/api/federated/loginByMember'),
103
+ {
104
+ signer: permanentWallet.address,
105
+ data: signV2(permanentWallet.address, permanentWallet.secretKey, {
106
+ user: postUser,
107
+ passport,
108
+ walletOS,
109
+ }),
110
+ }
111
+ );
112
+ return data;
113
+ }
114
+ return null;
115
+ }
116
+
25
117
  module.exports = {
26
118
  isMaster,
119
+ shouldSyncFederated,
27
120
  getFederatedMaster,
28
121
  getUserAvatarUrl,
122
+ loginAuth0,
123
+ migrateAuth0,
124
+ getOAuthUserInfo,
125
+ loginByMember,
29
126
  };