@abtnode/blocklet-services 1.16.33-beta-20241024-064549-2c1ad302 → 1.16.33-beta-20241028-164124-17cf3c21

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 (306) hide show
  1. package/api/cache.js +39 -0
  2. package/api/index.js +121 -2
  3. package/api/libs/api.js +3 -3
  4. package/api/libs/connect/session.js +44 -53
  5. package/api/libs/kyc.js +9 -0
  6. package/api/libs/push-kit/index.js +17 -2
  7. package/api/middlewares/verify-sig.js +35 -3
  8. package/api/routes/blocklet.js +0 -13
  9. package/api/routes/env.js +2 -2
  10. package/api/routes/oauth.js +11 -7
  11. package/api/routes/user-session.js +38 -23
  12. package/api/routes/user.js +6 -7
  13. package/api/services/auth/index.js +43 -64
  14. package/api/services/kyc/index.js +56 -32
  15. package/api/util/attach-shared-utils.js +113 -19
  16. package/api/util/index.js +13 -12
  17. package/dist/assets/{Add-Bl82G48c.js → Add-DhnwVxhZ.js} +1 -1
  18. package/dist/assets/{Alert-B9Rlqmtk.js → Alert-C2mTW_RW.js} +1 -1
  19. package/dist/assets/{ArrowDropDown-z6CkvFic.js → ArrowDropDown-wj9U9ZE8.js} +1 -1
  20. package/dist/assets/{Autocomplete-C0mtAXbg.js → Autocomplete-CmEAN8J-.js} +1 -1
  21. package/dist/assets/{Avatar-LMc5QpZl.js → Avatar-BZ_OPd3a.js} +1 -1
  22. package/dist/assets/{ButtonGroup-Bvw5eHAy.js → ButtonGroup-CFQqy_jV.js} +1 -1
  23. package/dist/assets/CSSTransition-CJDdpnYB.js +1 -0
  24. package/dist/assets/{CheckCircle-CW1NWF0M.js → CheckCircle-DK6y1v0b.js} +1 -1
  25. package/dist/assets/{ChevronLeft-Bc2dOBpo.js → ChevronLeft-BqHB6tsg.js} +1 -1
  26. package/dist/assets/{ChevronRight-y7cPaDQ3.js → ChevronRight-DwKqpeOS.js} +1 -1
  27. package/dist/assets/{Close-DLWmZbtN.js → Close-CdDd2weK.js} +1 -1
  28. package/dist/assets/{CloseOutlined-7w3yHb7q.js → CloseOutlined-KF-hdrv3.js} +1 -1
  29. package/dist/assets/{Delete-FZyEAOwe.js → Delete-P7WqUbyQ.js} +1 -1
  30. package/dist/assets/{DeleteOutline-B-H27VeQ.js → DeleteOutline-BrrioL98.js} +1 -1
  31. package/dist/assets/{DialogContentText-CiyJlDpv.js → DialogContentText-BECZzyeS.js} +1 -1
  32. package/dist/assets/{Done-BEW0zhw2.js → Done-B8u3JQ36.js} +1 -1
  33. package/dist/assets/{Download-BfRlCRO0.js → Download-DBU6UuKg.js} +1 -1
  34. package/dist/assets/{EditIcon-CG4JGMyT.js → EditIcon-BV3Q9c3s.js} +1 -1
  35. package/dist/assets/{Error-C2cvwDlh.js → Error-CjCi6iqE.js} +1 -1
  36. package/dist/assets/{ExpandMore-CVPXcP59.js → ExpandMore-BjFaf3Fo.js} +1 -1
  37. package/dist/assets/FormControl-B9P20sHZ.js +1 -0
  38. package/dist/assets/FormControlLabel-C2tfmf09.js +1 -0
  39. package/dist/assets/{FormGroup-DoibujUR.js → FormGroup-QeEOGRIO.js} +1 -1
  40. package/dist/assets/{Google-BkswiX56.js → Google-B7LRQAsM.js} +3 -3
  41. package/dist/assets/{Grid-DmS931mb.js → Grid-BArO7d1G.js} +1 -1
  42. package/dist/assets/HelpOutline-It0-5Kn2.js +1 -0
  43. package/dist/assets/{Hidden-DFLNRBK7.js → Hidden-CpExY3Hv.js} +1 -1
  44. package/dist/assets/{InfoOutlined-BGl9NpGF.js → InfoOutlined-DEMaFK-w.js} +1 -1
  45. package/dist/assets/{InputAdornment-BfRAjWFP.js → InputAdornment-BFyVcV9g.js} +1 -1
  46. package/dist/assets/{InputLabel-snet_z2M.js → InputLabel-FW_WnrBG.js} +1 -1
  47. package/dist/assets/{LastPage-KoP1Fd4R.js → LastPage-BbNDF-1B.js} +1 -1
  48. package/dist/assets/{Launch-DaqmeZ7p.js → Launch-CM54bxPy.js} +1 -1
  49. package/dist/assets/{LaunchOutlined-D8_8q_U2.js → LaunchOutlined-DQOUx0IB.js} +1 -1
  50. package/dist/assets/{Link-ZwKMc2xW.js → Link-BLv1ybKR.js} +1 -1
  51. package/dist/assets/ListItemButton-BhIitXNK.js +1 -0
  52. package/dist/assets/{LoadingButton-DAYzECCB.js → LoadingButton-Do8QGr9D.js} +1 -1
  53. package/dist/assets/{LockIcon-CzOlJg7E.js → LockIcon-uGDnriV5.js} +1 -1
  54. package/dist/assets/{Loop-DdSi2a5X.js → Loop-DQX1T4wF.js} +1 -1
  55. package/dist/assets/MarkEmailRead-BdVitMKq.js +1 -0
  56. package/dist/assets/{Menu-cPWOWdJv.js → Menu-B60nijwd.js} +1 -1
  57. package/dist/assets/{MoreHoriz-CCaXi0-D.js → MoreHoriz-Cwgb_ZWA.js} +1 -1
  58. package/dist/assets/MoreVert-6z9sYyBh.js +1 -0
  59. package/dist/assets/{OpenInNew-DhmdNIIA.js → OpenInNew-B7MVFrbE.js} +1 -1
  60. package/dist/assets/Pagination-C8kC-7d4.js +2 -0
  61. package/dist/assets/{PlayArrow-dbaJvP3i.js → PlayArrow-CyW2vtN8.js} +1 -1
  62. package/dist/assets/{QuestionMarkCircle-ClghFyf8.js → QuestionMarkCircle-Dkgs-LrD.js} +1 -1
  63. package/dist/assets/{RadioGroup-h39eYIOw.js → RadioGroup-F9HJgTgP.js} +1 -1
  64. package/dist/assets/{Search-Deg4mgEt.js → Search-Bm4BV5ff.js} +1 -1
  65. package/dist/assets/{Select-D8wgZEYi.js → Select-DN5ZDrhq.js} +2 -2
  66. package/dist/assets/{ServerLogo-C-IdWQab.js → ServerLogo-qj6BKZhH.js} +1 -1
  67. package/dist/assets/{Skeleton-DTHod0yi.js → Skeleton-BHxGQUwb.js} +4 -4
  68. package/dist/assets/{Slider-BGdMADx-.js → Slider-DZmSOFez.js} +1 -1
  69. package/dist/assets/{Stack-Cp3hYWEn.js → Stack-CcM0sATd.js} +1 -1
  70. package/dist/assets/{Stepper-BYg7nOyi.js → Stepper-VAkPR7Rp.js} +1 -1
  71. package/dist/assets/{TextField-COEnibZX.js → TextField-CVbbJh-y.js} +1 -1
  72. package/dist/assets/{Toolbar-gvJQuyml.js → Toolbar-DMWwm961.js} +1 -1
  73. package/dist/assets/{Verified-BYBUZULO.js → Verified-CracX5_0.js} +1 -1
  74. package/dist/assets/{ViewColumn-C-7sjz0Y.js → ViewColumn-cHwmzgaQ.js} +1 -1
  75. package/dist/assets/{ViewList-JViuspE8.js → ViewList-DEr3Y-iU.js} +1 -1
  76. package/dist/assets/access-control-DEaRRq7A.js +13 -0
  77. package/dist/assets/{actions-BvIgnlgP.js → actions-BaCBwrwa.js} +1 -1
  78. package/dist/assets/{add-component-core-CF3Wvpy3.js → add-component-core-CTd25DO_.js} +38 -38
  79. package/dist/assets/add-resource-BcsfLDaF.js +1 -0
  80. package/dist/assets/{addon-BN5Sfj4m.js → addon-B5M4Vtbg.js} +1 -1
  81. package/dist/assets/{analytics-jhEGduS7.js → analytics-DKUh0ZA1.js} +8 -8
  82. package/dist/assets/api-noKs5rUY.js +1 -0
  83. package/dist/assets/ar-2TonDRvZ.js +1 -0
  84. package/dist/assets/ar-j9K5GatZ.js +1 -0
  85. package/dist/assets/audit-logs-DEv30kSD.js +58 -0
  86. package/dist/assets/{base32-RJwtUwTG.js → base32-BbBkrI_s.js} +1 -1
  87. package/dist/assets/{bundle-avatar-CYj37kYo.js → bundle-avatar-DFcMZdHK.js} +1 -1
  88. package/dist/assets/{button-Bzg3GLCP.js → button-WHxIb92N.js} +1 -1
  89. package/dist/assets/{click-to-copy-BxqXxgUi.js → click-to-copy-DSLKklSI.js} +1 -1
  90. package/dist/assets/{complete-DkKqvq-n.js → complete-CAaHcOBS.js} +1 -1
  91. package/dist/assets/{component-CBSn0ylq.js → component-_5q7tWN6.js} +81 -81
  92. package/dist/assets/{config-W5zOORTl.js → config-COlGV3BW.js} +2 -2
  93. package/dist/assets/config-_6fNEXak.js +1 -0
  94. package/dist/assets/{config-navigation-acog9zxt.js → config-navigation-DdfU54Ga.js} +5 -5
  95. package/dist/assets/{confirm-BD8lcIjf.js → confirm-CPhW4Ln4.js} +1 -1
  96. package/dist/assets/{connect-DUt6GuMA.js → connect-CJYVrjZW.js} +1 -1
  97. package/dist/assets/{connect-Cau7HJrv.js → connect-CutE2j6W.js} +1 -1
  98. package/dist/assets/connect-to-ByrmSC7Q.js +54 -0
  99. package/dist/assets/{content-layout--Pzx1mcC.js → content-layout-NMxrW85n.js} +1 -1
  100. package/dist/assets/{dashboard-CIOwnQZx.js → dashboard-yyANkyH0.js} +9 -9
  101. package/dist/assets/de-B1aG8zWS.js +1 -0
  102. package/dist/assets/de-BVh3hwT3.js +1 -0
  103. package/dist/assets/{deprecate-D_97v-_E.js → deprecate-TLU2j5Nl.js} +1 -1
  104. package/dist/assets/{did-address-DgsfKQl1.js → did-address-qp4O986k.js} +1 -1
  105. package/dist/assets/{domain-zy-h52DT.js → domain-BobgkNRn.js} +1 -1
  106. package/dist/assets/{domain-list-tyAcumiG.js → domain-list-nelUcVaZ.js} +2 -2
  107. package/dist/assets/email-BmqNkTVh.js +18 -0
  108. package/dist/assets/emotion-cache.browser.esm-CRw46sQ7.js +1 -0
  109. package/dist/assets/es-B78wkrSg.js +1 -0
  110. package/dist/assets/es-BEwxvJ2s.js +1 -0
  111. package/dist/assets/{exchange-passport-DPiMkxjA.js → exchange-passport-YyjxxQGp.js} +1 -1
  112. package/dist/assets/{fallback-DUmnMg78.js → fallback-DpZp1UKo.js} +1 -1
  113. package/dist/assets/form-text-input-Dnp-THZ5.js +11 -0
  114. package/dist/assets/{format-error-D0C8Qna1.js → format-error-BvNwPRch.js} +1 -1
  115. package/dist/assets/fr-Cvy3dZN3.js +1 -0
  116. package/dist/assets/fr-CyBvbwlz.js +1 -0
  117. package/dist/assets/{fuel-CZZpMc32.js → fuel-DwAfHv3P.js} +1 -1
  118. package/dist/assets/{fullpage-ov1kRa00.js → fullpage-BFccehDH.js} +1 -1
  119. package/dist/assets/hi-CiLl3Zi6.js +1 -0
  120. package/dist/assets/hi-nvWOxhan.js +1 -0
  121. package/dist/assets/{home-gwd5aHrM.js → home-BF01oQMN.js} +1 -1
  122. package/dist/assets/id-Cl0lvxW7.js +1 -0
  123. package/dist/assets/id-FWMMrTxm.js +1 -0
  124. package/dist/assets/{iframe-BIzC7nPA.js → iframe-CGjP6x7t.js} +1 -1
  125. package/dist/assets/index-0R3zcGhj.js +126 -0
  126. package/dist/assets/{index-BcvXX_mO.js → index-4YjFb1t8.js} +1 -1
  127. package/dist/assets/{index-DcKMlzdo.js → index-B1jXhAXk.js} +1 -1
  128. package/dist/assets/{index-rOGdJKYL.js → index-B61Zk4zc.js} +1 -1
  129. package/dist/assets/{index-AfbTuUW5.js → index-B6rU6yZ1.js} +7 -7
  130. package/dist/assets/{index-C_0JNAm2.js → index-BAsIkYmI.js} +1 -1
  131. package/dist/assets/{index-Q7ZUJ_jr.js → index-BEmU10Y0.js} +11 -11
  132. package/dist/assets/index-BFsNvHHz.js +22 -0
  133. package/dist/assets/{index-BjLsHd9C.js → index-BHRFloRH.js} +1 -1
  134. package/dist/assets/index-BZ9M67Kd.js +5 -0
  135. package/dist/assets/{index-COU4Nu6y.js → index-BZKKn0ch.js} +1 -1
  136. package/dist/assets/{index-B-DC1bkM.js → index-BnLNgi5J.js} +1 -1
  137. package/dist/assets/{index-CES_wWCV.js → index-BowU-Rc8.js} +183 -183
  138. package/dist/assets/index-Br6smtqw.js +1 -0
  139. package/dist/assets/{index-bwXQ8Wpi.js → index-BxX33nUX.js} +14 -13
  140. package/dist/assets/{index-B8-zdW7s.js → index-C4-tvqA6.js} +5 -5
  141. package/dist/assets/{index-BqpKWYMh.js → index-C6bJ8C3n.js} +1 -1
  142. package/dist/assets/{index-BJmzQOKo.js → index-CDo-yvx8.js} +1 -1
  143. package/dist/assets/index-C_izWh42.js +11 -0
  144. package/dist/assets/{index-D8OsCndp.js → index-CxykcKWh.js} +1 -1
  145. package/dist/assets/{index-QTPBiLZh.js → index-D0Foc0Tz.js} +1 -1
  146. package/dist/assets/{index-BYSwxOyW.js → index-D5jbzTmg.js} +1 -1
  147. package/dist/assets/index-DH4lKXWs.js +11 -0
  148. package/dist/assets/{index-DsWS2z9f.js → index-DaCSO68v.js} +1 -1
  149. package/dist/assets/{index-XlLZRf68.js → index-DaRP45oo.js} +1 -1
  150. package/dist/assets/{index-Bv4e_rV5.js → index-DbC1wngE.js} +1 -1
  151. package/dist/assets/index-Dnw0yymR.js +1 -0
  152. package/dist/assets/{index-Wi2p68c2.js → index-DsX4E8f1.js} +1 -1
  153. package/dist/assets/{index-C2AukIic.js → index-DtHgjXc_.js} +1 -1
  154. package/dist/assets/{index-DS-kwJv8.js → index-DusV8FU1.js} +1 -1
  155. package/dist/assets/index-FWU8WNJ8.js +1 -0
  156. package/dist/assets/{index-BA1E4qQ4.js → index-LmZHdjQZ.js} +1 -1
  157. package/dist/assets/{index-CE4JYDnG.js → index-RHJlosGb.js} +4 -4
  158. package/dist/assets/index-_uCAkv_0.js +316 -0
  159. package/dist/assets/{index-CNybmfDH.js → index-dmc3Tzez.js} +1 -1
  160. package/dist/assets/{index.es-HA92kWdG.js → index.es-DjXtuSXa.js} +3 -3
  161. package/dist/assets/{invitation-B49_oImo.js → invitation-CitdNTlE.js} +1 -1
  162. package/dist/assets/{invite-V3Nbkyr9.js → invite-8bX-82iQ.js} +1 -1
  163. package/dist/assets/isEmail-DlDmj0fr.js +1 -0
  164. package/dist/assets/{issue-passport-BK_rmsMU.js → issue-passport-DlN6RZob.js} +1 -1
  165. package/dist/assets/{item-ChdkonTR.js → item-CKNXAp6H.js} +1 -1
  166. package/dist/assets/ja-Be6ZrJ3j.js +1 -0
  167. package/dist/assets/ja-Uy7OpVJX.js +1 -0
  168. package/dist/assets/{jss-plugin-props-sort.esm-DBVL9gMW.js → jss-plugin-props-sort.esm-DoSjjNR1.js} +5 -5
  169. package/dist/assets/ko-631_NPZL.js +1 -0
  170. package/dist/assets/ko-RAcT5Den.js +1 -0
  171. package/dist/assets/{launch-result-message-BAr02bV5.js → launch-result-message-JFKmiVbN.js} +1 -1
  172. package/dist/assets/{layout-bf8MnH7p.js → layout-DEXenHhy.js} +1 -1
  173. package/dist/assets/{list-header-BdXS3bwO.js → list-header-7vVYIW_T.js} +1 -1
  174. package/dist/assets/localization-DdE_yTeV.js +1 -0
  175. package/dist/assets/{log-CEafQKJ9.js → log-ZCJiZb-D.js} +1 -1
  176. package/dist/assets/{login-CEkmeGqM.js → login-64rLho-5.js} +1 -1
  177. package/dist/assets/{login-oauth-callback-BKsN-may.js → login-oauth-callback-nOgNHNCk.js} +1 -1
  178. package/dist/assets/logo-uploader-Cz1267Av.js +133 -0
  179. package/dist/assets/{lost-passport-BKV23uoE.js → lost-passport-DjJtlNVj.js} +3 -3
  180. package/dist/assets/{lottie-Bmh0Xil_.js → lottie-DoYE5XDB.js} +1 -1
  181. package/dist/assets/notifications-Cv1XH2yb.js +65 -0
  182. package/dist/assets/{open-window-BxfESFgZ.js → open-window-CN5TQ87C.js} +1 -1
  183. package/dist/assets/overview-kalRt_uR.js +12 -0
  184. package/dist/assets/{page-header-C6Www8xa.js → page-header-BmLNlOnD.js} +1 -1
  185. package/dist/assets/{permission-C0wbV6KF.js → permission-DUsbjffq.js} +1 -1
  186. package/dist/assets/{preferences-DgOndnl4.js → preferences-ZO1kLbOx.js} +1 -1
  187. package/dist/assets/pt-BlLvTTrm.js +1 -0
  188. package/dist/assets/pt-CTpkGCgP.js +1 -0
  189. package/dist/assets/publish-resource-B2rKe7a9.js +1 -0
  190. package/dist/assets/purify.es-Bq0E5Q3l.js +2 -0
  191. package/dist/assets/react-BTu1Y-_j.js +56 -0
  192. package/dist/assets/{redux-B8mroqAb.js → redux-CJ8S87pk.js} +1 -1
  193. package/dist/assets/refType-CT_vAXIZ.js +1 -0
  194. package/dist/assets/resource-dialog-D_8tTarn.js +4 -0
  195. package/dist/assets/ru-Culp1KLs.js +1 -0
  196. package/dist/assets/ru-sSBv7F2t.js +1 -0
  197. package/dist/assets/sdk-C3SAOjUt.js +1 -0
  198. package/dist/assets/{selector-B2UrJyEC.js → selector-Rhni_cbO.js} +3 -3
  199. package/dist/assets/session-4S4FY2oN.js +1 -0
  200. package/dist/assets/setup-BQ-DnQht.js +19 -0
  201. package/dist/assets/{shorten-label-C69K-2N4.js → shorten-label-8aKNnW15.js} +1 -1
  202. package/dist/assets/simple-select-CNSx0Qbg.js +1 -0
  203. package/dist/assets/{slicedToArray-Btbq_uXo.js → slicedToArray-vg-R5s0s.js} +2 -2
  204. package/dist/assets/{spaces-CKA3haGw.js → spaces-BcZSz_wm.js} +1 -1
  205. package/dist/assets/{start-E4q8KtSK.js → start-CqQHbsvY.js} +1 -1
  206. package/dist/assets/{step-actions-Dv65pQs7.js → step-actions-DV3o9hve.js} +1 -1
  207. package/dist/assets/{studio-C9Z81BQt.js → studio-D_pIJx8G.js} +1 -1
  208. package/dist/assets/{switch-control-Cct9SW8-.js → switch-control-C-X_dl1C.js} +1 -1
  209. package/dist/assets/th-Dqms8yb0.js +1 -0
  210. package/dist/assets/th-Dv20telW.js +1 -0
  211. package/dist/assets/{toUpper-DjVC4j_j.js → toUpper-CqfCm6FQ.js} +1 -1
  212. package/dist/assets/{transfer-W8UlEJt-.js → transfer-CSfZjjyt.js} +1 -1
  213. package/dist/assets/trim-CXCEOOfq.js +1 -0
  214. package/dist/assets/{uniqBy-BzzuWGYh.js → uniqBy--m6Xe_2K.js} +1 -1
  215. package/dist/assets/{unsubscribe-BkeOgqWI.js → unsubscribe-BJWyVFrT.js} +1 -1
  216. package/dist/assets/{url-join-BLh7jCrJ.js → url-join-CAnJBM33.js} +1 -1
  217. package/dist/assets/use-blocklet-info-for-connect-did-spaces-BWR6SXSQ.js +1 -0
  218. package/dist/assets/{use-mobile-BJoJTGF0.js → use-mobile-BBtcVjXr.js} +1 -1
  219. package/dist/assets/{useAsync-CvPpFYs-.js → useAsync-DTvP9Zxi.js} +1 -1
  220. package/dist/assets/{useFormControl-BXRE7Su9.js → useFormControl-CqDUGVwx.js} +1 -1
  221. package/dist/assets/{useLocalStorage-BJH73q2r.js → useLocalStorage-BSk8yrmI.js} +1 -1
  222. package/dist/assets/{useSetState-CJBhbXdV.js → useSetState-Dvi1U0Nw.js} +1 -1
  223. package/dist/assets/useSlot-CBvar7i-.js +1 -0
  224. package/dist/assets/{useSlotProps-Bo-Lx2a7.js → useSlotProps-BO61t83_.js} +1 -1
  225. package/dist/assets/useThemeProps-BVeww5NE.js +1 -0
  226. package/dist/assets/user-center-DxinbhvA.js +1 -0
  227. package/dist/assets/{user-sessions-9jxxDLYT.js → user-sessions-BGeFoCxv.js} +1 -1
  228. package/dist/assets/{util-ZHGnEGmF.js → util-DQZs28G6.js} +1 -1
  229. package/dist/assets/vi-B-VzHaKw.js +1 -0
  230. package/dist/assets/vi-DjcU4tKh.js +1 -0
  231. package/dist/assets/wrap-locale-B-fXOOcn.js +1 -0
  232. package/dist/assets/zh-DWYwLndz.js +1 -0
  233. package/dist/assets/zh-tw-3Ki06u1b.js +1 -0
  234. package/dist/assets/zh-tw-B7lbXLVn.js +1 -0
  235. package/dist/assets/zh-u8iElwOC.js +2 -0
  236. package/dist/index.html +1 -1
  237. package/dist/service-worker.js +1 -1
  238. package/package.json +30 -27
  239. package/api/util/get-dynamic-service-config.js +0 -48
  240. package/dist/assets/Edit-Cbvlvh2w.js +0 -11
  241. package/dist/assets/FormControl-vM9EJwp4.js +0 -1
  242. package/dist/assets/FormControlLabel-CS28YgVs.js +0 -1
  243. package/dist/assets/MoreVert-D4SS6MnA.js +0 -1
  244. package/dist/assets/Pagination-BXlUtx3B.js +0 -2
  245. package/dist/assets/access-control-BDg9FQV3.js +0 -13
  246. package/dist/assets/add-resource-DLKAe3re.js +0 -1
  247. package/dist/assets/api-JbjuY7JN.js +0 -1
  248. package/dist/assets/ar-BcsWe-M7.js +0 -1
  249. package/dist/assets/ar-rur8F6ox.js +0 -1
  250. package/dist/assets/audit-logs-Vn5iZ4P_.js +0 -58
  251. package/dist/assets/config-ONP_4X_B.js +0 -1
  252. package/dist/assets/connect-to-GhSR8jRw.js +0 -54
  253. package/dist/assets/de-C-5DrcsF.js +0 -1
  254. package/dist/assets/de-f8XZAb4q.js +0 -1
  255. package/dist/assets/email-BINRPUSY.js +0 -18
  256. package/dist/assets/emotion-cache.browser.esm-ByukGais.js +0 -1
  257. package/dist/assets/es-CDmziQ2d.js +0 -1
  258. package/dist/assets/es-Dkw0SgdE.js +0 -1
  259. package/dist/assets/fr-CutjrzQz.js +0 -1
  260. package/dist/assets/fr-RdOP2uWC.js +0 -1
  261. package/dist/assets/hi-BwtTylyX.js +0 -1
  262. package/dist/assets/hi-V6iw7v5V.js +0 -1
  263. package/dist/assets/id-CeB6Ugb-.js +0 -1
  264. package/dist/assets/id-Dz8dfVhg.js +0 -1
  265. package/dist/assets/index-BHXHtIJm.js +0 -126
  266. package/dist/assets/index-CXg0jLCN.js +0 -11
  267. package/dist/assets/index-DW7dwoqE.js +0 -11
  268. package/dist/assets/index-DmdwpBJN.js +0 -261
  269. package/dist/assets/index-DqHzmyne.js +0 -68
  270. package/dist/assets/index-HqFqdQ4r.js +0 -1
  271. package/dist/assets/index-RVvYAb40.js +0 -1
  272. package/dist/assets/index-wVSweHe6.js +0 -1
  273. package/dist/assets/index.esm-S4QOHn5V.js +0 -1
  274. package/dist/assets/ja-BZrZ4ULY.js +0 -1
  275. package/dist/assets/ja-DlWywLev.js +0 -1
  276. package/dist/assets/ko-DLaz-pjP.js +0 -1
  277. package/dist/assets/ko-ESHUwy9c.js +0 -1
  278. package/dist/assets/localization-BlAk-2Dh.js +0 -1
  279. package/dist/assets/logo-uploader-DO_ePInN.js +0 -122
  280. package/dist/assets/mode-B2dWMeTO.js +0 -1
  281. package/dist/assets/notifications-CDn5GICo.js +0 -62
  282. package/dist/assets/overview-DvxryhGu.js +0 -12
  283. package/dist/assets/pt-BMSFPKAT.js +0 -1
  284. package/dist/assets/pt-CysEhQ_Z.js +0 -1
  285. package/dist/assets/publish-resource-BK8LfyYg.js +0 -1
  286. package/dist/assets/react-DWdAOKA_.js +0 -57
  287. package/dist/assets/resource-dialog-CxQ2RdqX.js +0 -57
  288. package/dist/assets/ru-2aTr2i-M.js +0 -1
  289. package/dist/assets/ru-C-IO4heq.js +0 -1
  290. package/dist/assets/sdk-BzFjs0zU.js +0 -1
  291. package/dist/assets/session-CPw6Z6tL.js +0 -1
  292. package/dist/assets/setup-C-eSKhTS.js +0 -19
  293. package/dist/assets/th-Bd6_ise5.js +0 -1
  294. package/dist/assets/th-D2W7tb3N.js +0 -1
  295. package/dist/assets/trim-pCqXvQz3.js +0 -1
  296. package/dist/assets/use-blocklet-info-for-connect-did-spaces-BfIvMuGO.js +0 -1
  297. package/dist/assets/useSlot-BnpRF9Wf.js +0 -1
  298. package/dist/assets/useThemeProps-NLTP4qET.js +0 -1
  299. package/dist/assets/user-center-DSwKYf1W.js +0 -1
  300. package/dist/assets/vi-BrQQz2Dk.js +0 -1
  301. package/dist/assets/vi-DTSqGMo-.js +0 -1
  302. package/dist/assets/wrap-locale-De5w1_ZO.js +0 -1
  303. package/dist/assets/zh-BUjxGa7K.js +0 -1
  304. package/dist/assets/zh-CT0fSzRS.js +0 -2
  305. package/dist/assets/zh-tw-GFcs7F29.js +0 -1
  306. package/dist/assets/zh-tw-i93Px0uV.js +0 -1
