@abtnode/blocklet-services 1.16.39-beta-20250218-132815-6baaf20e → 1.16.39-beta-20250220-212222-627e9ea7

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 (202) hide show
  1. package/api/index.js +1 -1
  2. package/api/libs/push-kit/index.js +2 -2
  3. package/api/services/auth/index.js +1 -2
  4. package/api/services/dashboard/index.js +32 -48
  5. package/api/services/notification/notification-queue.js +77 -165
  6. package/api/socket/channel/did.js +44 -32
  7. package/api/util/attach-shared-utils.js +11 -4
  8. package/dist/assets/{Add-meGhscd6.js → Add-qzAc2S9X.js} +1 -1
  9. package/dist/assets/{ArrowDropDown-B7S4xnEe.js → ArrowDropDown-CH-FgtE-.js} +1 -1
  10. package/dist/assets/{CheckCircle-CnvZ4oB1.js → CheckCircle-Bk5vNiEj.js} +1 -1
  11. package/dist/assets/{ChevronLeft-D1qkw0FM.js → ChevronLeft-CtdCxfvp.js} +1 -1
  12. package/dist/assets/{ChevronRight-CEkTH0up.js → ChevronRight-C0FYeIUm.js} +1 -1
  13. package/dist/assets/{DeleteOutline-BjrgG_HY.js → DeleteOutline-DJPUGW0c.js} +1 -1
  14. package/dist/assets/{Done-7hvoRcVZ.js → Done-BBJndopl.js} +1 -1
  15. package/dist/assets/{Download-CMvqPsK9.js → Download-DR7jogQn.js} +1 -1
  16. package/dist/assets/{EditIcon-BOr0kf6I.js → EditIcon-Mm3W5DE6.js} +1 -1
  17. package/dist/assets/{Error-D3I1nNnO.js → Error-DtmzeQ7l.js} +1 -1
  18. package/dist/assets/{Google-TNOfJ3uU.js → Google-DLwblvhu.js} +1 -1
  19. package/dist/assets/{InfoOutlined-CwoytfGr.js → InfoOutlined-D5FF63tH.js} +1 -1
  20. package/dist/assets/{Launch-wyBVNKfb.js → Launch-CmFwRERO.js} +1 -1
  21. package/dist/assets/{LaunchOutlined-B2ZU9fkg.js → LaunchOutlined-DBHgr88s.js} +1 -1
  22. package/dist/assets/{LockIcon-D-W4Rph6.js → LockIcon-BbWIWjve.js} +1 -1
  23. package/dist/assets/{Loop-CQAI5rIS.js → Loop-Bca4uFY8.js} +1 -1
  24. package/dist/assets/{MoreHoriz-CyCcv2bV.js → MoreHoriz-Dye919yY.js} +1 -1
  25. package/dist/assets/{PlayArrow-B5ZFUKPq.js → PlayArrow-C2iusqXD.js} +1 -1
  26. package/dist/assets/{QuestionMarkCircle-BvUTckGB.js → QuestionMarkCircle-D5Im4T0u.js} +1 -1
  27. package/dist/assets/{ServerLogo-BDEZRDcg.js → ServerLogo-DWgX8KHy.js} +1 -1
  28. package/dist/assets/{ViewList-C8AcRueZ.js → ViewList-DKhSCuMV.js} +1 -1
  29. package/dist/assets/access-control-B0LaD0k_.js +13 -0
  30. package/dist/assets/{actions-C0a0eUYM.js → actions-yv07Sweq.js} +1 -1
  31. package/dist/assets/{add-component-core-CK3SAdlQ.js → add-component-core-C2j8WeZe.js} +35 -35
  32. package/dist/assets/add-resource-BqHzz2Ig.js +1 -0
  33. package/dist/assets/addon-B-oiJMyb.js +31 -0
  34. package/dist/assets/{analytics-CjaAB5m2.js → analytics-Djm-FxYj.js} +1 -1
  35. package/dist/assets/{ar-DoIWDL3Q.js → ar-BIivBIFd.js} +1 -1
  36. package/dist/assets/ar-COZYSjgL.js +3 -0
  37. package/dist/assets/{audit-logs-bl5st5Lr.js → audit-logs-e69kZ-on.js} +1 -1
  38. package/dist/assets/{base32-9oQoOkFy.js → base32-CD3Vv-Tv.js} +1 -1
  39. package/dist/assets/branding-BxqW8Sc9.js +40 -0
  40. package/dist/assets/{bundle-avatar-Dnk7mw7b.js → bundle-avatar-BHE5y99P.js} +1 -1
  41. package/dist/assets/button-DYvqAiv_.js +1 -0
  42. package/dist/assets/{click-to-copy-C9X-UQyL.js → click-to-copy-Do3l3xtT.js} +1 -1
  43. package/dist/assets/complete-BHA60Kfa.js +45 -0
  44. package/dist/assets/{component-B0WI6_H4.js → component-CkH8Sb15.js} +96 -88
  45. package/dist/assets/config-CGVl3CyQ.js +32 -0
  46. package/dist/assets/{config-C0wq7rMr.js → config-CZ4gUB4m.js} +1 -1
  47. package/dist/assets/{config-navigation-Dskr7Yic.js → config-navigation-B_PVAliu.js} +3 -3
  48. package/dist/assets/{config-space-BYYAVRcS.js → config-space-Cjs4lh6z.js} +1 -1
  49. package/dist/assets/{confirm-BmLsHbj9.js → confirm-HOW8FaxK.js} +1 -1
  50. package/dist/assets/{connect-06lWrPrR.js → connect--Oy8GGMA.js} +1 -1
  51. package/dist/assets/{connect-hhGPDSK8.js → connect-D4PAe19d.js} +1 -1
  52. package/dist/assets/{connect-to-DIJ57-hM.js → connect-to-aA5MeDcj.js} +1 -1
  53. package/dist/assets/{content-layout-cWwRTmIc.js → content-layout-CE2kjm54.js} +1 -1
  54. package/dist/assets/{dashboard-PlqPcVrd.js → dashboard-CiOynIcf.js} +10 -10
  55. package/dist/assets/de-C2zBBjYP.js +3 -0
  56. package/dist/assets/{de-BVgb1fEg.js → de-CQlYxUo4.js} +1 -1
  57. package/dist/assets/delete-confirm-CsLJksmh.js +1 -0
  58. package/dist/assets/{did-address-Bl2N44vc.js → did-address-5heyoc8D.js} +1 -1
  59. package/dist/assets/domain-DH9NJU3V.js +9 -0
  60. package/dist/assets/domain-action-card-COoKhuua.js +15 -0
  61. package/dist/assets/domains-CyoWnOlx.js +1 -0
  62. package/dist/assets/{email-9CbD02fM.js → email-kdvuQq1P.js} +1 -1
  63. package/dist/assets/es-BeW3ehjv.js +3 -0
  64. package/dist/assets/{es-CWcVPAna.js → es-CiFVrJLk.js} +1 -1
  65. package/dist/assets/{exchange-passport-ZTeqENxf.js → exchange-passport-DC5cSNtB.js} +1 -1
  66. package/dist/assets/{form-text-input-DEadnM80.js → form-text-input-Vg6k4hxG.js} +1 -1
  67. package/dist/assets/{fr-C8Jr_C8u.js → fr-ByVHFXxu.js} +1 -1
  68. package/dist/assets/fr-D2xyGusB.js +3 -0
  69. package/dist/assets/{fuel-AxStjHWS.js → fuel-BtUPmbM2.js} +1 -1
  70. package/dist/assets/{fullpage-BXvfrD1C.js → fullpage-9ClXH1L9.js} +1 -1
  71. package/dist/assets/{get-safe-url-BVjMxmwp.js → get-safe-url-BRR4RLgg.js} +1 -1
  72. package/dist/assets/{get-safe-url-BxZD1oA_.js → get-safe-url-bdLdP6Lf.js} +1 -1
  73. package/dist/assets/{hi-DTqZQNNB.js → hi-BIS_6XAM.js} +1 -1
  74. package/dist/assets/hi-OH9OAZfb.js +1 -0
  75. package/dist/assets/{home-CrkVy1DG.js → home-DERpglCy.js} +1 -1
  76. package/dist/assets/{id-CUsGyKYW.js → id-BK78HolG.js} +1 -1
  77. package/dist/assets/id-BNCctHPN.js +3 -0
  78. package/dist/assets/{iframe-BcWepstA.js → iframe-D3k1dg5d.js} +1 -1
  79. package/dist/assets/index-8p3WpvMR.js +192 -0
  80. package/dist/assets/{index-DIQ33Q8Z.js → index-B0unYdcz.js} +1 -1
  81. package/dist/assets/{index-BBOSdbE7.js → index-B3zo8s95.js} +1 -1
  82. package/dist/assets/{index-BtFCAsqh.js → index-BQSYz_Lo.js} +1 -1
  83. package/dist/assets/{index-DgaUl_lv.js → index-BbnozP7b.js} +1 -1
  84. package/dist/assets/index-BelkkFch.js +228 -0
  85. package/dist/assets/index-BtWvJbA-.js +52 -0
  86. package/dist/assets/{index-DkVoxpR-.js → index-BwEZdySL.js} +7 -7
  87. package/dist/assets/{index-Be9vrMiA.js → index-Bygo8biQ.js} +1 -1
  88. package/dist/assets/{index-CHFvfli7.js → index-CF4Aobpk.js} +1 -1
  89. package/dist/assets/{index-CDvqNewi.js → index-CR0qrcky.js} +1 -1
  90. package/dist/assets/{index-BSC2apzE.js → index-CfM3rPHl.js} +1 -1
  91. package/dist/assets/{index-DtwN19zv.js → index-DIP3om2u.js} +1 -1
  92. package/dist/assets/{index-C-D-nCB1.js → index-DQ3_atB3.js} +1 -1
  93. package/dist/assets/{index-DfBNyFsV.js → index-DV2omMe2.js} +1 -1
  94. package/dist/assets/{index-ChSPqVLh.js → index-DcvnbXW2.js} +1 -1
  95. package/dist/assets/index-H3wqK9-u.js +109 -0
  96. package/dist/assets/{index-BXlJ03I_.js → index-XiSmd1mo.js} +1 -1
  97. package/dist/assets/index-dZzRZ2ZY.js +104 -0
  98. package/dist/assets/{invitation-BzHMoDRH.js → invitation-CxmBuTs1.js} +6 -6
  99. package/dist/assets/{invite-BBcuJaUv.js → invite-B874TDmG.js} +1 -1
  100. package/dist/assets/{issue-passport-sgBfFZ4Y.js → issue-passport-D9TAuz7P.js} +1 -1
  101. package/dist/assets/item-Bl6VQtAH.js +2 -0
  102. package/dist/assets/ja-BP7svMm3.js +3 -0
  103. package/dist/assets/{ja-B0U7M2t1.js → ja-C_qbKn0g.js} +1 -1
  104. package/dist/assets/ko-Bucx3EaX.js +3 -0
  105. package/dist/assets/{ko-CpDA9JjF.js → ko-Dlp9c2u9.js} +1 -1
  106. package/dist/assets/{launch-result-message-keU5grqY.js → launch-result-message-B237vj_f.js} +1 -1
  107. package/dist/assets/{layout-CGas_HfS.js → layout--JdBWkq8.js} +1 -1
  108. package/dist/assets/{list-cZ-OXxN0.js → list-D6KYwBs8.js} +1 -1
  109. package/dist/assets/{list-header-Dd4BEf4y.js → list-header-CRB0LxnL.js} +1 -1
  110. package/dist/assets/localization-CfyOuYf8.js +1 -0
  111. package/dist/assets/{log-BFj6TDz5.js → log-CY8wNU8M.js} +1 -1
  112. package/dist/assets/{login-B-6s411x.js → login-B248a-js.js} +1 -1
  113. package/dist/assets/login-oauth-callback-BLrbomPI.js +1 -0
  114. package/dist/assets/{logo-uploader-pyVqJwKp.js → logo-uploader-CXyCerZA.js} +3 -3
  115. package/dist/assets/{lost-passport-DKkxzCH8.js → lost-passport-BviMxb1A.js} +1 -1
  116. package/dist/assets/{open-window-Cvetj9Mn.js → open-window-Ch1rgFaC.js} +1 -1
  117. package/dist/assets/overview-B6x2PVnm.js +12 -0
  118. package/dist/assets/{page-header--y63DY5K.js → page-header-BVxfqM_P.js} +1 -1
  119. package/dist/assets/{permission-Be_APIVZ.js → permission-Ct9GXCMW.js} +1 -1
  120. package/dist/assets/{preferences-D-NDmLhf.js → preferences-BhZaRM6Y.js} +1 -1
  121. package/dist/assets/pt-DWx2CRwy.js +1 -0
  122. package/dist/assets/{pt-7r06GaNd.js → pt-SFZ6JUYf.js} +1 -1
  123. package/dist/assets/publish-resource-DcoLPJys.js +1 -0
  124. package/dist/assets/{react-beautiful-dnd.esm-Czr1mmuu.js → react-beautiful-dnd.esm-Bj96SiFV.js} +1 -1
  125. package/dist/assets/{relative-time-D0P0AJUI.js → relative-time-cY8dsU43.js} +1 -1
  126. package/dist/assets/{ru-MS-ksi2g.js → ru-Bz5lOwmE.js} +1 -1
  127. package/dist/assets/ru-CCmcxEDp.js +1 -0
  128. package/dist/assets/sdk-DQoMrTNt.js +1 -0
  129. package/dist/assets/{session-CV6ez46v.js → session-CldqrK3N.js} +1 -1
  130. package/dist/assets/setup-AfPc0iVj.js +19 -0
  131. package/dist/assets/{shorten-label-J69eHfMN.js → shorten-label-la5sIm_0.js} +1 -1
  132. package/dist/assets/{simple-select-D06JmA0a.js → simple-select-Cu-p9eCv.js} +1 -1
  133. package/dist/assets/{slicedToArray-CXBLQZX4.js → slicedToArray-DBh5Z78L.js} +2 -2
  134. package/dist/assets/{start-BjFFihjS.js → start-D-vJAX65.js} +1 -1
  135. package/dist/assets/{step-actions-qXq3r5tX.js → step-actions-EEz4d7kn.js} +1 -1
  136. package/dist/assets/{studio-BNGylnt7.js → studio-BfuxFzVZ.js} +1 -1
  137. package/dist/assets/{switch-control-DmKC0hpm.js → switch-control-DkVbfEAf.js} +1 -1
  138. package/dist/assets/{th-gcuRSNHo.js → th-B1jLPjfm.js} +1 -1
  139. package/dist/assets/th-yhtyMUEz.js +1 -0
  140. package/dist/assets/{traffic-Djmt2Ph8.js → traffic-DIdLhQbQ.js} +1 -1
  141. package/dist/assets/{transfer-B9ohZjja.js → transfer-CSUEJJtc.js} +1 -1
  142. package/dist/assets/{unsubscribe-6xRksnNz.js → unsubscribe-Dma6eGwK.js} +1 -1
  143. package/dist/assets/{use-mobile-DnWfrhc7.js → use-mobile-B7gJcr5J.js} +1 -1
  144. package/dist/assets/{useAsync-Ua5iss51.js → useAsync-CEZQNMFX.js} +1 -1
  145. package/dist/assets/{useAsyncRetry-Bmo6a1Zp.js → useAsyncRetry-BEB-tWmQ.js} +2 -2
  146. package/dist/assets/{useLocalStorage-B5t6MEw6.js → useLocalStorage-CM7gP1Ni.js} +1 -1
  147. package/dist/assets/{user-center-DEGm9vzv.js → user-center-BkMU0Sgl.js} +1 -1
  148. package/dist/assets/util-C5G3YrVZ.js +1 -0
  149. package/dist/assets/{util-Bl4vyFsm.js → util-Dn2l5LdV.js} +1 -1
  150. package/dist/assets/{vendor-arcblock-BFUPp1Ez.js → vendor-arcblock-CLdpcBR_.js} +73 -73
  151. package/dist/assets/{vendor-hooks-BKxTDk_P.js → vendor-hooks-ZnvK17j8.js} +2 -2
  152. package/dist/assets/vendor-mui-core-DrGFkjqr.js +266 -0
  153. package/dist/assets/{vendor-mui-x-CSUdon8K.js → vendor-mui-x-vjsTA-wt.js} +1 -1
  154. package/dist/assets/vi-C8K3TxgS.js +1 -0
  155. package/dist/assets/{vi-CGYOhf_R.js → vi-RXH5xiEz.js} +1 -1
  156. package/dist/assets/wrap-locale-fZXg9Dsd.js +1 -0
  157. package/dist/assets/zh-BZ_tPxRT.js +4 -0
  158. package/dist/assets/{zh-BYS_9r4v.js → zh-NJ5wkDCG.js} +1 -1
  159. package/dist/assets/{zh-tw-BR5CO3an.js → zh-tw-BpuS6s2j.js} +1 -1
  160. package/dist/assets/zh-tw-DKnxL7q7.js +3 -0
  161. package/dist/index.html +4 -4
  162. package/dist/service-worker.js +1 -1
  163. package/package.json +34 -34
  164. package/dist/assets/access-control-ClVHa3J1.js +0 -13
  165. package/dist/assets/add-resource-hs_iM1xk.js +0 -1
  166. package/dist/assets/addon-C7fx4MJ0.js +0 -31
  167. package/dist/assets/ar-BFUPmTkR.js +0 -3
  168. package/dist/assets/branding-5S3zjZlC.js +0 -40
  169. package/dist/assets/button-BTVoaDd7.js +0 -1
  170. package/dist/assets/complete-C3yyjx_N.js +0 -45
  171. package/dist/assets/config-DINcJX6A.js +0 -32
  172. package/dist/assets/de-hV0yD3gq.js +0 -3
  173. package/dist/assets/domain-DDa_Ldun.js +0 -9
  174. package/dist/assets/domain-list-DXbfS21Z.js +0 -15
  175. package/dist/assets/es-BcSAobJW.js +0 -3
  176. package/dist/assets/fr-8qti32p1.js +0 -3
  177. package/dist/assets/hi-DDEUhQcX.js +0 -1
  178. package/dist/assets/id-DkUYINLx.js +0 -3
  179. package/dist/assets/index-BJA4YPaC.js +0 -243
  180. package/dist/assets/index-CoxJ8G1A.js +0 -77
  181. package/dist/assets/index-DcfIKM1A.js +0 -9
  182. package/dist/assets/index-DkufOgYs.js +0 -125
  183. package/dist/assets/index-MxM82EtU.js +0 -228
  184. package/dist/assets/index-uYcwdGZL.js +0 -104
  185. package/dist/assets/item-C5sAxGxS.js +0 -2
  186. package/dist/assets/ja-C2LP4WQG.js +0 -3
  187. package/dist/assets/ko-C-DMeONa.js +0 -3
  188. package/dist/assets/localization-Z_CTe1Z8.js +0 -1
  189. package/dist/assets/login-oauth-callback-aKbzfltj.js +0 -1
  190. package/dist/assets/overview-BxbJCUbS.js +0 -12
  191. package/dist/assets/pt-CbxvF__Z.js +0 -1
  192. package/dist/assets/publish-resource-CxkiI4_n.js +0 -1
  193. package/dist/assets/ru-DLHrAeE7.js +0 -1
  194. package/dist/assets/sdk-NKQJT0FS.js +0 -1
  195. package/dist/assets/setup-CF2VhAxD.js +0 -19
  196. package/dist/assets/th-Dil9kwjH.js +0 -1
  197. package/dist/assets/util-PzCAH0nE.js +0 -1
  198. package/dist/assets/vendor-mui-core-xF5F4eT7.js +0 -266
  199. package/dist/assets/vi-B46hyfUM.js +0 -1
  200. package/dist/assets/wrap-locale-6MxBCfA2.js +0 -1
  201. package/dist/assets/zh-DWWuPzr1.js +0 -4
  202. package/dist/assets/zh-tw-Ci21sS2Y.js +0 -3
