@abtnode/blocklet-services 1.16.14-beta-a898bfcb → 1.16.14-beta-d802cd3c

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 (96) hide show
  1. package/api/index.js +5 -0
  2. package/api/libs/auth/utils.js +6 -8
  3. package/api/libs/connect/session.js +75 -23
  4. package/api/libs/connect/shared.js +12 -1
  5. package/api/libs/connect/v1.js +32 -3
  6. package/api/libs/jwt.js +8 -3
  7. package/api/middlewares/check-federated-cors-call.js +15 -0
  8. package/api/middlewares/ensure-blocklet.js +13 -0
  9. package/api/middlewares/verify-federated-call.js +35 -0
  10. package/api/routes/blocklet.js +20 -7
  11. package/api/routes/federated.js +365 -0
  12. package/api/routes/oauth.js +8 -7
  13. package/api/services/auth/connect/invite.js +2 -1
  14. package/api/services/auth/connect/issue-passport.js +2 -8
  15. package/api/services/auth/connect/login.js +9 -1
  16. package/api/services/auth/connect/receive-transfer-app-owner.js +3 -1
  17. package/api/services/auth/session.js +3 -1
  18. package/api/services/dashboard/index.js +1 -1
  19. package/api/services/notification/blocklet-events-notifier.js +79 -28
  20. package/api/util/blocklet-utils.js +27 -0
  21. package/api/util/federated.js +41 -0
  22. package/build/asset-manifest.json +70 -69
  23. package/build/index.html +1 -1
  24. package/build/service-worker.js +1 -1
  25. package/build/service-worker.js.map +1 -1
  26. package/build/static/css/4603.dce369d5.chunk.css +2 -0
  27. package/build/static/js/{1162.40dc4181.chunk.js → 1162.ff3136ae.chunk.js} +2 -2
  28. package/build/static/js/1237.1d0b8f1e.chunk.js +3 -0
  29. package/build/static/js/2130.59fef4ad.chunk.js +3 -0
  30. package/build/static/js/3242.5dea77f3.chunk.js +2 -0
  31. package/build/static/js/3464.12806bfe.chunk.js +2 -0
  32. package/build/static/js/{3953.b81b810f.chunk.js → 3953.e3e51520.chunk.js} +2 -2
  33. package/build/static/js/3963.2e06f9bc.chunk.js +3 -0
  34. package/build/static/js/4319.e99b5af9.chunk.js +2 -0
  35. package/build/static/js/{445.080a986b.chunk.js → 445.6da52f3e.chunk.js} +3 -3
  36. package/build/static/js/4492.97b0d4f6.chunk.js +2 -0
  37. package/build/static/js/4547.b26ceabb.chunk.js +2 -0
  38. package/build/static/js/4603.f6b8d272.chunk.js +2 -0
  39. package/build/static/js/4651.0a58cbc3.chunk.js +3 -0
  40. package/build/static/js/5050.538edf89.chunk.js +3 -0
  41. package/build/static/js/5176.68fd3fde.chunk.js +2 -0
  42. package/build/static/js/5233.faabaae9.chunk.js +2 -0
  43. package/build/static/js/{5430.e0f10ab3.chunk.js → 5430.8114614c.chunk.js} +2 -2
  44. package/build/static/js/5645.a17cd258.chunk.js +2 -0
  45. package/build/static/js/6315.59e078f6.chunk.js +2 -0
  46. package/build/static/js/652.d534b309.chunk.js +2 -0
  47. package/build/static/js/{6737.c05aedb4.chunk.js → 6737.4f37dd4a.chunk.js} +2 -2
  48. package/build/static/js/6891.6c7018ab.chunk.js +2 -0
  49. package/build/static/js/7345.4b4f8941.chunk.js +3 -0
  50. package/build/static/js/7371.da3c5cc3.chunk.js +2 -0
  51. package/build/static/js/{766.c7bfb323.chunk.js → 766.5dd16d47.chunk.js} +2 -2
  52. package/build/static/js/780.32bf1f5b.chunk.js +2 -0
  53. package/build/static/js/8031.d9af3d84.chunk.js +2 -0
  54. package/build/static/js/8395.e5aa519c.chunk.js +2 -0
  55. package/build/static/js/868.aa2a1c4d.chunk.js +2 -0
  56. package/build/static/js/9476.bc480cfc.chunk.js +2 -0
  57. package/build/static/js/982.11dc355f.chunk.js +3 -0
  58. package/build/static/js/main.0357601e.js +3 -0
  59. package/build/static/media/index.20414a3fa1e6c5498a67.cjs +1 -0
  60. package/package.json +36 -35
  61. package/build/static/js/1237.7fd9e6ea.chunk.js +0 -3
  62. package/build/static/js/1610.13323d09.chunk.js +0 -2
  63. package/build/static/js/2130.5655904d.chunk.js +0 -3
  64. package/build/static/js/3242.86fc9bc6.chunk.js +0 -2
  65. package/build/static/js/338.2f0211d7.chunk.js +0 -2
  66. package/build/static/js/3464.54f63e09.chunk.js +0 -2
  67. package/build/static/js/3963.f4a75432.chunk.js +0 -3
  68. package/build/static/js/4319.5363b467.chunk.js +0 -2
  69. package/build/static/js/4547.b013b965.chunk.js +0 -2
  70. package/build/static/js/4651.ea828d09.chunk.js +0 -3
  71. package/build/static/js/5050.af9b1e9c.chunk.js +0 -3
  72. package/build/static/js/5176.52b53df7.chunk.js +0 -2
  73. package/build/static/js/5233.e44190bf.chunk.js +0 -2
  74. package/build/static/js/5645.48cf12d4.chunk.js +0 -2
  75. package/build/static/js/6315.dec40b9b.chunk.js +0 -2
  76. package/build/static/js/652.7a2367a9.chunk.js +0 -2
  77. package/build/static/js/6891.eed3eb07.chunk.js +0 -2
  78. package/build/static/js/7345.fb7fa7cf.chunk.js +0 -3
  79. package/build/static/js/7371.0b48d1c0.chunk.js +0 -2
  80. package/build/static/js/780.860d0370.chunk.js +0 -2
  81. package/build/static/js/7902.9316a419.chunk.js +0 -2
  82. package/build/static/js/8395.656effd4.chunk.js +0 -2
  83. package/build/static/js/868.cd5abe55.chunk.js +0 -2
  84. package/build/static/js/9476.302a7b02.chunk.js +0 -2
  85. package/build/static/js/9645.8ef1036e.chunk.js +0 -2
  86. package/build/static/js/982.3e297296.chunk.js +0 -3
  87. package/build/static/js/main.d78266c4.js +0 -3
  88. /package/build/static/js/{1237.7fd9e6ea.chunk.js.LICENSE.txt → 1237.1d0b8f1e.chunk.js.LICENSE.txt} +0 -0
  89. /package/build/static/js/{2130.5655904d.chunk.js.LICENSE.txt → 2130.59fef4ad.chunk.js.LICENSE.txt} +0 -0
  90. /package/build/static/js/{3963.f4a75432.chunk.js.LICENSE.txt → 3963.2e06f9bc.chunk.js.LICENSE.txt} +0 -0
  91. /package/build/static/js/{445.080a986b.chunk.js.LICENSE.txt → 445.6da52f3e.chunk.js.LICENSE.txt} +0 -0
  92. /package/build/static/js/{4651.ea828d09.chunk.js.LICENSE.txt → 4651.0a58cbc3.chunk.js.LICENSE.txt} +0 -0
  93. /package/build/static/js/{5050.af9b1e9c.chunk.js.LICENSE.txt → 5050.538edf89.chunk.js.LICENSE.txt} +0 -0
  94. /package/build/static/js/{7345.fb7fa7cf.chunk.js.LICENSE.txt → 7345.4b4f8941.chunk.js.LICENSE.txt} +0 -0
  95. /package/build/static/js/{982.3e297296.chunk.js.LICENSE.txt → 982.11dc355f.chunk.js.LICENSE.txt} +0 -0
  96. /package/build/static/js/{main.d78266c4.js.LICENSE.txt → main.0357601e.js.LICENSE.txt} +0 -0
