1- import React , { useEffect , useState } from "react" ;
1+ import React , { useCallback , useEffect , useState } from "react" ;
22import { MetaTags } from "react-meta-tags" ;
33import { withTranslation } from "react-i18next" ;
44
@@ -26,70 +26,103 @@ import { deleteUserData } from "../utils/auth-token";
2626function Login ( { t } ) {
2727 const history = useHistory ( ) ;
2828 const { loginUser, loginWithPhoneNumber, setUserDataLogin } = useUser ( ) ;
29- const [ openSMS2Fa , setOpenSMS2Fa ] = useState ( false ) ;
30- const [ openGAuthFa , setOpenGAuth2Fa ] = useState ( false ) ;
29+ // UI state
3130 const [ submitting , setSubmitting ] = useState ( false ) ;
32- const [ userSignInSms , setUserSignInSms ] = useState ( { } ) ;
33- const [ userSignInGAuth , setUserSignInGAuth ] = useState ( "" ) ;
31+ const [ active2FAMethod , setActive2FAMethod ] = useState ( null ) ; // 'sms' | 'gauth' | null
32+
33+ // 2FA session state (in-memory, only during current login flow)
34+ const [ pendingUser , setPendingUser ] = useState ( null ) ; // firebase user from base login
35+ const [ pendingPassword , setPendingPassword ] = useState ( "" ) ; // used to create seed after 2FA
36+ const [ smsConfirmation , setSmsConfirmation ] = useState ( null ) ; // result from signInWithPhoneNumber
37+ const [ gauthContext , setGauthContext ] = useState ( null ) ; // { ...user, secret }
3438
3539 useEffect ( ( ) => {
3640 return ( ) => {
3741 setSubmitting ( false ) ;
38- setOpenGAuth2Fa ( false ) ;
39- setOpenSMS2Fa ( false ) ;
42+ setActive2FAMethod ( null ) ;
4043 } ;
4144 } , [ ] ) ;
4245
46+ // Alert helpers
47+ const showLoading = useCallback ( ( title ) => {
48+ swal . fire ( {
49+ title : title || "Processing" ,
50+ showConfirmButton : false ,
51+ willOpen : ( ) => swal . showLoading ( ) ,
52+ } ) ;
53+ } , [ ] ) ;
54+
55+ const showSuccess = useCallback ( async ( message = "Logged in" ) => {
56+ await swal . fire ( {
57+ icon : "success" ,
58+ title : message ,
59+ timer : 2000 ,
60+ showConfirmButton : false ,
61+ } ) ;
62+ } , [ ] ) ;
63+
64+ const showError = useCallback ( ( message = "Error" ) => {
65+ swal . fire ( { icon : "error" , title : "Error" , text : message } ) ;
66+ } , [ ] ) ;
67+
68+ // Finalize login: persist and navigate
69+ const finalizeLogin = useCallback (
70+ async ( user ) => {
71+ if ( pendingPassword ) {
72+ createSeed ( pendingPassword ) ;
73+ }
74+ setUserDataLogin ( user ) ;
75+ history . push ( "/governance" ) ;
76+ } ,
77+ [ history , pendingPassword , setUserDataLogin ]
78+ ) ;
79+
4380 /**
4481 * Function that verifies the user2fa and proceeds to open the 2faModal; in case 2fa isn't active, it signs in the user
4582 * @param {{email:string, password: string} } loginData Login data received from LoginForm it has email and password
4683 */
4784 const loginToApp = async ( loginData ) => {
48- swal . fire ( {
49- title : "Submitting" ,
50- showConfirmButton : false ,
51- willOpen : ( ) => {
52- swal . showLoading ( ) ;
53- } ,
54- } ) ;
85+ showLoading ( "Submitting" ) ;
5586 setSubmitting ( true ) ;
5687 try {
57- let user = await loginUser ( loginData ) ;
58- createSeed ( loginData . password ) ;
59- let user2fa = await get2faInfoUser ( user . uid ) ;
60- if ( user2fa . twoFa === true && user2fa . sms === true ) {
88+ const user = await loginUser ( loginData ) ;
89+ // store ephemeral data for post-2FA persistence
90+ setPendingPassword ( loginData . password ) ;
91+ setPendingUser ( user ) ;
92+
93+ const user2fa = await get2faInfoUser ( user . uid , user . accessToken ) ;
94+ const hasSms2FA = user2fa . twoFa === true && user2fa . sms === true ;
95+ const hasGAuth2FA = user2fa . twoFa === true && user2fa . gAuth === true ;
96+
97+ if ( hasSms2FA ) {
6198 swal . close ( ) ;
62- let phoneProvider = await loginWithPhoneNumber (
99+ const confirmation = await loginWithPhoneNumber (
63100 user . phoneNumber ,
64101 window . recaptchaVerifier
65102 ) ;
66- setUserSignInSms ( phoneProvider ) ;
67- setOpenSMS2Fa ( true ) ;
103+ setSmsConfirmation ( confirmation ) ;
104+ setActive2FAMethod ( "sms" ) ;
68105 setSubmitting ( false ) ;
69- } else if ( user2fa . twoFa === true && user2fa . gAuth === true ) {
106+ return ;
107+ }
108+
109+ if ( hasGAuth2FA ) {
70110 swal . close ( ) ;
71- setUserSignInGAuth ( { ...user , secret : user2fa . gAuthSecret } ) ;
72- setOpenGAuth2Fa ( true ) ;
111+ setGauthContext ( { ...user , secret : user2fa . gAuthSecret } ) ;
112+ setActive2FAMethod ( "gauth" ) ;
73113 setSubmitting ( false ) ;
74- } else {
75- await swal . fire ( {
76- icon : "success" ,
77- title : "Logged in" ,
78- timer : 2000 ,
79- showConfirmButton : false ,
80- } ) ;
81- setUserDataLogin ( user ) ;
82- history . push ( "/governance" ) ;
114+ return ;
83115 }
116+
117+ // No 2FA: finalize immediately
118+ await showSuccess ( "Logged in" ) ;
119+ createSeed ( loginData . password ) ;
120+ await finalizeLogin ( user ) ;
84121 } catch ( error ) {
85122 deleteUserData ( ) ;
86- swal . fire ( {
87- icon : "error" ,
88- title : "Error" ,
89- text : error . message ,
90- } ) ;
123+ showError ( error . message ) ;
91124 removeSeed ( ) ;
92- return setSubmitting ( false ) ;
125+ setSubmitting ( false ) ;
93126 }
94127 } ;
95128
@@ -98,67 +131,30 @@ function Login({ t }) {
98131 * @param {string } gAuthCode gAuthcode submitted by the user in the 2fa modal
99132 */
100133 const verifyGAuth = async ( { gAuthCode } ) => {
101- swal . fire ( {
102- title : "Verifying" ,
103- showConfirmButton : false ,
104- willOpen : ( ) => {
105- swal . showLoading ( ) ;
106- } ,
107- } ) ;
108-
109- verifyGauthCode ( gAuthCode )
110- . then ( ( ) => {
111- setOpenGAuth2Fa ( false ) ;
112- swal . fire ( {
113- icon : "success" ,
114- title : "Logged in" ,
115- text : "Code verified" ,
116- timer : 2000 ,
117- showConfirmButton : false ,
118- } ) ;
119- setUserDataLogin ( userSignInGAuth ) ;
120- history . push ( "/governance" ) ;
121- } )
122- . catch ( ( err ) => {
123- swal . fire ( {
124- icon : "error" ,
125- title : "Invalid code" ,
126- } ) ;
127- } ) ;
134+ showLoading ( "Verifying" ) ;
135+ try {
136+ await verifyGauthCode ( gAuthCode , pendingUser ?. accessToken ) ;
137+ setActive2FAMethod ( null ) ;
138+ await showSuccess ( "Logged in" ) ;
139+ await finalizeLogin ( gauthContext ) ;
140+ } catch ( err ) {
141+ showError ( "Invalid code" ) ;
142+ }
128143 } ;
129144
130145 /**
131146 * Function that verifies the SMS verification code and proceeds to login
132147 * @param {string } phoneCode phoneCode submitted by the user in the 2fa modal
133148 */
134149 const verifyPhone = async ( { phoneCode } ) => {
135- swal . fire ( {
136- title : "Verifying" ,
137- showConfirmButton : false ,
138- willOpen : ( ) => {
139- swal . showLoading ( ) ;
140- } ,
141- } ) ;
150+ showLoading ( "Verifying" ) ;
142151 try {
143- let { user } = await userSignInSms . confirm ( phoneCode ) . catch ( ( err ) => {
144- throw err ;
145- } ) ;
146- setOpenSMS2Fa ( false ) ;
147- await swal . fire ( {
148- icon : "success" ,
149- title : "Logged in" ,
150- text : "Code verified" ,
151- timer : 2000 ,
152- showConfirmButton : false ,
153- } ) ;
154- setUserDataLogin ( user ) ;
155- history . push ( "/governance" ) ;
152+ const { user } = await smsConfirmation . confirm ( phoneCode ) ;
153+ setActive2FAMethod ( null ) ;
154+ await showSuccess ( "Logged in" ) ;
155+ await finalizeLogin ( user ) ;
156156 } catch ( error ) {
157- swal . fire ( {
158- icon : "error" ,
159- title : "Error" ,
160- text : error . message ,
161- } ) ;
157+ showError ( error . message ) ;
162158 }
163159 } ;
164160
@@ -193,13 +189,13 @@ function Login({ t }) {
193189 </ div >
194190 </ div >
195191 </ main >
196- < CustomModal open = { openSMS2Fa } onClose = { ( ) => setOpenSMS2Fa ( false ) } >
192+ < CustomModal open = { active2FAMethod === "sms" } onClose = { ( ) => setActive2FAMethod ( null ) } >
197193 < SMSTwoFAFormLogin
198194 userSignInSms = { verifyPhone }
199- closeModal = { ( ) => setOpenSMS2Fa ( false ) }
195+ closeModal = { ( ) => setActive2FAMethod ( null ) }
200196 />
201197 </ CustomModal >
202- < CustomModal open = { openGAuthFa } onClose = { ( ) => setOpenGAuth2Fa ( false ) } >
198+ < CustomModal open = { active2FAMethod === "gauth" } onClose = { ( ) => setActive2FAMethod ( null ) } >
203199 < GAuthTwoFAFormLogin userSignInGAuth = { verifyGAuth } />
204200 </ CustomModal >
205201 </ Background >
0 commit comments