@abtnode/blocklet-services 1.16.41-beta-20250325-154552-2bf78c26 → 1.16.41-beta-20250331-010247-966fcfb0

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 (258) hide show
  1. package/api/emails/_components/actions.js +9 -0
  2. package/api/emails/{components → _components}/article.js +1 -1
  3. package/api/emails/{components → _components}/asset.js +2 -2
  4. package/api/emails/{components → _components}/attachments.js +15 -13
  5. package/api/emails/{components → _components}/compose.js +2 -2
  6. package/api/emails/_components/content.js +15 -0
  7. package/api/emails/{components → _components}/footer.js +1 -1
  8. package/api/emails/{components → _components}/powered-by.js +1 -1
  9. package/api/emails/{components → _components}/token.js +2 -2
  10. package/api/emails/{components → _components}/transaction.js +1 -1
  11. package/api/emails/{pages → _templates}/notification.js +10 -10
  12. package/api/emails/_templates/verify-code-body.js +49 -0
  13. package/api/emails/_templates/verify-code.js +37 -0
  14. package/api/index.js +59 -71
  15. package/api/libs/auth/utils.js +20 -1
  16. package/api/libs/connect/session.js +55 -3
  17. package/api/libs/email.js +48 -16
  18. package/api/middlewares/body-parser.js +10 -0
  19. package/api/routes/blocklet.js +17 -4
  20. package/api/routes/federated.js +36 -13
  21. package/api/routes/mcp.js +87 -0
  22. package/api/routes/user-session.js +16 -1
  23. package/api/routes/user.js +442 -40
  24. package/api/services/auth/connect/issue-passport.js +4 -3
  25. package/api/services/auth/connect/receive-transfer-app-owner.js +17 -1
  26. package/api/services/auth/connect/verify-destroy.js +20 -0
  27. package/api/services/auth/connect/verify-elevated.js +20 -0
  28. package/api/services/auth/index.js +0 -2
  29. package/api/services/auth/session.js +1 -1
  30. package/api/services/kyc/index.js +1 -1
  31. package/api/services/mcp/server.js +37 -0
  32. package/api/services/notification/queue.js +5 -4
  33. package/api/services/studio/index.js +4 -0
  34. package/api/util/federated.js +16 -0
  35. package/dist/assets/{ArrowDropDown-DH8_DBvh.js → ArrowDropDown-odHjNJIs.js} +1 -1
  36. package/dist/assets/{CheckCircle-W4GlzCdu.js → CheckCircle-BqOSvJMp.js} +1 -1
  37. package/dist/assets/{ChevronLeft-B2SRhM5v.js → ChevronLeft-Dv7rlUf5.js} +1 -1
  38. package/dist/assets/{ChevronRight-ZvmzY6T1.js → ChevronRight-CWeJn1iz.js} +1 -1
  39. package/dist/assets/{Community-DxXfm8O3.js → Community-CMFBTMi_.js} +1 -1
  40. package/dist/assets/{DeleteOutline-ClZd2kP1.js → DeleteOutline-Cr-TyrUV.js} +1 -1
  41. package/dist/assets/{Done-DAdEZjfp.js → Done-C1TA1wbA.js} +1 -1
  42. package/dist/assets/{Download-fAYCJ3Zn.js → Download-DxhnUTM_.js} +1 -1
  43. package/dist/assets/{EditIcon-jPGouFji.js → EditIcon-Bgmg6UE0.js} +1 -1
  44. package/dist/assets/{Email-Cj6caJ_8.js → Email-BphlAPta.js} +1 -1
  45. package/dist/assets/{Error-DzDuzV0d.js → Error-pXXvJFxN.js} +1 -1
  46. package/dist/assets/{ExpandLess-CSwVcrV9.js → ExpandLess-Dc_dI20M.js} +1 -1
  47. package/dist/assets/{Google-DaNgbmbg.js → Google-DNUuYFIA.js} +1 -1
  48. package/dist/assets/{Holiday-1uY1QmAp.js → Holiday-DKefG3Bb.js} +1 -1
  49. package/dist/assets/{InfoOutlined-o8YCo8qy.js → InfoOutlined-CEUhR4DY.js} +1 -1
  50. package/dist/assets/{Launch-B5cUT_sx.js → Launch-BUTOr3cR.js} +1 -1
  51. package/dist/assets/{LaunchOutlined-CqJ3-tbE.js → LaunchOutlined-QHq-RUJt.js} +1 -1
  52. package/dist/assets/{Location-C1pAq6lI.js → Location-BuaxMxu4.js} +1 -1
  53. package/dist/assets/{LockIcon-CydBoNUN.js → LockIcon-CQ1tExIY.js} +1 -1
  54. package/dist/assets/{Meeting-tZebh2B1.js → Meeting-Cs60QtvP.js} +1 -1
  55. package/dist/assets/{MoreHoriz-C_oNEMFs.js → MoreHoriz-D1SOL47a.js} +1 -1
  56. package/dist/assets/{OffSick-BYC1oqk1.js → OffSick-DinPaelp.js} +1 -1
  57. package/dist/assets/{Phone-DIzOgVDd.js → Phone-BmouKMyi.js} +1 -1
  58. package/dist/assets/{PlayArrow-BVARrWHX.js → PlayArrow-D7cGSxeN.js} +1 -1
  59. package/dist/assets/{QuestionMarkCircle-B5JWLChh.js → QuestionMarkCircle-Dt9XJWEe.js} +1 -1
  60. package/dist/assets/{ServerLogo-DIfW0NaH.js → ServerLogo-B33ZRE5q.js} +1 -1
  61. package/dist/assets/{Timezone-D7zhOyHu.js → Timezone-CyMhRxlx.js} +1 -1
  62. package/dist/assets/{ViewList-93ffk7kT.js → ViewList-vu1qOJ6P.js} +1 -1
  63. package/dist/assets/{WorkingRemotely-0VF9S3Zo.js → WorkingRemotely-BP_VIHeM.js} +1 -1
  64. package/dist/assets/access-control-CpxcJItK.js +14 -0
  65. package/dist/assets/{actions-D-igEkC_.js → actions-4oGfCMlR.js} +1 -1
  66. package/dist/assets/add-component-core-CE0nArG4.js +761 -0
  67. package/dist/assets/add-resource-BYM4JwzE.js +1 -0
  68. package/dist/assets/{addon-DKPnFM-d.js → addon-B9bb2bvM.js} +1 -1
  69. package/dist/assets/analytics-BXLe73MI.js +11 -0
  70. package/dist/assets/api-D9Yi7Zdr.js +1 -0
  71. package/dist/assets/appearance-DX7SoW1u.js +1 -0
  72. package/dist/assets/ar-2k9jaPIk.js +3 -0
  73. package/dist/assets/{audit-logs-BQlJ8qXs.js → audit-logs-D8H5E0fC.js} +3 -3
  74. package/dist/assets/{base32-CUcA0Dp2.js → base32-BNpDT-6Q.js} +1 -1
  75. package/dist/assets/{branding-DxSd76KG.js → branding-BW1rhy8d.js} +2 -2
  76. package/dist/assets/bundle-avatar-DHwmIozH.js +1 -0
  77. package/dist/assets/button-CNnuiac8.js +1 -0
  78. package/dist/assets/{click-to-copy-DiELz5Xb.js → click-to-copy-B0HMuCN_.js} +1 -1
  79. package/dist/assets/complete-BNf0-iqY.js +45 -0
  80. package/dist/assets/{component-DXUL6eiU.js → component-1r0VSsqq.js} +2 -2
  81. package/dist/assets/{config-CCTS8ZgJ.js → config-BeD5_8kr.js} +2 -2
  82. package/dist/assets/config-CqHmZdZv.js +1 -0
  83. package/dist/assets/{config-navigation-DH0a1AcG.js → config-navigation-DtN0_qFZ.js} +3 -3
  84. package/dist/assets/{config-space-CDBT30Fy.js → config-space-DlwZewcm.js} +1 -1
  85. package/dist/assets/{confirm-H5SukzMZ.js → confirm-DmMN-34s.js} +2 -2
  86. package/dist/assets/connect-BfSOEYV-.js +1 -0
  87. package/dist/assets/{connect-BQBuxZq7.js → connect-CC9dcVMV.js} +1 -1
  88. package/dist/assets/{connect-to-DqrgfOZi.js → connect-to-CzffwD9G.js} +1 -1
  89. package/dist/assets/{content-layout-CIzNOca5.js → content-layout-7vu3yv_f.js} +1 -1
  90. package/dist/assets/dashboard-C_Q4TjPa.js +216 -0
  91. package/dist/assets/de-B9cLhykn.js +3 -0
  92. package/dist/assets/{delete-confirm-CdzeQQ8r.js → delete-confirm-BTaU_6Kx.js} +1 -1
  93. package/dist/assets/did-address-BC-0j4Pt.js +1 -0
  94. package/dist/assets/{domain-B79dyXvl.js → domain-CLMRXecU.js} +1 -1
  95. package/dist/assets/{domain-action-card-DB2tCUnz.js → domain-action-card-DwQ7Q8wY.js} +2 -2
  96. package/dist/assets/domains-DF7TtN5q.js +1 -0
  97. package/dist/assets/{email-DArp9y3R.js → email-mj0bVFDS.js} +2 -2
  98. package/dist/assets/es-BoQohonz.js +3 -0
  99. package/dist/assets/{exchange-passport-CcBW-4OT.js → exchange-passport--DeUPzbW.js} +1 -1
  100. package/dist/assets/form-text-input-BYF6lVnE.js +11 -0
  101. package/dist/assets/fr-doSYAOrt.js +3 -0
  102. package/dist/assets/{fuel-BXqPbUK0.js → fuel-D-kOZuF6.js} +1 -1
  103. package/dist/assets/{fullpage-BAGs-W5J.js → fullpage-DO8Hcbkl.js} +1 -1
  104. package/dist/assets/{get-safe-url-Bs400iLS.js → get-safe-url-BKl2A9x2.js} +1 -1
  105. package/dist/assets/{get-safe-url-DtTGgWbn.js → get-safe-url-QFq5JNoE.js} +1 -1
  106. package/dist/assets/hi-B_BwhpD8.js +1 -0
  107. package/dist/assets/{home-C9GJ4K7b.js → home-CpnMpXiw.js} +1 -1
  108. package/dist/assets/id-BgYIZCvk.js +3 -0
  109. package/dist/assets/{iframe-_xmo1lin.js → iframe-B9mCpo4I.js} +1 -1
  110. package/dist/assets/{index-BHs362aB.js → index-79U1RPaq.js} +1 -1
  111. package/dist/assets/{index-CfSdyisA.js → index-B4Q2DAdn.js} +11 -11
  112. package/dist/assets/index-BJ2lJo7L.js +346 -0
  113. package/dist/assets/{index-Ca7t5vsG.js → index-BMSA5TdD.js} +1 -1
  114. package/dist/assets/{index-B8YUhcxT.js → index-BVOYP6aR.js} +2 -2
  115. package/dist/assets/{index-Dz061vzT.js → index-BZvVDfZ4.js} +1 -1
  116. package/dist/assets/index-BsUr7wGb.js +104 -0
  117. package/dist/assets/index-C44fECmB.js +138 -0
  118. package/dist/assets/{index-CHdEjF6N.js → index-CGK3FEjY.js} +2 -2
  119. package/dist/assets/{index-Cr3r3Dk2.js → index-CJCg9yIK.js} +1 -1
  120. package/dist/assets/index-CmKAznDh.js +109 -0
  121. package/dist/assets/{index-G1H3TvXv.js → index-Ct7s2LPI.js} +3 -3
  122. package/dist/assets/{index-cfNltkU-.js → index-DQ_RzIwU.js} +2 -2
  123. package/dist/assets/{index-Dq2tckVf.js → index-D_wVtHmh.js} +1 -1
  124. package/dist/assets/{index-CyBY00Un.js → index-DqC2o5PB.js} +1 -1
  125. package/dist/assets/index-DyTFEgKr.js +1 -0
  126. package/dist/assets/index-eCY24sH9.js +137 -0
  127. package/dist/assets/{index-CHtbhPPM.js → index-fWGZM-oP.js} +1 -1
  128. package/dist/assets/index-gTQQ3SoE.js +290 -0
  129. package/dist/assets/index-gcSQTx25.js +1 -0
  130. package/dist/assets/{index-rEtARSUO.js → index-m8CaSxXx.js} +1 -1
  131. package/dist/assets/{index-BI7HW_KL.js → index-u-lA6P_E.js} +1 -1
  132. package/dist/assets/invitation-B8Qx_pFq.js +176 -0
  133. package/dist/assets/invite-BBaF_vyc.js +1 -0
  134. package/dist/assets/{issue-passport-D2H1iXFG.js → issue-passport-DC-ly7xg.js} +1 -1
  135. package/dist/assets/{item-BZnflB1r.js → item-BSGXym2I.js} +1 -1
  136. package/dist/assets/ja-FMMLI8YD.js +3 -0
  137. package/dist/assets/ko-C0kmRXYE.js +3 -0
  138. package/dist/assets/{launch-result-message-JdCxLBHF.js → launch-result-message-ByEG8r_7.js} +1 -1
  139. package/dist/assets/{layout-BKTXvgtN.js → layout-BqhTD729.js} +1 -1
  140. package/dist/assets/list-BHs8uNT5.js +200 -0
  141. package/dist/assets/{list-header-C3JMIP96.js → list-header-BmTDmRY0.js} +1 -1
  142. package/dist/assets/localization-daPAWMzR.js +1 -0
  143. package/dist/assets/{log-DSC3nDef.js → log-o_Cadt8j.js} +7 -7
  144. package/dist/assets/{login-B_V3KWS7.js → login-BQozrLDm.js} +1 -1
  145. package/dist/assets/{login-oauth-callback-GH6m7W6J.js → login-oauth-callback-D7lIww1c.js} +1 -1
  146. package/dist/assets/{logo-uploader-B-xodQLr.js → logo-uploader-CUQ3aWZJ.js} +3 -3
  147. package/dist/assets/{lost-passport-BY5kSBj4.js → lost-passport-DkETH2Lu.js} +3 -3
  148. package/dist/assets/{omit-Ci0YZl3b.js → omit-DZNQhOf-.js} +1 -1
  149. package/dist/assets/{open-window-BZb1m3jN.js → open-window-BOl-kTC2.js} +1 -1
  150. package/dist/assets/{overview-5mVt0_gG.js → overview-Bxm05EH6.js} +1 -1
  151. package/dist/assets/{page-header-Mpx7DhlL.js → page-header-Dm1v9v5q.js} +1 -1
  152. package/dist/assets/{permission-EnWLSYpS.js → permission-B5jnw9r2.js} +1 -1
  153. package/dist/assets/{preferences-BzIch5vg.js → preferences-uri2RXdB.js} +1 -1
  154. package/dist/assets/profile-embed-DnIQcD-H.js +1 -0
  155. package/dist/assets/pt-C2UJZK-O.js +1 -0
  156. package/dist/assets/publish-resource-V53U1NNv.js +1 -0
  157. package/dist/assets/{react-beautiful-dnd.esm-DMqCPytx.js → react-beautiful-dnd.esm-B9MfX9Xl.js} +1 -1
  158. package/dist/assets/{relative-time-DmrCbKZi.js → relative-time-RQnsWZQc.js} +1 -1
  159. package/dist/assets/ru-DDA5s4-r.js +1 -0
  160. package/dist/assets/sdk-BKSsfgrc.js +1 -0
  161. package/dist/assets/{session-hH9Eluc3.js → session-6ZeN-aF2.js} +1 -1
  162. package/dist/assets/{setup-BQ9DJQAR.js → setup-7Gq9K_8k.js} +3 -3
  163. package/dist/assets/{shorten-label-Blq5nIR4.js → shorten-label-DkFTGSoy.js} +1 -1
  164. package/dist/assets/simple-select-CqakAZFe.js +1 -0
  165. package/dist/assets/{slicedToArray-0JAP92RR.js → slicedToArray-BuQur6Mi.js} +2 -2
  166. package/dist/assets/{start-Cqxem84z.js → start-BSUY3DBl.js} +1 -1
  167. package/dist/assets/{status-BEcCvVw5.js → status-C52-BFuY.js} +1 -1
  168. package/dist/assets/{step-actions-D1R71ufh.js → step-actions-CA74dwgt.js} +1 -1
  169. package/dist/assets/{studio-CWSkuYqL.js → studio-CAnZfyBM.js} +1 -1
  170. package/dist/assets/{switch-control-j36Oahia.js → switch-control-BBlLGjaH.js} +1 -1
  171. package/dist/assets/th-DmqOUn4C.js +1 -0
  172. package/dist/assets/{traffic-G34OrdMK.js → traffic-CJDIGmp5.js} +3 -3
  173. package/dist/assets/{transfer-CN7lhztm.js → transfer-cG2e24sz.js} +1 -1
  174. package/dist/assets/{unsubscribe-DO25Mrza.js → unsubscribe-afXXIHEf.js} +1 -1
  175. package/dist/assets/{use-mobile-Cz1u01jc.js → use-mobile-CUT5hy9q.js} +1 -1
  176. package/dist/assets/{useAsync-C8pcYSnj.js → useAsync-DM8qaMe4.js} +1 -1
  177. package/dist/assets/{useAsyncRetry-Hh30zerD.js → useAsyncRetry-B7SbzXVI.js} +1 -1
  178. package/dist/assets/{useLocalStorage-CBIpQ2Ch.js → useLocalStorage-Dd4pybDP.js} +1 -1
  179. package/dist/assets/user-center-T8Xw464s.js +67 -0
  180. package/dist/assets/{util-0vNCtiZj.js → util-C_BCTHfw.js} +1 -1
  181. package/dist/assets/{util-BfC763vn.js → util-YyWTpLT7.js} +1 -1
  182. package/dist/assets/vendor-arcblock-DvaaLvvM.js +2361 -0
  183. package/dist/assets/{vendor-hooks-CBQlROWx.js → vendor-hooks-sw5wvnca.js} +2 -2
  184. package/dist/assets/vendor-mui-core-DxqV1NVn.js +266 -0
  185. package/dist/assets/{vendor-mui-x-Bv7Ku5uo.js → vendor-mui-x-BjL1xCkk.js} +1 -1
  186. package/dist/assets/{vendor-utils-C7-Bj8sT.js → vendor-utils-DR57WNxP.js} +7 -7
  187. package/dist/assets/{vendor-ux-did-connect-BH_4FkUq.js → vendor-ux-did-connect-Bciw9Ypu.js} +56 -56
  188. package/dist/assets/vi-Cf__CtPD.js +1 -0
  189. package/dist/assets/wrap-locale-CX50Vz0w.js +1 -0
  190. package/dist/assets/zh-NXspK2yu.js +4 -0
  191. package/dist/assets/zh-tw-DYYDVX5I.js +3 -0
  192. package/dist/index.html +6 -6
  193. package/dist/service-worker.js +2 -2
  194. package/package.json +41 -36
  195. package/api/emails/components/actions.js +0 -9
  196. package/api/emails/components/content.js +0 -15
  197. package/dist/assets/ExternalIssuerIcon-D0E4reWK.js +0 -1
  198. package/dist/assets/access-control-DjkJ52P9.js +0 -13
  199. package/dist/assets/add-component-core-CcInVCBe.js +0 -765
  200. package/dist/assets/add-resource-Bcw4sA7r.js +0 -1
  201. package/dist/assets/analytics-Co9lkVsN.js +0 -11
  202. package/dist/assets/api-tckMpb-p.js +0 -1
  203. package/dist/assets/ar-2G9aaruy.js +0 -3
  204. package/dist/assets/bundle-avatar-BwOOmJKx.js +0 -1
  205. package/dist/assets/button-DmhvlTQK.js +0 -1
  206. package/dist/assets/complete-ClE81Ny0.js +0 -45
  207. package/dist/assets/config-Bn72hRZH.js +0 -1
  208. package/dist/assets/connect-CWgAo1rD.js +0 -1
  209. package/dist/assets/dashboard-Bqm_hK4M.js +0 -218
  210. package/dist/assets/de-DuOaMdcm.js +0 -3
  211. package/dist/assets/did-address-xFa47-Qp.js +0 -1
  212. package/dist/assets/domains-A7coEqfv.js +0 -1
  213. package/dist/assets/es-B_z4kZV7.js +0 -3
  214. package/dist/assets/form-text-input-CFoWUNjT.js +0 -11
  215. package/dist/assets/fr-U4jlLji5.js +0 -3
  216. package/dist/assets/hi-CgWMOeSW.js +0 -1
  217. package/dist/assets/id-DcVdw_iD.js +0 -3
  218. package/dist/assets/index-BAJ44Gvx.js +0 -104
  219. package/dist/assets/index-BGBHkKrL.js +0 -109
  220. package/dist/assets/index-BPRjg-Ha.js +0 -346
  221. package/dist/assets/index-CJi_sgz3.js +0 -137
  222. package/dist/assets/index-CscSMswD.js +0 -1
  223. package/dist/assets/index-CvTkROvr.js +0 -1
  224. package/dist/assets/index-Dkv68xvd.js +0 -138
  225. package/dist/assets/index-DuWgtqAp.js +0 -134
  226. package/dist/assets/invitation-D8ocHjTZ.js +0 -176
  227. package/dist/assets/invite-CtafhjzX.js +0 -1
  228. package/dist/assets/ja-CqyNiw8I.js +0 -3
  229. package/dist/assets/ko-CwboHZNL.js +0 -3
  230. package/dist/assets/list-BiMW09TE.js +0 -195
  231. package/dist/assets/localization-B4PX_18r.js +0 -1
  232. package/dist/assets/login-bg-CBktcoss.jpg +0 -0
  233. package/dist/assets/profile-embed-BAeyCzz5.js +0 -1
  234. package/dist/assets/pt-UQ_ShTDa.js +0 -1
  235. package/dist/assets/publish-resource-OFt0IRNl.js +0 -1
  236. package/dist/assets/ru-BJ0AXHkS.js +0 -1
  237. package/dist/assets/sdk-B1fQwlHL.js +0 -1
  238. package/dist/assets/simple-select-DZdEq8ET.js +0 -1
  239. package/dist/assets/th-CxA-Ohjf.js +0 -1
  240. package/dist/assets/user-center-He8jbYsT.js +0 -79
  241. package/dist/assets/vendor-arcblock-CxRF9kO4.js +0 -2361
  242. package/dist/assets/vendor-mui-core-ClwXKILA.js +0 -266
  243. package/dist/assets/vi-Dp8eof12.js +0 -1
  244. package/dist/assets/wrap-locale-BI93VtNG.js +0 -1
  245. package/dist/assets/zh-D2dwMdph.js +0 -4
  246. package/dist/assets/zh-tw-9pjBCUZn.js +0 -3
  247. /package/api/emails/{components → _components}/copyright.js +0 -0
  248. /package/api/emails/{components → _components}/dapp.js +0 -0
  249. /package/api/emails/{components → _components}/header.js +0 -0
  250. /package/api/emails/{components → _components}/layout.js +0 -0
  251. /package/api/emails/{libs → _libs}/chain.js +0 -0
  252. /package/api/emails/{libs → _libs}/config.js +0 -0
  253. /package/api/emails/{libs → _libs}/constant.js +0 -0
  254. /package/api/emails/{libs → _libs}/explorer-url.js +0 -0
  255. /package/api/emails/{libs → _libs}/func.js +0 -0
  256. /package/api/emails/{libs → _libs}/highlight.js +0 -0
  257. /package/api/emails/{libs → _libs}/style.js +0 -0
  258. /package/api/emails/{libs → _libs}/util.js +0 -0
