From 65b757a5991be086dc08b81188d0626e36cc9a44 Mon Sep 17 00:00:00 2001 From: razputshivanshu <89507255+razputshivanshu@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:13:49 +0530 Subject: [PATCH 1/4] I have implemented the validation for the new users --- src/App.js | 44 ++++++------ src/components/Login.js | 40 ++++++++--- src/components/Navbar.js | 114 ++++++++++--------------------- src/components/ProtectedRoute.js | 36 ++++++++++ src/components/Register.js | 88 ++++++++---------------- src/context/AuthContext.js | 21 +++++- src/firebase.js | 4 +- 7 files changed, 174 insertions(+), 173 deletions(-) create mode 100644 src/components/ProtectedRoute.js diff --git a/src/App.js b/src/App.js index 4fede8f..043d34c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,3 +1,4 @@ +// App.js import React from 'react'; import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import Navbar from './components/Navbar'; @@ -11,36 +12,37 @@ import { AuthProvider } from './context/AuthContext'; import Support from './components/Support'; import Settings from './components/Setting'; import ImageQRCodeGenerator from './components/ImageQRCodeGenerator'; -import SocialMedia from './components/SocialMedia'; +import SocialMedia from './components/SocialMedia'; import BulkQRCode from './components/BulkQRCode'; import QRScanner from './components/QRScanner'; import PdfQRCodeGenerator from './components/PDFToQR'; import { ThemeProvider } from './context/ThemeContext'; -import { Toaster } from 'react-hot-toast'; +import ProtectedRoute from './components/ProtectedRoute'; export default function App() { return ( - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + {/* Remove the line for Verify */} + {/* } /> */} + + ); diff --git a/src/components/Login.js b/src/components/Login.js index c3d7b78..4dabe72 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -1,36 +1,56 @@ + + import React, { useState } from 'react'; import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; import { auth } from '../firebase'; import { useNavigate } from 'react-router-dom'; import { FcGoogle } from "react-icons/fc"; import { motion } from 'framer-motion'; -import toast from 'react-hot-toast'; +import { useAuth } from "../context/AuthContext"; export default function Login() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const navigate = useNavigate(); + const { setCurrentUser } = useAuth(); // Get setCurrentUser from Auth context const handleSubmit = async (e) => { e.preventDefault(); try { - await signInWithEmailAndPassword(auth, email, password); - navigate('/dashboard'); - toast.success("Login Successful"); + const userCredential = await signInWithEmailAndPassword(auth, email, password); + const user = userCredential.user; + + // Set currentUser from context + setCurrentUser(user); + + // Navigate only if user is verified + if (user.emailVerified) { + navigate('/dashboard'); + } else { + alert('Please verify your email before logging in.'); + } } catch (error) { - toast.error('Something went wrong'); - console.error(error.message); + alert(error.message); } }; const handleGoogleLogin = async () => { const provider = new GoogleAuthProvider(); try { - await signInWithPopup(auth, provider); - navigate('/dashboard'); + const userCredential = await signInWithPopup(auth, provider); + const user = userCredential.user; + + // Set currentUser from context + setCurrentUser(user); + + // Navigate only if user is verified + if (user.emailVerified) { + navigate('/dashboard'); + } else { + alert('Please verify your email before logging in.'); + } } catch (error) { - toast.error('Something went wrong'); - console.error(error.message); + alert(error.message); } }; diff --git a/src/components/Navbar.js b/src/components/Navbar.js index a10d93e..f8bcf1a 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -1,8 +1,8 @@ + import React, { useState, useEffect, useRef, useContext } from "react"; import { useAuth } from "../context/AuthContext"; import { Link, useNavigate } from "react-router-dom"; import { ThemeContext } from "../context/ThemeContext"; -import toast from "react-hot-toast"; import { FaUser, @@ -22,69 +22,17 @@ export default function Navbar() { const navigate = useNavigate(); const [dropdownOpen, setDropdownOpen] = useState(false); const dropdownRef = useRef(null); - const { darkMode, setDarkMode } = useContext(ThemeContext); const handleLogout = async () => { - // Show a confirmation toast - const confirmation = toast( - (t) => ( -
-

Are you sure you want to log out?