@@ -1,6 +1,11 @@
1
1
  const { handleInvitationReceive, getApplicationInfo } = require('@abtnode/auth/lib/auth');
2
2
  const { upsertToPassports, createPassportSvg } = require('@abtnode/auth/lib/passport');
3
- const { WELLKNOWN_SERVICE_PATH_PREFIX, NODE_SERVICES, PASSPORT_STATUS, ROLES } = require('@abtnode/constant');
3
+ const {
4
+ WELLKNOWN_SERVICE_PATH_PREFIX,
5
+ PASSPORT_STATUS,
6
+ ROLES,
7
+ SECURITY_RULE_DEFAULT_ID,
8
+ } = require('@abtnode/constant');
4
9
  const { extractUserAvatar, getUserAvatarUrl, getAppAvatarUrl } = require('@abtnode/util/lib/user');
5
10
  const { fromAppDid } = require('@arcblock/did-ext');
6
11
  const { getBlockletAppIdList } = require('@blocklet/meta/lib/util');
@@ -28,7 +33,7 @@ const OAuthApple = require('../libs/auth/adapters/apple');
28
33
  const { getAvatarByEmail, transferPassport, getAvatarByUrl } = require('../libs/auth/utils');
29
34
  const initJwt = require('../libs/jwt');
30
35
  const { sendToUser } = require('../libs/notification');