@@ -1,7 +1,15 @@
1
- const { WELLKNOWN_SERVICE_PATH_PREFIX, SECURITY_RULE_DEFAULT_ID } = require('@abtnode/constant');
1
+ const {
2
+ WELLKNOWN_SERVICE_PATH_PREFIX,
3
+ SECURITY_RULE_DEFAULT_ID,
4
+ ROLES,
5
+ VERIFY_CODE_TTL,
6
+ PASSPORT_STATUS,
7
+ } = require('@abtnode/constant');
8
+ const JWT = require('@arcblock/jwt');
9
+ const { render } = require('@react-email/components');
2
10
  const { messages, getApplicationInfo } = require('@abtnode/auth/lib/auth');
3
11
  const { fromAppDid } = require('@arcblock/did-ext');
4
- const { extractUserAvatar } = require('@abtnode/util/lib/user');
12
+ const { extractUserAvatar, getUserAvatarUrl } = require('@abtnode/util/lib/user');
5
13
  const formatContext = require('@abtnode/util/lib/format-context');
6
14
  const createTranslator = require('@abtnode/util/lib/translate');
7
15
  const { fromBase64 } = require('@ocap/util');
@@ -12,8 +20,9 @@ const merge = require('lodash/merge');
12
20
  const omitBy = require('lodash/omitBy');
