@@ -22,63 +22,31 @@ import okxModule from "@web3-onboard/okx";
2222import frontierModule from "@web3-onboard/frontier" ;
2323import { useAuth } from "@/lib/context/AuthContext" ;
2424import { useSettings } from "@/components/context/SettingsContext" ;
25- import CryptoJS from "crypto-js" ; // Still imported but not used in encryption here
26- import bcrypt from "bcryptjs" ; // Import bcryptjs
25+ import { Subscription } from "@supabase/supabase-js" ;
26+ import bcrypt from "bcryptjs" ; // Thêm bcryptjs để hash mật khẩu
27+ import crypto from "crypto" ; // Dùng crypto để mã hóa dữ liệu
2728
28- // Secret key (should ideally be stored in environment variables)
29- const SECRET_KEY = process . env . NEXT_PUBLIC_ENCRYPTION_KEY || "my-secret-key-1234567890" ;
30-
31- // Function to hash a password
32- const hashPassword = ( password : string ) : string => {
33- const salt = bcrypt . genSaltSync ( 10 ) ;
34- return bcrypt . hashSync ( password , salt ) ;
35- } ;
36-
37- // Function to hash data (replacing encryptData)
38- const encryptData = ( data : string ) : string => {
39- return bcrypt . hashSync ( data , 10 ) ;
40- } ;
41-
42- // Function to "decrypt" data (not possible with bcrypt)
43- const decryptData = ( encryptedData : string ) : string => {
44- // bcrypt is a one-way hashing algorithm, so we cannot decrypt
45- throw new Error ( "Cannot decrypt data hashed with bcrypt" ) ;
46- } ;
47-
48- // Rest of your wallet configurations remain unchanged
49- const dcent = dcentModule ( ) ;
29+ // Web3-Onboard configuration
5030const INFURA_KEY = "7d389678fba04ceb9510b2be4fff5129" ;
51-
5231const walletConnect = walletConnectModule ( {
5332 projectId : "b773e42585868b9b143bb0f1664670f1" ,
5433 optionalChains : [ 1 , 137 ] ,
5534} ) ;
5635
57- const injected = injectedModule ( ) ;
58- const coinbase = coinbaseModule ( ) ;
59- const infinityWallet = infinityWalletModule ( ) ;
60- const safe = safeModule ( ) ;
61- const sequence = sequenceModule ( ) ;
62- const taho = tahoModule ( ) ;
63- const trust = trustModule ( ) ;
64- const okx = okxModule ( ) ;
65- const frontier = frontierModule ( ) ;
66- const trezor = trezorModule ( { email : "test@test.com" , appUrl : "https://www.blocknative.com" } ) ;
67- const magic = magicModule ( { apiKey : "pk_live_E9B0C0916678868E" } ) ;
68-
6936const wallets = [
70- infinityWallet ,
71- sequence ,
72- injected ,
73- trust ,
74- okx ,
75- frontier ,
76- taho ,
77- coinbase ,
78- dcent ,
37+ infinityWalletModule ( ) ,
38+ sequenceModule ( ) ,
39+ injectedModule ( ) ,
40+ trustModule ( ) ,
41+ okxModule ( ) ,
42+ frontierModule ( ) ,
43+ tahoModule ( ) ,
44+ coinbaseModule ( ) ,
45+ dcentModule ( ) ,
7946 walletConnect ,
80- safe ,
81- magic ,
47+ safeModule ( ) ,
48+ magicModule ( { apiKey : "pk_live_E9B0C0916678868E" } ) ,
49+ trezorModule ( { email : "test@test.com" , appUrl : "https://www.blocknative.com" } ) ,
8250] ;
8351
8452const chains = [
@@ -104,43 +72,103 @@ const appMetadata = {
10472
10573const web3Onboard = init ( { wallets, chains, appMetadata } ) ;
10674
75+ // Debounce utility with proper TypeScript types
76+ const debounce = < T extends ( ...args : any [ ] ) => void > (
77+ func : T ,
78+ wait : number
79+ ) : ( ( ...args : Parameters < T > ) => void ) => {
80+ let timeout : NodeJS . Timeout | undefined ;
81+ return ( ...args : Parameters < T > ) => {
82+ clearTimeout ( timeout ) ;
83+ timeout = setTimeout ( ( ) => func ( ...args ) , wait ) ;
84+ } ;
85+ } ;
86+
87+ // Khóa bí mật để mã hóa dữ liệu (nên lưu trong biến môi trường trong thực tế)
88+ const ENCRYPTION_KEY = process . env . NEXT_PUBLIC_ENCRYPTION_KEY || "your-secret-key-here-32bytes-long" ;
89+ const IV_LENGTH = 16 ; // Độ dài IV cho AES
90+
91+ // Hàm mã hóa dữ liệu
92+ const encryptData = ( text : string ) : string => {
93+ const iv = crypto . randomBytes ( IV_LENGTH ) ;
94+ const cipher = crypto . createCipheriv ( "aes-256-cbc" , Buffer . from ( ENCRYPTION_KEY ) , iv ) ;
95+ let encrypted = cipher . update ( text ) ;
96+ encrypted = Buffer . concat ( [ encrypted , cipher . final ( ) ] ) ;
97+ return iv . toString ( "hex" ) + ":" + encrypted . toString ( "hex" ) ;
98+ } ;
99+
100+ // Hàm giải mã dữ liệu
101+ const decryptData = ( text : string ) : string => {
102+ const [ iv , encryptedText ] = text . split ( ":" ) ;
103+ const decipher = crypto . createDecipheriv (
104+ "aes-256-cbc" ,
105+ Buffer . from ( ENCRYPTION_KEY ) ,
106+ Buffer . from ( iv , "hex" )
107+ ) ;
108+ let decrypted = decipher . update ( Buffer . from ( encryptedText , "hex" ) ) ;
109+ decrypted = Buffer . concat ( [ decrypted , decipher . final ( ) ] ) ;
110+ return decrypted . toString ( ) ;
111+ } ;
112+
107113function LoginPageContent ( ) {
108114 const router = useRouter ( ) ;
109115 const { signInWithWalletConnect, signIn } = useAuth ( ) ;
110116 const { updateProfile, addWallet, syncWithSupabase } = useSettings ( ) ;
111117
112- const [ email , setEmail ] = useState ( "" ) ;
113- const [ password , setPassword ] = useState ( "" ) ;
114- const [ emailError , setEmailError ] = useState ( "" ) ;
115- const [ passwordError , setPasswordError ] = useState ( "" ) ;
116- const [ showPassword , setShowPassword ] = useState ( false ) ;
117- const [ isLoading , setIsLoading ] = useState ( false ) ;
118+ const [ email , setEmail ] = useState < string > ( "" ) ;
119+ const [ password , setPassword ] = useState < string > ( "" ) ;
120+ const [ emailError , setEmailError ] = useState < string > ( "" ) ;
121+ const [ passwordError , setPasswordError ] = useState < string > ( "" ) ;
122+ const [ showPassword , setShowPassword ] = useState < boolean > ( false ) ;
123+ const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
118124
119125 const [ { wallet, connecting } , connect , disconnect ] = useConnectWallet ( ) ;
120- const [ isLoggedOut , setIsLoggedOut ] = useState ( false ) ;
126+ const [ isLoggedOut , setIsLoggedOut ] = useState < boolean > ( false ) ;
121127
122128 interface Account {
123129 address : string ;
124130 ens : string | null ;
125131 }
126132
127- const formatWalletAddress = ( walletAddress : string ) => {
133+ const [ account , setAccount ] = useState < Account | null > ( null ) ;
134+
135+ const formatWalletAddress = ( walletAddress : string ) : string => {
128136 if ( ! walletAddress ) return "" ;
129137 return `${ walletAddress . slice ( 0 , 6 ) } ...${ walletAddress . slice ( - 4 ) } ` ;
130138 } ;
131139
132- const [ account , setAccount ] = useState < Account | null > ( null ) ;
133-
140+ // Check session and listen to auth state changes
134141 useEffect ( ( ) => {
135142 const checkExistingSession = async ( ) => {
136- const { data : { session } } = await supabase . auth . getSession ( ) ;
143+ const { data : { session } , error } = await supabase . auth . getSession ( ) ;
144+ if ( error ) {
145+ console . error ( "Error checking session:" , error . message ) ;
146+ return ;
147+ }
137148 if ( session ) {
149+ console . log ( "Initial session found, redirecting to dashboard" ) ;
138150 router . push ( "/" ) ;
139151 }
140152 } ;
141153 checkExistingSession ( ) ;
154+
155+ const { data : { subscription } } = supabase . auth . onAuthStateChange ( ( event , session ) => {
156+ console . log ( "Auth state changed:" , event ) ;
157+ if ( event === "SIGNED_IN" && session ) {
158+ console . log ( "User signed in, redirecting to dashboard" ) ;
159+ router . push ( "/" ) ;
160+ } else if ( event === "SIGNED_OUT" ) {
161+ console . log ( "User signed out, staying on login page" ) ;
162+ setIsLoggedOut ( true ) ;
163+ }
164+ } ) ;
165+
166+ return ( ) => {
167+ subscription . unsubscribe ( ) ;
168+ } ;
142169 } , [ router ] ) ;
143170
171+ // Handle wallet connection and authentication
144172 useEffect ( ( ) => {
145173 if ( wallet ?. provider && ! isLoggedOut ) {
146174 const { address, ens } = wallet . accounts [ 0 ] ;
@@ -149,11 +177,27 @@ function LoginPageContent() {
149177 const authenticateWithWallet = async ( ) => {
150178 try {
151179 setIsLoading ( true ) ;
180+ const hashedAddress = await bcrypt . hash ( address , 10 ) ; // Hash địa chỉ ví
152181 const { data, error } = await signInWithWalletConnect ( address ) ;
153182 if ( error ) {
154- console . error ( "Wallet auth error:" , error ) ;
155- toast . error ( `Failed to authenticate with wallet: ${ error . message } ` ) ;
156- return ;
183+ if ( error . message . includes ( "User already registered" ) ) {
184+ toast . info ( "User already exists. Logging in instead." ) ;
185+ const { data : loginData , error : loginError } = await supabase . auth . signInWithPassword ( {
186+ email : `${ address } @cryptopath.local` ,
187+ password : hashedAddress , // Sử dụng hashed address làm mật khẩu
188+ } ) ;
189+ if ( loginError ) throw new Error ( loginError . message ) ;
190+ if ( ! loginData . session ) throw new Error ( "No session returned from login" ) ;
191+ const encryptedToken = encryptData ( JSON . stringify ( loginData . session . access_token ) ) ;
192+ localStorage . setItem ( "userToken" , encryptedToken ) ;
193+ } else {
194+ throw new Error ( error . message ) ;
195+ }
196+ } else if ( ! data || ! data . session ) {
197+ throw new Error ( "No session data returned from sign-in" ) ;
198+ } else {
199+ const encryptedToken = encryptData ( JSON . stringify ( data . session . access_token ) ) ;
200+ localStorage . setItem ( "userToken" , encryptedToken ) ;
157201 }
158202
159203 updateProfile ( {
@@ -169,15 +213,16 @@ function LoginPageContent() {
169213 name : ens ?. name || formatWalletAddress ( address ) ,
170214 isLoggedIn : true ,
171215 } ;
172- // Hash before storing in localStorage
173- localStorage . setItem ( "userDisplayInfo" , encryptData ( JSON . stringify ( publicUserData ) ) ) ;
174- localStorage . setItem ( "userToken" , encryptData ( data . session ?. access_token || "" ) ) ;
216+ const encryptedUserData = encryptData ( JSON . stringify ( publicUserData ) ) ;
217+ localStorage . setItem ( "userDisplayInfo" , encryptedUserData ) ;
175218
219+ console . log ( "Wallet login successful, redirecting to dashboard" ) ;
176220 toast . success ( "Successfully authenticated with wallet" ) ;
177221 router . push ( "/" ) ;
178- } catch ( error : any ) {
179- console . error ( "Error authenticating with wallet:" , error ) ;
180- toast . error ( `Authentication failed: ${ error ?. message || "Unknown error" } ` ) ;
222+ } catch ( error : unknown ) {
223+ const errorMessage = error instanceof Error ? error . message : "Unknown error" ;
224+ console . error ( "Wallet authentication error:" , error ) ;
225+ toast . error ( `Authentication failed: ${ errorMessage } ` ) ;
181226 } finally {
182227 setIsLoading ( false ) ;
183228 }
@@ -187,27 +232,25 @@ function LoginPageContent() {
187232 }
188233 } , [ wallet , router , isLoggedOut , signInWithWalletConnect , updateProfile , addWallet , syncWithSupabase ] ) ;
189234
235+ // Handle email/password login
190236 const handleSubmit = async ( e : React . FormEvent < HTMLFormElement > ) => {
191237 e . preventDefault ( ) ;
192238 setEmailError ( "" ) ;
193239 setPasswordError ( "" ) ;
194240 setIsLoading ( true ) ;
195241
196242 try {
197- // Hash the password before sending it to the signIn function
198- const hashedPassword = hashPassword ( password ) ;
199- const { data, error } = await signIn ( email , hashedPassword ) ; // Assuming signIn accepts hashed password
243+ const hashedPassword = await bcrypt . hash ( password , 10 ) ; // Hash mật khẩu trước khi gửi
244+ const { data, error } = await signIn ( email , hashedPassword ) ; // Gửi hashed password
200245 if ( error ) {
201246 if ( error . message . includes ( "email" ) ) setEmailError ( error . message ) ;
202247 else if ( error . message . includes ( "password" ) ) setPasswordError ( error . message ) ;
203248 else toast . error ( error . message ) ;
204- setIsLoading ( false ) ;
205249 return ;
206250 }
207251
208- if ( ! data . user ) {
252+ if ( ! data . user || ! data . session ) {
209253 toast . error ( "Something went wrong with the login" ) ;
210- setIsLoading ( false ) ;
211254 return ;
212255 }
213256
@@ -230,35 +273,38 @@ function LoginPageContent() {
230273 email,
231274 isLoggedIn : true ,
232275 } ;
233- // Hash before storing in localStorage
234- localStorage . setItem ( "currentUser" , encryptData ( JSON . stringify ( publicUserData ) ) ) ;
235- localStorage . setItem ( "userToken" , encryptData ( data . session ?. access_token || "" ) ) ;
276+ const encryptedUserData = encryptData ( JSON . stringify ( publicUserData ) ) ;
277+ const encryptedToken = encryptData ( JSON . stringify ( data . session . access_token ) ) ;
278+ localStorage . setItem ( "currentUser" , encryptedUserData ) ;
279+ localStorage . setItem ( "userToken" , encryptedToken ) ;
236280
281+ console . log ( "Email login successful, redirecting to dashboard" ) ;
237282 toast . success ( "Login successful!" ) ;
238283 router . push ( "/" ) ;
239- } catch ( error : any ) {
284+ } catch ( error : unknown ) {
285+ const errorMessage = error instanceof Error ? error . message : "Unknown error" ;
240286 console . error ( "Login error:" , error ) ;
241- toast . error ( " An unexpected error occurred. Please try again." ) ;
287+ toast . error ( ` An unexpected error occurred: ${ errorMessage } ` ) ;
242288 } finally {
243289 setIsLoading ( false ) ;
244290 }
245291 } ;
246292
247- const handleWalletConnect = async ( ) => {
293+ // Handle wallet connect/disconnect with debounce
294+ const handleWalletConnect = debounce ( async ( ) => {
248295 if ( ! wallet ) {
249- connect ( ) ;
296+ await connect ( ) ;
250297 } else {
251- disconnect ( { label : wallet . label } ) ;
298+ await disconnect ( { label : wallet . label } ) ;
252299 setAccount ( null ) ;
253300 setIsLoggedOut ( true ) ;
254301 await supabase . auth . signOut ( ) ;
255302 localStorage . removeItem ( "userDisplayInfo" ) ;
256303 localStorage . removeItem ( "userToken" ) ;
257304 router . push ( "/login" ) ;
258305 }
259- } ;
306+ } , 1000 ) ;
260307
261- // The rest of your JSX remains unchanged
262308 return (
263309 < >
264310 < div className = "relative" >
@@ -347,9 +393,10 @@ function LoginPageContent() {
347393 options : { redirectTo : `${ window . location . origin } /` } ,
348394 } ) ;
349395 if ( error ) throw error ;
350- } catch ( error ) {
396+ } catch ( error : unknown ) {
397+ const errorMessage = error instanceof Error ? error . message : "Unknown error" ;
351398 console . error ( "Google login error:" , error ) ;
352- toast . error ( " Google login failed. Please try again." ) ;
399+ toast . error ( ` Google login failed: ${ errorMessage } ` ) ;
353400 } finally {
354401 setIsLoading ( false ) ;
355402 }
0 commit comments