@@ -0,0 +1,365 @@
1
+ const { WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
2
+ const { signV2 } = require('@arcblock/jwt');
3
+ const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
4
+ const cloneDeep = require('lodash/cloneDeep');
5
+ const get = require('lodash/get');
6
+
7
+ const cors = require('cors');
8
+ const { LOGIN_PROVIDER } = require('@blocklet/constant');
9
+ const pick = require('lodash/pick');
10
+
11
+ const { api } = require('../libs/api');
12
+ const initJwt = require('../libs/jwt');
13
+ const { createTokenFn, getDidConnectVersion } = require('../util');
14
+ const verifyFederatedCall = require('../middlewares/verify-federated-call');
15
+ const ensureBlocklet = require('../middlewares/ensure-blocklet');
16
+ const checkFederatedCorsCall = require('../middlewares/check-federated-cors-call');
17
+ const { getUserAvatarUrl } = require('../util/federated');
18
+
19
+ const PREFIX = WELLKNOWN_SERVICE_PATH_PREFIX;
20
+
21
+ const prefix = `${PREFIX}/api/federated`;
22
+
23
+ module.exports = {
24
+ preInit(server) {
25
+ server.options(`${prefix}/prelogin`, cors({ credentials: true, origin: true }));
26
+ server.options(`${prefix}/login`, cors({ credentials: true, origin: true }));
27
+ server.options(`${prefix}/logout`, cors({ credentials: true, origin: true }));
28
+ },
29
+ init(server, node, options) {
30
+ // step 1 申请加入(member 向 master 申请)
31
+ server.post(`${prefix}/join`, ensureBlocklet(), async (req, res) => {
32
+ const { blocklet } = req;
33
+ const { site } = req.body;
34
+
35
+ const federated = cloneDeep(blocklet.settings.federated || {});
36
+ let sites = federated?.sites || [];
37
+ if (sites.length === 0) {
38
+ const nodeInfo = await req.getNodeInfo();
39
+ const blockletInfo = await req.getBlockletInfo();
40
+ const masterSite = {
41
+ appId: blockletInfo.wallet.address,
42
+ appPid: blockletInfo.permanentWallet.address,
43
+ migratedFrom: blocklet.migratedFrom || [],
44
+ appName: blockletInfo.name,
45
+ appDescription: blockletInfo.description,
46
+ appUrl: blockletInfo.appUrl,
47
+ appLogo:
48
+ blocklet.environmentObj.BLOCKLET_APP_LOGO ||
49
+ normalizePathPrefix(`${WELLKNOWN_SERVICE_PATH_PREFIX}/blocklet/logo`) ||
50
+ '/',
51
+ appLogoRect: blocklet.environmentObj.BLOCKLET_APP_LOGO_RECT,
52
+ did: blockletInfo.did,
53
+ pk: blockletInfo.permanentWallet.publicKey,
54
+ serverId: nodeInfo.did,
55
+ serverVersion: nodeInfo.version,
56
+ version: blocklet.meta.version,
57
+ };
58
+ sites = [masterSite];
59
+ }
60
+
61
+ let masterConfig = federated.config;
62
+ if (!masterConfig) {
63
+ masterConfig = {
64
+ appId: blocklet.appDid,
65
+ appPid: blocklet.appPid || blocklet.appDid,
66
+ };
67
+ }
68
+ if (site) {
69
+ sites.push({
70
+ ...site,
71
+ appliedAt: new Date(),
72
+ status: 'pending',
73
+ isMaster: false,
74
+ });
75
+ }
76
+ // member 申请后,将 member 展示在列表中
77
+ // 更新的是自己
78
+ await node.setFederated({
79
+ did: blocklet.appDid,
80
+ config: {
81
+ config: masterConfig,
82
+ sites,
83
+ },
84
+ });
85
+
86
+ // 将新增的数据返回给 member
87
+ res.json({
88
+ sites,
89
+ });
90
+ });
91
+
92
+ // step 2 审批(master 申批 member)
93
+ // core/state/lib/blocklet/manager/disk.js -> auditFederatedLogin
94
+ server.post(`${prefix}/audit-res`, ensureBlocklet(), verifyFederatedCall(), async (req, res) => {
95
+ const { blocklet } = req;
96
+ const { delegation, roles, appId, status } = req.body.verifyData;
97
+ const federated = cloneDeep(blocklet.settings.federated || {});
98
+ federated.config.delegation = delegation;
99
+ if (status === 'approved') {
100
+ const trustedPassports = blocklet.trustedPassports || [];
101
+ const hasTrustedPassport = trustedPassports.find((item) => item.issuerDid === appId);
102
+ if (!hasTrustedPassport) {
103
+ await node.configTrustedPassports({
104
+ teamDid: blocklet.meta.did,
105
+ trustedPassports: [
106
+ ...trustedPassports,
107
+ {
108
+ issuerDid: appId,
109
+ remark: 'Generated on join federated login',
110
+ mappings: roles.map((item) => {
111
+ return {
112
+ from: { passport: item.name },
113
+ to: { role: 'guest' },
114
+ };
115
+ }),
116
+ },
117
+ ],
118
+ });
119
+ }
120
+ }
121
+
122
+ await node.setFederated({
123
+ did: blocklet.meta.did,
124
+ config: federated,
125
+ });
126
+ res.json(federated);
127
+ });
128
+
129
+ // step 3 同步站点群信息(master 向 member 广播站点群信息,广播请求在 manager/disk.js 文件中 class FederatedBlockletManager 发起 )
130
+ // 该路由为 member 接受响应的 api(只允许 master 调用)
131
+ server.post(`${prefix}/sync`, ensureBlocklet(), verifyFederatedCall({ isMaster: true }), async (req, res) => {
132
+ const { sites } = req.body.verifyData;
133
+ const { blocklet } = req;
134
+ const federated = cloneDeep(blocklet.settings.federated || {});
135
+ federated.sites = sites;
136
+ await node.setFederated({
137
+ did: blocklet.meta.did,
138
+ config: federated,
139
+ });
140
+ res.json(federated);
141
+ });
142
+
143
+ // step 4 检测自动登录条件(member 向 master 发起请求)
144
+ server.post(
145
+ `${prefix}/prelogin`,
146
+ cors({ credentials: true, origin: true }),
147
+ ensureBlocklet(),
148
+ checkFederatedCorsCall(),
149
+ async (req, res) => {
150
+ const { blocklet } = req;
151
+
152
+ const teamDid = blocklet.meta.did;
153
+ let user = null;
154
+ if (req.user) {
155
+ user = { ...req.user };
156
+ const currentUser = await node.getUser({
157
+ teamDid,
158
+ user: {
159
+ did: req.user.did,
160
+ },
161
+ options: {
162
+ enableConnectedAccount: true,
163
+ },
164
+ });
165
+ user.avatar = getUserAvatarUrl(currentUser.avatar, blocklet);
166
+ }
167
+ const blockletInfo = await req.getBlockletInfo();
168
+ const site = {
169
+ appId: blockletInfo.wallet.address,
170
+ appPid: blockletInfo.permanentWallet.address,
171
+ appName: blockletInfo.name,
172
+ appDescription: blockletInfo.description,
173
+ appUrl: blockletInfo.appUrl,
174
+ appLogo:
175
+ blocklet.environmentObj.BLOCKLET_APP_LOGO ||
176
+ normalizePathPrefix(`${WELLKNOWN_SERVICE_PATH_PREFIX}/blocklet/logo`) ||
177
+ '/',
178
+ appLogoRect: blocklet.environmentObj.BLOCKLET_APP_LOGO_RECT,
179
+ did: blockletInfo.did,
180
+ };
181
+ res.json({ user, site });
182
+ }
183
+ );
184
+
185
+ // step 5 完成自动登录(member 向 master 请求)
186
+ server.post(
187
+ `${prefix}/login`,
188
+ cors({ credentials: true, origin: true }),
189
+ ensureBlocklet(),
190
+ checkFederatedCorsCall(),
191
+ async (req, res) => {
192
+ if (!req.user) {
193
+ res.status(401).send('Unauthorized');
194
+ return;
195
+ }
196
+ let data;
197
+ const { onlyWriteCookie = false } = req.body;
198
+
199
+ if (!onlyWriteCookie) {
200
+ const { blocklet } = req;
201
+ const { permanentWallet } = await req.getBlockletInfo();
202
+ const teamDid = blocklet.meta.did;
203
+ const federatedSites = blocklet.settings?.federated?.sites || [];
204
+ const loginSite = federatedSites.find((item) => item.appUrl === req.headers.origin);
205
+
206
+ const currentUser = await node.getUser({
207
+ teamDid,
208
+ user: {
209
+ did: req.user.did,
210
+ },
211
+ options: {
212
+ enableConnectedAccount: true,
213
+ },
214
+ });
215
+
216
+ const user = pick(currentUser, ['did', 'pk', 'fullName', 'locale']);
217
+ user.lastLoginIp = get(req, 'headers[x-real-ip]') || '';
218
+
219
+ if (currentUser.email) {
220
+ user.email = currentUser.email;
221
+ }
222
+ if (currentUser.avatar) {
223
+ user.avatar = getUserAvatarUrl(currentUser.avatar, blocklet);
224
+ }
225
+
226
+ try {
227
+ ({ data } = await api.post(`${loginSite.appUrl}${prefix}/token`, {
228
+ signer: permanentWallet.address,
229
+ data: signV2(permanentWallet.address, permanentWallet.secretKey, {
230
+ appId: teamDid,
231
+ role: req.user.role,
232
+ user,
233
+ passport: req.user.passport,
234
+ }),
235
+ }));
236
+ } catch {
237
+ res.status(500).send('Generate token error');
238
+ }
239
+ }
240
+
241
+ res.cookie('login_token', req.token, {
242
+ // HACK: 目前 sessionToken 的有效期就是 1h
243
+ maxAge: 60 * 60 * 1000,
244
+ expires: new Date(Date.now() + 60 * 60 * 1000),
245
+ sameSite: 'none',
246
+ secure: true,
247
+ });
248
+ res.json(data);
249
+ }
250
+ );
251
+
252
+ // step 6 发放自动登录 token(master 向 member 发起生成 token 请求)
253
+ server.post(`${prefix}/token`, ensureBlocklet(), verifyFederatedCall(), async (req, res) => {
254
+ const { user, appId, role, passport } = req.body.verifyData;
255
+ const { createSessionToken } = initJwt(node, options);
256
+ const createToken = createTokenFn(createSessionToken);
257
+ const { secret } = await req.getBlockletInfo();
258
+ const { blocklet } = req;
259
+ const teamDid = blocklet.meta.did;
260
+
261
+ const sessionConfig = blocklet.settings?.session || {};
262
+ const trustedPassports = blocklet.trustedPassports || [];
263
+ const masterPassport = trustedPassports.find((item) => item.issuerDid === appId);
264
+ const findMapping = masterPassport ? masterPassport.mappings.find((item) => item.from.passport === role) : null;
265
+ const targetPassport = findMapping
266
+ ? {
267
+ role: findMapping.to?.role || 'guest',
268
+ name: findMapping.to?.role || 'Guest',
269
+ id: passport?.id || '',
270
+ }
271
+ : { role: 'guest', name: 'Guest' };
272
+ const doc = await node.loginUser({
273
+ teamDid,
274
+ user: {
275
+ ...user,
276
+ // HACK: @zhanghan 这里会将 passport 插入到当前用户的 passport 列表中,federated 登录不应该插入 passport
277
+ // passport: findMapping ? targetPassport : null,
278
+ connectedAccount: {
279
+ provider: LOGIN_PROVIDER.FEDERATED,
280
+ id: appId,
281
+ did: user.did,
282
+ pk: user.pk,
283
+ },
284
+ },
285
+ });
286
+ const { sessionToken, refreshToken } = createToken(
287
+ doc.did,
288
+ {
289
+ secret,
290
+ role: targetPassport.role,
291
+ passport: targetPassport,
292
+ fullName: doc.fullName,
293
+ provider: LOGIN_PROVIDER.FEDERATED,
294
+ },
295
+ {
296
+ ...sessionConfig,
297
+ didConnectVersion: getDidConnectVersion(req),
298
+ }
299
+ );
300
+
301
+ res.json({ sessionToken, refreshToken });
302
+ });
303
+
304
+ // member 要求 master 退出登录
305
+ server.post(
306
+ `${prefix}/logout`,
307
+ cors({ credentials: true, origin: true }),
308
+ ensureBlocklet(),
309
+ checkFederatedCorsCall(),
310
+ (req, res) => {
311
+ res.clearCookie('login_token');
312
+ res.send('');
313
+ }
314
+ );
315
+
316
+ // member 主动调起 master 登录(实现登录 member 时,自动登录 master)
317
+
318
+ server.post(`${prefix}/loginByMember`, ensureBlocklet(), verifyFederatedCall(), async (req, res) => {
319
+ const { user, appId, passport } = req.body.verifyData;
320
+ const { createSessionToken } = initJwt(node, options);
321
+ const createToken = createTokenFn(createSessionToken);
322
+ const { secret } = await req.getBlockletInfo();
323
+ const { blocklet } = req;
324
+ const teamDid = blocklet.meta.did;
325
+
326
+ const sessionConfig = blocklet.settings?.session || {};
327
+ const prevUser = await node.getUser({
328
+ teamDid,
329
+ user: { did: user.did },
330
+ options: { enableConnectedAccount: true },
331
+ });
332
+ // HACK: member 调用 master 时,将 passport 的 role 还原为 master 中原有的 role
333
+ const targetPassport = passport?.id ? (prevUser?.passports || []).find((item) => item.id === passport.id) : null;
334
+ const doc = await node.loginUser({
335
+ teamDid,
336
+ user: {
337
+ ...user,
338
+ passport: targetPassport,
339
+ connectedAccount: {
340
+ provider: LOGIN_PROVIDER.WALLET,
341
+ id: appId,
342
+ did: user.did,
343
+ pk: user.pk,
344
+ },
345
+ },
346
+ });
347
+
348
+ const { sessionToken, refreshToken } = createToken(
349
+ doc.did,
350
+ {
351
+ secret,
352
+ passport: targetPassport,
353
+ role: targetPassport?.role || 'guest',
354
+ fullName: doc.fullName,
355
+ },
356
+ {
357
+ ...sessionConfig,
358
+ didConnectVersion: getDidConnectVersion(req),
359
+ }
360
+ );
361
+
362
+ res.json({ sessionToken, refreshToken });
363
+ });
364
+ },
365
+ };
@@ -1,7 +1,7 @@
1
1
  const { handleInvitationReceive, getApplicationInfo } = require('@abtnode/auth/lib/auth');
2
2
  const { upsertToPassports, createPassportSvg } = require('@abtnode/auth/lib/passport');
3
3
  const { WELLKNOWN_SERVICE_PATH_PREFIX, NODE_SERVICES, PASSPORT_STATUS } = require('@abtnode/constant');
4
- const { parseUserAvatar, extractUserAvatar } = require('@abtnode/util/lib/user');
4
+ const { extractUserAvatar, getUserAvatarUrl, getAppAvatarUrl } = require('@abtnode/util/lib/user');
5
5
  const { fromAppDid } = require('@arcblock/did-ext');
6
6
  const { getBlockletAppIdList } = require('@blocklet/meta/lib/util');
7
7
  const get = require('lodash/get');
@@ -198,11 +198,10 @@ async function invite(req, node, options) {
198
198
  });