-
- - -
-
- ), - { - duration: 0, // Keep the toast open until dismissed - position: 'top-center', // Adjust position if needed - } - ) - }; - - const handleToggleTheme = () => { - setDarkMode((prevMode) => { - const newMode = !prevMode; - - // Show toast notification when theme changes - toast(`Theme changed to ${newMode ? 'Dark' : 'Light'} mode!`, { - icon: `${newMode ? '🌙' :'☀️'}`, - style: { - borderRadius: '10px', - background: `${newMode ? '#333' : '#fff'} `, - color: `${newMode ? '#fff' : '#333'}`, - }, - }); - - return newMode; - }); + try { + await logout(); + navigate("/"); // Redirect to the home page after logout + } catch (error) { + console.error("Failed to log out", error); + } }; - const toggleDropdown = () => { setDropdownOpen(!dropdownOpen); }; @@ -105,10 +53,11 @@ export default function Navbar() { return ( ); } + + + diff --git a/src/components/ProtectedRoute.js b/src/components/ProtectedRoute.js new file mode 100644 index 0000000..5e474b1 --- /dev/null +++ b/src/components/ProtectedRoute.js @@ -0,0 +1,36 @@ + + +import React, { useEffect, useState } from 'react'; +import { Navigate } from 'react-router-dom'; +import { auth, onAuthStateChanged } from '../firebase'; // Ensure the correct import + +const ProtectedRoute = ({ children }) => { + const [loading, setLoading] = useState(true); + const [isAuthorized, setIsAuthorized] = useState(false); + + useEffect(() => { + const unsubscribe = onAuthStateChanged(auth, (user) => { + if (user) { + // Check if the user has verified their email + setIsAuthorized(user.emailVerified); + } else { + setIsAuthorized(false); + } + setLoading(false); + }); + + return () => unsubscribe(); + }, []); + + if (loading) { + return
Loading...
; // Show loading indicator while checking auth + } + + if (!isAuthorized) { + return ; + } + + return children; +}; + +export default ProtectedRoute; diff --git a/src/components/Register.js b/src/components/Register.js index beed8af..c10e314 100644 --- a/src/components/Register.js +++ b/src/components/Register.js @@ -1,44 +1,45 @@ + import React, { useState } from 'react'; -import { createUserWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; -import { auth } from '../firebase'; +import { getAuth, createUserWithEmailAndPassword, sendEmailVerification } from 'firebase/auth'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; -import { FcGoogle } from 'react-icons/fc'; -import toast from 'react-hot-toast'; export default function Register() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); const navigate = useNavigate(); - const handleSubmit = async (e) => { + const handleRegister = async (e) => { e.preventDefault(); - try { - await createUserWithEmailAndPassword(auth, email, password); - navigate('/dashboard'); - toast.success('Registered successfully'); - } catch (error) { - toast.error('Something went wrong'); - console.error(error.message); - } - }; + const auth = getAuth(); - const handleGoogleRegister = async () => { - const provider = new GoogleAuthProvider(); try { - await signInWithPopup(auth, provider); - navigate('/dashboard'); - toast.success('Registered successfully'); + const userCredential = await createUserWithEmailAndPassword(auth, email, password); + const user = userCredential.user; + + await sendEmailVerification(user); + setSuccessMessage('Registration successful! Please check your email to verify your account.'); + + // Navigate to the login page after 3 seconds + setTimeout(() => { + navigate('/login'); + }, 3000); // 3000 milliseconds = 3 seconds + + // Clear message after 3 seconds + setTimeout(() => setSuccessMessage(''), 3000); + } catch (error) { - toast.error('Something went wrong'); - console.error(error.message); + setError(error.message); + console.error("Error during registration", error); } }; return (

Create an Account

-
- setEmail(e.target.value)} - className="w-full p-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition duration-300" - required - whileFocus={{ scale: 1.02, boxShadow: "0 0 10px rgba(59, 130, 246, 0.5)" }} - /> -
-
- setPassword(e.target.value)} - className="w-full p-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition duration-300" - required - whileFocus={{ scale: 1.02, boxShadow: "0 0 10px rgba(59, 130, 246, 0.5)" }} - /> -
- - Register - - - - Register with Google - + {error &&

{error}

} + {successMessage &&

{successMessage}

} + setEmail(e.target.value)} required className="w-full p-4 border border-gray-300 rounded-lg mb-4" /> + setPassword(e.target.value)} required className="w-full p-4 border border-gray-300 rounded-lg mb-8" /> + Register
); diff --git a/src/context/AuthContext.js b/src/context/AuthContext.js index 0feb584..5166349 100644 --- a/src/context/AuthContext.js +++ b/src/context/AuthContext.js @@ -1,3 +1,6 @@ + + + import React, { createContext, useContext, useState, useEffect } from 'react'; import { onAuthStateChanged, signOut } from "firebase/auth"; import { auth } from '../firebase'; @@ -14,7 +17,17 @@ export function AuthProvider({ children }) { useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { - setCurrentUser(user); + if (user) { + // Check if the user is verified + if (user.emailVerified) { + setCurrentUser(user); + } else { + // If not verified, set currentUser to null + setCurrentUser(null); + } + } else { + setCurrentUser(null); + } setLoading(false); }); @@ -24,7 +37,7 @@ export function AuthProvider({ children }) { const logout = async () => { try { await signOut(auth); - setCurrentUser(null); // Clear the current user + setCurrentUser(null); } catch (error) { console.error("Failed to log out", error); } @@ -32,12 +45,14 @@ export function AuthProvider({ children }) { const value = { currentUser, + setCurrentUser, // Expose setCurrentUser logout, + loading, // Expose loading state }; return ( - {!loading && children} + {!loading && children} {/* Prevent rendering until loading is false */} ); } diff --git a/src/firebase.js b/src/firebase.js index 22b8922..41d327a 100644 --- a/src/firebase.js +++ b/src/firebase.js @@ -1,5 +1,5 @@ import { initializeApp } from "firebase/app"; -import { getAuth } from "firebase/auth"; +import { getAuth, onAuthStateChanged } from "firebase/auth"; // Import onAuthStateChanged here import { getFirestore } from "firebase/firestore"; import { getStorage } from "firebase/storage"; @@ -18,4 +18,4 @@ const auth = getAuth(app); const db = getFirestore(app); const storage = getStorage(app); -export { auth, db, storage }; +export { auth, db, storage, onAuthStateChanged }; // Export onAuthStateChanged From ddfd52fca36b8e5234b8fde747e1a20923656f75 Mon Sep 17 00:00:00 2001 From: razputshivanshu <89507255+razputshivanshu@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:31:41 +0530 Subject: [PATCH 2/4] Fixed the GAccount of Singup --- .env | 7 +++++++ src/components/Login.js | 3 +++ src/components/Register.js | 34 ++++++++++++++++++++++------------ 3 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..e9354e8 --- /dev/null +++ b/.env @@ -0,0 +1,7 @@ +REACT_APP_FIREBASE_API_KEY="AIzaSyDIsJ2hzh4-3GPvaXB8dLCNTVK5OqP8t-A" +REACT_APP_FIREBASE_AUTH_DOMAIN="qr-code-2308a.firebaseapp.com" +REACT_APP_FIREBASE_PROJECT_ID="qr-code-2308a" +REACT_APP_FIREBASE_STORAGE_BUCKET="qr-code-2308a.appspot.com" +REACT_APP_FIREBASE_MESSAGING_SENDER_ID="193948546902" +REACT_APP_FIREBASE_APP_ID="1:193948546902:web:447a74d54ade94eb3788f7" +REACT_APP_FIREBASE_MEASUREMENT_ID="" diff --git a/src/components/Login.js b/src/components/Login.js index 4dabe72..6114d1e 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -104,6 +104,9 @@ export default function Login() { Sign in with Google + + + ); } diff --git a/src/components/Register.js b/src/components/Register.js index c10e314..54054c5 100644 --- a/src/components/Register.js +++ b/src/components/Register.js @@ -1,8 +1,8 @@ - import React, { useState } from 'react'; import { getAuth, createUserWithEmailAndPassword, sendEmailVerification } from 'firebase/auth'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; +import { FcGoogle } from 'react-icons/fc'; // Import Google icon export default function Register() { const [email, setEmail] = useState(''); @@ -16,20 +16,19 @@ export default function Register() { const auth = getAuth(); try { - const userCredential = await createUserWithEmailAndPassword(auth, email, password); - const user = userCredential.user; - - await sendEmailVerification(user); - setSuccessMessage('Registration successful! Please check your email to verify your account.'); + const userCredential = await createUserWithEmailAndPassword(auth, email, password); + const user = userCredential.user; - // Navigate to the login page after 3 seconds - setTimeout(() => { - navigate('/login'); - }, 3000); // 3000 milliseconds = 3 seconds + await sendEmailVerification(user); + setSuccessMessage('Registration successful! Please check your email to verify your account.'); - // Clear message after 3 seconds - setTimeout(() => setSuccessMessage(''), 3000); + // Navigate to the login page after 3 seconds + setTimeout(() => { + navigate('/login'); + }, 3000); // 3000 milliseconds = 3 seconds + // Clear message after 3 seconds + setTimeout(() => setSuccessMessage(''), 3000); } catch (error) { setError(error.message); console.error("Error during registration", error); @@ -52,6 +51,17 @@ export default function Register() { setEmail(e.target.value)} required className="w-full p-4 border border-gray-300 rounded-lg mb-4" /> setPassword(e.target.value)} required className="w-full p-4 border border-gray-300 rounded-lg mb-8" /> Register + + {/* Google Register Button */} + + + Register with Google + ); From e589a84b14c01af8d394a054c9865912898946f5 Mon Sep 17 00:00:00 2001 From: razputshivanshu <89507255+razputshivanshu@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:37:37 +0530 Subject: [PATCH 3/4] removed env --- .env | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index e9354e8..0000000 --- a/.env +++ /dev/null @@ -1,7 +0,0 @@ -REACT_APP_FIREBASE_API_KEY="AIzaSyDIsJ2hzh4-3GPvaXB8dLCNTVK5OqP8t-A" -REACT_APP_FIREBASE_AUTH_DOMAIN="qr-code-2308a.firebaseapp.com" -REACT_APP_FIREBASE_PROJECT_ID="qr-code-2308a" -REACT_APP_FIREBASE_STORAGE_BUCKET="qr-code-2308a.appspot.com" -REACT_APP_FIREBASE_MESSAGING_SENDER_ID="193948546902" -REACT_APP_FIREBASE_APP_ID="1:193948546902:web:447a74d54ade94eb3788f7" -REACT_APP_FIREBASE_MEASUREMENT_ID="" From b76d85eb8eb2e5221190292fc1d149f0e45256be Mon Sep 17 00:00:00 2001 From: razputshivanshu <89507255+razputshivanshu@users.noreply.github.com> Date: Sat, 5 Oct 2024 08:35:15 +0530 Subject: [PATCH 4/4] fixed the validation issue for old users also --- src/components/Login.js | 53 ++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/components/Login.js b/src/components/Login.js index 6114d1e..cd73ee8 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -1,7 +1,5 @@ - - import React, { useState } from 'react'; -import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; +import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider, sendEmailVerification } from "firebase/auth"; import { auth } from '../firebase'; import { useNavigate } from 'react-router-dom'; import { FcGoogle } from "react-icons/fc"; @@ -11,23 +9,24 @@ import { useAuth } from "../context/AuthContext"; export default function Login() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [showVerificationModal, setShowVerificationModal] = useState(false); + const [emailAuthVerified, setEmailAuthVerified] = useState(false); + const [googleAuthVerified, setGoogleAuthVerified] = useState(false); const navigate = useNavigate(); - const { setCurrentUser } = useAuth(); // Get setCurrentUser from Auth context + const { setCurrentUser } = useAuth(); const handleSubmit = async (e) => { e.preventDefault(); try { const userCredential = await signInWithEmailAndPassword(auth, email, password); const user = userCredential.user; - - // Set currentUser from context setCurrentUser(user); - // Navigate only if user is verified if (user.emailVerified) { + setEmailAuthVerified(true); navigate('/dashboard'); } else { - alert('Please verify your email before logging in.'); + setShowVerificationModal(true); } } catch (error) { alert(error.message); @@ -39,21 +38,29 @@ export default function Login() { try { const userCredential = await signInWithPopup(auth, provider); const user = userCredential.user; - - // Set currentUser from context setCurrentUser(user); - // Navigate only if user is verified if (user.emailVerified) { + setGoogleAuthVerified(true); navigate('/dashboard'); } else { - alert('Please verify your email before logging in.'); + setShowVerificationModal(true); } } catch (error) { alert(error.message); } }; + const handleSendVerificationEmail = async () => { + try { + await sendEmailVerification(auth.currentUser); + alert('Verification email sent! Please check your inbox.'); + setShowVerificationModal(false); + } catch (error) { + alert(error.message); + } + }; + return (
- - + {showVerificationModal && ( +
+
+

Email Verification Required

+

Your email address is not verified. Please verify your email to continue.

+ + +
+
+ )}
); }