Completed Firebase Authentication Project

This commit is contained in:
Deepak Kumar
2024-06-04 18:44:40 +05:30
parent aa2b0207a9
commit 272ee3f7f5
26 changed files with 19614 additions and 8 deletions

View File

@@ -0,0 +1,5 @@
# .gitignore
# Ignore the following files
node_modules
dist

View File

@@ -2,20 +2,136 @@
## Description
A brief description of the firebase authentication project.
Firebase Authentication provides a comprehensive and secure solution for authenticating users in web applications. It supports various authentication methods, including email and password, Google Sign-In, Facebook Login, and more. This project demonstrates how to integrate Firebase Authentication in a React application, offering a seamless and secure user login experience.
## Features
- Feature 1
- Feature 2
- Feature 3
- **User Registration:** Allow users to sign up with email and password.
- **User Login:** Enable users to log in using their email and password.
- **Password Reset:** Provide users with the option to reset their password via email.
## Technologies Used
- JavaScript
- HTML
- CSS
- **React:** For building the user interface.
- **Firebase:** For backend authentication services.
## Setup
Instructions to set up and run the project.
Follow these instructions to set up and run the project locally:
1. **Clone the Repository:**
```bash
git clone https://github.com/deepakkumar55/ULTIMATE-JAVASCRIPT-PROJECT.git
cd Database Integration/1-firebase_authentication
```
2. **Install Dependencies:**
```bash
npm install
npm install firebase
```
3. **Firebase Configuration:**
- 1. **Create a Firebase Project**:
- Go to the [Firebase Console](https://console.firebase.google.com/).
- Click on "Add project" and follow the instructions to create a new Firebase project.
- 2. **Enable Authentication Methods**:
- In the Firebase Console, navigate to the "Authentication" section.
- Click on the "Sign-in method" tab.
- Enable "Email/Password" and "Google" sign-in methods.
- 3. **Get Firebase SDK Config**:
- In the Firebase Console, navigate to "Project settings".
- Under "Your apps", add a new web app and register it.
- Copy the Firebase SDK configuration snippet provided.
```javascript
// src/firebase.js
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
```
4. **Run the Project:**
- Start the backend server:
```bash
npm run dev
```
- Start the frontend server:
```bash
cd frontend
npm start
```
- Open your browser and navigate to `http://localhost:3000` to see the application in action.
## Contribution
Contributions are welcome! If you'd like to contribute to this project, please follow these steps:
1. **Fork the Repository:**
Click the "Fork" button at the top right corner of the repository page.
2. **Clone Your Fork:**
```bash
git clone https://github.com/your-username/firebase-authentication-mern.git
cd Database Integration/1-firebase_authentication
```
3. **Create a Branch:**
```bash
git checkout -b feature-branch
```
4. **Make Your Changes:**
Implement your feature or fix the bug you want to address.
5. **Commit Your Changes:**
```bash
git add .
git commit -m "Description of the changes"
```
6. **Push to Your Fork:**
```bash
git push origin feature-branch
```
7. **Create a Pull Request:**
Go to the original repository on GitHub, and you should see a prompt to create a pull request from your new branch. Provide a clear description of your changes and submit the pull request for review.
## Get in Touch
If you have any questions or need further assistance, feel free to open an issue on GitHub or contact us directly. Your contributions and feedback are highly appreciated!
---
Thank you for your interest in the Firebase Authentication project. Together, we can build a more robust and feature-rich application. Happy coding!

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"firebase": "^10.12.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3"
}
}

View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -0,0 +1,38 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@@ -0,0 +1,50 @@
import React from 'react';
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom';
import { UserProvider } from './UserContext.js';
import SignUp from './SignUp';
import SignIn from './SignIn';
import ResetPassword from './ResetPassword';
import { useUser } from './UserContext.js';
const App = () => {
return (
<UserProvider>
<Router>
<div className="flex flex-col items-center min-h-screen bg-gray-100">
<h1 className="text-3xl font-bold my-8">Firebase Authentication in MERN Stack</h1>
<nav className="mb-4">
<Link to="/signup" className="mr-4 text-blue-500">Sign Up</Link>
<Link to="/signin" className="mr-4 text-blue-500">Sign In</Link>
<Link to="/resetpassword" className="text-blue-500">Reset Password</Link>
</nav>
<Routes>
<Route path="/signup" element={<SignUp />} />
<Route path="/signin" element={<SignIn />} />
<Route path="/resetpassword" element={<ResetPassword />} />
<Route path="/" element={<Home />} />
</Routes>
</div>
</Router>
</UserProvider>
);
};
const Home = () => {
const { user } = useUser();
return (
<div className="text-center">
<h2 className="text-xl">Welcome to Firebase Authentication Example</h2>
{user ? (
<div>
<p>User Email: {user.email}</p>
<p>User UID: {user.uid}</p>
</div>
) : (
<p>Please sign in to see your details.</p>
)}
</div>
);
};
export default App;