199
199
  const { dataDir, name: applicationName } = await getApplicationInfo({ node, nodeInfo, teamDid });
200
200
  if (currentUser) {
201
- const avatar = await parseUserAvatar(currentUser.avatar, { did: teamDid, dataDir });
202
201
  profile = {
203
202
  email: currentUser.email,
204
203
  fullName: currentUser.fullName,
205
- avatar,
204
+ avatar: getUserAvatarUrl(baseUrl, currentUser.avatar),
206
205
  };
207
206
  userDid = currentUser.did;
208
207
  userPk = currentUser.pk;
@@ -213,7 +212,7 @@ async function invite(req, node, options) {
213
212
  profile = {
214
213
  email,
215
214
  fullName,
216
- avatar,
215
+ avatar: getUserAvatarUrl(baseUrl, avatar),
217
216
  };
218
217
  }
219
218
 
@@ -390,12 +389,12 @@ module.exports = {
390
389
  const userDid = req.user.did;
391
390
  const blocklet = await req.getBlockletInfo();
392
391
  const nodeInfo = await req.getNodeInfo();
393
- const { did: teamDid, wallet: blockletWallet } = blocklet;
394
- const { dataDir, passportColor } = await getApplicationInfo({ node, nodeInfo, teamDid });
392
+ const { did: teamDid, wallet: blockletWallet, appUrl } = blocklet;
393
+ const { passportColor } = await getApplicationInfo({ node, nodeInfo, teamDid });
395
394
  const issuerDidList = uniq([blockletWallet.address, ...getBlockletAppIdList(blocklet)]);
396
395
  // NOTICE: 这里获取的 did 是当前登录用户的永久 did,无需查询 connectedAccount
397
396
  const user = await node.getUser({ teamDid, user: { did: userDid } });
398
- const ownerAvatarUrl = await parseUserAvatar(user?.avatar, { dataDir });
397
+ const ownerAvatarUrl = getUserAvatarUrl(appUrl, user.avatar);
399
398
  const { passports = [] } = user || {};
400
399
  // NOTICE: 保持每一种 role 的 passport 只有一个即可
401
400
  const passportTypes = uniqBy(
@@ -417,7 +416,9 @@ module.exports = {
417
416
  title: x.title,
418
417
  issuer: x.issuer.name,
419
418
  issuerDid: x.issuer.id,
419
+ issuerAvatarUrl: getAppAvatarUrl(appUrl),
420
420
  ownerName: user?.fullName,
421
+ ownerDid: userDid,
421
422
  ownerAvatarUrl,
422
423
  isDataUrl: true,
423
424
  preferredColor: passportColor || 'auto',
@@ -36,7 +36,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
36
36
  };
37
37
  },
38
38
 
39
- signature: async ({ extraParams, context: { request, didwallet } }) => {
39
+ signature: async ({ extraParams, context: { request, baseUrl, didwallet } }) => {
40
40
  const { locale, inviteId } = extraParams;
41
41
  checkWalletVersion({ didwallet, locale });
42
42
  const nodeInfo = await request.getNodeInfo();
@@ -48,6 +48,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
48
48
  teamDid,
49
49
  inviteId,
50
50
  locale,
51
+ baseUrl,
51
52
  });
52
53
  },
53
54
  },