31
- const { isInvitedUserOnly, createTokenFn, getDidConnectVersion, redirectWithoutCache } = require('../util');
36
+ const { checkInvitedUserOnly, createTokenFn, getDidConnectVersion, redirectWithoutCache } = require('../util');
32
37
  const { ApiError } = require('../util/error');
33
38
  const federatedUtil = require('../util/federated');
34
39
  const { isOAuthEmailVerified, isEmailUniqueRequired, isEmailKycRequired, isSameEmail } = require('../libs/kyc');
@@ -172,7 +177,7 @@ function getAuthClient(blocklet, provider, { legacy = false, appPid } = {}) {
172
177
 
173
178
  async function login(req, node, options) {
174
179
  const blocklet = await req.getBlocklet();
175
- const { locale = 'en', provider, componentId, inviter = null, sourceAppPid = null } = req.body;
180
+ const { locale = 'en', provider, inviter = null, sourceAppPid = null } = req.body;
176
181
  let visitorId = req.body?.visitorId;
177
182
  if (!visitorId) {
178
183
  visitorId = req.get('x-blocklet-visitor-id');
@@ -189,11 +194,10 @@ async function login(req, node, options) {
189
194
  const userDid = userWallet.address;
190
195
  const userPk = userWallet.publicKey;
191
196
 
192
- // FIXME: @zhanghan 这里通过 componentId 来判断权限的方式实际上没有意义,因为用户可以尝试从别的 url 来登录
193
- const config = await req.getServiceConfig(NODE_SERVICES.AUTH, { componentId });
197
+ const { accessPolicyConfig } = await req.getSecurityConfig({ id: SECURITY_RULE_DEFAULT_ID });
194
198
  const nodeInfo = await req.getNodeInfo();
195
199
  const { dataDir } = await getApplicationInfo({ node, nodeInfo, teamDid });
196
- const [invitedUserOnly] = await isInvitedUserOnly(config, node, teamDid);
200
+ const isInvitedUserOnly = await checkInvitedUserOnly(accessPolicyConfig, node, teamDid);
197
201
 
198
202
  const lastLoginIp = getRequestIP(req);
199
203
  let passport = { name: 'Guest', role: 'guest' };
@@ -248,7 +252,7 @@ async function login(req, node, options) {
248
252
  let avatar = oauthInfo.picture ? await getAvatarByUrl(oauthInfo.picture) : await getAvatarByEmail(oauthInfo.email);
249
253
  avatar = await extractUserAvatar(avatar, { dataDir });
250
254
  // 当前 oauth 账户不存在,自动添加一个新用户
251
- if (invitedUserOnly) {
255
+ if (isInvitedUserOnly) {
252
256
  throw new ApiError(403, t('needInviteToLogin', locale));
253
257
  }
254
258
 
@@ -93,27 +93,27 @@ module.exports = {
93
93
  // NOTE: 保留 /login 路由,该功能不是针对于某一个实体来操作的,需要更明确表达意图
94
94
  app.post(`${prefix}/login`, ensureBlocklet(), async (req, res) => {
95
95
  const { blocklet } = req;
96
- const { userDid, appPid, passportId } = req.body;
96
+ const loginUserSession = req.body;
97
97
  let visitorId = req.body?.visitorId;
98
98
  if (!visitorId) {
99
99
  visitorId = req.get('x-blocklet-visitor-id');
100
100
  }
101
101
 
102
- if (!userDid) {
102
+ if (!loginUserSession.userDid) {
103
103
  res.status(400).json({ error: 'userDid is required' });
104
104
  return;
105
105
  }
106
- if (!appPid) {
106
+ if (!loginUserSession.appPid) {
107
107
  res.status(400).json({ error: 'appPid is required' });
108
108
  return;
109
109
  }
110
110
 
111
111
  const teamDid = blocklet.appPid;
112
-
113
112
  const userSessions = await node.getUserSession({
114
113
  teamDid,
115
- userDid,
114
+ userDid: loginUserSession.userDid,
116
115
  visitorId,
116
+ id: loginUserSession.id,
117
117
  });
118
118
  const now = Date.now();
119
119
  const sessionTtl = blocklet.settings?.session?.ttl || SESSION_TTL;
@@ -122,7 +122,7 @@ module.exports = {
122
122
  const validSession = sortedUserSessions.some((x) => now - new Date(x.updatedAt).getTime() < sessionTtl * 1000);
123
123
 
124
124
  if (validSession) {
125
- const user = await node.getUser({ teamDid, user: { did: userDid } });
125
+ const user = await node.getUser({ teamDid, user: { did: loginUserSession.userDid } });
126
126
  if (!user.approved) {
127
127
  res.status(401).json(messages.notAllowedAppUser.en);
128
128
  return;
@@ -138,7 +138,9 @@ module.exports = {
138
138
 
139
139
  const provider = sourceProvider || LOGIN_PROVIDER.WALLET;
140
140
 
141
- const memberSite = federated.sites.find((item) => item.appPid === appPid && item.isMaster === false);
141
+ const memberSite = federated.sites.find(
142
+ (item) => item.appPid === loginUserSession.appPid && item.isMaster === false
143
+ );
142
144
  const postUser = pick(user, ['did', 'pk', 'fullName', 'locale', 'inviter', 'generation']);
143
145
  postUser.lastLoginAt = getRequestIP(req);
144
146
 
@@ -160,7 +162,7 @@ module.exports = {
160
162
  did: teamDid,
161
163
  data: {
162
164
  user: postUser,
163
- passport: passportId ? { id: passportId } : undefined,
165
+ passport: loginUserSession.passportId ? { id: loginUserSession.passportId } : undefined,
164
166
  walletOS,
165
167
  provider,
166
168
  },
@@ -179,7 +181,9 @@ module.exports = {
179
181
  const createToken = createTokenFn(createSessionToken);
180
182
  const { secret } = await req.getBlockletInfo();
181
183
  const sessionConfig = blocklet.settings?.session || {};
182
- const targetPassport = passportId ? (user?.passports || []).find((item) => item.id === passportId) : null;
184
+ const targetPassport = loginUserSession.passportId
185
+ ? (user?.passports || []).find((item) => item.id === loginUserSession.passportId)
186
+ : null;
183
187
  const loggedInUser = await node.loginUser({
184
188
  teamDid,
185
189
  user: {
@@ -219,11 +223,12 @@ module.exports = {
219
223
  const walletDeviceId = req.get('wallet-device-id');
220
224
 
221
225
  const userSessionDoc = await node.upsertUserSession({
226
+ id: loginUserSession.id,
222
227
  teamDid,
223
- userDid,
228
+ userDid: loginUserSession.userDid,
224
229
  visitorId,
225
- appPid,
226
- passportId,
230
+ appPid: loginUserSession.appPid,
231
+ passportId: loginUserSession.passportId,
227
232
  status: 'online',
228
233
  ua,
229
234
  lastLoginIp,
@@ -237,10 +242,10 @@ module.exports = {
237
242
  if (isFederatedLogin) {
238
243
  node.syncUserSession({
239
244
  teamDid,
240
- userDid,
245
+ userDid: loginUserSession.userDid,
241
246
  visitorId: userSessionDoc.visitorId,
242
- passportId,
243
- targetAppPid: appPid,
247
+ passportId: loginUserSession.passportId,
248
+ targetAppPid: loginUserSession.appPid,
244
249
  ua,
245
250
  lastLoginIp,
246
251
  extra: {
@@ -254,9 +259,9 @@ module.exports = {
254
259
  logger.info('quick-login with', {
255
260
  teamDid,
256
261
  visitorId,
257
- userDid,
258
- appPid,
259
- passportId,
262
+ userDid: loginUserSession.userDid,
263
+ appPid: loginUserSession.appPid,
264
+ passportId: loginUserSession.passportId,
260
265
  extra: {
261
266
  walletOS,
262
267
  },
@@ -267,17 +272,22 @@ module.exports = {
267
272
  logger.warn('failed to quick-login with', {
268
273
  teamDid,
269
274
  visitorId,
270
- userDid,
271
- appPid,
272
- passportId,
275
+ userDid: loginUserSession.userDid,
276
+ appPid: loginUserSession.appPid,
277
+ passportId: loginUserSession.passportId,
273
278
  });
274
- res.status(403).json({ error: 'session expired' });
279
+ res.status(401).json({ error: 'session expired' });
275
280
  }
276
281
  });
277
282
 
283
+ /**
284
+ * 获取指定用户的所有登录会话
285
+ */
278
286
  app.get(`${prefix}`, ensureBlocklet(), async (req, res) => {
279
287
  const { blocklet } = req;
280
288
  const teamDid = blocklet.appPid;
289
+ const requestIp = getRequestIP(req);
290
+ const userAgent = req.get('user-agent');
281
291
 
282
292
  // NOTICE: 此处的 visitorId 必须显式传入,否则用户将无法正常查询自己的所有 sessions
283
293
  const { userDid, appPid, visitorId } = req.query;
@@ -308,7 +318,12 @@ module.exports = {
308
318
 
309
319
  // NOTICE: 移除 walletDeviceId 和 walletDeviceMessageToken,避免泄露
310
320
  const result = userSessions
311
- .filter((x) => x?.user?.approved)
321
+ .filter((x) => {
322
+ if (x.lastLoginIp !== requestIp || x.ua !== userAgent || x.status === 'expired') {
323
+ return false;
324
+ }
325
+ return x?.user?.approved;
326
+ })
312
327
  .map((x) => {
313
328
  return omit(x, ['extra.walletDeviceId', 'extra.walletDeviceMessageToken']);
314
329
  });
@@ -1,4 +1,4 @@
1
- const { NODE_SERVICES, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
1
+ const { WELLKNOWN_SERVICE_PATH_PREFIX, SECURITY_RULE_DEFAULT_ID } = require('@abtnode/constant');
2
2
  const { getApplicationInfo } = require('@abtnode/auth/lib/auth');
3
3
  const { fromAppDid } = require('@arcblock/did-ext');
4
4
  const { extractUserAvatar } = require('@abtnode/util/lib/user');
@@ -17,7 +17,7 @@ const { Joi } = require('@arcblock/validator');
17
17
  const { parse } = require('@abtnode/core/lib/util/ua');
18
18
  const getRequestIP = require('@abtnode/util/lib/get-request-ip');
19
19
 
20
- const { isInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../util');
20
+ const { checkInvitedUserOnly, createTokenFn, getDidConnectVersion } = require('../util');
21
21
  const initJwt = require('../libs/jwt');
22
22
  const { getAvatarByUrl } = require('../libs/auth/utils');
23
23
  const { ApiError } = require('../util/error');
@@ -61,10 +61,10 @@ const translations = {
61
61
 
62
62
  const t = createTranslator({ translations });
63
63
 
64
- async function checkNeedInvite({ req, node, teamDid, componentId, locale }) {
65
- const config = await req.getServiceConfig(NODE_SERVICES.AUTH, { componentId });
66
- const [invitedUserOnly] = await isInvitedUserOnly(config, node, teamDid);
67
- if (invitedUserOnly) {
64
+ async function checkNeedInvite({ req, node, teamDid, locale }) {
65
+ const { accessPolicyConfig } = await req.getSecurityConfig({ id: SECURITY_RULE_DEFAULT_ID });
66
+ const isInvitedUserOnly = await checkInvitedUserOnly(accessPolicyConfig, node, teamDid);
67
+ if (isInvitedUserOnly) {
68
68
  throw new ApiError(403, t('needInviteToLogin', locale));
69
69
  }
70
70
  }
@@ -467,7 +467,6 @@ module.exports = {
467
467
  if (error) {
468
468
  throw new ApiError(400, error.message);
469
469
  }
470
- // FIXME: @zhanghan 需要根据 componentId 来判断当前 component 设置的访问权限,来看当前要登录的用户是否有登录的权限
471
470
  const blocklet = await req.getBlocklet();
472
471
  const { did: teamDid, secret } = await req.getBlockletInfo();
473
472
  const currentUser = await verifyUserSig(
@@ -4,17 +4,9 @@ const cookie = require('cookie');
4
4
  const bearerToken = require('@abtnode/util/lib/express-bearer-token');
5
5
 
6
6
  const validators = require('@blocklet/sdk/lib/validators');
7
- const {
8
- genPermissionName,
9
- NODE_SERVICES,
10
- WHO_CAN_ACCESS,
11
- WHO_CAN_ACCESS_PREFIX_ROLES,
12
- ROLES,
13
- WELLKNOWN_SERVICE_PATH_PREFIX,
14
- } = require('@abtnode/constant');
7
+ const { NODE_SERVICES, ROLES, WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
15
8
  const { BLOCKLET_MODES } = require('@blocklet/constant');
16
9
  const { setUserInfoHeaders } = require('@abtnode/auth/lib/auth');
17
- const { getRolesFromAuthConfig } = require('@blocklet/meta/lib/util');
18
10
 
19
11
  const { createConnectToDidSpacesRoute } = require('@abtnode/auth/lib/connect-to-did-spaces');
20
12
  const logger = require('../../libs/logger')('auth');
@@ -45,7 +37,7 @@ const createSessionRoutes = require('./session');
45
37
  const createPassportRoutes = require('./passport');
46
38
  const { getRedirectUrl, shouldIgnoreUrl, redirectWithoutCache } = require('../../util');
47
39
  const { createConnectToDidSpacesForUserRoute } = require('./connect/connect-to-did-spaces-for-user');
48
- const { isEmailKycRequired } = require('../../libs/kyc');
40
+ const { isEmailKycRequired, isPhoneKycRequired } = require('../../libs/kyc');
49
41
 
50
42
  const getTokenFromWsConnect = (req, options) => {
51
43
  const cookies = cookie.parse(req.headers.cookie || '');
@@ -90,9 +82,9 @@ const init = ({ node, options }) => {
90
82
  * @returns {CheckAuthRes} res
91
83
  */
92
84
  const checkAuth = async ({ req } = {}) => {
93
- const config = (await req.getServiceConfig(NODE_SERVICES.AUTH)) || {};
85
+ const serviceConfig = (await req.getServiceConfig(NODE_SERVICES.AUTH)) || {};
94
86
 
95
- const ignoreUrls = (get(config, 'ignoreUrls') || []).filter(Boolean);
87
+ const ignoreUrls = (get(serviceConfig, 'ignoreUrls') || []).filter(Boolean);
96
88
 
97
89
  // default public url
98
90
  // developers need not config the following urls in blocklet.yml
@@ -105,47 +97,35 @@ const init = ({ node, options }) => {
105
97
 
106
98
  const teamDid = req.getBlockletDid();
107
99
 
108
- // 所有人都可以访问的情况
109
- if (!config.whoCanAccess || config.whoCanAccess === WHO_CAN_ACCESS.ALL) {
110
- if (config.blockUnauthenticated && !req.user) {
111
- return {
112
- blocked: true,
113
- authenticated: false,
114
- };
115
- }
116
- } else if (!req.user) {
117
- // 需要被邀请才能访问的情况
118
- const rbac = await node.getRBAC(teamDid);
119
- const allRoles = await rbac.getRoles(teamDid);
100
+ const rbac = await node.getRBAC(teamDid);
101
+ const [allRoles, { accessPolicyConfig }] = await Promise.all([rbac.getRoles(teamDid), req.getSecurityConfig()]);
102
+
103
+ const accessRoles = accessPolicyConfig?.accessPolicy?.roles || null;
104
+ const accessReverse = accessPolicyConfig?.accessPolicy?.reverse || false;
105
+
106
+ // public 公开权限,不做任何拦截
107
+ if (accessRoles === null && accessReverse === false) {
108
+ return { ignored: true };
109
+ }
110
+
111
+ // invite only, 需要被邀请才能访问的情况
112
+ // HACK: 不是公开的情况下,就是需要有通行证才能访问,此时只需要判断 req.user 是否存在即可
113
+ // if (accessRoles.length === 0 && accessReverse === true) {}
114
+ if (!req.user) {
120
115
  const payableRole = allRoles.find((x) => x.extra?.acquire?.pay);
121
116
  return {
122
117
  blocked: true,
123
118
  authenticated: false,
124
119
  payable: payableRole?.extra?.acquire?.pay,
125
120
  };
126
- } else if (config.whoCanAccess === WHO_CAN_ACCESS.OWNER && req.user.role !== ROLES.OWNER) {
127
- // 需要 owner 才能访问
128
- return {
129
- blocked: true,
130
- authenticated: true,
131
- authorized: false,
132
- requiredRoles: [
133
- {
134
- name: ROLES.OWNER,
135
- title: 'Owner',
136
- description: 'Owner',
137
- },
138
- ],
139
- };
140
- } else if (config.whoCanAccess.startsWith(WHO_CAN_ACCESS_PREFIX_ROLES)) {
141
- // 指定 passport 才能访问
142
- // 需要用户拥有的权限
143
- const roles = getRolesFromAuthConfig(config);
144
- if (!roles.includes(req.user.role)) {
145
- const rbac = await node.getRBAC(teamDid);
146
- // 系统中的所有权限
147
- const allRoles = await rbac.getRoles(teamDid);
121
+ }
148
122
 
123
+ // 指定 role 访问权限
124
+ if (accessRoles.length > 0) {
125
+ const roles = accessReverse
126
+ ? allRoles.filter((role) => !accessRoles.includes(role.name)).map((role) => role.name)
127
+ : accessRoles;
128
+ if (!roles.includes(req.user.role)) {
149
129
  return {
150
130
  blocked: true,
151
131
  authenticated: true,
@@ -176,22 +156,6 @@ const init = ({ node, options }) => {
176
156
  }
177
157
  }
178
158
 
179
- if (!config.blockUnauthorized) {
180
- return { ignored: true, ignoreReason: 'blockUnauthorized' };
181
- }
182
-
183
- const rule = await req.getRoutingRule();
184
- if (rule.to && rule.to.interfaceName) {
185
- const permissionName = genPermissionName(rule.to.interfaceName);
186
- const rbac = await node.getRBAC(teamDid);
187
-
188
- if (await rbac.can(req.user.role, ...permissionName.split('_'))) {
189
- return {};
190
- }
191
-
192
- return { blocked: true, authenticated: true, authorized: false };
193
- }
194
-
195
159
  return {};
196
160
  };
197
161
 
@@ -312,6 +276,7 @@ const init = ({ node, options }) => {
312
276
  setUserInfoHeaders(req);
313
277
 
314
278
  const { blocked } = await checkAuth({ req });
279
+
315
280
  if (blocked) {
316
281
  const component = await req.getComponent();
317
282
  if (component?.mode === 'development') {
@@ -346,13 +311,23 @@ const init = ({ node, options }) => {
346
311
  }
347
312
 
348
313
  // Security principles: user should not known the reason
349
- return res.status(403).json({ code: 403, error: REASON_403 });
314
+ return res.status(403).json({ code: 403, error: REASON_403, reason: 'email_not_verified' });
315
+ }
316
+
317
+ if (isPhoneKycRequired(blocklet) && !req.user.phoneVerified) {
318
+ if (req.accepts(['html', 'json']) === 'html') {
319
+ return redirectWithoutCache(res, getRedirectUrl({ req, pagePath: '/kyc/phone', params: { updateKyc: 1 } }));
320
+ }
321
+
322
+ // Security principles: user should not known the reason
323
+ return res.status(403).json({ code: 403, error: REASON_403, reason: 'phone_not_verified' });
350
324
  }
351
325
  }
352
326
 
353
327
  return next();
354
328
  };
355
329
 
330
+ // 检查是否符合访问权限控制,不符合的就进行重定向
356
331
  middlewares.checkAuth = async (req, res, next) => {
357
332
  res.locals.auth = await checkAuth({ req });
358
333
  const { blocked, authenticated, authorized, payable, requiredRoles } = res.locals.auth;
@@ -380,7 +355,11 @@ const init = ({ node, options }) => {
380
355
  getRedirectUrl({
381
356
  req,
382
357
  pagePath: '/login',
383
- params: { authenticated: 1, payable, requiredRoles: JSON.stringify(requiredRoles) },
358
+ params: {
359
+ authenticated: 1,
360
+ payable,
361
+ requiredRoles: JSON.stringify(requiredRoles),
362
+ },
384
363
  })
385
364
  );
386
365
  } else {
@@ -1,14 +1,53 @@
1
1
  const { WELLKNOWN_SERVICE_PATH_PREFIX, VERIFY_CODE_TTL } = require('@abtnode/constant');
2
- const { LOGIN_PROVIDER } = require('@blocklet/constant');
2
+ const createTranslator = require('@abtnode/util/lib/translate');
3
3
 
4
4
  const { emailSchema } = require('../../socket/channel/did');
5
5
  const { sendEmail } = require('../../libs/email');
6
- const { isEmailKycRequired, isEmailUniqueRequired, isEmailBlocked, isEmailAllowed } = require('../../libs/kyc');
6
+ const { isEmailBlocked, isEmailAllowed } = require('../../libs/kyc');
7
7
 
8
8
  const logger = require('../../libs/logger')('kyc');
9
9
 
10
+ const translations = {
11
+ en: {
12
+ emailInvalid: 'Email is invalid',
13
+ emailAlreadyVerified:
14
+ 'This email has already been verified. You can recover the verification NFT from your DID Wallet.',
15
+ emailNotAllowed:
16
+ "Sorry, we can't accept email addresses from this domain. Please use an email address from a different provider.",
17
+ emailBlocked: "We're unable to use this email address. Please try a different email address from another provider.",
18
+ emailSendSuccess: 'Verify code successfully sent',
19
+ emailAlreadySent:
20
+ "We've already sent a verification email. Please check your inbox or spam folder. If you don't see it, you can try again in a few minutes.",
21
+ emailVerifySuccess: 'Email is successfully verified',
22
+ emailTitle: 'Verify Your Email for {appName}',
23
+ emailHeadline:
24
+ 'To ensure the security of your account and enhance your experience, you need to use following code to verify your email, and you will receive a NFT in your DID Wallet upon verification.',
25
+ emailValidCode:
26
+ "This code is valid for {ttl} minutes. If you don't want to verify your email, you can ignore this message.",
27
+ emailWarning:
28
+ '{appName} will never email you and ask you to disclose your password, credit card, or banking account number.',
29
+ },
30
+ zh: {
31
+ emailInvalid: '邮箱格式不正确',
32
+ emailAlreadyVerified: '此邮箱已验证。您可以从 DID 钱包中恢复验证证书。',
33
+ emailNotAllowed: '对不起,我们不接受此域名的电子邮件地址。请使用来自不同提供商的电子邮件地址。',
34
+ emailBlocked: '我们无法使用此电子邮件地址。请尝试使用来自不同提供商的电子邮件地址。',
35
+ emailSendSuccess: '验证码发送成功',
36
+ emailAlreadySent: '我们已发送验证电子邮件。请检查您的收件箱或垃圾邮件文件夹。如果您没有看到它,您可以稍后再试。',
37
+ emailVerifySuccess: '邮箱验证成功',
38
+ emailTitle: '验证您在 {appName} 的邮箱',
39
+ emailHeadline:
40
+ '为确保您的帐户安全并增强您的体验,您需要使用以下代码验证您的邮箱,并在验证后在您的 DID 钱包中收到 NFT。',
41
+ emailValidCode: '此代码有效期为 {ttl} 分钟。如果您不想验证您的邮箱,您可以忽略此消息。',
42
+ emailWarning: '{appName} 永远不会向您发送电子邮件并要求您披露您的密码、信用卡或银行账户信息。',
43
+ },
44
+ };
45
+
46
+ const t = createTranslator({ translations });
47
+
10
48
  const init = ({ node }) => {
11
49
  const onStartEmailVerify = async (req, res) => {
50
+ const { locale = 'en' } = req.query;
12
51
  try {
13
52
  const [blocklet, info] = await Promise.all([req.getBlocklet(), req.getBlockletInfo()]);
14
53
  const teamDid = blocklet.meta.did;
@@ -16,28 +55,14 @@ const init = ({ node }) => {
16
55
  const { error, value: subject } = emailSchema.validate(req.body.email);
17
56
 
18
57
  if (error) {
19
- return res.status(400).send({ error: 'Email is invalid', code: 'email_invalid' });
58
+ return res.status(400).send({ error: t('emailInvalid', locale), code: 'email_invalid' });
20
59
  }
21
60
 
22
- if (isEmailUniqueRequired(blocklet)) {
23
- if (
24
- await node.isEmailUsed({
25
- teamDid,
26
- email: subject,
27
- verified: isEmailKycRequired(blocklet),
28
- sourceProvider: LOGIN_PROVIDER.WALLET,
29
- })
30
- ) {
31
- return res.status(400).send({
32
- error: 'This email address is already in use. Please try a different email address.',
33
- code: 'email_already_used',
34
- });
35
- }
36
-
37
- if (await node.isSubjectIssued({ teamDid, subject })) {
61
+ // Do not issue duplicate email nft to same user
62
+ if (req.user) {
63
+ if (await node.isSubjectIssued({ teamDid, userDid: req.user.did, subject })) {
38
64
  return res.status(400).send({
39
- error:
40
- 'This email has already been verified. You can log in using your DID Wallet or recover your certificate from the login page.',
65
+ error: t('emailAlreadyVerified', locale),
41
66
  code: 'email_already_verified',
42
67
  });
43
68
  }
@@ -47,8 +72,7 @@ const init = ({ node }) => {
47
72
  if (!isAllowed) {
48
73
  logger.warn('Email domain is not allowed', { teamDid, subject });
49
74
  return res.status(400).send({
50
- error:
51
- "Sorry, we can't accept email addresses from this domain. Please use an email address from a different provider.",
75
+ error: t('emailNotAllowed', locale),
52
76
  code: 'email_not_allowed',
53
77
  });
54
78
  }
@@ -57,15 +81,14 @@ const init = ({ node }) => {
57
81
  if (isBlocked) {
58
82
  logger.warn('Email domain is blocked', { teamDid, subject });
59
83
  return res.status(400).send({
60
- error: "We're unable to use this email address. Please try a different email address from another provider.",
84
+ error: t('emailBlocked', locale),
61
85
  code: 'email_blocked',
62
86
  });
63
87
  }
64
88
 
65
89
  if (await node.isSubjectSent({ teamDid, subject })) {
66
90
  return res.status(400).send({
67
- error:
68
- "We've already sent a verification email. Please check your inbox or spam folder. If you don't see it, you can try again in a few minutes.",
91
+ error: t('emailAlreadySent', locale),
69
92
  code: 'email_already_sent',
70
93
  });
71
94
  }
@@ -76,11 +99,11 @@ const init = ({ node }) => {
76
99
  const result = await sendEmail(
77
100
  subject,
78
101
  {
79
- title: `Verify Your Email on ${info.name}`,
80
- body: `<p style="font-size:14px;line-height:24px;margin:16px 0;">To ensure the security of your account and enhance your experience, you need to use following code to verify your email, and you will receive a certificate in your DID Wallet upon verification.</p>
102
+ title: t('emailTitle', locale, { appName: info.name }),
103
+ body: `<p style="font-size:14px;line-height:24px;margin:16px 0;">${t('emailHeadline', locale)}</p>
81
104
  <p style="font-size:36px; line-height:24px; color: #333; font-weight: bold; text-align: center;">${doc.code}</p>
82
- <p style="font-size:14px;line-height:24px;margin:16px 0;">This code is valid for ${VERIFY_CODE_TTL / 60 / 1000} minutes. If you don't want to verify your email, you can ignore this message.</p>
83
- <p style="font-size:14px;line-height:24px;margin:16px 0;">${info.name} will never email you and ask you to disclose your password, credit card, or banking account number. </p>`,
105
+ <p style="font-size:14px;line-height:24px;margin:16px 0;">${t('emailValidCode', locale, { ttl: VERIFY_CODE_TTL / 60 / 1000 })}</p>
106
+ <p style="font-size:14px;line-height:24px;margin:16px 0;">${t('emailWarning', locale, { appName: info.name })}</p>`,
84
107
  },
85
108
  {
86
109
  teamDid,
@@ -92,7 +115,7 @@ const init = ({ node }) => {
92
115
  logger.info('send verify code', { teamDid, result });
93
116
  await node.sendVerifyCode({ teamDid, code: doc.code });
94
117
 
95
- return res.status(200).send({ message: 'Verify code successfully sent' });
118
+ return res.status(200).send({ message: t('emailSendSuccess', locale) });
96
119
  } catch (error) {
97
120
  logger.error('Send mail failed', { error });
98
121
  return res.status(400).send(error.message);
@@ -100,6 +123,7 @@ const init = ({ node }) => {
100
123
  };
101
124
 
102
125
  const onEndEmailVerify = async (req, res) => {
126
+ const { locale = 'en' } = req.query;
103
127
  try {
104
128
  const blocklet = await req.getBlocklet();
105
129
  const teamDid = blocklet.meta.did;
@@ -108,7 +132,7 @@ const init = ({ node }) => {
108
132
  const result = await node.consumeVerifyCode({ teamDid, code });
109
133
  logger.info('consume verify code', { teamDid, code, result });
110
134
 
111
- return res.status(200).send({ message: 'Email is successfully verified' });
135
+ return res.status(200).send({ message: t('emailVerifySuccess', locale) });
112
136
  } catch (error) {
113
137
  logger.error('Verify mail failed', { error });
114
138
  return res.status(400).send(error.message);