@abtnode/blocklet-services 1.16.41 → 1.16.42-beta-20250402-131159-7647e64d
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.
- package/api/emails/_templates/verify-code-body.js +4 -4
- package/api/routes/blocklet.js +1 -1
- package/api/routes/oauth.js +56 -270
- package/api/routes/user-session.js +1 -1
- package/api/routes/user.js +247 -254
- package/api/services/notification/queue.js +9 -1
- package/api/socket/util.js +1 -4
- package/api/util/federated.js +1 -1
- package/api/util/user-util.js +298 -0
- package/dist/assets/{ArrowDropDown-odHjNJIs.js → ArrowDropDown-B6RijoMg.js} +1 -1
- package/dist/assets/{CheckCircle-BqOSvJMp.js → CheckCircle-Bme_BHSe.js} +1 -1
- package/dist/assets/{ChevronLeft-Dv7rlUf5.js → ChevronLeft-CDiNoyQS.js} +1 -1
- package/dist/assets/{ChevronRight-CWeJn1iz.js → ChevronRight-DyMxK2ti.js} +1 -1
- package/dist/assets/{DeleteOutline-Cr-TyrUV.js → DeleteOutline-C5oIt-tc.js} +1 -1
- package/dist/assets/{Done-C1TA1wbA.js → Done-uAJ8-whC.js} +1 -1
- package/dist/assets/{Download-DxhnUTM_.js → Download-CAwoUjYq.js} +1 -1
- package/dist/assets/{Error-pXXvJFxN.js → Error-J1wFafzM.js} +1 -1
- package/dist/assets/{ExpandLess-Dc_dI20M.js → ExpandLess-B0AhRxh8.js} +1 -1
- package/dist/assets/{Google-DNUuYFIA.js → Google-blbcHt2R.js} +1 -1
- package/dist/assets/{InfoOutlined-CEUhR4DY.js → InfoOutlined-BjH1JBg3.js} +1 -1
- package/dist/assets/{Launch-BUTOr3cR.js → Launch-DJqhcPtC.js} +1 -1
- package/dist/assets/{LaunchOutlined-QHq-RUJt.js → LaunchOutlined-CzBae9mQ.js} +1 -1
- package/dist/assets/{MoreHoriz-D1SOL47a.js → MoreHoriz-Dd-9O1iw.js} +1 -1
- package/dist/assets/{PlayArrow-D7cGSxeN.js → PlayArrow-BEPk9nzV.js} +1 -1
- package/dist/assets/{ViewList-vu1qOJ6P.js → ViewList-CNnrIxVS.js} +1 -1
- package/dist/assets/{access-control-CpxcJItK.js → access-control-PfmU_lzC.js} +1 -1
- package/dist/assets/{actions-4oGfCMlR.js → actions-pYJdaWX5.js} +1 -1
- package/dist/assets/{add-component-core-CE0nArG4.js → add-component-core-CgEuYlWv.js} +31 -31
- package/dist/assets/{add-resource-BYM4JwzE.js → add-resource-Dw_ZKqq3.js} +1 -1
- package/dist/assets/{addon-B9bb2bvM.js → addon-BqlSMpSy.js} +1 -1
- package/dist/assets/{analytics-BXLe73MI.js → analytics-DLD8w-rR.js} +2 -2
- package/dist/assets/api-0KF6Hg7c.js +1 -0
- package/dist/assets/appearance-DyZRbR6W.js +1 -0
- package/dist/assets/ar-HpV-sy4C.js +3 -0
- package/dist/assets/{audit-logs-D8H5E0fC.js → audit-logs-BFKcADf-.js} +2 -2
- package/dist/assets/base32-C0ClYUu9.js +1 -0
- package/dist/assets/{branding-BW1rhy8d.js → branding-8XaHoIBD.js} +2 -2
- package/dist/assets/{bundle-avatar-DHwmIozH.js → bundle-avatar-BYZp7KRE.js} +1 -1
- package/dist/assets/{button-CNnuiac8.js → button-K0-gOTcS.js} +1 -1
- package/dist/assets/{click-to-copy-B0HMuCN_.js → click-to-copy-BfRimSvL.js} +1 -1
- package/dist/assets/{complete-BNf0-iqY.js → complete-1MMVAc2H.js} +1 -1
- package/dist/assets/{component-1r0VSsqq.js → component-BZKPS6he.js} +3 -3
- package/dist/assets/{config-BeD5_8kr.js → config-DRS6lRly.js} +1 -1
- package/dist/assets/{config-CqHmZdZv.js → config-DtYY5NrA.js} +1 -1
- package/dist/assets/{config-navigation-DtN0_qFZ.js → config-navigation-BHoOsyWp.js} +5 -5
- package/dist/assets/{config-space-DlwZewcm.js → config-space-DxdlQBdo.js} +1 -1
- package/dist/assets/{confirm-DmMN-34s.js → confirm-C57Q7ZWM.js} +1 -1
- package/dist/assets/{connect-CC9dcVMV.js → connect-PChwPX8g.js} +1 -1
- package/dist/assets/connect-p9koIBBk.js +1 -0
- package/dist/assets/{connect-to-CzffwD9G.js → connect-to-QLfyUtYC.js} +1 -1
- package/dist/assets/{dashboard-C_Q4TjPa.js → dashboard-Di0Efjh1.js} +4 -4
- package/dist/assets/de-zgFs6Kvs.js +3 -0
- package/dist/assets/{delete-confirm-BTaU_6Kx.js → delete-confirm-L9JNVh3W.js} +1 -1
- package/dist/assets/{did-address-BC-0j4Pt.js → did-address-Bz2Y86pP.js} +1 -1
- package/dist/assets/{domain-action-card-DwQ7Q8wY.js → domain-action-card-Bovam4dU.js} +2 -2
- package/dist/assets/domain-fVU92lIu.js +9 -0
- package/dist/assets/domains-Cs6tdpUa.js +1 -0
- package/dist/assets/{email-mj0bVFDS.js → email-SVI5bjle.js} +2 -2
- package/dist/assets/es-CmwByMO0.js +3 -0
- package/dist/assets/exchange-passport-B3N7KRar.js +1 -0
- package/dist/assets/{form-text-input-BYF6lVnE.js → form-text-input-Cp0lmtAk.js} +2 -2
- package/dist/assets/fr-CLYepc9p.js +3 -0
- package/dist/assets/{fuel-D-kOZuF6.js → fuel-DT6O2ymR.js} +1 -1
- package/dist/assets/{get-safe-url-BKl2A9x2.js → get-safe-url-CJRwqFgD.js} +1 -1
- package/dist/assets/{get-safe-url-QFq5JNoE.js → get-safe-url-DLBNTOpr.js} +1 -1
- package/dist/assets/hi-CSSYN7n8.js +1 -0
- package/dist/assets/{home-CpnMpXiw.js → home-CQ7SI4ml.js} +1 -1
- package/dist/assets/id-C5CwopKG.js +3 -0
- package/dist/assets/{iframe-B9mCpo4I.js → iframe-DPBwIvsP.js} +1 -1
- package/dist/assets/{index-gTQQ3SoE.js → index-8I2oAbEz.js} +9 -9
- package/dist/assets/index-B5HkvoQC.js +4 -0
- package/dist/assets/{index-CmKAznDh.js → index-BYkIfvmH.js} +4 -4
- package/dist/assets/index-B_pl8AF-.js +11 -0
- package/dist/assets/{index-B4Q2DAdn.js → index-Bg3m8iJ-.js} +11 -11
- package/dist/assets/{index-BZvVDfZ4.js → index-Bhnq0cVQ.js} +1 -1
- package/dist/assets/{index-C44fECmB.js → index-BzblYn_P.js} +2 -2
- package/dist/assets/index-C9qItKIC.js +138 -0
- package/dist/assets/{index-Ct7s2LPI.js → index-CAFqxbeJ.js} +3 -3
- package/dist/assets/{index-u-lA6P_E.js → index-CLIxjSVZ.js} +1 -1
- package/dist/assets/{index-BJ2lJo7L.js → index-Cdm81c0H.js} +42 -42
- package/dist/assets/index-DAE7cdom.js +2 -0
- package/dist/assets/{index-DQ_RzIwU.js → index-DGkTgpZy.js} +1 -1
- package/dist/assets/{index-BsUr7wGb.js → index-DZAi-K_N.js} +47 -47
- package/dist/assets/{index-gcSQTx25.js → index-Db6WuAj_.js} +1 -1
- package/dist/assets/index-RSW2vc0s.js +2 -0
- package/dist/assets/{index-CJCg9yIK.js → index-RuFDBiVt.js} +1 -1
- package/dist/assets/{index-79U1RPaq.js → index-bIuZaDHS.js} +1 -1
- package/dist/assets/{index-CGK3FEjY.js → index-kAPvimmq.js} +2 -2
- package/dist/assets/{invitation-B8Qx_pFq.js → invitation-DG6QrvdE.js} +8 -7
- package/dist/assets/invite-CYIssZ1G.js +1 -0
- package/dist/assets/issue-passport-Cft19VvI.js +1 -0
- package/dist/assets/{item-BSGXym2I.js → item-at_gI9OW.js} +1 -1
- package/dist/assets/ja-BPVyKlMZ.js +3 -0
- package/dist/assets/ko-DGmHCGCI.js +3 -0
- package/dist/assets/landing-page-CXo1fefz.js +1 -0
- package/dist/assets/{layout-BqhTD729.js → layout-ChcSB0Y2.js} +1 -1
- package/dist/assets/list-DcSgz3EU.js +211 -0
- package/dist/assets/localization-DXf17X8p.js +1 -0
- package/dist/assets/{log-o_Cadt8j.js → log-D7ImQrI7.js} +1 -1
- package/dist/assets/{login-BQozrLDm.js → login-B9xuIjhY.js} +1 -1
- package/dist/assets/{login-oauth-callback-D7lIww1c.js → login-oauth-callback-BoFezOw0.js} +1 -1
- package/dist/assets/{logo-uploader-CUQ3aWZJ.js → logo-uploader-Bzpld3yG.js} +3 -3
- package/dist/assets/{lost-passport-DkETH2Lu.js → lost-passport-j4coS07J.js} +3 -3
- package/dist/assets/{omit-DZNQhOf-.js → omit-BXVmqD4a.js} +1 -1
- package/dist/assets/{open-window-BOl-kTC2.js → open-window-B8cxsAbD.js} +1 -1
- package/dist/assets/{overview-Bxm05EH6.js → overview-C9x4HKRi.js} +1 -1
- package/dist/assets/{page-header-Dm1v9v5q.js → page-header-YN9FqnGT.js} +1 -1
- package/dist/assets/{permission-B5jnw9r2.js → permission-CTDKdktZ.js} +1 -1
- package/dist/assets/{preferences-uri2RXdB.js → preferences-DM6b-Vr4.js} +1 -1
- package/dist/assets/{profile-embed-DnIQcD-H.js → profile-embed-8sjLgVfn.js} +1 -1
- package/dist/assets/pt-u5ojPOFS.js +1 -0
- package/dist/assets/publish-resource-BJIce778.js +1 -0
- package/dist/assets/{react-beautiful-dnd.esm-B9MfX9Xl.js → react-beautiful-dnd.esm-CkNk1XBJ.js} +4 -4
- package/dist/assets/{relative-time-RQnsWZQc.js → relative-time-BCARyhz6.js} +1 -1
- package/dist/assets/roboto-cyrillic-400-normal-DAIM1_dR.woff2 +0 -0
- package/dist/assets/roboto-cyrillic-400-normal-Dry59Hjn.woff +0 -0
- package/dist/assets/roboto-cyrillic-500-normal-CsCirF4J.woff +0 -0
- package/dist/assets/roboto-cyrillic-500-normal-hCeO1jFL.woff2 +0 -0
- package/dist/assets/roboto-cyrillic-700-normal-CB1Rmiii.woff +0 -0
- package/dist/assets/roboto-cyrillic-700-normal-CzEIZVQR.woff2 +0 -0
- package/dist/assets/roboto-cyrillic-ext-400-normal-BxX1-eA_.woff +0 -0
- package/dist/assets/roboto-cyrillic-ext-400-normal-DzMWdK87.woff2 +0 -0
- package/dist/assets/roboto-cyrillic-ext-500-normal-B7rQpwPu.woff2 +0 -0
- package/dist/assets/roboto-cyrillic-ext-500-normal-ElvJfk8V.woff +0 -0
- package/dist/assets/roboto-cyrillic-ext-700-normal-CIu0AXX2.woff +0 -0
- package/dist/assets/roboto-cyrillic-ext-700-normal-D_fA0fHY.woff2 +0 -0
- package/dist/assets/roboto-greek-400-normal-CAI06USH.woff +0 -0
- package/dist/assets/roboto-greek-400-normal-jFM2czAU.woff2 +0 -0
- package/dist/assets/roboto-greek-500-normal-BJMS0heP.woff2 +0 -0
- package/dist/assets/roboto-greek-500-normal-D8eQD5zT.woff +0 -0
- package/dist/assets/roboto-greek-700-normal-DCrt6r9F.woff +0 -0
- package/dist/assets/roboto-greek-700-normal-DpKAje7q.woff2 +0 -0
- package/dist/assets/roboto-latin-400-normal-551zQQ7R.woff +0 -0
- package/dist/assets/roboto-latin-400-normal-CNwBRw8h.woff2 +0 -0
- package/dist/assets/roboto-latin-500-normal-CkrA1NAy.woff2 +0 -0
- package/dist/assets/roboto-latin-500-normal-_8jDuD7w.woff +0 -0
- package/dist/assets/roboto-latin-700-normal-CTLkNcF_.woff +0 -0
- package/dist/assets/roboto-latin-700-normal-DZr4b_KL.woff2 +0 -0
- package/dist/assets/roboto-latin-ext-400-normal-ZYmyxeOy.woff2 +0 -0
- package/dist/assets/roboto-latin-ext-400-normal-uRIBRJt5.woff +0 -0
- package/dist/assets/roboto-latin-ext-500-normal-C_ARlJGk.woff2 +0 -0
- package/dist/assets/roboto-latin-ext-500-normal-eJ10kk0m.woff +0 -0
- package/dist/assets/roboto-latin-ext-700-normal-BNPgmEQS.woff2 +0 -0
- package/dist/assets/roboto-latin-ext-700-normal-Cnx4FGpK.woff +0 -0
- package/dist/assets/roboto-math-400-normal-B3wgz80t.woff2 +0 -0
- package/dist/assets/roboto-math-400-normal-DHrwdhE6.woff +0 -0
- package/dist/assets/roboto-math-500-normal-CFNaIMFC.woff2 +0 -0
- package/dist/assets/roboto-math-500-normal-CetgDdIa.woff +0 -0
- package/dist/assets/roboto-math-700-normal-CpTCM92H.woff +0 -0
- package/dist/assets/roboto-math-700-normal-xbpggnJp.woff2 +0 -0
- package/dist/assets/roboto-symbols-400-normal-bG5rsNFs.woff +0 -0
- package/dist/assets/roboto-symbols-400-normal-fF1SLJBj.woff2 +0 -0
- package/dist/assets/roboto-symbols-500-normal-BXFTxrNR.woff2 +0 -0
- package/dist/assets/roboto-symbols-500-normal-toKUCDph.woff +0 -0
- package/dist/assets/roboto-symbols-700-normal-B2QKVW64.woff +0 -0
- package/dist/assets/roboto-symbols-700-normal-DKkQdRpM.woff2 +0 -0
- package/dist/assets/roboto-vietnamese-400-normal-CDDxGrUb.woff2 +0 -0
- package/dist/assets/roboto-vietnamese-400-normal-DgufTq8s.woff +0 -0
- package/dist/assets/roboto-vietnamese-500-normal-Dw5heWgq.woff +0 -0
- package/dist/assets/roboto-vietnamese-500-normal-HYpufUYk.woff2 +0 -0
- package/dist/assets/roboto-vietnamese-700-normal-BFWtvCOj.woff2 +0 -0
- package/dist/assets/roboto-vietnamese-700-normal-ChAl_rRV.woff +0 -0
- package/dist/assets/ru-DBl90RHJ.js +1 -0
- package/dist/assets/sdk-DbmS8LqQ.js +1 -0
- package/dist/assets/session-BaYtKD4f.js +1 -0
- package/dist/assets/{setup-7Gq9K_8k.js → setup-BtUUdr-p.js} +3 -3
- package/dist/assets/{start-BSUY3DBl.js → start-CdXw9NWC.js} +1 -1
- package/dist/assets/{status-C52-BFuY.js → status-B6cew_GQ.js} +1 -1
- package/dist/assets/{step-actions-CA74dwgt.js → step-actions-D-RgRm8H.js} +1 -1
- package/dist/assets/{studio-CAnZfyBM.js → studio-KYZUr4tT.js} +1 -1
- package/dist/assets/{switch-control-BBlLGjaH.js → switch-control-CpOzvDua.js} +1 -1
- package/dist/assets/th-CbjesoRG.js +1 -0
- package/dist/assets/{traffic-CJDIGmp5.js → traffic-CvAD-wB3.js} +1 -1
- package/dist/assets/transfer-BSgBIknw.js +16 -0
- package/dist/assets/{unsubscribe-afXXIHEf.js → unsubscribe-I8S6Tbwg.js} +1 -1
- package/dist/assets/{useAsync-DM8qaMe4.js → useAsync-Cq0wbMuR.js} +1 -1
- package/dist/assets/{useAsyncRetry-B7SbzXVI.js → useAsyncRetry-BNLrNsx3.js} +1 -1
- package/dist/assets/{useLocalStorage-Dd4pybDP.js → useLocalStorage-Cligjpwl.js} +1 -1
- package/dist/assets/user-center-C1k0oYvY.js +67 -0
- package/dist/assets/{util-C_BCTHfw.js → util-BFBz0dr8.js} +1 -1
- package/dist/assets/{util-YyWTpLT7.js → util-COcKIr8L.js} +1 -1
- package/dist/assets/vendor-arcblock-krD2mwVA.js +1598 -0
- package/dist/assets/{vendor-hooks-sw5wvnca.js → vendor-hooks-BdjOQw7q.js} +1 -1
- package/dist/assets/vendor-utils-BbDUMsIF.js +11 -0
- package/dist/assets/vendor-ux-did-connect-BDmhBveY.css +1 -0
- package/dist/assets/vendor-ux-did-connect-YqGDzQ2U.js +1843 -0
- package/dist/assets/vi-xat6Zv0n.js +1 -0
- package/dist/assets/wrap-locale-BCL-ID0T.js +1 -0
- package/dist/assets/zh-BgH3IZTD.js +4 -0
- package/dist/assets/zh-tw-UWzs9p3g.js +3 -0
- package/dist/images/all-done.png +0 -0
- package/dist/index.html +6 -6
- package/dist/service-worker.js +1 -1
- package/package.json +37 -39
- package/dist/assets/api-D9Yi7Zdr.js +0 -1
- package/dist/assets/appearance-DX7SoW1u.js +0 -1
- package/dist/assets/ar-2k9jaPIk.js +0 -3
- package/dist/assets/base32-BNpDT-6Q.js +0 -1
- package/dist/assets/connect-BfSOEYV-.js +0 -1
- package/dist/assets/de-B9cLhykn.js +0 -3
- package/dist/assets/domain-CLMRXecU.js +0 -9
- package/dist/assets/domains-DF7TtN5q.js +0 -1
- package/dist/assets/es-BoQohonz.js +0 -3
- package/dist/assets/exchange-passport--DeUPzbW.js +0 -1
- package/dist/assets/fr-doSYAOrt.js +0 -3
- package/dist/assets/fullpage-DO8Hcbkl.js +0 -1
- package/dist/assets/hi-B_BwhpD8.js +0 -1
- package/dist/assets/id-BgYIZCvk.js +0 -3
- package/dist/assets/index-BVOYP6aR.js +0 -11
- package/dist/assets/index-DqC2o5PB.js +0 -4
- package/dist/assets/index-DyTFEgKr.js +0 -1
- package/dist/assets/index-eCY24sH9.js +0 -137
- package/dist/assets/inter-latin-300-normal-CvRFFuZy.woff2 +0 -0
- package/dist/assets/inter-latin-300-normal-ORCTF8i-.woff +0 -0
- package/dist/assets/inter-latin-400-normal-BOOGhInR.woff2 +0 -0
- package/dist/assets/inter-latin-400-normal-gitzw0hO.woff +0 -0
- package/dist/assets/inter-latin-500-normal-D2bGa7uu.woff2 +0 -0
- package/dist/assets/inter-latin-500-normal-deR1Tlfd.woff +0 -0
- package/dist/assets/inter-latin-700-normal-B8MtJ_2k.woff +0 -0
- package/dist/assets/inter-latin-700-normal-Sckx8rpT.woff2 +0 -0
- package/dist/assets/inter-latin-ext-300-normal-C2kLfG2J.woff2 +0 -0
- package/dist/assets/inter-latin-ext-300-normal-n8Ps4oXY.woff +0 -0
- package/dist/assets/inter-latin-ext-400-normal-C1t-h-pH.woff +0 -0
- package/dist/assets/inter-latin-ext-400-normal-hnt3BR84.woff2 +0 -0
- package/dist/assets/inter-latin-ext-500-normal-CIS2RHJS.woff2 +0 -0
- package/dist/assets/inter-latin-ext-500-normal-UMdmhHu2.woff +0 -0
- package/dist/assets/inter-latin-ext-700-normal-6V9MnIL5.woff +0 -0
- package/dist/assets/inter-latin-ext-700-normal-CzikT_rs.woff2 +0 -0
- package/dist/assets/invite-BBaF_vyc.js +0 -1
- package/dist/assets/issue-passport-DC-ly7xg.js +0 -1
- package/dist/assets/ja-FMMLI8YD.js +0 -3
- package/dist/assets/ko-C0kmRXYE.js +0 -3
- package/dist/assets/list-BHs8uNT5.js +0 -200
- package/dist/assets/localization-daPAWMzR.js +0 -1
- package/dist/assets/login-bg-Cbfh9Uc2.png +0 -0
- package/dist/assets/pt-C2UJZK-O.js +0 -1
- package/dist/assets/publish-resource-V53U1NNv.js +0 -1
- package/dist/assets/ru-DDA5s4-r.js +0 -1
- package/dist/assets/sdk-BKSsfgrc.js +0 -1
- package/dist/assets/session-6ZeN-aF2.js +0 -1
- package/dist/assets/th-DmqOUn4C.js +0 -1
- package/dist/assets/transfer-cG2e24sz.js +0 -16
- package/dist/assets/user-center-T8Xw464s.js +0 -67
- package/dist/assets/vendor-arcblock-DvaaLvvM.js +0 -2361
- package/dist/assets/vendor-utils-DR57WNxP.js +0 -11
- package/dist/assets/vendor-ux-did-connect-Bciw9Ypu.js +0 -1077
- package/dist/assets/vendor-ux-did-connect-DhgPdlEj.css +0 -1
- package/dist/assets/vi-Cf__CtPD.js +0 -1
- package/dist/assets/wrap-locale-CX50Vz0w.js +0 -1
- package/dist/assets/zh-NXspK2yu.js +0 -4
- package/dist/assets/zh-tw-DYYDVX5I.js +0 -3
package/api/routes/user.js
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
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');
|
|
1
|
+
const { WELLKNOWN_SERVICE_PATH_PREFIX, VERIFY_CODE_TTL } = require('@abtnode/constant');
|
|
8
2
|
const JWT = require('@arcblock/jwt');
|
|
9
3
|
const { render } = require('@react-email/components');
|
|
10
|
-
const {
|
|
4
|
+
const { getApplicationInfo, handleInvitationReceive } = require('@abtnode/auth/lib/auth');
|
|
11
5
|
const { fromAppDid } = require('@arcblock/did-ext');
|
|
12
6
|
const { extractUserAvatar, getUserAvatarUrl } = require('@abtnode/util/lib/user');
|
|
13
7
|
const formatContext = require('@abtnode/util/lib/format-context');
|
|
14
|
-
const createTranslator = require('@abtnode/util/lib/translate');
|
|
15
8
|
const { fromBase64 } = require('@ocap/util');
|
|
16
9
|
const { isFromPublicKey } = require('@arcblock/did');
|
|
17
10
|
const { LOGIN_PROVIDER } = require('@blocklet/constant');
|
|
@@ -20,20 +13,17 @@ const merge = require('lodash/merge');
|
|
|
20
13
|
const omitBy = require('lodash/omitBy');
|
|
21
14
|
const omit = require('lodash/omit');
|
|
22
15
|
const uniq = require('lodash/uniq');
|
|
23
|
-
const last = require('lodash/last');
|
|
24
|
-
const sortBy = require('lodash/sortBy');
|
|
25
16
|
const { getLastUsedPassport } = require('@abtnode/auth/lib/passport');
|
|
26
|
-
const { getWallet } = require('@blocklet/meta/lib/did-utils');
|
|
17
|
+
const { getWallet, getWalletDid } = require('@blocklet/meta/lib/did-utils');
|
|
27
18
|
const { Joi } = require('@arcblock/validator');
|
|
28
19
|
const { parse } = require('@abtnode/core/lib/util/ua');
|
|
29
|
-
const { checkInvitedUserOnly } = require('@abtnode/auth/lib/oauth');
|
|
30
20
|
const getRequestIP = require('@abtnode/util/lib/get-request-ip');
|
|
31
21
|
const formatError = require('@abtnode/util/lib/format-error');
|
|
32
22
|
const CustomError = require('@abtnode/util/lib/custom-error');
|
|
33
|
-
const { callFederated } = require('@abtnode/auth/lib/util/federated');
|
|
34
23
|
const { xss } = require('@blocklet/xss');
|
|
35
|
-
const { withQuery } = require('ufo');
|
|
24
|
+
const { withQuery, joinURL } = require('ufo');
|
|
36
25
|
const cors = require('cors');
|
|
26
|
+
const createTranslator = require('@abtnode/util/lib/translate');
|
|
37
27
|
|
|
38
28
|
const { createTokenFn, getDidConnectVersion } = require('../util');
|
|
39
29
|
const initJwt = require('../libs/jwt');
|
|
@@ -44,13 +34,14 @@ const { getAvatarByEmail } = require('../libs/auth/utils');
|
|
|
44
34
|
const logger = require('../libs/logger')('user');
|
|
45
35
|
const ensureBlocklet = require('../middlewares/ensure-blocklet');
|
|
46
36
|
const checkUser = require('../middlewares/check-user');
|
|
47
|
-
const { getUserWithinFederated, getUserAvatarUrl: getRawUserAvatarUrl } = require('../util/federated');
|
|
48
37
|
const { Profile } = require('../state/profile');
|
|
49
38
|
const { emailSchema } = require('../socket/channel/did');
|
|
50
39
|
const { sendEmail } = require('../libs/email');
|
|
51
40
|
const federatedUtil = require('../util/federated');
|
|
41
|
+
const userUtil = require('../util/user-util');
|
|
52
42
|
const { VerifyCodeBody } = require('../emails/_templates/verify-code-body');
|
|
53
43
|
const { checkFederatedCall } = require('../middlewares/check-federated');
|
|
44
|
+
const { sendToUser } = require('../libs/notification');
|
|
54
45
|
|
|
55
46
|
const validateUser = (user) => {
|
|
56
47
|
try {
|
|
@@ -69,6 +60,7 @@ const PREFIX = WELLKNOWN_SERVICE_PATH_PREFIX;
|
|
|
69
60
|
|
|
70
61
|
const prefix = `${PREFIX}/user`;
|
|
71
62
|
const prefixApi = `${PREFIX}/api/user`;
|
|
63
|
+
|
|
72
64
|
const translations = {
|
|
73
65
|
zh: {
|
|
74
66
|
notAllowed: '你已经被禁止访问该应用',
|
|
@@ -81,6 +73,8 @@ const translations = {
|
|
|
81
73
|
emailAlreadySent: '我们已发送验证电子邮件。请检查您的收件箱或垃圾邮件文件夹。如果您没有看到它,您可以稍后再试。',
|
|
82
74
|
emailVerifySuccess: '邮箱验证成功',
|
|
83
75
|
emailTitle: '登录 {appName}',
|
|
76
|
+
invalidVerifyCode: '验证码不正确',
|
|
77
|
+
missingInviteId: '缺少邀请 ID',
|
|
84
78
|
},
|
|
85
79
|
en: {
|
|
86
80
|
notAllowed: 'Your have been revoked access to this blocklet',
|
|
@@ -94,19 +88,13 @@ const translations = {
|
|
|
94
88
|
"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
89
|
emailVerifySuccess: 'Email verified successfully',
|
|
96
90
|
emailTitle: 'Login to {appName}',
|
|
91
|
+
invalidVerifyCode: 'Invalid verify code',
|
|
92
|
+
missingInviteId: 'Missing invite ID',
|
|
97
93
|
},
|
|
98
94
|
};
|
|
99
95
|
|
|
100
96
|
const t = createTranslator({ translations });
|
|
101
97
|
|
|
102
|
-
async function checkNeedInvite({ req, node, teamDid, locale }) {
|
|
103
|
-
const { accessPolicyConfig } = await req.getSecurityConfig({ id: SECURITY_RULE_DEFAULT_ID });
|
|
104
|
-
const isInvitedUserOnly = await checkInvitedUserOnly(accessPolicyConfig, node, teamDid);
|
|
105
|
-
if (isInvitedUserOnly) {
|
|
106
|
-
throw new CustomError(403, messages.notInvited[locale]);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
98
|
function ensureUserExist(user, { locale } = {}) {
|
|
111
99
|
if (!user) {
|
|
112
100
|
throw new CustomError(404, t('notExist', locale));
|
|
@@ -136,7 +124,7 @@ async function composeProfileData({ avatar, fullName, email }, { node, req, team
|
|
|
136
124
|
avatarLocal = await getAvatarByEmail(email);
|
|
137
125
|
}
|
|
138
126
|
if (!fullName) {
|
|
139
|
-
profile.fullName = email;
|
|
127
|
+
profile.fullName = userUtil.getUserNameByEmail(email);
|
|
140
128
|
}
|
|
141
129
|
}
|
|
142
130
|
}
|
|
@@ -191,7 +179,7 @@ async function loginWallet(
|
|
|
191
179
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid });
|
|
192
180
|
}
|
|
193
181
|
} else {
|
|
194
|
-
await checkNeedInvite({ req, node, teamDid, locale });
|
|
182
|
+
await userUtil.checkNeedInvite({ req, node, teamDid, locale });
|
|
195
183
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid, isCreate: true });
|
|
196
184
|
}
|
|
197
185
|
|
|
@@ -255,7 +243,7 @@ async function loginOAuth(
|
|
|
255
243
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid });
|
|
256
244
|
}
|
|
257
245
|
} else {
|
|
258
|
-
await checkNeedInvite({ req, node, teamDid, locale });
|
|
246
|
+
await userUtil.checkNeedInvite({ req, node, teamDid, locale });
|
|
259
247
|
profile = await composeProfileData({ avatar, email, fullName }, { node, req, teamDid, isCreate: true });
|
|
260
248
|
}
|
|
261
249
|
|
|
@@ -281,7 +269,7 @@ async function loginOAuth(
|
|
|
281
269
|
return doc;
|
|
282
270
|
}
|
|
283
271
|
|
|
284
|
-
async function
|
|
272
|
+
async function loginSDK(req, node, options) {
|
|
285
273
|
const {
|
|
286
274
|
provider = LOGIN_PROVIDER.WALLET,
|
|
287
275
|
did,
|
|
@@ -391,7 +379,10 @@ async function login(req, node, options) {
|
|
|
391
379
|
}
|
|
392
380
|
|
|
393
381
|
async function verifyUserSig({ userDid, signature, teamDid, sourceAppPid, userPk }, { node, locale, blocklet }) {
|
|
394
|
-
const currentUser = await getUserWithinFederated(
|
|
382
|
+
const currentUser = await federatedUtil.getUserWithinFederated(
|
|
383
|
+
{ sourceAppPid, teamDid, userDid, userPk },
|
|
384
|
+
{ node, blocklet }
|
|
385
|
+
);
|
|
395
386
|
ensureUserExist(currentUser, { locale });
|
|
396
387
|
ensureUserEnable(currentUser, { locale });
|
|
397
388
|
|
|
@@ -451,6 +442,212 @@ function checkUserSig({ node }) {
|
|
|
451
442
|
};
|
|
452
443
|
}
|
|
453
444
|
|
|
445
|
+
async function loginEmail(req, node, options) {
|
|
446
|
+
const { locale = 'en' } = req.query;
|
|
447
|
+
const { sourceAppPid = null, inviter = null } = req.body;
|
|
448
|
+
|
|
449
|
+
const blocklet = await req.getBlocklet();
|
|
450
|
+
const teamDid = blocklet.appPid;
|
|
451
|
+
const verifyCode = await userUtil.getVerifyCodeFromReq({ logger, req });
|
|
452
|
+
const verifyCodeResult = await node.consumeVerifyCode({ teamDid, code: verifyCode });
|
|
453
|
+
|
|
454
|
+
if (!verifyCodeResult) {
|
|
455
|
+
throw new CustomError(400, t('invalidVerifyCode', locale));
|
|
456
|
+
}
|
|
457
|
+
logger.info('Email login: consume verify code', { teamDid, code: verifyCode, result: verifyCodeResult });
|
|
458
|
+
|
|
459
|
+
// 保持跟 oauth 账户的格式一致
|
|
460
|
+
const sub = `email|${verifyCodeResult.subject}`;
|
|
461
|
+
const { wallet: userWallet } = await userUtil.getUserFromSub(sub, { req });
|
|
462
|
+
const userInfo = {
|
|
463
|
+
email: verifyCodeResult.subject,
|
|
464
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const userDid = userWallet.address;
|
|
468
|
+
const userPk = userWallet.publicKey;
|
|
469
|
+
|
|
470
|
+
let profile;
|
|
471
|
+
let currentUser = await federatedUtil.getUserWithinFederated(
|
|
472
|
+
{ sourceAppPid, teamDid, userDid, userPk },
|
|
473
|
+
{ node, blocklet }
|
|
474
|
+
);
|
|
475
|
+
const connectedAccount = {
|
|
476
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
477
|
+
did: userDid,
|
|
478
|
+
pk: userPk,
|
|
479
|
+
id: sub,
|
|
480
|
+
userInfo,
|
|
481
|
+
};
|
|
482
|
+
const lastUsedPassport = userUtil.getLastUsedPassport({ passports: currentUser?.passports });
|
|
483
|
+
|
|
484
|
+
if (!currentUser) {
|
|
485
|
+
await userUtil.checkNeedInvite({ req, node, teamDid, locale });
|
|
486
|
+
currentUser = {
|
|
487
|
+
did: userDid,
|
|
488
|
+
pk: userPk,
|
|
489
|
+
};
|
|
490
|
+
const avatar = await userUtil.getAvatarBnByEmail(verifyCodeResult.subject, { req, node });
|
|
491
|
+
profile = {
|
|
492
|
+
fullName: userUtil.getUserNameByEmail(verifyCodeResult.subject),
|
|
493
|
+
avatar,
|
|
494
|
+
inviter,
|
|
495
|
+
email: verifyCodeResult.subject,
|
|
496
|
+
// email 登录默认认为邮箱已验证
|
|
497
|
+
emailVerified: true,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const { sessionToken, refreshToken, visitorId } = await userUtil.loginUserSession(
|
|
502
|
+
{
|
|
503
|
+
did: currentUser.did || userDid,
|
|
504
|
+
pk: currentUser.pk,
|
|
505
|
+
profile,
|
|
506
|
+
passport: lastUsedPassport,
|
|
507
|
+
sourceAppPid,
|
|
508
|
+
connectedAccount,
|
|
509
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
510
|
+
},
|
|
511
|
+
{ req, node, options }
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
return {
|
|
515
|
+
sessionToken,
|
|
516
|
+
refreshToken,
|
|
517
|
+
visitorId,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async function inviteEmail(req, node, options) {
|
|
522
|
+
const { locale = 'en' } = req.query;
|
|
523
|
+
const { sourceAppPid = null, inviteId, baseUrl } = req.body;
|
|
524
|
+
|
|
525
|
+
if (!inviteId) {
|
|
526
|
+
throw new CustomError(400, t('missingInviteId', locale));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const blocklet = await req.getBlocklet();
|
|
530
|
+
const teamDid = blocklet.appPid;
|
|
531
|
+
const verifyCode = await userUtil.getVerifyCodeFromReq({ logger, req });
|
|
532
|
+
const verifyCodeResult = await node.consumeVerifyCode({ teamDid, code: verifyCode });
|
|
533
|
+
|
|
534
|
+
if (!verifyCodeResult) {
|
|
535
|
+
throw new CustomError(400, t('invalidVerifyCode', locale));
|
|
536
|
+
}
|
|
537
|
+
logger.info('Email invite: consume verify code', { teamDid, code: verifyCode, result: verifyCodeResult });
|
|
538
|
+
|
|
539
|
+
// 保持跟 oauth 账户的格式一致
|
|
540
|
+
const sub = `email|${verifyCodeResult.subject}`;
|
|
541
|
+
const { wallet: userWallet } = await userUtil.getUserFromSub(sub, { req });
|
|
542
|
+
const userInfo = {
|
|
543
|
+
email: verifyCodeResult.subject,
|
|
544
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const userDid = userWallet.address;
|
|
548
|
+
const userPk = userWallet.publicKey;
|
|
549
|
+
|
|
550
|
+
let profile;
|
|
551
|
+
let currentUser = await federatedUtil.getUserWithinFederated(
|
|
552
|
+
{ sourceAppPid, teamDid, userDid, userPk },
|
|
553
|
+
{ node, blocklet }
|
|
554
|
+
);
|
|
555
|
+
logger.info('Email invite: get user info', { teamDid, currentUser });
|
|
556
|
+
const nodeInfo = await req.getNodeInfo();
|
|
557
|
+
const { name: applicationName } = await getApplicationInfo({ node, nodeInfo, teamDid });
|
|
558
|
+
|
|
559
|
+
if (!currentUser) {
|
|
560
|
+
currentUser = {
|
|
561
|
+
did: userDid,
|
|
562
|
+
pk: userPk,
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
const avatar = await userUtil.getAvatarBnByEmail(verifyCodeResult.subject, { req, node });
|
|
566
|
+
profile = {
|
|
567
|
+
fullName: userUtil.getUserNameByEmail(verifyCodeResult.subject),
|
|
568
|
+
avatar,
|
|
569
|
+
email: verifyCodeResult.subject,
|
|
570
|
+
// email 登录默认认为邮箱已验证
|
|
571
|
+
emailVerified: true,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const statusEndpointBaseUrl = joinURL(baseUrl, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
576
|
+
const endpoint = baseUrl;
|
|
577
|
+
|
|
578
|
+
const { passport, response, role, inviteInfo, user } = await handleInvitationReceive({
|
|
579
|
+
req,
|
|
580
|
+
node,
|
|
581
|
+
endpoint,
|
|
582
|
+
inviteId,
|
|
583
|
+
nodeInfo,
|
|
584
|
+
profile: profile || {
|
|
585
|
+
email: currentUser.email,
|
|
586
|
+
fullName: currentUser.fullName,
|
|
587
|
+
avatar: getUserAvatarUrl(baseUrl, currentUser.avatar),
|
|
588
|
+
},
|
|
589
|
+
statusEndpointBaseUrl,
|
|
590
|
+
teamDid,
|
|
591
|
+
userDid: userWallet.address,
|
|
592
|
+
userPk: userWallet.publicKey,
|
|
593
|
+
locale,
|
|
594
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
if (currentUser) {
|
|
598
|
+
const walletDid = getWalletDid(currentUser);
|
|
599
|
+
if (walletDid) {
|
|
600
|
+
// 如果已经绑定了 wallet 账户,则将 passport 发送给 wallet 账户
|
|
601
|
+
await sendToUser(
|
|
602
|
+
walletDid,
|
|
603
|
+
{
|
|
604
|
+
title: 'Invitation accepted',
|
|
605
|
+
body: `You accept an invitation to be a ${role} of ${applicationName}`,
|
|
606
|
+
attachments: [
|
|
607
|
+
{
|
|
608
|
+
type: 'vc',
|
|
609
|
+
data: {
|
|
610
|
+
credential: response.data,
|
|
611
|
+
tag: role,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
],
|
|
615
|
+
},
|
|
616
|
+
{ req }
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const connectedAccount = {
|
|
621
|
+
provider: LOGIN_PROVIDER.EMAIL,
|
|
622
|
+
id: sub,
|
|
623
|
+
did: userWallet.address,
|
|
624
|
+
pk: userWallet.publicKey,
|
|
625
|
+
userInfo,
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
if (profile) {
|
|
629
|
+
profile.inviter = inviteInfo.inviter?.did;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const { sessionToken, refreshToken, visitorId } = await userUtil.loginUserSession(
|
|
633
|
+
{
|
|
634
|
+
did: currentUser.did,
|
|
635
|
+
pk: currentUser.pk,
|
|
636
|
+
profile,
|
|
637
|
+
passport,
|
|
638
|
+
sourceAppPid,
|
|
639
|
+
connectedAccount,
|
|
640
|
+
},
|
|
641
|
+
{ req, node, options, loggedUser: user }
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
return {
|
|
645
|
+
sessionToken,
|
|
646
|
+
refreshToken,
|
|
647
|
+
visitorId,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
454
651
|
const privacyConfigInputSchema = Joi.object({
|
|
455
652
|
userDid: Joi.DID().required(),
|
|
456
653
|
});
|
|
@@ -545,7 +742,7 @@ module.exports = {
|
|
|
545
742
|
// 应用后端自行登录逻辑(SDK 中调用)
|
|
546
743
|
server.post([`${prefix}/login`, `${prefixApi}/login`], verifySig, async (req, res) => {
|
|
547
744
|
try {
|
|
548
|
-
const data = await
|
|
745
|
+
const data = await loginSDK(req, node, options);
|
|
549
746
|
res.status(200).json(data);
|
|
550
747
|
} catch (err) {
|
|
551
748
|
logger.error('Failed login', { error: err });
|
|
@@ -700,7 +897,7 @@ module.exports = {
|
|
|
700
897
|
const { did: teamDid } = await req.getBlockletInfo();
|
|
701
898
|
const pendingList = users.map(async (item) => {
|
|
702
899
|
if (item?.did && item?.pk) {
|
|
703
|
-
const findUser = await getUserWithinFederated(
|
|
900
|
+
const findUser = await federatedUtil.getUserWithinFederated(
|
|
704
901
|
{ sourceAppPid, teamDid, userDid: item.did, userPk: item.pk },
|
|
705
902
|
{ node, blocklet }
|
|
706
903
|
);
|
|
@@ -971,230 +1168,26 @@ module.exports = {
|
|
|
971
1168
|
}
|
|
972
1169
|
});
|
|
973
1170
|
server.post(`${prefixApi}/email/login`, ensureBlocklet(), ensureCors, async (req, res) => {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
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);
|
|
1171
|
+
const { action = 'login' } = req.body;
|
|
1172
|
+
const actionMap = {
|
|
1173
|
+
login: loginEmail,
|
|
1174
|
+
invite: inviteEmail,
|
|
1175
|
+
};
|
|
1176
|
+
if (!actionMap[action]) {
|
|
1177
|
+
logger.error('Failed to login by email', { error: 'action not exist', action });
|
|
1178
|
+
throw new Error(`action not exist: ${action}`);
|
|
1179
|
+
}
|
|
1140
1180
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
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
|
-
});
|
|
1181
|
+
try {
|
|
1182
|
+
const result = await actionMap[action](req, node, options);
|
|
1183
|
+
res.json(result);
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
logger.error('Failed login email', { error: err, action });
|
|
1186
|
+
if (err instanceof CustomError) {
|
|
1187
|
+
res.status(err.code).send(err.message);
|
|
1188
|
+
return;
|
|
1170
1189
|
}
|
|
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);
|
|
1190
|
+
throw err;
|
|
1198
1191
|
}
|
|
1199
1192
|
});
|
|
1200
1193
|
|
|
@@ -1434,7 +1427,7 @@ module.exports = {
|
|
|
1434
1427
|
return;
|
|
1435
1428
|
}
|
|
1436
1429
|
if (user.avatar) {
|
|
1437
|
-
user.avatar =
|
|
1430
|
+
user.avatar = federatedUtil.getUserAvatarUrl(user.avatar, blocklet);
|
|
1438
1431
|
}
|
|
1439
1432
|
let returnFields = ['avatar', 'did', 'fullName', 'sourceAppPid', 'createdAt', 'email', 'phone', 'metadata'];
|
|
1440
1433
|
|
|
@@ -4,7 +4,7 @@ const states = require('@abtnode/core/lib/states');
|
|
|
4
4
|
const JWT = require('@arcblock/jwt');
|
|
5
5
|
const md5 = require('@abtnode/util/lib/md5');
|
|
6
6
|
const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
|
|
7
|
-
const cloneDeep = require('
|
|
7
|
+
const cloneDeep = require('@abtnode/util/lib/deep-clone');
|
|
8
8
|
const {
|
|
9
9
|
NODE_MODES,
|
|
10
10
|
EVENTS,
|
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
NOTIFICATION_SEND_STATUS,
|
|
13
13
|
NOTIFICATION_SEND_FAILED_REASON,
|
|
14
14
|
} = require('@abtnode/constant');
|
|
15
|
+
const { nanoid } = require('@blocklet/meta/lib/util');
|
|
15
16
|
const get = require('lodash/get');
|
|
16
17
|
const uniqBy = require('lodash/uniqBy');
|
|
17
18
|
const { getWalletDid } = require('@blocklet/meta/lib/did-utils');
|
|
@@ -554,6 +555,13 @@ const init = ({ node, notificationService }) => {
|
|
|
554
555
|
}
|
|
555
556
|
}
|
|
556
557
|
|
|
558
|
+
// 如果 notification 没有 id,则生成一个, wallet 要基于这唯一个ID进行处理
|
|
559
|
+
if (!notification.id) {
|
|
560
|
+
notification.id = nanoid();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
notification.type = notification.type || 'notification';
|
|
564
|
+
|
|
557
565
|
const baseParams = {
|
|
558
566
|
...rest,
|
|
559
567
|
teamDid,
|
package/api/socket/util.js
CHANGED
|
@@ -16,10 +16,7 @@ const parseNotification = (notification, senderInfo) => {
|
|
|
16
16
|
|
|
17
17
|
// TODO: 如果通过 message id 实现消息去重, 消息顺序等
|
|
18
18
|
notifications.forEach((x) => {
|
|
19
|
-
|
|
20
|
-
x.createdAt = new Date();
|
|
21
|
-
}
|
|
22
|
-
|
|
19
|
+
x.createdAt = x.createdAt || new Date();
|
|
23
20
|
x.type = x.type || 'notification';
|
|
24
21
|
|
|
25
22
|
x.sender = {
|
package/api/util/federated.js
CHANGED
|
@@ -2,7 +2,7 @@ const { joinURL } = require('ufo');
|
|
|
2
2
|
const { WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
|
|
3
3
|
const pick = require('lodash/pick');
|
|
4
4
|
const defaults = require('lodash/defaults');
|
|
5
|
-
const cloneDeep = require('
|
|
5
|
+
const cloneDeep = require('@abtnode/util/lib/deep-clone');
|
|
6
6
|
const {
|
|
7
7
|
shouldSyncFederated,
|
|
8
8
|
isMaster,
|