@@ -20,19 +20,13 @@ module.exports = function createRoutes(node) {
20
20
  },
21
21
 
22
22
  claims: {
23
- signature: async ({ extraParams, context: { request, didwallet } }) => {
23
+ signature: async ({ extraParams, context: { request, baseUrl, didwallet } }) => {
24
24
  const { id, locale } = extraParams;
25
25
  checkWalletVersion({ didwallet, locale });
26
26
  const nodeInfo = await node.getNodeInfo();
27
27
  const teamDid = request.headers['x-blocklet-did'];
28
28
 
29
- return createIssuePassportRequest({
30
- node,
31
- nodeInfo,
32
- teamDid,
33
- id,
34
- locale,
35
- });
29
+ return createIssuePassportRequest({ node, nodeInfo, teamDid, id, locale, baseUrl });
36
30
  },
37
31
  },
38
32
 
@@ -36,7 +36,15 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
36
36
  action: 'login',
37
37
  });
38
38
 
39
- await updateSession({ sessionToken: result.sessionToken, refreshToken: result.refreshToken }, true);
39
+ await updateSession(
40
+ {
41
+ sessionToken: result.sessionToken,
42
+ refreshToken: result.refreshToken,
43
+ federatedSessionToken: result.federatedSessionToken || '',
44
+ federatedRefreshToken: result.federatedRefreshToken || '',
45
+ },
46
+ true
47
+ );
40
48
 
