@abtnode/blocklet-services 1.16.18-beta-adeeb0b3 → 1.16.18-beta-aa01bd8e

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 (92) hide show
  1. package/api/index.js +1 -0
  2. package/api/libs/connect/session.js +45 -33
  3. package/api/middlewares/check-running.js +1 -1
  4. package/api/routes/blocklet.js +18 -0
  5. package/api/routes/federated.js +10 -9
  6. package/api/routes/oauth.js +79 -60
  7. package/api/routes/user-session.js +23 -16
  8. package/api/routes/user.js +160 -22
  9. package/api/services/auth/connect/invite.js +21 -12
  10. package/api/util/federated.js +13 -12
  11. package/api/validators/login.js +12 -0
  12. package/build/asset-manifest.json +100 -80
  13. package/build/index.html +1 -1
  14. package/build/service-worker.js +1 -1
  15. package/build/service-worker.js.map +1 -1
  16. package/build/static/css/{807.65f26433.chunk.css → 4448.de9040c4.chunk.css} +1 -1
  17. package/build/static/js/1.138935fc.chunk.js +2 -0
  18. package/build/static/js/{1148.4b2a7347.chunk.js → 1148.e614f706.chunk.js} +2 -2
  19. package/build/static/js/1343.69031e0b.chunk.js +2 -0
  20. package/build/static/js/1581.ed4544c6.chunk.js +2 -0
  21. package/build/static/js/2026.514f995a.chunk.js +2 -0
  22. package/build/static/js/{2291.7ffdc7df.chunk.js → 2291.37b0ad3a.chunk.js} +2 -2
  23. package/build/static/js/{3490.4d3a51ea.chunk.js → 2362.ab5308a8.chunk.js} +2 -2
  24. package/build/static/js/2506.dd9284b6.chunk.js +2 -0
  25. package/build/static/js/{2838.fcdea2fa.chunk.js → 2838.ec459fda.chunk.js} +3 -3
  26. package/build/static/js/{3025.a48c96f5.chunk.js → 3025.aa129833.chunk.js} +2 -2
  27. package/build/static/js/3076.28658ffc.chunk.js +2 -0
  28. package/build/static/js/3683.6f169a32.chunk.js +2 -0
  29. package/build/static/js/3920.5c63a2b9.chunk.js +3 -0
  30. package/build/static/js/3979.f9a5aa48.chunk.js +3 -0
  31. package/build/static/js/{807.249d2d01.chunk.js.LICENSE.txt → 3979.f9a5aa48.chunk.js.LICENSE.txt} +0 -18
  32. package/build/static/js/3994.e53e7ce2.chunk.js +2 -0
  33. package/build/static/js/4009.65d1c083.chunk.js +2 -0
  34. package/build/static/js/{4023.1658794f.chunk.js → 4023.a2e9db00.chunk.js} +2 -2
  35. package/build/static/js/4247.c25f1945.chunk.js +2 -0
  36. package/build/static/js/{4319.8d9e189e.chunk.js → 4319.9f120992.chunk.js} +2 -2
  37. package/build/static/js/4448.f0c62086.chunk.js +3 -0
  38. package/build/static/js/4448.f0c62086.chunk.js.LICENSE.txt +17 -0
  39. package/build/static/js/4461.26253c6a.chunk.js +2 -0
  40. package/build/static/js/4802.cd83ecef.chunk.js +2 -0
  41. package/build/static/js/4882.0435e418.chunk.js +2 -0
  42. package/build/static/js/5547.8447edf9.chunk.js +3 -0
  43. package/build/static/js/556.4d5cc702.chunk.js +3 -0
  44. package/build/static/js/{5683.47011724.chunk.js → 5683.051a03c1.chunk.js} +2 -2
  45. package/build/static/js/6032.48c0a152.chunk.js +2 -0
  46. package/build/static/js/6139.5867193a.chunk.js +2 -0
  47. package/build/static/js/655.cdee65b4.chunk.js +2 -0
  48. package/build/static/js/{6771.a1510398.chunk.js → 6771.920fa5b6.chunk.js} +3 -3
  49. package/build/static/js/7006.bb90b167.chunk.js +2 -0
  50. package/build/static/js/779.383b4b4a.chunk.js +2 -0
  51. package/build/static/js/{7832.741ac84f.chunk.js → 7832.81aaf011.chunk.js} +2 -2
  52. package/build/static/js/{7858.e4167dfd.chunk.js → 7858.4e5b7c88.chunk.js} +2 -2
  53. package/build/static/js/8181.86477cc5.chunk.js +2 -0
  54. package/build/static/js/8604.ece06cf7.chunk.js +3 -0
  55. package/build/static/js/{8622.f9639db9.chunk.js → 8622.66a81bc0.chunk.js} +2 -2
  56. package/build/static/js/8944.07bcf75f.chunk.js +2 -0
  57. package/build/static/js/8983.19b79a23.chunk.js +2 -0
  58. package/build/static/js/9017.56c20b17.chunk.js +2 -0
  59. package/build/static/js/9582.2c539fcf.chunk.js +2 -0
  60. package/build/static/js/9880.13ac9520.chunk.js +2 -0
  61. package/build/static/js/9996.5545ea26.chunk.js +2 -0
  62. package/build/static/js/main.63103d24.js +3 -0
  63. package/build/static/js/{main.50d5cec4.js.LICENSE.txt → main.63103d24.js.LICENSE.txt} +1 -1
  64. package/package.json +34 -34
  65. package/build/static/js/1431.29b0bc0a.chunk.js +0 -3
  66. package/build/static/js/2093.3ce9b59d.chunk.js +0 -3
  67. package/build/static/js/2686.890b32ed.chunk.js +0 -2
  68. package/build/static/js/4022.5ec79b56.chunk.js +0 -2
  69. package/build/static/js/4461.f412553b.chunk.js +0 -2
  70. package/build/static/js/4802.fe56c787.chunk.js +0 -2
  71. package/build/static/js/5465.dd0f7a20.chunk.js +0 -2
  72. package/build/static/js/5547.5a341867.chunk.js +0 -3
  73. package/build/static/js/5662.03f06ae0.chunk.js +0 -2
  74. package/build/static/js/5673.0dd67df6.chunk.js +0 -2
  75. package/build/static/js/5960.35db200d.chunk.js +0 -2
  76. package/build/static/js/6139.cabc22a2.chunk.js +0 -2
  77. package/build/static/js/6498.698608f8.chunk.js +0 -2
  78. package/build/static/js/6868.881bd141.chunk.js +0 -2
  79. package/build/static/js/7006.8f0645e5.chunk.js +0 -2
  80. package/build/static/js/7367.15383006.chunk.js +0 -2
  81. package/build/static/js/779.b64e7db1.chunk.js +0 -2
  82. package/build/static/js/807.249d2d01.chunk.js +0 -3
  83. package/build/static/js/8604.a8ef404e.chunk.js +0 -3
  84. package/build/static/js/8641.506d61d5.chunk.js +0 -2
  85. package/build/static/js/8944.2d60df14.chunk.js +0 -2
  86. package/build/static/js/main.50d5cec4.js +0 -3
  87. /package/build/static/js/{2838.fcdea2fa.chunk.js.LICENSE.txt → 2838.ec459fda.chunk.js.LICENSE.txt} +0 -0
  88. /package/build/static/js/{2093.3ce9b59d.chunk.js.LICENSE.txt → 3920.5c63a2b9.chunk.js.LICENSE.txt} +0 -0
  89. /package/build/static/js/{5547.5a341867.chunk.js.LICENSE.txt → 5547.8447edf9.chunk.js.LICENSE.txt} +0 -0
  90. /package/build/static/js/{1431.29b0bc0a.chunk.js.LICENSE.txt → 556.4d5cc702.chunk.js.LICENSE.txt} +0 -0
  91. /package/build/static/js/{6771.a1510398.chunk.js.LICENSE.txt → 6771.920fa5b6.chunk.js.LICENSE.txt} +0 -0
  92. /package/build/static/js/{8604.a8ef404e.chunk.js.LICENSE.txt → 8604.ece06cf7.chunk.js.LICENSE.txt} +0 -0