13
21
  const omit = require('lodash/omit');
14
22
  const uniq = require('lodash/uniq');
23
+ const last = require('lodash/last');
24
+ const sortBy = require('lodash/sortBy');
15
25
  const { getLastUsedPassport } = require('@abtnode/auth/lib/passport');
16
- const { verify, decode } = require('@arcblock/jwt');
17
26
  const { getWallet } = require('@blocklet/meta/lib/did-utils');
18
27
  const { Joi } = require('@arcblock/validator');
19
28
  const { parse } = require('@abtnode/core/lib/util/ua');
@@ -21,7 +30,11 @@ const { checkInvitedUserOnly } = require('@abtnode/auth/lib/oauth');
21
30
  const getRequestIP = require('@abtnode/util/lib/get-request-ip');
22
31
  const formatError = require('@abtnode/util/lib/format-error');
23
32
  const CustomError = require('@abtnode/util/lib/custom-error');
33
+ const { callFederated } = require('@abtnode/auth/lib/util/federated');
24
34
  const { xss } = require('@blocklet/xss');
35
+ const { withQuery } = require('ufo');
36
+ const cors = require('cors');
37
+
25
38
  const { createTokenFn, getDidConnectVersion } = require('../util');
26
39
  const initJwt = require('../libs/jwt');