41
49
  return result;
42
50
  } catch (err) {
@@ -203,7 +203,8 @@ module.exports = function createRoutes(node, _, createSessionToken) {
203
203
  passportColor,
204
204
  dataDir,
205
205
  secret,
206
- } = await getApplicationInfo({ node, teamDid: appPid });
206
+ logo,
207
+ } = await getApplicationInfo({ node, teamDid: appPid, baseUrl });
207
208
 
208
209
  const statusEndpointBaseUrl = baseUrl;
209
210
  const endpoint = baseUrl;
@@ -211,6 +212,7 @@ module.exports = function createRoutes(node, _, createSessionToken) {
211
212
  const vcParams = {
212
213
  issuerName,
213
214
  issuerWallet,
215
+ issuerAvatarUrl: logo,
214
216
  ownerDid: userDid,
215
217
  passport: await createPassport({
216
218
  name: ROLES.OWNER,
@@ -3,6 +3,7 @@ const joinUrl = require('url-join');
3
3
  const SealedBox = require('tweetnacl-sealedbox-js');
4
4
  const { decodeEncryptionKey } = require('@abtnode/util/lib/security');
5
5
  const { WELLKNOWN_SERVICE_PATH_PREFIX, USER_AVATAR_URL_PREFIX, USER_AVATAR_PATH_PREFIX } = require('@abtnode/constant');
6
+ const { LOGIN_PROVIDER } = require('@blocklet/constant');
6
7
 
7
8
  const { PREFIXES } = require('../../util/constants');
8
9
  const { createTokenFn, getDidConnectVersion } = require('../../util');
@@ -62,6 +63,7 @@ module.exports = {
62
63
  passport: req.user.passport,
63
64
  role: req.user.role,
64
65
  fullName: user.fullName,
66
+ provider: req.user.provider || LOGIN_PROVIDER.WALLET,
65
67
  },
66
68
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
67
69
  );
@@ -77,7 +79,7 @@ module.exports = {
77
79
  }
78
80
  }
79
81
 
80
- res.json({ user, nextToken, nextRefreshToken });
82
+ res.json({ user, nextToken, nextRefreshToken, provider: req.user.provider || LOGIN_PROVIDER.WALLET });
81
83
  };
82
84
 
83
85
  const sessionApi = `${prefix}/api/did/session`;
@@ -1,7 +1,7 @@
1
1
  const get = require('lodash/get');
2
2
  const { WsServer } = require('@arcblock/ws');
3
3
  const { WELLKNOWN_SERVICE_PATH_PREFIX, ROLES, EVENTS } = require('@abtnode/constant');
4
- const { createStreamLogManager, getLogFiles } = require('@abtnode/util/lib/log');
4
+ const { createStreamLogManager, getLogFiles } = require('@abtnode/core/lib/util/log');
5
5
  const { BlockletEvents } = require('@blocklet/constant');
6
6
  const eventHub =
7
7
  process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');