@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.
- package/api/index.js +1 -1
- package/api/libs/auth/utils.js +2 -1
- package/api/libs/connect/session.js +131 -72
- package/api/libs/connect/shared.js +36 -16
- package/api/libs/connect/v1.js +7 -9
- package/api/libs/jwt.js +5 -3
- package/api/routes/federated.js +145 -19
- package/api/routes/oauth.js +214 -53
- package/api/routes/user.js +8 -2
- package/api/services/auth/connect/invite.js +10 -1
- package/api/services/auth/connect/login.js +0 -2
- package/api/services/auth/connect/receive-transfer-app-owner.js +2 -1
- package/api/services/auth/connect/switch-passport.js +5 -1
- package/api/services/auth/session.js +14 -2
- package/api/util/blocklet-utils.js +2 -3
- package/api/util/federated.js +84 -0
- package/build/asset-manifest.json +63 -63
- 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.88c590c2.chunk.js +2 -0
- package/build/static/js/{1565.a6f98c38.chunk.js → 1565.6df974b9.chunk.js} +2 -2
- package/build/static/js/{1760.95d0c320.chunk.js → 1760.70492184.chunk.js} +2 -2
- package/build/static/js/{2653.11a1ad57.chunk.js → 2653.5dc29ed5.chunk.js} +2 -2
- package/build/static/js/2686.7ae70bfd.chunk.js +2 -0
- package/build/static/js/2836.f4b10b64.chunk.js +2 -0
- package/build/static/js/{4042.3c8e0025.chunk.js → 2838.6fa46760.chunk.js} +3 -3
- package/build/static/js/{1660.5c8ade93.chunk.js → 3025.7dc2fe04.chunk.js} +2 -2
- package/build/static/js/4023.202dcd9a.chunk.js +2 -0
- package/build/static/js/{4706.df5b600d.chunk.js → 4706.212c92c8.chunk.js} +3 -3
- package/build/static/js/4716.88f32cf2.chunk.js +2 -0
- package/build/static/js/{4802.63425dd4.chunk.js → 4802.3b60e453.chunk.js} +2 -2
- package/build/static/js/50.cbaa5a4e.chunk.js +3 -0
- package/build/static/js/{5176.42904a22.chunk.js → 5176.7e91bc3b.chunk.js} +2 -2
- package/build/static/js/{5628.773a32da.chunk.js → 5628.e46ecc79.chunk.js} +2 -2
- package/build/static/js/{6380.2b96be29.chunk.js → 5673.ab67c509.chunk.js} +2 -2
- package/build/static/js/5683.7e5d47f1.chunk.js +2 -0
- package/build/static/js/6186.ebbdb4b8.chunk.js +2 -0
- package/build/static/js/{6452.b1899621.chunk.js → 6452.143af37a.chunk.js} +2 -2
- package/build/static/js/{6629.36e61c26.chunk.js → 6629.376863d2.chunk.js} +3 -3
- package/build/static/js/{6640.53cdcb95.chunk.js → 6640.a4431c82.chunk.js} +2 -2
- package/build/static/js/6737.7d135225.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.e185e317.chunk.js} +2 -2
- package/build/static/js/{7006.9a53f7ed.chunk.js → 7006.b72aff66.chunk.js} +2 -2
- package/build/static/js/{8706.3d16907a.chunk.js → 7367.60cb10e0.chunk.js} +2 -2
- package/build/static/js/{7465.ba1027a7.chunk.js → 7465.2bb961d7.chunk.js} +3 -3
- package/build/static/js/{9409.befe72b4.chunk.js → 9409.62a2aee0.chunk.js} +2 -2
- package/build/static/js/{9620.59bc85b8.chunk.js → 9620.301493bc.chunk.js} +2 -2
- package/build/static/js/{9899.c8ff588e.chunk.js → 9899.b8d8a5ca.chunk.js} +2 -2
- package/build/static/js/main.a58f939e.js +3 -0
- package/build/static/js/{main.3ba3901e.js.LICENSE.txt → main.a58f939e.js.LICENSE.txt} +1 -1
- package/package.json +34 -34
- 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/4716.47aa133c.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/{4042.3c8e0025.chunk.js.LICENSE.txt → 2838.6fa46760.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{4706.df5b600d.chunk.js.LICENSE.txt → 4706.212c92c8.chunk.js.LICENSE.txt} +0 -0
- /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.376863d2.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.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: '
|
|
185
|
+
limit: '8mb',
|
|
186
186
|
|
|
187
187
|
// https://flaviocopes.com/express-get-raw-body/
|
|
188
188
|
// Side effects: this will double the memory consumption
|
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 });
|
|
@@ -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 {
|
|
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,
|
|
58
|
-
const trustedIssuers = await getTrustedIssuers(blocklet, {
|
|
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,
|
|
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
|
|
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, {
|
|
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,
|
|
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,
|
|
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
|
|
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: {
|
|
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
|
|
610
|
-
const trustedIssuers = await getTrustedIssuers(blocklet, {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
{
|
|
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
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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 {
|
|
6
|
-
|
|
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
|
|
27
|
+
appInfo: async ({ request, baseUrl }) => {
|
|
10
28
|
const groupPathPrefix = request.headers['x-group-path-prefix'] || '/';
|
|
11
29
|
|
|
12
|
-
const [blocklet,
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
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/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);
|