View File

@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@@ -0,0 +1,28 @@
// create simple Home component after login and before login
import React from 'react';
import { Link } from 'react-router-dom';
import { signOut } from 'firebase/auth';
import { auth } from './firebase';
const Home = () => {
const handleSignOut = async () => {
try {
await signOut(auth);
alert('User signed out successfully!');
} catch (error) {
console.error('Error signing out:', error);
}
};
return (
<div className="flex flex-col space-y-4 max-w-md mx-auto p-8 bg-white shadow-md rounded-lg">
<h2 className="text-2xl font-bold text-center">Home</h2>
<p className="text-center">Welcome, {auth.currentUser.email}</p>
<button onClick={handleSignOut} className="p-2 bg-red-500 text-white rounded">Sign Out</button>
<Link to="/reset-password" className="text-blue-500">Reset Password</Link>
</div>
);
}
export default Home;

View File

@@ -0,0 +1,34 @@
import React, { useState } from 'react';
import { auth } from './firebase';
import { sendPasswordResetEmail } from 'firebase/auth';
const ResetPassword = () => {
const [email, setEmail] = useState('');
const handleResetPassword = async (e) => {
e.preventDefault();
try {
await sendPasswordResetEmail(auth, email);
alert('Password reset email sent!');
} catch (error) {
console.error('Error resetting password:', error);
}
};
return (
<form onSubmit={handleResetPassword} className="flex flex-col space-y-4 max-w-md mx-auto p-8 bg-white shadow-md rounded-lg">
<h2 className="text-2xl font-bold text-center">Reset Password</h2>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
className="p-2 border border-gray-300 rounded"
required
/>
<button type="submit" className="p-2 bg-blue-500 text-white rounded">Reset Password</button>
</form>
);
};
export default ResetPassword;

View File

@@ -0,0 +1,62 @@
import React, { useState } from 'react';
import { auth } from './firebase';
import { signInWithEmailAndPassword, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import { useUser } from './UserContext';
import { useNavigate } from 'react-router-dom';
const SignIn = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { setUser } = useUser();
const navigate = useNavigate();
const handleSignIn = async (e) => {
e.preventDefault();
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
setUser(userCredential.user);
navigate('/');
} catch (error) {
console.error('Error signing in:', error);
}
};
const handleGoogleSignIn = async () => {
const provider = new GoogleAuthProvider();
try {
const result = await signInWithPopup(auth, provider);
setUser(result.user);
navigate('/');
} catch (error) {
console.error('Error signing in with Google:', error);
}
};
return (
<div className="flex flex-col space-y-4 max-w-md mx-auto p-8 bg-white shadow-md rounded-lg">
<form onSubmit={handleSignIn}>
<h2 className="text-2xl font-bold text-center">Sign In</h2>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
className="p-2 border border-gray-300 rounded"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
className="p-2 border border-gray-300 rounded"
required
/>
<button type="submit" className="p-2 bg-blue-500 text-white rounded">Sign In</button>
</form>
<button onClick={handleGoogleSignIn} className="p-2 bg-red-500 text-white rounded">Sign In with Google</button>
</div>
);
};
export default SignIn;

View File

@@ -0,0 +1,43 @@
import React, { useState } from 'react';
import { auth } from './firebase';
import { createUserWithEmailAndPassword } from 'firebase/auth';
const SignUp = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSignUp = async (e) => {
e.preventDefault();
try {
await createUserWithEmailAndPassword(auth, email, password);
alert('User signed up successfully!');
} catch (error) {
console.error('Error signing up:', error);
}
};
return (
<form onSubmit={handleSignUp} className="flex flex-col space-y-4 max-w-md mx-auto p-8 bg-white shadow-md rounded-lg">
<h2 className="text-2xl font-bold text-center">Sign Up</h2>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
className="p-2 border border-gray-300 rounded"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
className="p-2 border border-gray-300 rounded"
required
/>
<button type="submit" className="p-2 bg-blue-500 text-white rounded">Sign Up</button>
</form>
);
};
export default SignUp;

View File

@@ -0,0 +1,15 @@
import React, { createContext, useState, useContext } from 'react';
const UserContext = createContext();
export const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
export const useUser = () => useContext(UserContext);

View File

@@ -0,0 +1,14 @@
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,10 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}