@@ -1,5 +1,5 @@
1
1
  const { NODE_SERVICES, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
2
- const { getApplicationInfo, upsertUserSession } = require('@abtnode/auth/lib/auth');
2
+ const { getApplicationInfo } = require('@abtnode/auth/lib/auth');
3
3
  const { fromAppDid } = require('@arcblock/did-ext');
4
4
  const { extractUserAvatar } = require('@abtnode/util/lib/user');
5
5
  const formatContext = require('@abtnode/util/lib/format-context');
@@ -7,12 +7,15 @@ const createTranslator = require('@abtnode/util/lib/translate');
7
7
  const logger = require('@abtnode/logger')('blocklet-services:user');
8
8
  const { isFromPublicKey } = require('@arcblock/did');
9
9
  const { LOGIN_PROVIDER } = require('@blocklet/constant');
10
+ const { fromPublicKey } = require('@ocap/wallet');
11
+ const sortBy = require('lodash/sortBy');
12
+ const head = require('lodash/head');
10
13
 
11
14
  const { isInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../util');
12
15
  const initJwt = require('../libs/jwt');
13
16
  const { getAvatarByUrl } = require('../libs/auth/utils');
14
17
  const { ApiError } = require('../util/error');
15
- const { loginWalletSchema, loginOAuthSchema } = require('../validators/login');
18
+ const { loginWalletSchema, loginOAuthSchema, loginUserWalletSchema } = require('../validators/login');
16
19
  const verifySig = require('../middlewares/verify-sig');
17
20
  const { getAvatarByEmail } = require('../libs/auth/utils');
18
21
  const ensureBlocklet = require('../middlewares/ensure-blocklet');
@@ -213,7 +216,6 @@ async function loginOAuth(
213
216
  if (!validateUser(loginParams.user) || !validateUser(loginParams.user.connectedAccount)) {
214
217
  throw new ApiError(400, t('userInfoError', locale));
215
218
  }
216
- // TODO: @zhanghan 暂不支持统一登录模式登录
217
219
  const doc = await node.loginUser(loginParams);
218
220
  return doc;
219
221
  }
@@ -240,14 +242,14 @@ async function login(req, node, options) {
240
242
  const { did: teamDid, wallet: blockletWallet, secret } = await req.getBlockletInfo();
241
243
  const blocklet = await req.getBlocklet();
242
244
 
243
- let doc;
245
+ let userDoc;
244
246
  if (provider === LOGIN_PROVIDER.WALLET) {
245
- doc = await loginWallet(
247
+ userDoc = await loginWallet(
246
248
  { did, pk, avatar, email, fullName },
247
249
  { node, req, locale, componentId, teamDid, updateInfo, sourceAppPid }
248
250
  );
249
251
  } else {
250
- doc = await loginOAuth(
252
+ userDoc = await loginOAuth(
251
253
  { provider, id, avatar, email, fullName },
252
254
  { node, req, locale, componentId, teamDid, blockletWallet, updateInfo, sourceAppPid }
253
255
  );
@@ -259,9 +261,9 @@ async function login(req, node, options) {
259
261
  await node.createAuditLog(
260
262
  {
261
263
  action: 'login',
262
- args: { teamDid, userDid: doc.did, passport, provider },
263
- context: formatContext(Object.assign(req, { user: doc })),
264
- result: doc,
264
+ args: { teamDid, userDid: userDoc.did, passport, provider },
265
+ context: formatContext(Object.assign(req, { user: userDoc })),
266
+ result: userDoc,
265
267
  },
266
268
  node
267
269
  );
@@ -271,35 +273,66 @@ async function login(req, node, options) {
271
273
  const createToken = createTokenFn(createSessionToken);
272
274
  const sessionConfig = blocklet.settings?.session || {};
273
275
  const { sessionToken, refreshToken } = createToken(
274
- doc.did,
276
+ userDoc.did,
275
277
  {
276
278
  secret,
277
279
  passport,
278
280
  role: passport.role,
279
- fullName: doc.fullName,
281
+ fullName: userDoc.fullName,
280
282
  provider,
281
283
  walletOS: 'api',
282
284
  },
283
285
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
284
286
  );
285
- const userSession = await upsertUserSession(
286
- {
287
- visitorId,
288
- teamDid,
289
- userDid: doc.did,
290
- appPid: teamDid,
291
- status: 'online',
292
- },
293
- { req, node }
294
- );
287
+ const lastLoginIp = req.headers['x-real-ip'];
288
+ const ua = req.headers['user-agent'];
289
+ const userSession = await node.upsertUserSession({
290
+ visitorId,
291
+ teamDid,
292
+ userDid: userDoc.did,
293
+ appPid: teamDid,
294
+ status: 'online',
295
+ ua,
296
+ lastLoginIp,
297
+ });
298
+ node.syncUserSession({
299
+ teamDid,
300
+ userDid: userDoc.did,
301
+ visitorId: userSession.visitorId,
302
+ passportId: passport?.id,
303
+ targetAppPid: sourceAppPid,
304
+ ua,
305
+ lastLoginIp,
306
+ });
295
307
  return {
296
- user: doc,
308
+ user: userDoc,
297
309
  token: sessionToken,
298
310
  refreshToken,
299
311
  visitorId: userSession?.visitorId || '',
300
312
  };
301
313
  }
302
314
 
315
+ async function verifyUserSig({ userDid, signature, teamDid, data }, { node }) {
316
+ const currentUser = await node.getUser({
317
+ teamDid,
318
+ user: {
319
+ did: userDid,
320
+ },
321
+ options: {
322
+ enableConnectedAccount: true,
323
+ },
324
+ });
325
+ if (!currentUser) {
326
+ throw new Error('user is not exist');
327
+ }
328
+ const userWallet = fromPublicKey(currentUser.pk);
329
+ const valid = userWallet.verify(data, signature);
330
+ if (!valid) {
331
+ throw new Error('invalid signature');
332
+ }
333
+ return currentUser;
334
+ }
335
+
303
336
  module.exports = {
304
337
  init(server, node, options) {
305
338
  async function loginFn(req, res) {
@@ -318,6 +351,111 @@ module.exports = {
318
351
  server.post(`${prefix}/login`, verifySig, loginFn);
319
352
  server.post(`${prefixApi}/login`, verifySig, loginFn);
320
353
 
354
+ /**
355
+ * @description 用于在 native 钱包中完成用户的自动登录
356
+ * @summary 暂时不允许用户注册,只允许登录
357
+ */
358
+ server.post(`${prefixApi}/loginByWallet`, async (req, res) => {
359
+ const { userDid, signature, walletOS, nonce, visitorId, passportId, sourceAppPid, locale } = req.body;
360
+ const { error } = loginUserWalletSchema.validate({
361
+ userDid,
362
+ signature,
363
+ walletOS,
364
+ nonce,
365
+ visitorId,
366
+ passportId,
367
+ sourceAppPid,
368
+ locale,
369
+ });
370
+ if (error) {
371
+ throw new ApiError(400, error.message);
372
+ }
373
+ const { did: teamDid, secret } = await req.getBlockletInfo();
374
+ const currentUser = await verifyUserSig({ userDid, signature, teamDid, data: nonce }, { node });
375
+ const { createSessionToken } = initJwt(node, options);
376
+ const createToken = createTokenFn(createSessionToken);
377
+ const blocklet = await req.getBlocklet();
378
+ const sessionConfig = blocklet.settings?.session || {};
379
+ const passports = currentUser?.passports || [];
380
+
381
+ let passport = null;
382
+ if (passportId) {
383
+ passport = passports.find((x) => x.passportId === passportId);
384
+ }
385
+ if (!passport) {
386
+ const now = new Date().getTime();
387
+ passport = head(
388
+ sortBy(passports, (x) => {
389
+ const lastLoginAt = new Date(x.lastLoginAt).getTime();
390
+ if (typeof lastLoginAt === 'number') {
391
+ return now - lastLoginAt;
392
+ }
393
+ return now;
394
+ })
395
+ );
396
+ }
397
+
398
+ if (!passport) {
399
+ passport = { name: 'Guest', role: 'guest' };
400
+ }
401
+
402
+ const lastLoginIp = req.get('x-real-ip');
403
+ const loginedUser = await node.loginUser({
404
+ teamDid,
405
+ user: {
406
+ did: currentUser.did,
407
+ pk: currentUser.pk,
408
+ locale,
409
+ lastLoginIp,
410
+ sourceAppPid,
411
+ connectedAccount: {
412
+ provider: LOGIN_PROVIDER.WALLET,
413
+ did: currentUser.did,
414
+ pk: currentUser.pk,
415
+ },
416
+ },
417
+ });
418
+
419
+ const { sessionToken, refreshToken } = createToken(
420
+ loginedUser.did,
421
+ {
422
+ secret,
423
+ passport,
424
+ role: passport?.role || 'guest',
425
+ fullName: loginedUser.fullName,
426
+ provider: 'wallet',
427
+ walletOS,
428
+ },
429
+ { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
430
+ );
431
+ const ua = req.headers['user-agent'];
432
+ const userSession = await node.upsertUserSession({
433
+ visitorId,
434
+ teamDid,
435
+ userDid: loginedUser.did,
436
+ appPid: teamDid,
437
+ status: 'online',
438
+ ua,
439
+ lastLoginIp,
440
+ });
441
+ node.syncUserSession({
442
+ teamDid,
443
+ userDid,
444
+ visitorId: userSession.visitorId,
445
+ passportId,
446
+ targetAppPid: sourceAppPid,
447
+ ua,
448
+ lastLoginIp,
449
+ });
450
+
451
+ res.json({
452
+ sessionToken,
453
+ refreshToken,
454
+ nonce,
455
+ visitorId: userSession.visitorId,
456
+ });
457
+ });
458
+
321
459
  server.post(`${prefixApi}/logout`, ensureBlocklet(), async (req, res) => {
322
460
  if (req.user) {
323
461
  const { blocklet } = req;
@@ -6,7 +6,6 @@ const {
6
6
  messages,
7
7
  checkWalletVersion,
8
8
  beforeInvitationRequest,
9
- upsertUserSession,
10
9
  } = require('@abtnode/auth/lib/auth');
11
10
  const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
12
11
  const { NODE_SERVICES, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
@@ -98,17 +97,27 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
98
97
  { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
99
98
  );
100
99
 
101
- const userSessionDoc = await upsertUserSession(
102
- {
103
- teamDid,
104
- visitorId,
105
- userDid,
106
- appPid: teamDid,
107
- passportId: response.data.id,
108
- status: 'online',
109
- },
110
- { req, node, sourceAppPid }
111
- );
100
+ const lastLoginIp = req.headers['x-real-ip'];
101
+ const ua = req.headers['user-agent'];
102
+ const userSessionDoc = await node.upsertUserSession({
103
+ teamDid,
104
+ visitorId,
105
+ userDid,
106
+ appPid: teamDid,
107
+ passportId: response.data.id,
108
+ status: 'online',
109
+ ua,
110
+ lastLoginIp,
111
+ });
112
+ node.syncUserSession({
113
+ teamDid,
114
+ userDid,
115
+ visitorId: userSessionDoc.visitorId,
116
+ passportId: passport?.id,
117
+ targetAppPid: sourceAppPid,
118
+ ua,
119
+ lastLoginIp,
120
+ });
112
121
  await updateSession(
113
122
  {
114
123
  sessionToken,
@@ -6,18 +6,6 @@ const { signV2 } = require('@arcblock/jwt');
6
6
  const { api } = require('../libs/api');
7
7
  const { getDidConnectVersion } = require('./index');
8
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
- }
20
-
21
9
  function getFederatedMaster(blocklet) {
22
10
  const { sites } = blocklet?.settings?.federated || {};
23
11
  const masterSite = (sites || []).find((item) => isMaster(item));
@@ -114,6 +102,19 @@ async function loginByMember({ blockletInfo, blocklet, request, user, passport }
114
102
  return null;
115
103
  }
116
104
 
105
+ function shouldSyncFederated(sourceAppPid, blocklet) {
106
+ if (sourceAppPid) {
107
+ return true;
108
+ }
109
+
110
+ const masterSite = getFederatedMaster(blocklet);
111
+ if (masterSite && blocklet && masterSite.appPid === blocklet.appPid) {
112
+ return true;
113
+ }
114
+
115
+ return false;
116
+ }
117
+
117
118
  module.exports = {
118
119
  isMaster,
119
120
  shouldSyncFederated,
@@ -18,5 +18,17 @@ const loginOAuthSchema = Joi.object({
18
18
  fullName: Joi.string().optional(),
19
19
  }).empty(null);
20
20
 
21
+ const loginUserWalletSchema = Joi.object({
22
+ userDid: Joi.DID().trim().required(),
23
+ signature: Joi.string().required(),
24
+ walletOS: Joi.string().required(),
25
+ nonce: Joi.string().required(),
26
+ visitorId: Joi.string().optional(),
27
+ passportId: Joi.string().optional(),
28
+ sourceAppPid: Joi.DID().trim().optional(),
29
+ locale: Joi.string().optional(),
30
+ }).empty(null);
31
+
21
32
  exports.loginWalletSchema = loginWalletSchema;
33
+ exports.loginUserWalletSchema = loginUserWalletSchema;
22
34
  exports.loginOAuthSchema = loginOAuthSchema;