@abtnode/blocklet-services 1.17.3-beta-20251119-034511-f26047c0 → 1.17.3-beta-20251119-102907-28b69b76

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.
@@ -30,6 +30,7 @@ const { createOrgValidators } = require('@abtnode/core/lib/util/org');
30
30
  const { isAllowedURL } = require('@abtnode/util/lib/ssrf-protector');
31
31
 
32
32
  const { getApplicationWallet } = require('@blocklet/meta/lib/wallet');
33
+ const dayjs = require('@abtnode/util/lib/dayjs');
33
34
  const { createTokenFn, getDidConnectVersion } = require('../../util');
34
35
  const checkUser = require('../../middlewares/check-user');
35
36
  const cache = require('../../cache');
@@ -337,194 +338,213 @@ module.exports = {
337
338
  res.json({ success: true });
338
339
  });
339
340
 
340
- router.post(`${WELLKNOWN_SERVICE_PATH_PREFIX}/api/did/refreshSession`, refreshBearerToken, async (req, res) => {
341
- const token = req.refreshToken;
342
- if (token) {
343
- const teamDid = req.getBlockletDid();
344
- const blocklet = await req.getBlocklet();
345
- if (blocklet.settings?.session?.enableBlacklist) {
346
- const cacheData = await cache.refreshToken.get(md5(token));
347
- if (cacheData?.block) {
348
- res.status(400).send(t('userSessionLogout', req.blockletLocale));
349
- return;
341
+ router.post(
342
+ `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/did/refreshSession`,
343
+ refreshBearerToken,
344
+ /**
345
+ * @description 刷新 session token
346
+ * @param {import('express').Request} req
347
+ * @param {import('express').Response} res
348
+ * @returns {Promise<void>}
349
+ *
350
+ */
351
+ async (req, res) => {
352
+ const token = req.refreshToken;
353
+ if (token) {
354
+ const teamDid = req.getBlockletDid();
355
+ const blocklet = await req.getBlocklet();
356
+ if (blocklet.settings?.session?.enableBlacklist) {
357
+ const cacheData = await cache.refreshToken.get(md5(token));
358
+ if (cacheData?.block) {
359
+ res.status(400).send(t('userSessionLogout', req.blockletLocale));
360
+ return;
361
+ }
350
362
  }
351
- }
352
- const visitorId = req.get('x-blocklet-visitor-id');
353
- const ua = req.get('user-agent');
354
- // FIXME: @zhanghan BlockletSDK 和 Aistro 来的请求暂时不需要检查 visitorId,需要在 aistro 适配新的逻辑
355
- if (!(isAistroUserAgent(ua) || isBlockletSDKUserAgent(ua))) {
356
- if (!visitorId) {
363
+ const visitorId = req.get('x-blocklet-visitor-id');
364
+ const ua = req.get('user-agent');
365
+ // FIXME: @zhanghan BlockletSDK 和 Aistro 来的请求暂时不需要检查 visitorId,需要在 aistro 适配新的逻辑
366
+ if (!(isAistroUserAgent(ua) || isBlockletSDKUserAgent(ua))) {
367
+ if (!visitorId) {
368
+ res.status(400).send(t('userSessionLogout', req.blockletLocale));
369
+ return;
370
+ }
371
+ }
372
+ const { appPid = teamDid } = req.query;
373
+ // FIXME: @zhanghan BlockletSDK 和 Aistro 来的请求暂时不需要检查 visitorId,需要在 aistro 适配新的逻辑
374
+ if (isAistroUserAgent(ua) || isBlockletSDKUserAgent(ua)) {
375
+ await req.ensureUser({ token, appPid });
376
+ } else {
377
+ await req.ensureUser({ token, visitorId, appPid });
378
+ }
379
+ if (!req.user) {
357
380
  res.status(400).send(t('userSessionLogout', req.blockletLocale));
358
381
  return;
359
382
  }
360
- }
361
- const { appPid = teamDid } = req.query;
362
- // FIXME: @zhanghan BlockletSDK 和 Aistro 来的请求暂时不需要检查 visitorId,需要在 aistro 适配新的逻辑
363
- if (isAistroUserAgent(ua) || isBlockletSDKUserAgent(ua)) {
364
- await req.ensureUser({ token, appPid });
365
- } else {
366
- await req.ensureUser({ token, visitorId, appPid });
367
- }
368
- if (!req.user) {
369
- res.status(400).send(t('userSessionLogout', req.blockletLocale));
370
- return;
371
- }
372
383
 
373
- try {
374
- const blockletInfo = await req.getBlockletInfo();
375
-
376
- const refreshTokenType = 'refresh';
377
- const {
378
- did: userPid, // 从 token 拿到的 did 就是 userPid
379
- role,
380
- passport,
381
- provider = LOGIN_PROVIDER.WALLET,
382
- walletOS,
383
- org, // 从 token 拿到的 orgId
384
- } = await verifySessionToken(token, blockletInfo.secret, {
385
- checkFromDb: true,
386
- teamDid,
387
- checkToken: (_token) => {
388
- if (_token.tokenType !== refreshTokenType) {
389
- throw new Error(`invalid token type ${_token.tokenType}`);
390
- }
391
- },
392
- locale: req.blockletLocale,
393
- });
384
+ try {
385
+ const blockletInfo = await req.getBlockletInfo();
386
+
387
+ const refreshTokenType = 'refresh';
388
+ const {
389
+ did: userPid, // 从 token 拿到的 did 就是 userPid
390
+ role,
391
+ passport,
392
+ provider = LOGIN_PROVIDER.WALLET,
393
+ walletOS,
394
+ org, // 从 token 拿到的 orgId
395
+ } = await verifySessionToken(token, blockletInfo.secret, {
396
+ checkFromDb: true,
397
+ teamDid,
398
+ checkToken: (_token) => {
399
+ if (_token.tokenType !== refreshTokenType) {
400
+ throw new Error(`invalid token type ${_token.tokenType}`);
401
+ }
402
+ },
403
+ locale: req.blockletLocale,
404
+ });
394
405
 
395
- const user = await node.getUser({ teamDid, user: { did: userPid } });
396
-
397
- if (role) {
398
- const rbac = await node.getRBAC(teamDid);
399
- user.permissions = await rbac.getScope(role);
400
- user.role = role;
401
- // 根据 role 获取所在的 org 信息
402
- const { getOrgSettings } = createOrgValidators(blocklet);
403
- const orgSettings = getOrgSettings();
404
- if (orgSettings?.enabled) {
405
- try {
406
- const roleInfo = await node.getRole({ teamDid, role: { name: user.role } });
407
- if (roleInfo?.orgId) {
408
- const orgInfo = await node.getOrg({ teamDid, id: roleInfo?.orgId }, { user: req.user });
409
- user.org = orgInfo || null;
406
+ const user = await node.getUser({ teamDid, user: { did: userPid } });
407
+
408
+ if (role) {
409
+ const rbac = await node.getRBAC(teamDid);
410
+ user.permissions = await rbac.getScope(role);
411
+ user.role = role;
412
+ // 根据 role 获取所在的 org 信息
413
+ const { getOrgSettings } = createOrgValidators(blocklet);
414
+ const orgSettings = getOrgSettings();
415
+ if (orgSettings?.enabled) {
416
+ try {
417
+ const roleInfo = await node.getRole({ teamDid, role: { name: user.role } });
418
+ if (roleInfo?.orgId) {
419
+ const orgInfo = await node.getOrg({ teamDid, id: roleInfo?.orgId }, { user: req.user });
420
+ user.org = orgInfo || null;
421
+ }
422
+ } catch (err) {
423
+ logger.error('get role error', err);
410
424
  }
411
- } catch (err) {
412
- logger.error('get role error', err);
413
425
  }
414
426
  }
415
- }
416
427
 
417
- if (user.avatar && user.avatar.startsWith(USER_AVATAR_URL_PREFIX)) {
418
- user.avatar = `${WELLKNOWN_SERVICE_PATH_PREFIX}${USER_AVATAR_PATH_PREFIX}/${
419
- user.avatar.split('/').slice(-1)[0]
420
- }`;
428
+ if (user.avatar && user.avatar.startsWith(USER_AVATAR_URL_PREFIX)) {
429
+ user.avatar = `${WELLKNOWN_SERVICE_PATH_PREFIX}${USER_AVATAR_PATH_PREFIX}/${
430
+ user.avatar.split('/').slice(-1)[0]
431
+ }`;
421
432
 
422
- if (req.get('x-avatar-host') === '1') {
423
- const appUrl = blocklet.environmentObj.BLOCKLET_APP_URL;
424
- user.avatar = joinURL(appUrl, user.avatar);
433
+ if (req.get('x-avatar-host') === '1') {
434
+ const appUrl = blocklet.environmentObj.BLOCKLET_APP_URL;
435
+ user.avatar = joinURL(appUrl, user.avatar);
436
+ }
425
437
  }
426
- }
427
438
 
428
- const sessionConfig = blocklet.settings?.session || {};
429
- let userOrg = org;
430
- if (!userOrg) {
431
- userOrg = await req.getUserOrg(role);
432
- }
433
- const { sessionToken, refreshToken } = createToken(
434
- userPid,
435
- {
436
- secret: blockletInfo.secret,
437
- passport,
438
- role,
439
- fullName: user.fullName,
440
- provider,
441
- walletOS,
442
- emailVerified: !!user?.emailVerified,
443
- phoneVerified: !!user?.phoneVerified,
444
- org: userOrg,
445
- },
446
- { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
447
- );
448
- const lastLoginIp = getRequestIP(req);
449
- const deviceData = getDeviceData({ req });
450
- const userSession = await node.upsertUserSession({
451
- visitorId,
452
- teamDid,
453
- userDid: userPid,
454
- appPid: teamDid,
455
- status: USER_SESSION_STATUS.ONLINE,
456
- // refreshSession 时更新 ua 可以解决浏览器升级导致 ua 变化产生的问题
457
- ua,
458
- lastLoginIp,
459
- extra: {
460
- walletOS,
461
- device: deviceData,
462
- },
463
- origin: await getOrigin({ req }),
464
- });
465
- if (user?.sourceAppPid) {
466
- await node.syncUserSession({
439
+ const sessionConfig = blocklet.settings?.session || {};
440
+ let userOrg = org;
441
+ if (!userOrg) {
442
+ userOrg = await req.getUserOrg(role);
443
+ }
444
+ const { sessionToken, refreshToken } = createToken(
445
+ userPid,
446
+ {
447
+ secret: blockletInfo.secret,
448
+ passport,
449
+ role,
450
+ fullName: user.fullName,
451
+ provider,
452
+ walletOS,
453
+ emailVerified: !!user?.emailVerified,
454
+ phoneVerified: !!user?.phoneVerified,
455
+ org: userOrg,
456
+ },
457
+ { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
458
+ );
459
+ const lastLoginIp = getRequestIP(req);
460
+ const deviceData = getDeviceData({ req });
461
+ const userSession = await node.upsertUserSession({
462
+ visitorId,
467
463
  teamDid,
468
- userDid: userSession.userDid,
469
- visitorId: userSession.visitorId,
470
- targetAppPid: user.sourceAppPid,
464
+ userDid: userPid,
465
+ appPid: teamDid,
466
+ status: USER_SESSION_STATUS.ONLINE,
467
+ // refreshSession 时更新 ua 可以解决浏览器升级导致 ua 变化产生的问题
471
468
  ua,
472
469
  lastLoginIp,
473
470
  extra: {
474
471
  walletOS,
475
472
  device: deviceData,
476
473
  },
474
+ origin: await getOrigin({ req }),
477
475
  });
478
- }
476
+ if (user?.sourceAppPid) {
477
+ await node.syncUserSession({
478
+ teamDid,
479
+ userDid: userSession.userDid,
480
+ visitorId: userSession.visitorId,
481
+ targetAppPid: user.sourceAppPid,
482
+ ua,
483
+ lastLoginIp,
484
+ extra: {
485
+ walletOS,
486
+ device: deviceData,
487
+ },
488
+ });
489
+ }
479
490
 
480
- // 颁发新的 token 前,将原有的 token 和 refreshToken 拉黑
481
- // req.token 无法正确获得 login_token,所以需要通过 getTokenFromReq 获取
482
- const { token: requestSessionToken } = getTokenFromReq(req, {
483
- cookie: {
484
- key: 'login_token',
485
- },
486
- headerKey: false,
487
- });
488
- if (requestSessionToken) {
489
- const sessionTtl = jwtDecode(requestSessionToken).exp * 1000 - Date.now();
490
- if (sessionTtl > 0) {
491
- await cache.sessionToken.set(md5(requestSessionToken), { block: true }, { ttl: sessionTtl });
491
+ // 颁发新的 token 前,将原有的 token 和 refreshToken 拉黑
492
+ // req.token 无法正确获得 login_token,所以需要通过 getTokenFromReq 获取
493
+ const { token: requestSessionToken } = getTokenFromReq(req, {
494
+ cookie: {
495
+ key: 'login_token',
496
+ },
497
+ headerKey: false,
498
+ });
499
+ if (requestSessionToken) {
500
+ const sessionTtl = jwtDecode(requestSessionToken).exp * 1000 - Date.now();
501
+ if (sessionTtl > 0) {
502
+ await cache.sessionToken.set(md5(requestSessionToken), { block: true }, { ttl: sessionTtl });
503
+ }
492
504
  }
493
- }
494
- if (req.refreshToken) {
495
- const refreshTtl = jwtDecode(req.refreshToken).exp * 1000 - Date.now();
496
- if (refreshTtl > 0) {
497
- await cache.refreshToken.set(md5(req.refreshToken), { block: true }, { ttl: refreshTtl });
505
+ if (req.refreshToken) {
506
+ const refreshTtl = jwtDecode(req.refreshToken).exp * 1000 - Date.now();
507
+ if (refreshTtl > 0) {
508
+ await cache.refreshToken.set(md5(req.refreshToken), { block: true }, { ttl: refreshTtl });
509
+ }
498
510
  }
499
- }
500
511
 
501
- // 刷新 csrf token
502
- const nodeInfo = await node.getNodeInfo();
503
- const accessWallet = getApplicationWallet(blocklet.appDid || blocklet.meta.did, nodeInfo.sk, undefined, 2);
504
- const csrfToken = await sign(accessWallet.secretKey, sessionToken);
505
- res.cookie('x-csrf-token', csrfToken, {
506
- sameSite: 'strict',
507
- secure: true,
508
- });
512
+ // 刷新 csrf token
513
+ const nodeInfo = await node.getNodeInfo();
514
+ const accessWallet = getApplicationWallet(blocklet.appDid || blocklet.meta.did, nodeInfo.sk, undefined, 2);
515
+ const csrfToken = await sign(accessWallet.secretKey, sessionToken);
516
+ // @note: 同时设置 token
517
+ res.cookie('x-csrf-token', csrfToken, {
518
+ sameSite: 'strict',
519
+ secure: true,
520
+ });
521
+ res.cookie('login_token', sessionToken, {
522
+ sameSite: 'lax',
523
+ secure: true,
524
+ expires: dayjs()
525
+ .add(blocklet?.settings?.session?.cacheTtl || 3600, 's')
526
+ .toDate(),
527
+ });
509
528
 
510
- res.json(
511
- await signResponse(
512
- {
513
- user: omit(user, ['extra']),
514
- nextToken: sessionToken,
515
- nextRefreshToken: refreshToken,
516
- provider,
517
- walletOS,
518
- },
519
- blockletInfo.wallet
520
- )
521
- );
522
- } catch (err) {
523
- res.status(400).send(err.message);
529
+ res.json(
530
+ await signResponse(
531
+ {
532
+ user: omit(user, ['extra']),
533
+ nextToken: sessionToken,
534
+ nextRefreshToken: refreshToken,
535
+ provider,
536
+ walletOS,
537
+ },
538
+ blockletInfo.wallet
539
+ )
540
+ );
541
+ } catch (err) {
542
+ res.status(400).send(err.message);
543
+ }
544
+ } else {
545
+ res.status(400).send(t('emptyRefreshToken', req.blockletLocale));
524
546
  }
525
- } else {
526
- res.status(400).send(t('emptyRefreshToken', req.blockletLocale));
527
547
  }
528
- });
548
+ );
529
549
  },
530
550
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.17.3-beta-20251119-034511-f26047c0",
6
+ "version": "1.17.3-beta-20251119-102907-28b69b76",
7
7
  "description": "Provide unified services for every blocklet",
8
8
  "main": "api/index.js",
9
9
  "files": [
@@ -32,17 +32,17 @@
32
32
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
33
33
  "license": "Apache-2.0",
34
34
  "dependencies": {
35
- "@abtnode/analytics": "1.17.3-beta-20251119-034511-f26047c0",
36
- "@abtnode/auth": "1.17.3-beta-20251119-034511-f26047c0",
37
- "@abtnode/connect-storage": "1.17.3-beta-20251119-034511-f26047c0",
38
- "@abtnode/constant": "1.17.3-beta-20251119-034511-f26047c0",
39
- "@abtnode/core": "1.17.3-beta-20251119-034511-f26047c0",
40
- "@abtnode/cron": "1.17.3-beta-20251119-034511-f26047c0",
41
- "@abtnode/db-cache": "1.17.3-beta-20251119-034511-f26047c0",
42
- "@abtnode/logger": "1.17.3-beta-20251119-034511-f26047c0",
43
- "@abtnode/models": "1.17.3-beta-20251119-034511-f26047c0",
44
- "@abtnode/router-templates": "1.17.3-beta-20251119-034511-f26047c0",
45
- "@abtnode/util": "1.17.3-beta-20251119-034511-f26047c0",
35
+ "@abtnode/analytics": "1.17.3-beta-20251119-102907-28b69b76",
36
+ "@abtnode/auth": "1.17.3-beta-20251119-102907-28b69b76",
37
+ "@abtnode/connect-storage": "1.17.3-beta-20251119-102907-28b69b76",
38
+ "@abtnode/constant": "1.17.3-beta-20251119-102907-28b69b76",
39
+ "@abtnode/core": "1.17.3-beta-20251119-102907-28b69b76",
40
+ "@abtnode/cron": "1.17.3-beta-20251119-102907-28b69b76",
41
+ "@abtnode/db-cache": "1.17.3-beta-20251119-102907-28b69b76",
42
+ "@abtnode/logger": "1.17.3-beta-20251119-102907-28b69b76",
43
+ "@abtnode/models": "1.17.3-beta-20251119-102907-28b69b76",
44
+ "@abtnode/router-templates": "1.17.3-beta-20251119-102907-28b69b76",
45
+ "@abtnode/util": "1.17.3-beta-20251119-102907-28b69b76",
46
46
  "@arcblock/did": "^1.27.7",
47
47
  "@arcblock/did-connect-js": "^1.27.7",
48
48
  "@arcblock/did-ext": "^1.27.7",
@@ -52,18 +52,18 @@
52
52
  "@arcblock/jwt": "^1.27.7",
53
53
  "@arcblock/validator": "^1.27.7",
54
54
  "@arcblock/ws": "^1.27.7",
55
- "@blocklet/constant": "1.17.3-beta-20251119-034511-f26047c0",
55
+ "@blocklet/constant": "1.17.3-beta-20251119-102907-28b69b76",
56
56
  "@blocklet/dbhub": "^0.2.9",
57
- "@blocklet/env": "1.17.3-beta-20251119-034511-f26047c0",
57
+ "@blocklet/env": "1.17.3-beta-20251119-102907-28b69b76",
58
58
  "@blocklet/error": "^0.3.3",
59
59
  "@blocklet/form-builder": "^0.1.12",
60
60
  "@blocklet/form-collector": "^0.1.8",
61
- "@blocklet/images": "1.17.3-beta-20251119-034511-f26047c0",
62
- "@blocklet/js-sdk": "1.17.3-beta-20251119-034511-f26047c0",
63
- "@blocklet/meta": "1.17.3-beta-20251119-034511-f26047c0",
64
- "@blocklet/rate-limit": "1.17.3-beta-20251119-034511-f26047c0",
65
- "@blocklet/sdk": "1.17.3-beta-20251119-034511-f26047c0",
66
- "@blocklet/server-js": "1.17.3-beta-20251119-034511-f26047c0",
61
+ "@blocklet/images": "1.17.3-beta-20251119-102907-28b69b76",
62
+ "@blocklet/js-sdk": "1.17.3-beta-20251119-102907-28b69b76",
63
+ "@blocklet/meta": "1.17.3-beta-20251119-102907-28b69b76",
64
+ "@blocklet/rate-limit": "1.17.3-beta-20251119-102907-28b69b76",
65
+ "@blocklet/sdk": "1.17.3-beta-20251119-102907-28b69b76",
66
+ "@blocklet/server-js": "1.17.3-beta-20251119-102907-28b69b76",
67
67
  "@blocklet/theme": "^3.2.6",
68
68
  "@blocklet/theme-builder": "0.4.8",
69
69
  "@blocklet/uploader-server": "^0.3.11",
@@ -123,7 +123,7 @@
123
123
  "whatwg-url": "14.0.0"
124
124
  },
125
125
  "devDependencies": {
126
- "@abtnode/ux": "1.17.3-beta-20251119-034511-f26047c0",
126
+ "@abtnode/ux": "1.17.3-beta-20251119-102907-28b69b76",
127
127
  "@arcblock/bridge": "^3.2.6",
128
128
  "@arcblock/did-connect-react": "^3.2.6",
129
129
  "@arcblock/icons": "^3.2.6",
@@ -133,7 +133,7 @@
133
133
  "@blocklet/did-space-react": "^1.2.4",
134
134
  "@blocklet/launcher-layout": "^3.2.6",
135
135
  "@blocklet/payment-react": "^1.22.14",
136
- "@blocklet/tracker": "1.17.3-beta-20251119-034511-f26047c0",
136
+ "@blocklet/tracker": "1.17.3-beta-20251119-102907-28b69b76",
137
137
  "@blocklet/ui-react": "^3.2.6",
138
138
  "@blocklet/uploader": "^0.3.11",
139
139
  "@emotion/react": "^11.14.0",
@@ -213,5 +213,5 @@
213
213
  "url": "https://github.com/ArcBlock/blocklet-server/issues",
214
214
  "email": "shijun@arcblock.io"
215
215
  },
216
- "gitHead": "7ab331f3b29e171a1e02aca80e73f35b6a161b86"
216
+ "gitHead": "6ae74784386f183ac410a226b6b9334c0f722fcc"
217
217
  }