@abtnode/blocklet-services 1.16.16-beta-740ea329 → 1.16.16-beta-d6c5ed65
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/api/libs/auth/utils.js +2 -1
- package/api/libs/connect/session.js +75 -30
- package/api/libs/connect/shared.js +4 -5
- package/api/libs/connect/v1.js +7 -9
- package/api/routes/federated.js +84 -11
- package/api/routes/oauth.js +140 -37
- package/api/routes/user.js +7 -2
- package/api/services/auth/connect/switch-passport.js +5 -5
- package/api/util/blocklet-utils.js +2 -3
- package/build/asset-manifest.json +55 -55
- package/build/index.html +1 -1
- package/build/service-worker.js +1 -1
- package/build/service-worker.js.map +1 -1
- package/build/static/js/1480.36129849.chunk.js +2 -0
- package/build/static/js/{1565.a6f98c38.chunk.js → 1565.ad002b88.chunk.js} +2 -2
- package/build/static/js/{1660.5c8ade93.chunk.js → 1660.9fb17942.chunk.js} +2 -2
- package/build/static/js/{1760.95d0c320.chunk.js → 1760.71e0c151.chunk.js} +2 -2
- package/build/static/js/{2653.11a1ad57.chunk.js → 2653.6f37e8a0.chunk.js} +2 -2
- package/build/static/js/2686.7ae70bfd.chunk.js +2 -0
- package/build/static/js/4023.4be0c818.chunk.js +2 -0
- package/build/static/js/{4716.47aa133c.chunk.js → 4716.17a45b6a.chunk.js} +2 -2
- package/build/static/js/{4802.63425dd4.chunk.js → 4802.b7fa8e82.chunk.js} +2 -2
- package/build/static/js/50.cbaa5a4e.chunk.js +3 -0
- package/build/static/js/{5176.42904a22.chunk.js → 5176.53f7f419.chunk.js} +2 -2
- package/build/static/js/{5628.773a32da.chunk.js → 5628.aa14b1a7.chunk.js} +2 -2
- package/build/static/js/5662.522d3713.chunk.js +2 -0
- package/build/static/js/5683.7e5d47f1.chunk.js +2 -0
- package/build/static/js/6186.6462ea21.chunk.js +2 -0
- package/build/static/js/{6452.b1899621.chunk.js → 6452.4226209b.chunk.js} +2 -2
- package/build/static/js/{6629.36e61c26.chunk.js → 6629.785fe237.chunk.js} +3 -3
- package/build/static/js/{6640.53cdcb95.chunk.js → 6640.e453c619.chunk.js} +2 -2
- package/build/static/js/6737.7fe9f13a.chunk.js +2 -0
- package/build/static/js/{6771.735ebd3f.chunk.js → 6771.1e778542.chunk.js} +3 -3
- package/build/static/js/{6856.e5c166e6.chunk.js → 6856.9aaf692c.chunk.js} +2 -2
- package/build/static/js/{7006.9a53f7ed.chunk.js → 7006.b72aff66.chunk.js} +2 -2
- package/build/static/js/{7465.ba1027a7.chunk.js → 7465.999f0039.chunk.js} +3 -3
- package/build/static/js/{9409.befe72b4.chunk.js → 9409.fe4a0af0.chunk.js} +2 -2
- package/build/static/js/{9620.59bc85b8.chunk.js → 9620.db1568ef.chunk.js} +2 -2
- package/build/static/js/{9899.c8ff588e.chunk.js → 9899.92626f0a.chunk.js} +2 -2
- package/build/static/js/main.85d66eb2.js +3 -0
- package/build/static/js/{main.3ba3901e.js.LICENSE.txt → main.85d66eb2.js.LICENSE.txt} +1 -1
- package/package.json +23 -23
- package/build/static/js/1480.30b94380.chunk.js +0 -2
- package/build/static/js/2307.2e451912.chunk.js +0 -2
- package/build/static/js/2686.07687254.chunk.js +0 -2
- package/build/static/js/4023.0f348986.chunk.js +0 -2
- package/build/static/js/5683.3bdd2338.chunk.js +0 -2
- package/build/static/js/6186.61596c22.chunk.js +0 -2
- package/build/static/js/6606.9f17eaa6.chunk.js +0 -3
- package/build/static/js/6737.5f735a29.chunk.js +0 -2
- package/build/static/js/main.3ba3901e.js +0 -3
- /package/build/static/js/{6606.9f17eaa6.chunk.js.LICENSE.txt → 50.cbaa5a4e.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{6629.36e61c26.chunk.js.LICENSE.txt → 6629.785fe237.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{6771.735ebd3f.chunk.js.LICENSE.txt → 6771.1e778542.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{7465.ba1027a7.chunk.js.LICENSE.txt → 7465.999f0039.chunk.js.LICENSE.txt} +0 -0
package/api/libs/auth/utils.js
CHANGED
|
@@ -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 ===
|
|
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 });
|
|
@@ -41,7 +41,7 @@ const pick = require('lodash/pick');
|
|
|
41
41
|
const createTranslator = require('@abtnode/util/lib/translate');
|
|
42
42
|
|
|
43
43
|
const { getRolesFromAuthConfig, getBlockletAppIdList } = require('@blocklet/meta/lib/util');
|
|
44
|
-
const { getLoginProvider } = require('@blocklet/sdk/lib/util/login');
|
|
44
|
+
const { getSourceAppPid, getLoginProvider } = require('@blocklet/sdk/lib/util/login');
|
|
45
45
|
|
|
46
46
|
const logger = require('@abtnode/logger')(require('../../../package.json').name);
|
|
47
47
|
|
|
@@ -54,8 +54,8 @@ const { api } = require('../api');
|
|
|
54
54
|
|
|
55
55
|
const vcTypes = [VC_TYPE_GENERAL_PASSPORT, VC_TYPE_NODE_PASSPORT];
|
|
56
56
|
|
|
57
|
-
const getPassportVc = async ({ blocklet, claims, challenge, locale,
|
|
58
|
-
const trustedIssuers = await getTrustedIssuers(blocklet, {
|
|
57
|
+
const getPassportVc = async ({ blocklet, claims, challenge, locale, sourceAppPid }) => {
|
|
58
|
+
const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
|
|
59
59
|
const { vc } = await getVCFromClaims({
|
|
60
60
|
claims,
|
|
61
61
|
challenge,
|
|
@@ -67,7 +67,7 @@ const getPassportVc = async ({ blocklet, claims, challenge, locale, provider })
|
|
|
67
67
|
return vc;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid,
|
|
70
|
+
const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid, sourceAppPid }) => {
|
|
71
71
|
let role = ROLES.GUEST;
|
|
72
72
|
if (vc) {
|
|
73
73
|
await validatePassport(get(vc, 'credentialSubject.passport'));
|
|
@@ -77,8 +77,7 @@ const getRoleFromVC = async ({ vc, node, locale, blocklet, teamDid, provider })
|
|
|
77
77
|
role = getRoleFromLocalPassport(get(vc, 'credentialSubject.passport'));
|
|
78
78
|
} else {
|
|
79
79
|
// MEMO: 如果是 federated,需要将 actualIssuer 做一个转换
|
|
80
|
-
const actualIssuerList =
|
|
81
|
-
provider === LOGIN_PROVIDER.FEDERATED ? await getFederatedTrustedIssuers(blocklet) : [actualIssuer];
|
|
80
|
+
const actualIssuerList = sourceAppPid ? await getFederatedTrustedIssuers(blocklet) : [actualIssuer];
|
|
82
81
|
// map external passport to local role
|
|
83
82
|
const { mappings = [] } =
|
|
84
83
|
(blocklet.trustedPassports || []).find((x) => actualIssuerList.includes(x.issuerDid)) || {};
|
|
@@ -146,7 +145,7 @@ module.exports = {
|
|
|
146
145
|
const blocklet = await request.getBlocklet();
|
|
147
146
|
const config = await request.getServiceConfig(NODE_SERVICES.AUTH, { componentId });
|
|
148
147
|
const { did: teamDid, wallet: blockletWallet } = await request.getBlockletInfo();
|
|
149
|
-
const
|
|
148
|
+
const sourceAppPid = getSourceAppPid(request);
|
|
150
149
|
|
|
151
150
|
const profileFields = get(config, 'profileFields');
|
|
152
151
|
|
|
@@ -160,7 +159,7 @@ module.exports = {
|
|
|
160
159
|
if (action === 'login') {
|
|
161
160
|
const [invitedUserOnly] = config ? await isInvitedUserOnly(config, node, teamDid) : [false];
|
|
162
161
|
|
|
163
|
-
const trustedIssuers = await getTrustedIssuers(blocklet, {
|
|
162
|
+
const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
|
|
164
163
|
claims.verifiableCredential = {
|
|
165
164
|
type: 'verifiableCredential',
|
|
166
165
|
description: messages.requestPassport[locale],
|
|
@@ -246,11 +245,12 @@ module.exports = {
|
|
|
246
245
|
let defaultTtlPolicy = 'never';
|
|
247
246
|
let issuePassport = false;
|
|
248
247
|
|
|
248
|
+
const sourceAppPid = getSourceAppPid(request);
|
|
249
249
|
const provider = getLoginProvider(request);
|
|
250
250
|
|
|
251
251
|
// Get passport vc
|
|
252
252
|
if (action === 'login') {
|
|
253
|
-
vc = await getPassportVc({ blocklet, claims, challenge, locale,
|
|
253
|
+
vc = await getPassportVc({ blocklet, claims, challenge, locale, sourceAppPid });
|
|
254
254
|
[invitedUserOnly, defaultRole, issuePassport] = await isInvitedUserOnly(authConfig, node, teamDid);
|
|
255
255
|
if (invitedUserOnly && !vc) {
|
|
256
256
|
throw new Error(messages.missingCredentialClaim[locale]);
|
|
@@ -323,7 +323,7 @@ module.exports = {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
// Get role
|
|
326
|
-
const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid,
|
|
326
|
+
const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, sourceAppPid });
|
|
327
327
|
await validateRole({ role, authConfig, locale, node, teamDid });
|
|
328
328
|
|
|
329
329
|
checkAppOwner({ role, blocklet, userDid, locale });
|
|
@@ -347,14 +347,10 @@ module.exports = {
|
|
|
347
347
|
const passportForLog = passport || { name: 'Guest', role: 'guest' };
|
|
348
348
|
|
|
349
349
|
const masterSite = getFederatedMaster(blocklet);
|
|
350
|
-
|
|
350
|
+
const connectAccount = { provider, did: userDid, pk: userPk };
|
|
351
351
|
|
|
352
352
|
let updatedUser;
|
|
353
353
|
if (user) {
|
|
354
|
-
// Update user
|
|
355
|
-
if (masterSite && provider === LOGIN_PROVIDER.FEDERATED) {
|
|
356
|
-
connectAccount = { provider, did: userDid, pk: userPk, id: masterSite.appPid };
|
|
357
|
-
}
|
|
358
354
|
updatedUser = await node.loginUser({
|
|
359
355
|
teamDid,
|
|
360
356
|
user: {
|
|
@@ -362,6 +358,7 @@ module.exports = {
|
|
|
362
358
|
pk: user.pk,
|
|
363
359
|
locale,
|
|
364
360
|
passport,
|
|
361
|
+
sourceAppPid,
|
|
365
362
|
lastLoginIp: get(request, 'headers[x-real-ip]') || '',
|
|
366
363
|
connectedAccount: [connectAccount, connectedNft],
|
|
367
364
|
},
|
|
@@ -369,7 +366,7 @@ module.exports = {
|
|
|
369
366
|
await node.createAuditLog(
|
|
370
367
|
{
|
|
371
368
|
action,
|
|
372
|
-
args: { teamDid, userDid: realDid, passport: passportForLog, provider },
|
|
369
|
+
args: { teamDid, userDid: realDid, passport: passportForLog, provider, sourceAppPid },
|
|
373
370
|
context: formatContext(Object.assign(request, { user: updatedUser })),
|
|
374
371
|
result: updatedUser,
|
|
375
372
|
},
|
|
@@ -380,10 +377,6 @@ module.exports = {
|
|
|
380
377
|
const profile = claims.find((x) => x.type === 'profile');
|
|
381
378
|
fullName = profile.fullName;
|
|
382
379
|
|
|
383
|
-
if (masterSite && provider === LOGIN_PROVIDER.FEDERATED) {
|
|
384
|
-
connectAccount = { provider, did: userDid, pk: userPk, id: masterSite.appPid };
|
|
385
|
-
}
|
|
386
|
-
|
|
387
380
|
updatedUser = await node.loginUser({
|
|
388
381
|
teamDid,
|
|
389
382
|
user: {
|
|
@@ -395,6 +388,7 @@ module.exports = {
|
|
|
395
388
|
pk: realPk,
|
|
396
389
|
locale,
|
|
397
390
|
passport,
|
|
391
|
+
sourceAppPid,
|
|
398
392
|
lastLoginIp: get(request, 'headers[x-real-ip]') || '',
|
|
399
393
|
connectedAccount: [connectAccount, connectedNft],
|
|
400
394
|
},
|
|
@@ -402,7 +396,13 @@ module.exports = {
|
|
|
402
396
|
await node.createAuditLog(
|
|
403
397
|
{
|
|
404
398
|
action: 'addUser',
|
|
405
|
-
args: {
|
|
399
|
+
args: {
|
|
400
|
+
teamDid,
|
|
401
|
+
userDid: realDid,
|
|
402
|
+
sourceAppPid,
|
|
403
|
+
provider,
|
|
404
|
+
reason: `first login as ${passportForLog.role}`,
|
|
405
|
+
},
|
|
406
406
|
context: formatContext(Object.assign(request, { user: updatedUser })),
|
|
407
407
|
result: updatedUser,
|
|
408
408
|
},
|
|
@@ -410,6 +410,24 @@ module.exports = {
|
|
|
410
410
|
);
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
+
// NOTICE: 采用异步来更新,不阻塞接口的正常响应
|
|
414
|
+
node.syncFederated({
|
|
415
|
+
did: teamDid,
|
|
416
|
+
data: {
|
|
417
|
+
users: [
|
|
418
|
+
{
|
|
419
|
+
did: updatedUser.did,
|
|
420
|
+
pk: updatedUser.pk,
|
|
421
|
+
fullName: updatedUser.fullName,
|
|
422
|
+
email: updatedUser.email || '',
|
|
423
|
+
avatar: getUserAvatarUrl(updatedUser.avatar, blocklet),
|
|
424
|
+
connectedAccount: [connectAccount, connectedNft],
|
|
425
|
+
action: 'connectAccount',
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
|
|
413
431
|
// Generate new session token that client can save to localStorage
|
|
414
432
|
const createToken = createTokenFn(createSessionToken);
|
|
415
433
|
const sessionConfig = blocklet.settings?.session || {};
|
|
@@ -441,8 +459,8 @@ module.exports = {
|
|
|
441
459
|
|
|
442
460
|
let federatedSessionToken;
|
|
443
461
|
let federatedRefreshToken;
|
|
444
|
-
// member 使用
|
|
445
|
-
if (masterSite &&
|
|
462
|
+
// member 使用 federated login 时,总是会让 Master 自动登录
|
|
463
|
+
if (masterSite && sourceAppPid) {
|
|
446
464
|
const postUser = pick(updatedUser, ['did', 'pk', 'fullName', 'locale']);
|
|
447
465
|
postUser.lastLoginAt = get(request, 'headers[x-real-ip]') || '';
|
|
448
466
|
|
|
@@ -574,6 +592,18 @@ module.exports = {
|
|
|
574
592
|
},
|
|
575
593
|
node
|
|
576
594
|
);
|
|
595
|
+
|
|
596
|
+
const syncUserData = pick(doc, ['did', 'pk', 'fullName', 'avatar', 'email']);
|
|
597
|
+
if (syncUserData.avatar) {
|
|
598
|
+
syncUserData.avatar = getUserAvatarUrl(syncUserData.avatar, blocklet);
|
|
599
|
+
}
|
|
600
|
+
// NOTICE: 采用异步来更新,不阻塞接口的正常响应
|
|
601
|
+
node.syncFederated({
|
|
602
|
+
did: teamDid,
|
|
603
|
+
data: {
|
|
604
|
+
users: [{ ...syncUserData, action: 'switchProfile' }],
|
|
605
|
+
},
|
|
606
|
+
});
|
|
577
607
|
},
|
|
578
608
|
},
|
|
579
609
|
|
|
@@ -606,8 +636,8 @@ module.exports = {
|
|
|
606
636
|
const [invitedUserOnly] = await isInvitedUserOnly(config, node, teamDid);
|
|
607
637
|
|
|
608
638
|
const blocklet = await request.getBlocklet();
|
|
609
|
-
const
|
|
610
|
-
const trustedIssuers = await getTrustedIssuers(blocklet, {
|
|
639
|
+
const sourceAppPid = getSourceAppPid(request);
|
|
640
|
+
const trustedIssuers = await getTrustedIssuers(blocklet, { sourceAppPid });
|
|
611
641
|
|
|
612
642
|
return {
|
|
613
643
|
verifiableCredential: {
|
|
@@ -629,7 +659,7 @@ module.exports = {
|
|
|
629
659
|
userDid,
|
|
630
660
|
createSessionToken,
|
|
631
661
|
componentId,
|
|
632
|
-
|
|
662
|
+
sourceAppPid,
|
|
633
663
|
}) => {
|
|
634
664
|
const blocklet = await request.getBlocklet();
|
|
635
665
|
const { name, did: teamDid, secret } = await request.getBlockletInfo();
|
|
@@ -660,7 +690,7 @@ module.exports = {
|
|
|
660
690
|
claims: [verifiableCredential],
|
|
661
691
|
challenge,
|
|
662
692
|
locale,
|
|
663
|
-
|
|
693
|
+
sourceAppPid,
|
|
664
694
|
});
|
|
665
695
|
|
|
666
696
|
// Validate passport required
|
|
@@ -676,7 +706,7 @@ module.exports = {
|
|
|
676
706
|
}
|
|
677
707
|
|
|
678
708
|
// Get role
|
|
679
|
-
const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid,
|
|
709
|
+
const role = await getRoleFromVC({ vc, node, locale, blocklet, teamDid, sourceAppPid });
|
|
680
710
|
await validateRole({ role, authConfig, locale, node, teamDid });
|
|
681
711
|
|
|
682
712
|
checkAppOwner({ role, blocklet, userDid, locale });
|
|
@@ -701,7 +731,7 @@ module.exports = {
|
|
|
701
731
|
await node.createAuditLog(
|
|
702
732
|
{
|
|
703
733
|
action: 'switchPassport',
|
|
704
|
-
args: { teamDid, userDid, passport: passportForLog,
|
|
734
|
+
args: { teamDid, userDid, passport: passportForLog, sourceAppPid },
|
|
705
735
|
context: formatContext(Object.assign(request, { user })),
|
|
706
736
|
result: {},
|
|
707
737
|
},
|
|
@@ -713,7 +743,7 @@ module.exports = {
|
|
|
713
743
|
const sessionConfig = blocklet.settings?.session || {};
|
|
714
744
|
const { sessionToken, refreshToken } = createToken(
|
|
715
745
|
userDid,
|
|
716
|
-
{ secret, passport, role, fullName: user.fullName,
|
|
746
|
+
{ secret, passport, role, fullName: user.fullName, sourceAppPid },
|
|
717
747
|
{ ...sessionConfig, didConnectVersion: getDidConnectVersion(request) }
|
|
718
748
|
);
|
|
719
749
|
return { sessionToken, refreshToken };
|
|
@@ -875,6 +905,21 @@ module.exports = {
|
|
|
875
905
|
passports: mergePassport,
|
|
876
906
|
},
|
|
877
907
|
});
|
|
908
|
+
// NOTICE: 采用异步来更新,不阻塞接口的正常响应
|
|
909
|
+
node.syncFederated({
|
|
910
|
+
did: teamDid,
|
|
911
|
+
data: {
|
|
912
|
+
users: [
|
|
913
|
+
{
|
|
914
|
+
did: oauthUser.did,
|
|
915
|
+
pk: oauthUser.pk,
|
|
916
|
+
...mergeProfile,
|
|
917
|
+
connectedAccount: [connectedAccount],
|
|
918
|
+
action: 'connectAccount',
|
|
919
|
+
},
|
|
920
|
+
],
|
|
921
|
+
},
|
|
922
|
+
});
|
|
878
923
|
|
|
879
924
|
if (!bindUser) {
|
|
880
925
|
bindUser = {
|
|
@@ -2,11 +2,10 @@ 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 {
|
|
6
|
-
const { getLoginProvider } = require('@blocklet/sdk/lib/util/login');
|
|
5
|
+
const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
|
|
7
6
|
|
|
8
7
|
module.exports = {
|
|
9
|
-
appInfo: async ({ request, baseUrl
|
|
8
|
+
appInfo: async ({ request, baseUrl }) => {
|
|
10
9
|
const groupPathPrefix = request.headers['x-group-path-prefix'] || '/';
|
|
11
10
|
|
|
12
11
|
const [blocklet, meta, info] = await Promise.all([
|
|
@@ -16,9 +15,9 @@ module.exports = {
|
|
|
16
15
|
]);
|
|
17
16
|
// 对于 ux 来说, 要展示的始终是 pid,所以这个给 agentDid 的赋值也需要是 pid
|
|
18
17
|
let agentDid;
|
|
19
|
-
const
|
|
18
|
+
const sourceAppPid = getSourceAppPid(request);
|
|
20
19
|
// federated 登录模式下,需要告知原有的 blocklet-did
|
|
21
|
-
if (
|
|
20
|
+
if (sourceAppPid) {
|
|
22
21
|
agentDid = blocklet.appPid;
|
|
23
22
|
}
|
|
24
23
|
|
package/api/libs/connect/v1.js
CHANGED
|
@@ -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 {
|
|
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
|
|
28
|
-
const
|
|
26
|
+
delegator: async ({ request }) => {
|
|
27
|
+
const sourceAppPid = getSourceAppPid(request);
|
|
29
28
|
|
|
30
29
|
const blocklet = await request.getBlocklet();
|
|
31
|
-
if (
|
|
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
|
|
50
|
+
delegation: async ({ request }) => {
|
|
53
51
|
const { wallet: delegatee, permanentWallet: delegator } = await request.getBlockletInfo();
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
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/routes/federated.js
CHANGED
|
@@ -3,6 +3,7 @@ const { signV2 } = require('@arcblock/jwt');
|
|
|
3
3
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
4
4
|
const cloneDeep = require('lodash/cloneDeep');
|
|
5
5
|
const get = require('lodash/get');
|
|
6
|
+
const isNil = require('lodash/isNil');
|
|
6
7
|
const pLimit = require('p-limit');
|
|
7
8
|
const pRetry = require('p-retry');
|
|
8
9
|
|
|
@@ -29,8 +30,52 @@ const PREFIX = WELLKNOWN_SERVICE_PATH_PREFIX;
|
|
|
29
30
|
const prefix = `${PREFIX}/api/federated`;
|
|
30
31
|
const limitSync = pLimit(1);
|
|
31
32
|
|
|
33
|
+
async function syncSwitchProfile(user, { node, teamDid, dataDir }) {
|
|
34
|
+
const tempUser = pick(user, ['did', 'pk', 'avatar', 'fullName', 'email']);
|
|
35
|
+
|
|
36
|
+
// 处理 avatar
|
|
37
|
+
if (tempUser.avatar) {
|
|
38
|
+
try {
|
|
39
|
+
tempUser.avatar = await getAvatarByUrl(tempUser.avatar);
|
|
40
|
+
tempUser.avatar = await extractUserAvatar(tempUser.avatar, { dataDir });
|
|
41
|
+
} catch (err) {
|
|
42
|
+
logger.error('Failed to convert user avatar', { error: err });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await node.updateUser({
|
|
47
|
+
teamDid,
|
|
48
|
+
user: tempUser,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function syncConnectAccount(user, { node, teamDid, dataDir }) {
|
|
53
|
+
const tempUser = pick(user, ['did', 'pk', 'avatar', 'fullName', 'email', 'connectedAccount']);
|
|
54
|
+
|
|
55
|
+
// 处理 avatar
|
|
56
|
+
if (tempUser.avatar) {
|
|
57
|
+
try {
|
|
58
|
+
tempUser.avatar = await getAvatarByUrl(tempUser.avatar);
|
|
59
|
+
tempUser.avatar = await extractUserAvatar(tempUser.avatar, { dataDir });
|
|
60
|
+
} catch (err) {
|
|
61
|
+
logger.error('Failed to convert user avatar', { error: err });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await node.loginUser({
|
|
66
|
+
teamDid,
|
|
67
|
+
user: tempUser,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const syncFnMaps = {
|
|
72
|
+
switchProfile: syncSwitchProfile,
|
|
73
|
+
connectAccount: syncConnectAccount,
|
|
74
|
+
};
|
|
75
|
+
|
|
32
76
|
module.exports = {
|
|
33
77
|
preInit(server) {
|
|
78
|
+
// 这几个 route 是在前端跨域调用的,所以需要单独配置 cors
|
|
34
79
|
server.options(`${prefix}/prelogin`, cors({ credentials: true, origin: true }));
|
|
35
80
|
server.options(`${prefix}/login`, cors({ credentials: true, origin: true }));
|
|
36
81
|
server.options(`${prefix}/logout`, cors({ credentials: true, origin: true }));
|
|
@@ -200,16 +245,42 @@ module.exports = {
|
|
|
200
245
|
|
|
201
246
|
// step 3 同步站点群信息(master 向 member 广播站点群信息,广播请求在 manager/disk.js 文件中 class FederatedBlockletManager 发起 )
|
|
202
247
|
// 该路由为 member 接受响应的 api(只允许 master 调用)
|
|
203
|
-
server.post(`${prefix}/sync`, ensureBlocklet(), verifyFederatedCall(
|
|
204
|
-
const { sites } = req.body.verifyData;
|
|
248
|
+
server.post(`${prefix}/sync`, ensureBlocklet(), verifyFederatedCall(), async (req, res) => {
|
|
205
249
|
const { blocklet } = req;
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
250
|
+
const teamDid = blocklet.appPid;
|
|
251
|
+
const { users = null, sites = null } = req.body.verifyData;
|
|
252
|
+
|
|
253
|
+
// FIXME: @zhanghan 校验 users 和 sites 数据合法性
|
|
254
|
+
const pendingList = [];
|
|
255
|
+
if (!isNil(sites)) {
|
|
256
|
+
const federated = cloneDeep(blocklet.settings.federated || {});
|
|
257
|
+
federated.sites = sites;
|
|
258
|
+
pendingList.push(
|
|
259
|
+
limitSync(async () => {
|
|
260
|
+
await node.setFederated({
|
|
261
|
+
did: blocklet.appPid,
|
|
262
|
+
config: federated,
|
|
263
|
+
});
|
|
264
|
+
})
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (!isNil(users)) {
|
|
269
|
+
if (Array.isArray(users)) {
|
|
270
|
+
const nodeInfo = await req.getNodeInfo();
|
|
271
|
+
const { dataDir } = await getApplicationInfo({ node, nodeInfo, teamDid });
|
|
272
|
+
for (const user of users) {
|
|
273
|
+
pendingList.push(
|
|
274
|
+
limitSync(async () => {
|
|
275
|
+
await syncFnMaps[user.action]?.(user, { node, teamDid, dataDir });
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
await Promise.all(pendingList);
|
|
283
|
+
res.json({});
|
|
213
284
|
});
|
|
214
285
|
|
|
215
286
|
// step 4 检测自动登录条件(member 向 master 发起请求)
|
|
@@ -365,8 +436,9 @@ module.exports = {
|
|
|
365
436
|
avatar,
|
|
366
437
|
// HACK: @zhanghan 这里会将 passport 插入到当前用户的 passport 列表中,federated 登录不应该插入 passport
|
|
367
438
|
// passport: findMapping ? targetPassport : null,
|
|
439
|
+
sourceAppPid: masterPid,
|
|
368
440
|
connectedAccount: {
|
|
369
|
-
provider: LOGIN_PROVIDER.
|
|
441
|
+
provider: LOGIN_PROVIDER.WALLET,
|
|
370
442
|
id: masterPid,
|
|
371
443
|
did: user.did,
|
|
372
444
|
pk: user.pk,
|
|
@@ -380,7 +452,7 @@ module.exports = {
|
|
|
380
452
|
role: targetPassport.role,
|
|
381
453
|
passport: targetPassport,
|
|
382
454
|
fullName: doc.fullName,
|
|
383
|
-
provider: LOGIN_PROVIDER.
|
|
455
|
+
provider: LOGIN_PROVIDER.WALLET,
|
|
384
456
|
},
|
|
385
457
|
{
|
|
386
458
|
...sessionConfig,
|
|
@@ -439,6 +511,7 @@ module.exports = {
|
|
|
439
511
|
}
|
|
440
512
|
const realDid = prevUser?.did || user.did;
|
|
441
513
|
const realPk = prevUser?.pk || user.pk;
|
|
514
|
+
// NOTICE: 这里是 Master 登录,不需要 sourceAppPid 字段
|
|
442
515
|
const newUser = await node.loginUser({
|
|
443
516
|
teamDid,
|
|
444
517
|
user: {
|