27
40
  const { getAvatarByUrl } = require('../libs/auth/utils');
@@ -31,8 +44,13 @@ const { getAvatarByEmail } = require('../libs/auth/utils');
31
44
  const logger = require('../libs/logger')('user');
32
45
  const ensureBlocklet = require('../middlewares/ensure-blocklet');
33
46
  const checkUser = require('../middlewares/check-user');
34
- const { getUserWithinFederated, getUserAvatarUrl } = require('../util/federated');
47
+ const { getUserWithinFederated, getUserAvatarUrl: getRawUserAvatarUrl } = require('../util/federated');
35
48
  const { Profile } = require('../state/profile');
49
+ const { emailSchema } = require('../socket/channel/did');
50
+ const { sendEmail } = require('../libs/email');
51
+ const federatedUtil = require('../util/federated');
52
+ const { VerifyCodeBody } = require('../emails/_templates/verify-code-body');
53
+ const { checkFederatedCall } = require('../middlewares/check-federated');
36
54
 
37
55
  const validateUser = (user) => {
38
56
  try {
@@ -57,12 +75,25 @@ const translations = {
57
75
  needComponentId: '缺少登录参数: componentId',
58
76
  userInfoError: '登录用户信息有误',
59
77
  notExist: '用户不存在',
78
+ //
79
+ emailInvalid: '邮箱格式不正确',
80
+ emailSendSuccess: '验证码发送成功',
81
+ emailAlreadySent: '我们已发送验证电子邮件。请检查您的收件箱或垃圾邮件文件夹。如果您没有看到它,您可以稍后再试。',
82
+ emailVerifySuccess: '邮箱验证成功',
83
+ emailTitle: '登录 {appName}',
60
84
  },
61
85
  en: {
62
86
  notAllowed: 'Your have been revoked access to this blocklet',
63
87
  needComponentId: 'componentId is required when login user',
64
88
  userInfoError: 'Login user info is invalid',
65
89
  notExist: 'User does not exist',
90
+ //
91
+ emailInvalid: 'Invalid email format',
92
+ emailSendSuccess: 'Verification code sent successfully',
93
+ emailAlreadySent:
94
+ "We've sent a verification email. Please check your inbox and spam folder. If you don't see it, you can try again in a few minutes.",
95
+ emailVerifySuccess: 'Email verified successfully',
96
+ emailTitle: 'Login to {appName}',
66
97
  },
67
98
  };
68
99
 
@@ -367,7 +398,7 @@ async function verifyUserSig({ userDid, signature, teamDid, sourceAppPid, userPk
367
398
  const userDidWallet = getWallet(currentUser);
368
399
 
369
400
  // HACK: @zhanghan 钱包传递的签名使用的是 didWallet 账户,但这个账户可能是 原生的 oauth 账户,所以需要找到对应的 did-wallet 账户
370
- const valid = verify(signature, userDidWallet.pk);
401
+ const valid = await JWT.verify(signature, userDidWallet.pk);
371
402
  if (!valid) {
372
403
  throw new Error('invalid signature');
373
404
  }
@@ -395,7 +426,7 @@ function checkUserSig({ node }) {
395
426
  }
396
427
 
397
428
  const userDidWallet = getWallet(user);
398
- const valid = verify(userSig, userDidWallet.pk);
429
+ const valid = await JWT.verify(userSig, userDidWallet.pk);
399
430
  if (!valid) {
400
431
  logger.error('Verify sig failed', {
401
432
  userDid,
@@ -412,7 +443,7 @@ function checkUserSig({ node }) {
412
443
  fullName: user.fullName,
413
444
  walletOS,
414
445
  };
415
- const resData = decode(userSig, true);
446
+ const resData = JWT.decode(userSig, true);
416
447
  // NOTICE: set decode data to req.body, it's not a good practice, but we need it in next middleware
417
448
  req.body = pick(resData, ['notifications']);
418
449
  }
@@ -462,7 +493,7 @@ const profileSetSchema = Joi.object({
462
493
  metadata: Joi.object({
463
494
  email: Joi.string().email().optional(),
464
495
  phone: Joi.object({
465
- phoneNumber: Joi.string().optional(),
496
+ phoneNumber: Joi.string().allow('').optional(),
466
497
  country: Joi.string().optional(),
467
498
  }).optional(),
468
499
  bio: Joi.string().allow('').max(200).optional(),
@@ -501,6 +532,17 @@ const spaceGatewaySchema = Joi.object({
501
532
 
502
533
  module.exports = {
503
534
  init(server, node, options) {
535
+ const ensureCors = cors(async (req, callback) => {
536
+ const domains = await federatedUtil.getTrustedDomains({ node, req, blocklet: req.blocklet });
537
+ const host = req?.get('host') || req?.headers?.host;
538
+ if (domains.includes(host)) {
539
+ callback(null, { origin: true });
540
+ } else {
541
+ callback(null, { origin: false });
542
+ }
543
+ });
544
+
545
+ // 应用后端自行登录逻辑(SDK 中调用)
504
546
  server.post([`${prefix}/login`, `${prefixApi}/login`], verifySig, async (req, res) => {
505
547
  try {
506
548
  const data = await login(req, node, options);
@@ -797,6 +839,365 @@ module.exports = {
797
839
  }
798
840
  );
799
841
 
842
+ // master 帮 member 进行邮件代发
843
+ server.post(
844
+ `${prefixApi}/email/forwardSendCode`,
845
+ ensureBlocklet(),
846
+ checkFederatedCall({ mode: 'memberToMaster', allowStatus: ['approved'] }),
847
+ async (req, res) => {
848
+ const { blocklet, verifyData } = req;
849
+ const teamDid = blocklet.appPid;
850
+ const { subject, code, magicLink, appName, locale } = verifyData;
851
+
852
+ const emailBody = await render(
853
+ VerifyCodeBody({
854
+ code,
855
+ magicLink,
856
+ appName,
857
+ locale,
858
+ })
859
+ );
860
+ const result = await sendEmail(
861
+ subject,
862
+ {
863
+ title: t('emailTitle', locale, { appName }),
864
+ body: emailBody,
865
+ },
866
+ {
867
+ teamDid,
868
+ node,
869
+ locale,
870
+ raw: true,
871
+ launcher: true,
872
+ }
873
+ );
874
+ res.json(result);
875
+ }
876
+ );
877
+
878
+ server.post(`${prefixApi}/email/sendCode`, ensureBlocklet(), ensureCors, async (req, res) => {
879
+ const { locale = 'en' } = req.query;
880
+ const { blocklet } = req;
881
+ const teamDid = blocklet.appPid;
882
+ const { email, useCode = true, useMagicLink = true, sourceAppPid = null } = req.body;
883
+
884
+ const { error, value: subject } = emailSchema.validate(email);
885
+
886
+ if (error) {
887
+ res.status(400).send({ error: t('emailInvalid', locale), code: 'email_invalid' });
888
+ return;
889
+ }
890
+
891
+ if (await node.isSubjectSent({ teamDid, subject })) {
892
+ res.status(400).send({
893
+ error: t('emailAlreadySent', locale),
894
+ code: 'email_already_sent',
895
+ });
896
+ return;
897
+ }
898
+
899
+ const blockletInfo = await req.getBlockletInfo();
900
+ const doc = await node.createVerifyCode({ teamDid, subject, purpose: 'login' });
901
+ const now = Math.floor(Date.now() / 1000);
902
+ const magicLinkToken = JWT.signV2(blockletInfo.wallet.address, blockletInfo.wallet.secretKey, {
903
+ exp: String(now + VERIFY_CODE_TTL),
904
+ data: {
905
+ id: doc.id,
906
+ code: doc.code,
907
+ },
908
+ });
909
+ logger.info('Email login: create verify code', { teamDid, doc });
910
+
911
+ const emailData = {
912
+ appName: blockletInfo.name,
913
+ locale,
914
+ };
915
+ if (useCode) {
916
+ emailData.code = doc.code;
917
+ }
918
+ if (useMagicLink) {
919
+ emailData.magicLink = withQuery(req.get('referer'), {
920
+ magicToken: magicLinkToken,
921
+ sourceAppPid,
922
+ });
923
+ }
924
+
925
+ let result;
926
+ if (sourceAppPid) {
927
+ // 通知 master 去发送邮件
928
+ result = await federatedUtil.sendEmailVerifyCode({
929
+ blocklet,
930
+ blockletInfo,
931
+ request: req,
932
+ params: {
933
+ ...emailData,
934
+ subject,
935
+ },
936
+ });
937
+ } else {
938
+ const emailBody = await render(VerifyCodeBody(emailData));
939
+ result = await sendEmail(
940
+ subject,
941
+ {
942
+ title: t('emailTitle', locale, { appName: blockletInfo.name }),
943
+ body: emailBody,
944
+ },
945
+ {
946
+ teamDid,
947
+ node,
948
+ locale,
949
+ raw: true,
950
+ launcher: true,
951
+ }
952
+ );
953
+ }
954
+
955
+ logger.info('Email login: send verify code', { teamDid, result });
956
+ await node.sendVerifyCode({ teamDid, code: doc.code });
957
+
958
+ // 返回 verify code 的 id,用于后续状态的监听
959
+ res.json({ id: doc.id });
960
+ });
961
+ server.get(`${prefixApi}/email/status`, ensureBlocklet(), ensureCors, async (req, res) => {
962
+ const { codeId } = req.query;
963
+ const { blocklet } = req;
964
+ const teamDid = blocklet.appPid;
965
+ const doc = await node.getVerifyCode({ teamDid, id: codeId });
966
+ logger.info('Email login: check verify code status', { teamDid, codeId, doc });
967
+ if (doc) {
968
+ res.json({ verified: doc.verified, id: doc.id });
969
+ } else {
970
+ res.json({ verified: false, id: undefined });
971
+ }
972
+ });
973
+ server.post(`${prefixApi}/email/login`, ensureBlocklet(), ensureCors, async (req, res) => {
974
+ try {
975
+ const { locale = 'en' } = req.query;
976
+ const { blocklet } = req;
977
+ const teamDid = blocklet.appPid;
978
+ let passport = { name: 'Guest', role: 'guest' };
979
+
980
+ const { code, magicToken, sourceAppPid = null } = req.body;
981
+ const blockletInfo = await req.getBlockletInfo();
982
+ let finalCode = code;
983
+ if (!code && magicToken) {
984
+ const valid = await JWT.verify(magicToken, blockletInfo.wallet.publicKey);
985
+ if (!valid) {
986
+ logger.error('Email login: Invalid magic token', { teamDid, magicToken });
987
+ throw new CustomError(401, 'Invalid magic link');
988
+ }
989
+ const decodeData = JWT.decode(magicToken, true);
990
+ if (!decodeData?.data?.code) {
991
+ logger.error('Email login: failed to parse magicToken data', { teamDid, magicToken, decodeData });
992
+ throw new CustomError(400, 'Invalid magic token format');
993
+ }
994
+ finalCode = decodeData?.data?.code;
995
+ }
996
+ const verifyCodeResult = await node.consumeVerifyCode({ teamDid, code: finalCode });
997
+ if (!verifyCodeResult) {
998
+ throw new CustomError(400, 'Invalid verify code');
999
+ }
1000
+ logger.info('Email login: consume verify code', { teamDid, code, result: verifyCodeResult });
1001
+
1002
+ // 保持跟 oauth 账户的格式一致
1003
+ const sub = `email|${verifyCodeResult.subject}`;
1004
+ let userWallet;
1005
+ if (sourceAppPid) {
1006
+ const masterSite = federatedUtil.getFederatedMaster(blocklet);
1007
+ const { permanentWallet } = blockletInfo;
1008
+ const result = await callFederated({
1009
+ action: 'getUser',
1010
+ site: masterSite,
1011
+ permanentWallet,
1012
+ data: {
1013
+ userSub: sub,
1014
+ },
1015
+ });
1016
+ userWallet = result?.wallet;
1017
+ } else {
1018
+ userWallet = fromAppDid(sub, blockletInfo.wallet.secretKey);
1019
+ }
1020
+
1021
+ const lastLoginIp = getRequestIP(req);
1022
+
1023
+ const userDid = userWallet.address;
1024
+ const userPk = userWallet.publicKey;
1025
+
1026
+ let doc;
1027
+ let passportForLog;
1028
+ let profile;
1029
+ let currentUser = await node.getUser({ teamDid, user: { did: userWallet.address } });
1030
+ const connectedAccount = {
1031
+ provider: LOGIN_PROVIDER.EMAIL,
1032
+ did: userDid,
1033
+ pk: userPk,
1034
+ id: sub,
1035
+ };
1036
+
1037
+ if (currentUser) {
1038
+ profile = {
1039
+ fullName: currentUser.fullName,
1040
+ email: currentUser.email,
1041
+ avatar: currentUser.avatar,
1042
+ };
1043
+ const allPassports = currentUser.passports || [];
1044
+ const validPassports = allPassports.filter((item) => item.status === PASSPORT_STATUS.VALID);
1045
+ const lastUsedPassport = last(sortBy(validPassports, 'lastLoginAt'));
1046
+ passportForLog = lastUsedPassport;
1047
+ if (lastUsedPassport) {
1048
+ passport = pick(lastUsedPassport, ['id', 'name', 'role', 'scope']);
1049
+ }
1050
+ doc = await node.loginUser({
1051
+ teamDid,
1052
+ user: {
1053
+ did: currentUser.did,
1054
+ pk: currentUser.pk,
1055
+ locale,
1056
+ lastLoginIp,
1057
+ sourceAppPid,
1058
+ passport: lastUsedPassport,
1059
+ connectedAccount,
1060
+ },
1061
+ });
1062
+ } else {
1063
+ await checkNeedInvite({ req, node, teamDid, locale });
1064
+ currentUser = {
1065
+ did: userWallet.address,
1066
+ pk: userWallet.publicKey,
1067
+ };
1068
+ const nodeInfo = await req.getNodeInfo();
1069
+ const { dataDir } = await getApplicationInfo({ node, nodeInfo, teamDid });
1070
+ let avatar = await getAvatarByEmail(verifyCodeResult.subject);
1071
+ avatar = await extractUserAvatar(avatar, { dataDir });
1072
+ profile = {
1073
+ fullName: verifyCodeResult.subject.split('@')[0],
1074
+ email: verifyCodeResult.subject,
1075
+ avatar,
1076
+ // email 登录默认认为邮箱已验证
1077
+ emailVerified: true,
1078
+ };
1079
+ // 实际创建用户
1080
+ doc = await node.loginUser({
1081
+ teamDid,
1082
+ user: {
1083
+ did: currentUser.did,
1084
+ pk: currentUser.pk,
1085
+ ...profile,
1086
+ locale,
1087
+ lastLoginIp,
1088
+ sourceAppPid,
1089
+ connectedAccount,
1090
+ },
1091
+ });
1092
+ }
1093
+
1094
+ await node.createAuditLog(
1095
+ {
1096
+ action: 'login',
1097
+ args: {
1098
+ teamDid,
1099
+ userDid: currentUser.did || userDid,
1100
+ passport: passportForLog,
1101
+ provider: LOGIN_PROVIDER.EMAIL,
1102
+ sourceAppPid,
1103
+ },
1104
+ context: formatContext(Object.assign(req, { user: doc })),
1105
+ result: doc,
1106
+ },
1107
+ node
1108
+ );
1109
+
1110
+ const ua = req.get('user-agent');
1111
+ const visitorId = req.get('x-blocklet-visitor-id');
1112
+ const walletDeviceMessageToken = req.get('wallet-device-message-token');
1113
+ const walletDeviceId = req.get('wallet-device-id');
1114
+ const userSessionDoc = await node.upsertUserSession({
1115
+ teamDid,
1116
+ userDid: currentUser.did,
1117
+ visitorId,
1118
+ appPid: teamDid,
1119
+ passportId: passport?.id,
1120
+ status: 'online',
1121
+ ua: null,
1122
+ lastLoginIp,
1123
+ extra: {
1124
+ walletOS: 'web',
1125
+ walletDeviceMessageToken,
1126
+ walletDeviceId,
1127
+ },
1128
+ });
1129
+
1130
+ if (federatedUtil.shouldSyncFederated(sourceAppPid, blocklet)) {
1131
+ const syncUserData = {
1132
+ did: currentUser.did,
1133
+ pk: currentUser.pk,
1134
+ ...profile,
1135
+ avatar: getUserAvatarUrl(blockletInfo.appUrl, profile.avatar),
1136
+ connectedAccount: [connectedAccount],
1137
+ inviter: doc.inviter,
1138
+ };
1139
+ const masterSite = federatedUtil.getFederatedMaster(blocklet);
1140
+
1141
+ node
1142
+ .syncFederated({
1143
+ did: teamDid,
1144
+ data: {
1145
+ users: [
1146
+ {
1147
+ ...syncUserData,
1148
+ action: 'connectAccount',
1149
+ sourceAppPid: sourceAppPid || masterSite?.appPid,
1150
+ },
1151
+ ],
1152
+ },
1153
+ })
1154
+ .then(() => {
1155
+ node.syncUserSession({
1156
+ teamDid,
1157
+ userDid: userSessionDoc.userDid,
1158
+ visitorId: userSessionDoc.visitorId,
1159
+ passportId: passport?.id,
1160
+ targetAppPid: sourceAppPid,
1161
+ ua,
1162
+ lastLoginIp,
1163
+ extra: {
1164
+ walletOS: 'web',
1165
+ walletDeviceMessageToken,
1166
+ walletDeviceId,
1167
+ },
1168
+ });
1169
+ });
1170
+ }
1171
+
1172
+ const { createSessionToken } = initJwt(node, options);
1173
+ const createToken = createTokenFn(createSessionToken);
1174
+ const sessionConfig = blocklet.settings?.session || {};
1175
+ const { sessionToken, refreshToken } = createToken(
1176
+ currentUser.did,
1177
+ {
1178
+ secret: blockletInfo.secret,
1179
+ passport,
1180
+ role: passport.scope === 'passport' ? passport.role : ROLES.GUEST,
1181
+ fullName: doc.fullName,
1182
+ provider: LOGIN_PROVIDER.EMAIL,
1183
+ walletOS: 'web',
1184
+ emailVerified: !!doc?.emailVerified,
1185
+ phoneVerified: !!doc?.phoneVerified,
1186
+ },
1187
+ { ...sessionConfig, didConnectVersion: getDidConnectVersion(req) }
1188
+ );
1189
+
1190
+ return res.status(200).json({
1191
+ sessionToken,
1192
+ refreshToken,
1193
+ visitorId: userSessionDoc.visitorId,
1194
+ });
1195
+ } catch (error) {
1196
+ logger.error('Email login failed', { error });
1197
+ return res.status(400).send(error.message);
1198
+ }
1199
+ });
1200
+
800
1201
  server.put(`${prefixApi}/notification/webhook`, checkUser, ensureBlocklet(), async (req, res) => {
801
1202
  const { value, error } = webhookSetSchema.validate(req.body);
802
1203
  if (error) {
@@ -865,8 +1266,8 @@ module.exports = {
865
1266
  updateData.email = metadata.email;
866
1267
  }
867
1268
 
868
- if (metadata.phone?.phoneNumber) {
869
- updateData.phone = metadata.phone.phoneNumber;
1269
+ if (metadata.phone) {
1270
+ updateData.phone = metadata.phone?.phoneNumber || null;
870
1271
  }
871
1272
  }
872
1273
 
@@ -875,7 +1276,7 @@ module.exports = {
875
1276
  updateData.address = address;
876
1277
  }
877
1278
 
878
- const user = await node.updateUser({
1279
+ const user = await node.updateUserInfoAndSync({
879
1280
  teamDid,
880
1281
  user: updateData,
881
1282
  });
@@ -937,35 +1338,6 @@ module.exports = {
937
1338
  }
938
1339
  );
939
1340
 
940
- // public api
941
- server.get(`${prefixApi}`, ensureBlocklet(), async (req, res) => {
942
- const inputSchema = Joi.DID().required();
943
- const { error, value } = inputSchema.validate(req.query.did);
944
- if (error) {
945
- res.status(400).send({ error: error.details[0].message });
946
- return;
947
- }
948
-
949
- const { blocklet } = req;
950
- const teamDid = blocklet.appPid;
951
- const user = await node.getUser({ teamDid, user: { did: value } });
952
- if (!user || !user?.approved) {
953
- res.status(404).send({ error: 'User not found' });
954
- return;
955
- }
956
- if (user.avatar) {
957
- user.avatar = getUserAvatarUrl(user.avatar, blocklet);
958
- }
959
- let returnFields = ['avatar', 'did', 'fullName', 'sourceAppPid', 'createdAt', 'email', 'phone', 'metadata'];
960
-
961
- // 如果是自己查询,可以返回 address
962
- const reqUser = req.user;
963
- if (reqUser?.did === user.did) {
964
- returnFields = returnFields.concat(['address']);
965
- }
966
- res.json(pick(user, returnFields));
967
- });
968
-
969
1341
  // 支持用户更新 DID Space 信息
970
1342
  server.put(`${prefixApi}/updateDidSpace`, checkUser, ensureBlocklet(), async (req, res) => {
971
1343
  try {
@@ -1043,5 +1415,35 @@ module.exports = {
1043
1415
  res.status(400).send(formatError(err));
1044
1416
  }
1045
1417
  });
1418
+
1419
+ // public api
1420
+ // 获取用户可以公开的信息
1421
+ server.get(`${prefixApi}`, ensureBlocklet(), async (req, res) => {
1422
+ const inputSchema = Joi.DID().required();
1423
+ const { error, value } = inputSchema.validate(req.query.did);
1424
+ if (error) {
1425
+ res.status(400).send({ error: error.details[0].message });
1426
+ return;
1427
+ }
1428
+
1429
+ const { blocklet } = req;
1430
+ const teamDid = blocklet.appPid;
1431
+ const user = await node.getUser({ teamDid, user: { did: value } });
1432
+ if (!user || !user?.approved) {
1433
+ res.status(404).send({ error: 'User not found' });
1434
+ return;
1435
+ }
1436
+ if (user.avatar) {
1437
+ user.avatar = getRawUserAvatarUrl(user.avatar, blocklet);
1438
+ }
1439
+ let returnFields = ['avatar', 'did', 'fullName', 'sourceAppPid', 'createdAt', 'email', 'phone', 'metadata'];
1440
+
1441
+ // 如果是自己查询,可以返回 address
1442
+ const reqUser = req.user;
1443
+ if (reqUser?.did === user.did) {
1444
+ returnFields = returnFields.concat(['address']);
1445
+ }
1446
+ res.json(pick(user, returnFields));
1447
+ });
1046
1448
  },
1047
1449
  };
@@ -26,18 +26,18 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
26
26
 
27
27
  claims: {
28
28
  signature: async ({ extraParams, context: { request, baseUrl, didwallet } }) => {
29
- const { id, locale } = extraParams;
29
+ const { id, locale, inviteId } = extraParams;
30
30
  checkWalletVersion({ didwallet, locale });
31
31
  const nodeInfo = await node.getNodeInfo();
32
32
  const teamDid = request.get('x-blocklet-did');
33
33
 
34
- return createIssuePassportRequest({ node, nodeInfo, teamDid, id, locale, baseUrl });
34
+ return createIssuePassportRequest({ node, nodeInfo, teamDid, id, locale, baseUrl, inviteId });
35
35
  },
36
36
  },
37
37
 
38
38
  onAuth: async ({ userDid, userPk, claims, extraParams, updateSession, req, baseUrl }) => {
39
39
  // NOTICE: 和 did-connect 相关的 visitorId 需要从 extraParams 中获取,不能从 headers 中获取
40
- const { locale, id, visitorId, inviter } = extraParams;
40
+ const { locale, inviteId, id, visitorId, inviter } = extraParams;
41
41
  const sourceAppPid = getSourceAppPid(req);
42
42
  const nodeInfo = await node.getNodeInfo();
43
43
  const blocklet = await req.getBlocklet();
@@ -64,6 +64,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
64
64
  statusEndpointBaseUrl,
65
65
  updateSession,
66
66
  endpoint,
67
+ inviteId,
67
68
  });
68
69
 
69
70
  // NOTICE: 找回通行证的前提是用户已经存在,不存在需要更新 sourceAppPid 的情况,所以不会包含 sourceAppPid 字段
@@ -19,6 +19,7 @@ const getRequestIP = require('@abtnode/util/lib/get-request-ip');
19
19
  const { getBlockletChainInfo, isInProgress } = require('@blocklet/meta/lib/util');
20
20
  const { ROLES, MAIN_CHAIN_ENDPOINT } = require('@abtnode/constant');
21
21
  const { LOGIN_PROVIDER } = require('@blocklet/constant');
22
+ const { PASSPORT_SOURCE, PASSPORT_LOG_ACTION, PASSPORT_ISSUE_ACTION } = require('@abtnode/constant');
22
23
 
23
24
  const { createTokenFn, getDidConnectVersion } = require('../../../util');
24
25
  const logger = require('../../../libs/logger')('blocklet-service:transfer-blocklet-owner');
@@ -238,7 +239,7 @@ module.exports = function createRoutes(node, _, createSessionToken) {
238
239
 
239
240
  const vc = await createPassportVC(vcParams);
240
241
  const role = getRoleFromLocalPassport(get(vc, 'credentialSubject.passport'));
241
- const passport = createUserPassport(vc, { role });
242
+ const passport = createUserPassport(vc, { role, source: PASSPORT_SOURCE.ISSUE });
242
243
 
243
244
  // NOTICE: owner 必须是 did-wallet 账户,这里不应该去查询 connectedAccount
244
245
  const user = await getUser(node, appPid, userDid);
@@ -305,6 +306,21 @@ module.exports = function createRoutes(node, _, createSessionToken) {
305
306
  );
306
307
  }
307
308
 
309
+ if (passport) {
310
+ await node.createPassportLog(
311
+ appPid,
312
+ {
313
+ passportId: passport.id,
314
+ action: PASSPORT_LOG_ACTION.ISSUE,
315
+ operatorDid: userDid,
316
+ metadata: {
317
+ action: PASSPORT_ISSUE_ACTION.ISSUE_ON_RECEIVE_TRANSFER_APP_OWNER,
318
+ },
319
+ },
320
+ req
321
+ );
322
+ }
323
+
308
324
  // NOTICE: must NOT use appDid here if update BLOCKLET_APP_SK
309
325
  await node.configBlocklet(
310
326
  {
@@ -5,6 +5,7 @@ const { getSourceAppPid } = require('@blocklet/sdk/lib/util/login');
5
5
  const { fromBase64 } = require('@ocap/util');
6
6
  const { LOGIN_PROVIDER } = require('@blocklet/constant');
7
7
 
8
+ const { PASSPORT_LOG_ACTION } = require('@abtnode/constant');
8
9
  const logger = require('../../../libs/logger')();
9
10
  const { createTokenFn, getDidConnectVersion } = require('../../../util');
10
11
  const { PASSPORT_VC_TYPES } = require('../../../libs/auth/utils');
@@ -59,11 +60,30 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
59
60
  challenge,
60
61
  types: PASSPORT_VC_TYPES,
61
62
  trustedIssuers: await getTrustedIssuers(blocklet, { sourceAppPid }),
63
+ action: 'verify-destroy',
62
64
  });
65
+
63
66
  if (!ALLOWED_ROLES.includes(role)) {
64
67
  throw new Error(messages.notAllowed[locale]);
65
68
  }
66
69
 
70
+ if (passport) {
71
+ await node.createPassportLog(
72
+ blocklet.appPid,
73
+ {
74
+ passportId: passport.id,
75
+ action: PASSPORT_LOG_ACTION.USED,
76
+ operatorDid: userDid,
77
+ metadata: {
78
+ action: 'verify-destroy',
79
+ ownerDid: userDid,
80
+ userDid: user.did,
81
+ },
82
+ },
83
+ request
84
+ );
85
+ }
86
+
67
87
  const parsed = JSON.parse(fromBase64(payload).toString());
68
88
  const session = await node.startSession({ data: { ...parsed, type: 'destroy', operator: userDid } });
69
89