package/api/index.js CHANGED
@@ -110,7 +110,7 @@ module.exports = function createServer(node, serverOptions = {}) {
110
110
  const kycService = initKyc({ node });
111
111
  const relayService = initRelay({ node });
112
112
  const imageService = initImageService({ node });
113
- const dashboardService = initDashboard({ node, ensureWsUser });
113
+ const dashboardService = initDashboard({ node, ensureWsUser, options });
114
114
 
115
115
  // Proxy engine
116
116
  const proxy = httpProxy.createProxyServer({
@@ -11,14 +11,14 @@ async function sendPush(receiver, notification, { node, teamDid }) {
11
11
  const blocklet = await node.getBlocklet({ did: teamDid, useCache: true });
12
12
  if (!blocklet) {
13
13
  logger.warn(`Failed to get blocklet: ${teamDid}`);
14
- return null;
14
+ throw new Error(`Failed to get blocklet: ${teamDid}`);
15
15
  }
16
16
 
17
17
  const config = blocklet.settings?.notification?.pushKit || {};
18
18
 
19
19
  if (!config.enabled || !config.endpoint) {
20
20
  // skip send email
21
- return null;
21
+ throw new Error('Push Kit Service is not Enabled.');
22
22
  }
23
23
 
24
24
  const pushKitConfig = {
@@ -285,7 +285,6 @@ const init = ({ node, options }) => {
285
285
  return;
286
286
  }
287
287
 
288
- // FIXME: @zhanghan ws 如何处理 cookie 已过期的情况
289
288
  await req.ensureUser({ token });
290
289
  };
291
290
 
@@ -299,7 +298,6 @@ const init = ({ node, options }) => {
299
298
  return;
300
299
  }
301
300
 
302
- // FIXME: @zhanghan ws 如何处理 cookie 已过期的情况
303
301
  await req.ensureUser({ token });
304
302
 
305
303
  setUserInfoHeaders(req);
@@ -417,4 +415,5 @@ const init = ({ node, options }) => {
417
415
  module.exports = {
418
416
  init,
419
417
  validators,
418
+ getTokenFromWsConnect,
420
419
  };
@@ -7,6 +7,7 @@ const eventHub =
7
7
  process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
8
8
 
9
9
  const logger = require('../../libs/logger')('ws');
10
+ const { getTokenFromWsConnect } = require('../auth');
10
11
 
11
12
  function commonListen(wsServer, node) {
12
13
  const streamLogManager = createStreamLogManager({
@@ -49,38 +50,40 @@ function commonListen(wsServer, node) {
49
50
  return streamLogManager;
50
51
  }
51
52
 
52
- function createWebsocketServer(node, ensureWsUser) {
53
- const wsServer = new WsServer({
54
- broadcastEventName: '@abtnode/blocklet-services:dashboard',
55
- heartbeatTimeout: 60 * 1000 * 10,
53
+ function createWebsocketAuthenticator(ensureWsUser, roles, options) {
54
+ return async (req, cb) => {
55
+ const token = getTokenFromWsConnect(req, options);
56
+ if (!token) {
57
+ cb(new Error('token not found'), null);
58
+ return;
59
+ }
56
60
 
57
- logger,
61
+ await ensureWsUser(req);
58
62
 
59
- authenticate: async (req, cb) => {
60
- const { searchParams } = new URL(req.url, `http://${req.headers.host || 'unknown'}`);
63
+ if (!req.user) {
64
+ cb(new Error('user not found'), null);
65
+ return;
66
+ }
61
67
 
62
- const token = searchParams.get('token');
63
- if (!token) {
64
- cb(new Error('token not found'), null);
65
- return;
66
- }
68
+ if (roles.length && !roles.includes(req.user.role)) {
69
+ cb(new Error('user does not have permission'), null);
70
+ return;
71
+ }
67
72
 
68
- await ensureWsUser(req);
73
+ const teamDid = req.getBlockletDid();
69
74
 
70
- if (!req.user) {
71
- cb(new Error('user not found'), null);
72
- return;
73
- }
75
+ cb(null, { did: req.user.did, teamDid });
76
+ };
77
+ }
74
78
 
75
- if (![ROLES.OWNER, ROLES.ADMIN].includes(req.user.role)) {
76
- cb(new Error('user does not have permission'), null);
77
- return;
78
- }
79
+ function createWebsocketServer(node, ensureWsUser, options) {
80
+ const wsServer = new WsServer({
81
+ broadcastEventName: '@abtnode/blocklet-services:dashboard',
82
+ heartbeatTimeout: 60 * 1000 * 10,
79
83
 
80
- const teamDid = req.getBlockletDid();
84
+ logger,
81
85
 
82
- cb(null, { did: req.user.did, teamDid });
83
- },
86
+ authenticate: createWebsocketAuthenticator(ensureWsUser, [ROLES.OWNER, ROLES.ADMIN], options),
84
87
 
85
88
  hooks: {
86
89
  authenticateJoinChannel: ({ topic: channel, socket }) => {
@@ -148,33 +151,14 @@ function createWebsocketServer(node, ensureWsUser) {
148
151
  return wsServer;
149
152
  }
150
153
 
151
- function createNotificationWebsocketServer(node, ensureWsUser) {
154
+ function createNotificationWebsocketServer(node, ensureWsUser, options) {
152
155
  const wsServer = new WsServer({
153
156
  broadcastEventName: '@abtnode/blocklet-services:dashboard',
154
157
  heartbeatTimeout: 60 * 1000 * 10,
155
158
 
156
159
  logger,
157
160
 
158
- authenticate: async (req, cb) => {
159
- const { searchParams } = new URL(req.url, `http://${req.headers.host || 'unknown'}`);
160
-
161
- const token = searchParams.get('token');
162
- if (!token) {
163
- cb(new Error('token not found'), null);
164
- return;
165
- }
166
-
167
- await ensureWsUser(req);
168
-
169
- if (!req.user) {
170
- cb(new Error('user not found'), null);
171
- return;
172
- }
173
-
174
- const teamDid = req.getBlockletDid();
175
-
176
- cb(null, { did: req.user.did, teamDid });
177
- },
161
+ authenticate: createWebsocketAuthenticator(ensureWsUser, [], options),
178
162
 
179
163
  hooks: {
180
164
  authenticateJoinChannel: ({ topic: channel, socket }) => {
@@ -207,9 +191,9 @@ function createNotificationWebsocketServer(node, ensureWsUser) {
207
191
  return wsServer;
208
192
  }
209
193
 
210
- const init = ({ node, ensureWsUser }) => {
211
- const dashboardWsServer = createWebsocketServer(node, ensureWsUser);
212
- const notificationWsServer = createNotificationWebsocketServer(node, ensureWsUser);
194
+ const init = ({ node, ensureWsUser, options }) => {
195
+ const dashboardWsServer = createWebsocketServer(node, ensureWsUser, options);
196
+ const notificationWsServer = createNotificationWebsocketServer(node, ensureWsUser, options);
213
197
 
214
198
  return {
215
199
  attachWsServer: (wsRouter) => {
@@ -60,26 +60,14 @@ const init = ({ node, notificationService }) => {
60
60
  retryDelay: 0,
61
61
  },
62
62
  async (job) => {
63
- const { receiver, notification, sender, options } = job;
63
+ const { receiver, notification, sender, options, isResend } = job;
64
64
 
65
65
  if (!receiver) {
66
66
  logger.error('Invalid receiver', { did: receiver });
67
67
  throw new Error('Invalid receiver');
68
68
  }
69
69
 
70
- const nodeInfo = await node.getNodeInfo({ useCache: true });
71
-
72
- if (nodeInfo.mode !== NODE_MODES.DEBUG) {
73
- try {
74
- await validateNotification(notification);
75
- } catch (error) {
76
- logger.error('Failed to validate notification', { error });
77
- // 抛出错误,阻止后续执行
78
- throw error;
79
- }
80
- }
81
-
82
- if (sender.type === 'server' && !sender.token) {
70
+ if ((sender.type === 'server' || isResend) && !sender.token) {
83
71
  sender.token = JWT.sign(sender.appDid, sender.appSk);
84
72
  }
85
73
 
@@ -97,26 +85,14 @@ const init = ({ node, notificationService }) => {
97
85
  * Push Kit 推送队列
98
86
  */
99
87
  const pushKitPushQueue = createNotificationQueue('send-notification-push', {}, async (job) => {
100
- const { notification, receiver, sender } = job;
88
+ const { notification, receiver, sender, isResend } = job;
101
89
 
102
90
  if (!receiver) {
103
91
  logger.error('Invalid receiver', { did: receiver });
104
92
  throw new Error('Invalid receiver');
105
93
  }
106
94
 
107
- const nodeInfo = await node.getNodeInfo({ useCache: true });
108
-
109
- if (nodeInfo.mode !== NODE_MODES.DEBUG) {
110
- try {
111
- await validateNotification(notification);
112
- } catch (error) {
113
- logger.error('Failed to validate notification', { error });
114
- // 抛出错误,阻止后续执行
115
- throw error;
116
- }
117
- }
118
-
119
- if (sender.type === 'server' && !sender.token) {
95
+ if ((sender.type === 'server' || isResend) && !sender.token) {
120
96
  sender.token = JWT.sign(sender.appDid, sender.appSk);
121
97
  }
122
98
 
@@ -154,26 +130,14 @@ const init = ({ node, notificationService }) => {
154
130
  throw new Error('Email address is missing. Unable to send email notification');
155
131
  }
156
132
 
157
- const { notification, sender, teamDid, receivers = [], userInfo } = input;
133
+ const { notification, sender, teamDid, receivers = [], userInfo, isResend } = input;
158
134
 
159
135
  if (!userInfo) {
160
136
  logger.error('Invalid receiver', { dids: userInfo.did });
161
137
  throw new Error('Invalid receiver');
162
138
  }
163
139
 
164
- const nodeInfo = await node.getNodeInfo({ useCache: true });
165
-
166
- if (nodeInfo.mode !== NODE_MODES.DEBUG) {
167
- try {
168
- await validateNotification(notification);
169
- } catch (error) {
170
- logger.error('Failed to validate notification', { error });
171
- // 抛出错误,阻止后续执行
172
- throw error;
173
- }
174
- }
175
-
176
- if (sender.type === 'server' && !sender.token) {
140
+ if ((sender.type === 'server' || isResend) && !sender.token) {
177
141
  sender.token = JWT.sign(sender.appDid, sender.appSk);
178
142
  }
179
143
 
@@ -227,35 +191,23 @@ const init = ({ node, notificationService }) => {
227
191
  throw new Error('Invalid job');
228
192
  }
229
193
 
230
- const { notification, webhook, sender, receivers = [] } = input;
194
+ const { notification, webhook, sender, receivers = [], isResend } = input;
231
195
 
232
196
  if (!receivers.length) {
233
197
  logger.error('Invalid receiver', { dids: receivers });
234
198
  throw new Error('Invalid receiver');
235
199
  }
236
200
 
237
- const nodeInfo = await node.getNodeInfo({ useCache: true });
238
-
239
- if (nodeInfo.mode !== NODE_MODES.DEBUG) {
240
- try {
241
- await validateNotification(notification);
242
- } catch (error) {
243
- logger.error('Failed to validate notification', { error });
244
- // 抛出错误,阻止后续执行
245
- throw error;
246
- }
247
- }
248
-
249
201
  if (!webhook || !webhook.url) {
250
202
  logger.error('Invalid webhook', { webhook });
251
203
  throw new Error('Invalid webhook');
252
204
  }
253
205
 
254
- if (sender.type === 'server' && !sender.token) {
206
+ if ((sender.type === 'server' || isResend) && !sender.token) {
255
207
  sender.token = JWT.sign(sender.appDid, sender.appSk);
256
208
  }
257
209
 
258
- notificationService.sendToWebhook.exec({
210
+ await notificationService.sendToWebhook.exec({
259
211
  sender,
260
212
  receiver: receivers,
261
213
  notification: {
@@ -269,7 +221,7 @@ const init = ({ node, notificationService }) => {
269
221
  }
270
222
  );
271
223
 
272
- const insertToEmailPushQueue = (props, nodeInfo, emailMap) => {
224
+ const insertToEmailPushQueue = (props, nodeInfo, isResend) => {
273
225
  const { channels, notification, sender, userInfo, teamDid } = props;
274
226
 
275
227
  const commonParams = {
@@ -286,14 +238,14 @@ const init = ({ node, notificationService }) => {
286
238
 
287
239
  const channelEnabled = emailEnabled && channels.includes(NOTIFICATION_SEND_CHANNEL.EMAIL);
288
240
 
289
- const { receivers, pushUser } = emailMap.get(email) || { receivers: [], pushUser: {} };
241
+ // const { receivers, pushUser } = emailMap.get(email) || { receivers: [], pushUser: {} };
290
242
 
291
- const pushUserDid = getWalletDid(pushUser) || pushUser.did;
243
+ // const pushUserDid = getWalletDid(pushUser) || pushUser.did;
292
244
 
293
- // 如果 receivers 中已经存在 receiverDid,并且 pushUserDid 和 receiverDid 不一致,则不发送
294
- if (receivers.includes(receiverDid) && pushUserDid !== receiverDid) {
295
- return;
296
- }
245
+ // // 如果 receivers 中已经存在 receiverDid,并且 pushUserDid 和 receiverDid 不一致,则不发送
246
+ // if (receivers.includes(receiverDid) && pushUserDid !== receiverDid) {
247
+ // return;
248
+ // }
297
249
 
298
250
  if (channelEnabled && email) {
299
251
  const _userInfo = {
@@ -309,27 +261,32 @@ const init = ({ node, notificationService }) => {
309
261
  notification,
310
262
  sender,
311
263
  teamDid,
312
- receivers,
264
+ receivers: [receiverDid],
313
265
  userInfo: _userInfo,
266
+ isResend,
314
267
  },
315
268
  },
316
269
  delay: 5,
317
270
  });
318
271
  } else {
319
- updateNotificationSendStatus({
320
- ...commonParams,
321
- receivers: receivers.length > 0 ? receivers : [receiverDid],
322
- channel: NOTIFICATION_SEND_CHANNEL.EMAIL,
323
- status: NOTIFICATION_SEND_STATUS.FAILED,
324
- failedReason:
325
- !emailEnabled || !email
326
- ? NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED
327
- : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
328
- });
272
+ // eslint-disable-next-line no-lonely-if
273
+ if (!isResend) {
274
+ updateNotificationSendStatus({
275
+ ...commonParams,
276
+ email,
277
+ receivers: [receiverDid],
278
+ channel: NOTIFICATION_SEND_CHANNEL.EMAIL,
279
+ status: NOTIFICATION_SEND_STATUS.FAILED,
280
+ failedReason:
281
+ !emailEnabled || !email
282
+ ? NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED
283
+ : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
284
+ });
285
+ }
329
286
  }
330
287
  };
331
288
 
332
- const insertToWebhookPushQueue = async (props, nodeInfo, webhookMap) => {
289
+ const insertToWebhookPushQueue = async (props, nodeInfo, isResend) => {
333
290
  const { channels, notification, sender, userInfo, teamDid } = props;
334
291
 
335
292
  const receiverDid = getWalletDid(userInfo) || userInfo.did;
@@ -347,30 +304,11 @@ const init = ({ node, notificationService }) => {
347
304
  webhooks = await getServerWebhooks();
348
305
  }
349
306
 
350
- const webhookList = uniqBy(webhooks, 'url')
351
- .map((webhook) => {
352
- const { url, type } = webhook;
353
- const { receivers, pushUser } = webhookMap.get(url) || {
354
- type: type ?? 'api',
355
- receivers: [],
356
- pushUser: {},
357
- };
358
- const pushUserDid = getWalletDid(pushUser) || pushUser.did;
359
- if (receivers.includes(receiverDid) && pushUserDid !== receiverDid) {
360
- return false;
361
- }
362
- return {
363
- url,
364
- type,
365
- receivers,
366
- pushUser,
367
- };
368
- })
369
- .filter(Boolean);
307
+ const webhookList = uniqBy(webhooks, 'url');
370
308
 
371
309
  if (webhookList.length > 0 && channels.includes(NOTIFICATION_SEND_CHANNEL.WEBHOOK)) {
372
310
  for (const webhook of webhookList) {
373
- const { url, type, receivers } = webhook;
311
+ const { url, type } = webhook;
374
312
  webhookQueue.push({
375
313
  job: {
376
314
  url,
@@ -378,7 +316,8 @@ const init = ({ node, notificationService }) => {
378
316
  input: {
379
317
  notification,
380
318
  sender,
381
- receivers: receivers.length > 0 ? receivers : [receiverDid],
319
+ receivers: [receiverDid],
320
+ isResend,
382
321
  webhook: {
383
322
  url,
384
323
  type,
@@ -390,10 +329,10 @@ const init = ({ node, notificationService }) => {
390
329
  }
391
330
  } else {
392
331
  // eslint-disable-next-line no-lonely-if
393
- if (webhookList.length > 0) {
332
+ if (webhookList.length > 0 && !isResend) {
394
333
  const webhookParams = {};
395
334
 
396
- for (const { url, type, receivers } of webhookList) {
335
+ for (const { url, type } of webhookList) {
397
336
  webhookParams[url] = {
398
337
  type,
399
338
  sendAt: new Date(),
@@ -404,7 +343,7 @@ const init = ({ node, notificationService }) => {
404
343
  // eslint-disable-next-line no-await-in-loop
405
344
  await updateNotificationSendStatus({
406
345
  ...commonParams,
407
- receivers: receivers.length > 0 ? receivers : [receiverDid],
346
+ receivers: [receiverDid],
408
347
  channel: NOTIFICATION_SEND_CHANNEL.WEBHOOK,
409
348
  status: NOTIFICATION_SEND_STATUS.FAILED,
410
349
  webhookParams: { [url]: webhookParams[url] },
@@ -414,7 +353,7 @@ const init = ({ node, notificationService }) => {
414
353
  }
415
354
  };
416
355
 
417
- const insertToPushKitPushQueue = (props, nodeInfo) => {
356
+ const insertToPushKitPushQueue = (props, nodeInfo, isResend) => {
418
357
  const { channels, notification, sender, userInfo, teamDid, options = {} } = props;
419
358
 
420
359
  const receiverDid = getWalletDid(userInfo) || userInfo.did;
@@ -431,21 +370,25 @@ const init = ({ node, notificationService }) => {
431
370
  sender,
432
371
  options,
433
372
  receiver: receiverDid,
373
+ isResend,
434
374
  });
435
375
  } else {
436
- updateNotificationSendStatus({
437
- ...commonParams,
438
- receivers: [receiverDid],
439
- channel: NOTIFICATION_SEND_CHANNEL.PUSH,
440
- status: NOTIFICATION_SEND_STATUS.FAILED,
441
- failedReason: !pushEnabled
442
- ? NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED
443
- : NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED,
444
- });
376
+ // eslint-disable-next-line no-lonely-if
377
+ if (!isResend) {
378
+ updateNotificationSendStatus({
379
+ ...commonParams,
380
+ receivers: [receiverDid],
381
+ channel: NOTIFICATION_SEND_CHANNEL.PUSH,
382
+ status: NOTIFICATION_SEND_STATUS.FAILED,
383
+ failedReason: !pushEnabled
384
+ ? NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED
385
+ : NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED,
386
+ });
387
+ }
445
388
  }
446
389
  };
447
390
 
448
- const insertToWalletPushQueue = (props, nodeInfo) => {
391
+ const insertToWalletPushQueue = (props, nodeInfo, isResend) => {
449
392
  const { channels, notification, sender, userInfo, teamDid, options = {} } = props;
450
393
 
451
394
  const receiverDid = getWalletDid(userInfo) || userInfo.did;
@@ -463,21 +406,26 @@ const init = ({ node, notificationService }) => {
463
406
  sender,
464
407
  options,
465
408
  receiver: receiverDid,
409
+ isResend,
466
410
  });
467
411
  } else {
468
- updateNotificationSendStatus({
469
- ...commonParams,
470
- receivers: [receiverDid],
471
- channel: NOTIFICATION_SEND_CHANNEL.WALLET,
472
- status: NOTIFICATION_SEND_STATUS.FAILED,
473
- failedReason: !walletEnabled
474
- ? NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED
475
- : NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED,
476
- });
412
+ // 如果是重发的消息,只需要更新推送状态,不需要更新 channel状态
413
+ // eslint-disable-next-line no-lonely-if
414
+ if (!isResend) {
415
+ updateNotificationSendStatus({
416
+ ...commonParams,
417
+ receivers: [receiverDid],
418
+ channel: NOTIFICATION_SEND_CHANNEL.WALLET,
419
+ status: NOTIFICATION_SEND_STATUS.FAILED,
420
+ failedReason: !walletEnabled
421
+ ? NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED
422
+ : NOTIFICATION_SEND_FAILED_REASON.USER_DISABLED,
423
+ });
424
+ }
477
425
  }
478
426
  };
479
427
 
480
- const insertToNotificationReceiver = async (nodeInfo, userInfo, teamDid, notificationId, channels) => {
428
+ const insertToNotificationReceiver = async (nodeInfo, userInfo, teamDid, notificationId) => {
481
429
  const receiverDid = getWalletDid(userInfo) || userInfo.did;
482
430
 
483
431
  const receiverInstance = {
@@ -488,7 +436,7 @@ const init = ({ node, notificationService }) => {
488
436
  const emailEnabled = get(userInfo, 'extra.notifications.email', true);
489
437
  const email = userInfo?.email;
490
438
 
491
- if (emailEnabled && email && channels.includes(NOTIFICATION_SEND_CHANNEL.EMAIL)) {
439
+ if (emailEnabled && email) {
492
440
  receiverInstance.email = email;
493
441
  }
494
442
  const isServer = teamDid === nodeInfo.did;
@@ -504,7 +452,7 @@ const init = ({ node, notificationService }) => {
504
452
  }
505
453
  });
506
454
 
507
- if (webhookMap.size > 0 && channels.includes(NOTIFICATION_SEND_CHANNEL.WEBHOOK)) {
455
+ if (webhookMap.size > 0) {
508
456
  receiverInstance.webhookUrls = Array.from(webhookMap.keys()).join('#');
509
457
  }
510
458
 
@@ -523,8 +471,7 @@ const init = ({ node, notificationService }) => {
523
471
  * }
524
472
  */
525
473
  const queue = createNotificationQueue('notification-receivers', {}, async (job) => {
526
- const { teamDid, channels, receiver, sender, notification, nodeInfo, userInfo, emailMap, webhookMap, ...rest } =
527
- job;
474
+ const { teamDid, channels, receiver, sender, notification, nodeInfo, userInfo, ...rest } = job;
528
475
 
529
476
  try {
530
477
  if (!userInfo) {
@@ -550,27 +497,27 @@ const init = ({ node, notificationService }) => {
550
497
  // 每个渠道之间的推送不会影响
551
498
  // 添加到 wallet 推送队列
552
499
  try {
553
- insertToWalletPushQueue(baseParams, nodeInfo);
500
+ insertToWalletPushQueue(baseParams, nodeInfo, job.isExist);
554
501
  } catch (error) {
555
502
  logger.error('Failed to insert to wallet push queue', { error });
556
503
  }
557
504
  // 添加到 push 推送队列
558
505
  try {
559
- insertToPushKitPushQueue(baseParams, nodeInfo);
506
+ insertToPushKitPushQueue(baseParams, nodeInfo, job.isExist);
560
507
  } catch (error) {
561
508
  logger.error('Failed to insert to push kit push queue', { error });
562
509
  }
563
510
 
564
511
  // 添加到 email 推送队列
565
512
  try {
566
- insertToEmailPushQueue(baseParams, nodeInfo, emailMap);
513
+ insertToEmailPushQueue(baseParams, nodeInfo, job.isExist);
567
514
  } catch (error) {
568
515
  logger.error('Failed to insert to email push queue', { error });
569
516
  }
570
517
 
571
518
  //
572
519
  try {
573
- insertToWebhookPushQueue(baseParams, nodeInfo, webhookMap);
520
+ insertToWebhookPushQueue(baseParams, nodeInfo, job.isExist);
574
521
  } catch (error) {
575
522
  logger.error('Failed to insert to webhook push queue', { error });
576
523
  }
@@ -609,45 +556,12 @@ const init = ({ node, notificationService }) => {
609
556
  type: 'server',
610
557
  };
611
558
 
612
- const isServer = teamDid === nodeInfo.did;
613
-
614
559
  const users = await node.getNotificationReceivers({
615
560
  teamDid,
616
561
  userDids: receivers,
617
562
  enableConnectedAccounts: true,
618
563
  });
619
564
 
620
- const webhookMap = new Map();
621
- const emailMap = new Map();
622
- const serverWebhooks = await getServerWebhooks();
623
-
624
- users.forEach((userInfo) => {
625
- const receiverDid = getWalletDid(userInfo) || userInfo.did;
626
-
627
- // 获取 email 列表
628
- const { email } = userInfo;
629
- const enabledEmail = get(userInfo, 'extra.notifications.email', true);
630
- if (enabledEmail && email) {
631
- const emailEntry = emailMap.get(email) || { receivers: [], pushUser: userInfo };
632
- emailEntry.receivers = [...emailEntry.receivers, receiverDid];
633
- emailEntry.pushUser = userInfo;
634
- emailMap.set(email, emailEntry);
635
- }
636
-
637
- // 获取 webhook 列表
638
- const webhooks = isServer ? serverWebhooks : get(userInfo, 'extra.webhooks', []);
639
- webhooks.forEach((webhook) => {
640
- const webhookEntry = webhookMap.get(webhook.url) || {
641
- type: webhook.type ?? 'api',
642
- receivers: [],
643
- pushUser: userInfo,
644
- };
645
- webhookEntry.receivers = [...webhookEntry.receivers, receiverDid];
646
- webhookEntry.pushUser = userInfo;
647
- webhookMap.set(webhook.url, webhookEntry);
648
- });
649
- });
650
-
651
565
  users.forEach((userInfo) => {
652
566
  const receiverDid = getWalletDid(userInfo) || userInfo.did;
653
567
  queue.push({
@@ -658,8 +572,6 @@ const init = ({ node, notificationService }) => {
658
572
  sender,
659
573
  nodeInfo,
660
574
  userInfo,
661
- emailMap,
662
- webhookMap,
663
575
  });
664
576
  });
665
577
  } catch (error) {