From 757e0648b15f9fc5407ba53ef70039f20b50f813 Mon Sep 17 00:00:00 2001 From: "Aditya_Parmar@dev" <105008414+Adityajparmar37@users.noreply.github.com> Date: Sat, 8 Jun 2024 18:04:59 +0530 Subject: [PATCH 1/3] fix/feat-forgot-password-added --- server/controllers/Auth.js | 314 ++++++++++++++++++++++++--- server/package.json | 1 + server/routes/student.js | 4 + server/utils/PasswordTokenAndUser.js | 51 +++++ src/App.js | 4 + src/pages/ForgotPassword.jsx | 101 +++++++++ src/pages/Login.jsx | 168 ++++++++------ src/pages/ResetPassword.jsx | 302 ++++++++++++++++++++++++++ src/pages/Signup.jsx | 9 +- 9 files changed, 853 insertions(+), 101 deletions(-) create mode 100644 server/utils/PasswordTokenAndUser.js create mode 100644 src/pages/ForgotPassword.jsx create mode 100644 src/pages/ResetPassword.jsx diff --git a/server/controllers/Auth.js b/server/controllers/Auth.js index 31e876c..123ee3f 100644 --- a/server/controllers/Auth.js +++ b/server/controllers/Auth.js @@ -3,14 +3,29 @@ const User = require("../models/studentLoginInfo"); const jwt = require("jsonwebtoken"); const Canteen = require("../models/canteenLoginInfo"); const Session = require("../models/session"); +const { + forgotPasswordToken, + verifyToken, + findUserByEmail, + findUserById, +} = require("../utils/PasswordTokenAndUser"); +const nodemailer = require("nodemailer"); require("dotenv").config(); exports.studentSignup = async (req, res) => { try { console.log(req.body); - const { name, email, collegeName, accountType, password } = await req.body; - const existingUser = await User.findOne({ email }); + const { + name, + email, + collegeName, + accountType, + password, + } = await req.body; + const existingUser = await User.findOne({ + email, + }); if (existingUser) { return res.status(400).json({ @@ -22,7 +37,10 @@ exports.studentSignup = async (req, res) => { let hashedPassword; try { - hashedPassword = await bcrypt.hash(password, 10); + hashedPassword = await bcrypt.hash( + password, + 10 + ); } catch (error) { console.log(error); return res.status(500).json({ @@ -80,13 +98,25 @@ exports.studentLogin = async (req, res) => { accountType: user.accountType, }; - if (await bcrypt.compare(password, user.password)) { - let token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "2h", - }); + if ( + await bcrypt.compare( + password, + user.password + ) + ) { + let token = jwt.sign( + payload, + process.env.JWT_SECRET, + { + expiresIn: "2h", + } + ); // creating a session - const session = new Session({ userId: user._id, token }); + const session = new Session({ + userId: user._id, + token, + }); await session.save(); user = user.toObject(); @@ -106,13 +136,18 @@ exports.studentLogin = async (req, res) => { // message: "User logged in succesfully", // }); - // Setting cookie + // Setting cookie res.cookie("token", token, { httpOnly: true, secure: true, maxAge: 3600000, }); - res.json({ success: true, message: "Logged in successfully", token, user }); + res.json({ + success: true, + message: "Logged in successfully", + token, + user, + }); } else { return res.status(403).json({ success: false, @@ -154,13 +189,18 @@ exports.studentLogout = async (req, res) => { const token = req.cookies?.token || - req?.header("Authorization")?.replace("Bearer ", ""); + req + ?.header("Authorization") + ?.replace("Bearer ", ""); if (token) { await Session.findOneAndDelete({ token }); res.clearCookie("token"); } - res.status(200).json({ success: true, message: "Logged out successfully" }); + res.status(200).json({ + success: true, + message: "Logged out successfully", + }); } catch (error) { console.log(error); return res.status(500).json({ @@ -171,11 +211,17 @@ exports.studentLogout = async (req, res) => { }; // Controller for changing the student password -exports.changeStudentPassword = async (req, res) => { +exports.changeStudentPassword = async ( + req, + res +) => { const { oldPassword, newPassword } = req.body; const user = await User.findById(req.user._id); - const isPasswordCorrect = await bcrypt.compare(oldPassword, user.password); + const isPasswordCorrect = await bcrypt.compare( + oldPassword, + user.password + ); if (!isPasswordCorrect) { return res.status(400).json({ @@ -184,7 +230,10 @@ exports.changeStudentPassword = async (req, res) => { }); } - const newHashedPassword = await bcrypt.hash(newPassword, 10); + const newHashedPassword = await bcrypt.hash( + newPassword, + 10 + ); user.password = newHashedPassword; user.save(); @@ -199,8 +248,16 @@ exports.changeStudentPassword = async (req, res) => { exports.canteenSignup = async (req, res) => { try { - const { name, email, collegeName, accountType, password } = req.body; - const existingCanteen = await Canteen.findOne({ email }); + const { + name, + email, + collegeName, + accountType, + password, + } = req.body; + const existingCanteen = await Canteen.findOne( + { email } + ); if (existingCanteen) { return res.status(400).json({ @@ -212,7 +269,10 @@ exports.canteenSignup = async (req, res) => { let hashedPassword; try { - hashedPassword = await bcrypt.hash(password, 10); + hashedPassword = await bcrypt.hash( + password, + 10 + ); } catch (error) { return res.status(500).json({ success: false, @@ -253,7 +313,9 @@ exports.canteenLogin = async (req, res) => { }); } - let canteen = await Canteen.findOne({ email }); + let canteen = await Canteen.findOne({ + email, + }); if (!canteen) { return res.status(401).json({ success: false, @@ -267,10 +329,19 @@ exports.canteenLogin = async (req, res) => { accountType: canteen.accountType, }; - if (await bcrypt.compare(password, canteen.password)) { - let token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "2h", - }); + if ( + await bcrypt.compare( + password, + canteen.password + ) + ) { + let token = jwt.sign( + payload, + process.env.JWT_SECRET, + { + expiresIn: "2h", + } + ); canteen = canteen.toObject(); canteen.token = token; console.log(canteen); @@ -291,7 +362,10 @@ exports.canteenLogin = async (req, res) => { // }); // Create session - const session = new Session({ userId: canteen._id, token }); + const session = new Session({ + userId: canteen._id, + token, + }); await session.save(); // Set cookie @@ -300,8 +374,13 @@ exports.canteenLogin = async (req, res) => { secure: true, maxAge: 3600000, }); - res.json({ success: true, message: "Logged in successfully", token, canteen, cantId: canteen._id }); - + res.json({ + success: true, + message: "Logged in successfully", + token, + canteen, + cantId: canteen._id, + }); } else { return res.status(403).json({ success: false, @@ -343,13 +422,18 @@ exports.canteenLogout = async (req, res) => { const token = req.cookies?.token || - req?.header("Authorization")?.replace("Bearer ", ""); + req + ?.header("Authorization") + ?.replace("Bearer ", ""); if (token) { await Session.findOneAndDelete({ token }); res.clearCookie("token"); } - res.status(200).json({ success: true, message: "Logged out successfully" }); + res.status(200).json({ + success: true, + message: "Logged out successfully", + }); } catch (error) { console.log(error); return res.status(500).json({ @@ -360,11 +444,19 @@ exports.canteenLogout = async (req, res) => { }; // Canteen Reset Password -exports.changeCanteenPassword = async (req, res) => { +exports.changeCanteenPassword = async ( + req, + res +) => { const { oldPassword, newPassword } = req.body; - const user = await Canteen.findById(req.user._id); + const user = await Canteen.findById( + req.user._id + ); - const isPasswordCorrect = await bcrypt.compare(oldPassword, user.password); + const isPasswordCorrect = await bcrypt.compare( + oldPassword, + user.password + ); if (!isPasswordCorrect) { return res.status(400).json({ @@ -373,7 +465,10 @@ exports.changeCanteenPassword = async (req, res) => { }); } - const newHashedPassword = await bcrypt.hash(newPassword, 10); + const newHashedPassword = await bcrypt.hash( + newPassword, + 10 + ); user.password = newHashedPassword; user.save(); @@ -383,3 +478,158 @@ exports.changeCanteenPassword = async (req, res) => { message: "Password updated successfully.", }); }; + +// verify user for reset password +exports.forgotPassword = async (req, res) => { + try { + const { email } = req.body; + const existingUser = await findUserByEmail( + email + ); + + if (!existingUser) { + return res.status(400).json({ + success: false, + message: "User does not exist", + }); + } else { + const tokenReturn = + forgotPasswordToken(existingUser); + // const link = `http://localhost:3000/api/v1/newPassword/${existingUser._id}/${tokenReturn}`; + + const link = `https://foodies-web-app.vercel.app/api/v1/newPassword/${existingUser._id}/${tokenReturn}`; + + const transporter = + nodemailer.createTransport({ + service: "gmail", + auth: { + user: process.env.EMAIL, + pass: process.env.MAILPASS, + }, + }); + + const mailOptions = { + from: process.env.EMAIL, + to: email, + subject: "Password Reset Link", + html: ` +
+

Password Reset Request

+

Hello,

+

You have requested to reset your password. Please click the button below to reset your password:

+
+ Reset Password +
+

If you did not request this, please ignore this email.

+

Thank you,

+

FoodiesWeb

+
+

© 2024 Your Company Name. All rights reserved.

+
+ `, + }; + + await transporter.sendMail( + mailOptions, + function (error, info) { + if (error) { + console.log(error); + } + } + ); + + res.status(201).json({ + msg: "You should receive an email", + }); + } + } catch (error) { + console.error(error); + return res.status(500).json({ + success: false, + message: "User verification failed", + }); + } +}; + +//for verification of link +exports.verifyLink = async (req, res) => { + const { id, token } = req.params; + console.log(req.params); + + const oldUser = await findUserById(id); + if (!oldUser) { + return res.status(404).json({ + success: false, + message: "User not found!", + }); + } + + try { + console.log("Found user: ", oldUser); + const verify = verifyToken(oldUser, token); + console.log("VerifyToken result: ", verify); + + if (verify.id === id) { + res.status(201).json({ + email: verify.email, + status: "Verified", + }); + } else { + res.status(201).json({ + status: "Cannot Verify", + }); + } + } catch (error) { + res.status(201).json({ + status: "Not Verified", + }); + } +}; + +exports.resetPassword = async (req, res) => { + const { id, token } = req.params; + const { password } = req.body; + + console.log(password, " ", id, " ", token); + + try { + const oldUser = await findUserById(id); + + if (!oldUser) { + return res + .status(404) + .json("User not found"); + } + + const verify = verifyToken(oldUser, token); + if (verify.id !== id) { + return res + .status(201) + .json({ change: false }); + } + + const salt = await bcrypt.genSalt(10); + const newPassword = await bcrypt.hash( + password, + salt + ); + + if (oldUser instanceof User) { + await User.findByIdAndUpdate(id, { + password: newPassword, + }); + } else if (oldUser instanceof Canteen) { + await Canteen.findByIdAndUpdate(id, { + password: newPassword, + }); + } + + res.status(201).json({ change: true }); + } catch (error) { + console.log( + "Error while changing password: ", + error + ); + res.status(500).json("Some error occurred!"); + } +}; diff --git a/server/package.json b/server/package.json index c4dd360..d826ee9 100644 --- a/server/package.json +++ b/server/package.json @@ -23,6 +23,7 @@ "jsonwebtoken": "^9.0.2", "mongoose": "^7.6.2", "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.13", "nodemon": "^3.0.1", "path": "^0.12.7" } diff --git a/server/routes/student.js b/server/routes/student.js index 3168ac9..e6f2054 100644 --- a/server/routes/student.js +++ b/server/routes/student.js @@ -7,6 +7,9 @@ router.post("/studentSignup", authController.studentSignup); router.post("/studentLogin", authController.studentLogin); router.post("/canteenSignup", authController.canteenSignup); router.post("/canteenLogin", authController.canteenLogin); +router.post("/VerifyUser",authController.forgotPassword); +router.get("/resetPassword/:id/:token",authController.verifyLink); +router.post("/newPassword/:id/:token",authController.resetPassword); router.get("/studentLogout", studentAuth, authController.studentLogout); router.get("/canteenLogout", auth, authController.canteenLogout); router.post( @@ -20,4 +23,5 @@ router.post( isCanteen, authController.changeCanteenPassword ); + module.exports = router; diff --git a/server/utils/PasswordTokenAndUser.js b/server/utils/PasswordTokenAndUser.js new file mode 100644 index 0000000..a11723b --- /dev/null +++ b/server/utils/PasswordTokenAndUser.js @@ -0,0 +1,51 @@ +const jwt = require("jsonwebtoken"); +const User = require("../models/studentLoginInfo"); +const Canteen = require("../models/canteenLoginInfo"); + +const forgotPasswordToken = (oldUser) => { + const secret = + process.env.JWT_SECRET + oldUser.password; + const token = jwt.sign( + { + email: oldUser.email, + id: oldUser._id, + }, + secret, + { + expiresIn: "2m", + } + ); + return token; +}; + +const verifyToken = (oldUser, token) => { + const secret = + process.env.JWT_SECRET + oldUser.password; + const verify = jwt.verify(token, secret); + + return verify; +}; + +const findUserByEmail = async (email) => { + let user = await User.findOne({ email }); + if (!user) { + user = await Canteen.findOne({ email }); + } + return user; +}; + +const findUserById = async (id) => { + let user = await User.findById(id); + if (!user) { + user = await Canteen.findById(id); + } + return user; +}; + + +module.exports = { + forgotPasswordToken, + verifyToken, + findUserById, + findUserByEmail, +}; diff --git a/src/App.js b/src/App.js index fa87545..57c717a 100644 --- a/src/App.js +++ b/src/App.js @@ -11,6 +11,8 @@ import SectionPage from './pages/SectionPage'; import News from './pages/News'; import NotFound from './pages/NotFound'; import Loader from './components/Loader/Loader'; +import ForgotPassword from './pages/ForgotPassword'; +import ResetPassword from './pages/ResetPassword'; const Layout = ({ children }) => { return ( @@ -28,6 +30,8 @@ function App() { } /> } /> } /> + } /> + } /> } /> } /> } /> diff --git a/src/pages/ForgotPassword.jsx b/src/pages/ForgotPassword.jsx new file mode 100644 index 0000000..9541088 --- /dev/null +++ b/src/pages/ForgotPassword.jsx @@ -0,0 +1,101 @@ +import React, { useState } from "react"; +import axios from "axios"; +import { toast } from "react-hot-toast"; +import logo from "../assets/logo2.png"; +import Loader from "../components/Loader/Loader"; + + +function ForgotPassword() { + const [formData, setFormData] = useState({ + email: "", + }); + const [loading, setLoading] = useState(false); + + function changeHandler(event) { + setFormData((prevData) => ({ + ...prevData, + [event.target.name]: event.target.value, + })); + } + + function submitHandler(event) { + event.preventDefault(); + + setLoading(true); + + const apiUrl = `${process.env.REACT_APP_BASE_URL}/VerifyUser`; + // const apiUrl = `http://localhost:4000/api/v1/VerifyUser `; + + axios + .post(apiUrl, formData) + .then((response) => { + setLoading(false); + toast.success("Link sent to your email"); + }) + .catch((error) => { + console.log(error); + setLoading(false); + toast.error("Failed to send Link"); + }); + } + + return ( + <> + {loading ? ( + + ) : ( +
+
+
+ logo +

+ Connecting You to Your College + Canteens +

+
+
+
+
+
+
+ +
+
+

+ Recover Password +

+

+ Please enter your email +

+ +
+ +
+ +
+
+
+ )} + + ); +} + +export default ForgotPassword; diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx index b359ecd..36ba4ea 100644 --- a/src/pages/Login.jsx +++ b/src/pages/Login.jsx @@ -1,18 +1,27 @@ -import React, { useState, useEffect } from "react"; -import { AiOutlineEye, AiOutlineEyeInvisible } from "react-icons/ai"; -import { Link, useNavigate } from "react-router-dom"; +import React, { + useState, + useEffect, +} from "react"; +import { + AiOutlineEye, + AiOutlineEyeInvisible, +} from "react-icons/ai"; +import { + Link, + useNavigate, +} from "react-router-dom"; import { toast } from "react-hot-toast"; import axios from "axios"; -import logo from "../assets/logo2.png" - +import logo from "../assets/logo2.png"; function Login() { const [formData, setFormData] = useState({ email: "", - accountType : "", + accountType: "", password: "", }); - const [showPassword, setShowPassword] = useState(false); + const [showPassword, setShowPassword] = + useState(false); const navigate = useNavigate(); function changeHandler(event) { @@ -22,67 +31,70 @@ function Login() { })); } - function submitHandler(event) { - - event.preventDefault(); - - - if(formData.accountType === "User"){ - + if (formData.accountType === "User") { const apiUrl = `${process.env.REACT_APP_BASE_URL}/studentLogin`; // const apiUrl = `http://localhost:4000/api/v1/studentLogin`; - axios.post(apiUrl , formData) - .then((response)=>{ - toast.success("User Logged in "); - navigate("/home"); - }) - .catch((error)=>{ - toast.error("Failed to login") - }); - } - - else{ - + axios + .post(apiUrl, formData) + .then((response) => { + toast.success("User Logged in "); + navigate("/home"); + }) + .catch((error) => { + toast.error("Failed to login"); + }); + } else { const apiUrl = `${process.env.REACT_APP_BASE_URL}/canteenLogin`; - axios.post(apiUrl , formData) - .then((response)=>{ - toast.success("User Logged in "); - navigate(`/section/${response.data.cantId}`); - }) - .catch((error)=>{ - toast.error("Failed to login") - }); + axios + .post(apiUrl, formData) + .then((response) => { + toast.success("User Logged in "); + navigate( + `/section/${response.data.cantId}` + ); + }) + .catch((error) => { + toast.error("Failed to login"); + }); } } return (
-
-
- logo -

Connecting You to Your College Canteens

+ logo +

+ Connecting You to Your College + Canteens +

-
- -
- -

Hello Again!

-

Welcome Back

+ +

+ Hello Again! +

+

+ Welcome Back +

- +
- +
setShowPassword((prev) => !prev)} - > - {showPassword ? : } + onClick={() => + setShowPassword((prev) => !prev) + }> + {showPassword ? ( + + ) : ( + + )}
- - Don't have an account? Sign Up + + Don't have an account? Sign Up + - -
-
); } export default Login; - diff --git a/src/pages/ResetPassword.jsx b/src/pages/ResetPassword.jsx new file mode 100644 index 0000000..d2c3c2c --- /dev/null +++ b/src/pages/ResetPassword.jsx @@ -0,0 +1,302 @@ +import React, { useState } from "react"; +import axios from "axios"; +import { toast } from "react-hot-toast"; +import logo from "../assets/logo2.png"; +import Icon from "react-icons-kit"; +import { arrows_circle_check } from "react-icons-kit/linea/arrows_circle_check"; +import { arrows_exclamation } from "react-icons-kit/linea/arrows_exclamation"; +import Loader from "../components/Loader/Loader"; +import { useNavigate , useParams } from "react-router-dom"; +import { + AiOutlineEye, + AiOutlineEyeInvisible, +} from "react-icons/ai"; + +function ResetPassword() { + const { id, token } = useParams(); + const [formData, setFormData] = useState({ + password: "", + }); + const [loading, setLoading] = useState(false); + const [showPassword, setShowPassword] = + useState(false); + const [lowerValidated, setLowerValidated] = + useState(false); + const [upperValidated, setUpperValidated] = + useState(false); + const [numberValidated, setNumberValidated] = + useState(false); + const [specialValidated, setSpecialValidated] = + useState(false); + const [lengthValidated, setLengthValidated] = + useState(false); + + const navigate = useNavigate(); + + function PasswordChecker(event) { + const lower = new RegExp("(?=.*[a-z])"); + const upper = new RegExp("(?=.*[A-Z])"); + const number = new RegExp("(?=.*[0-9])"); + const special = new RegExp( + "(?=.*[!@#$%^&*])" + ); + const length = new RegExp("(?=.{8,})"); + const value = event.target.value; + setLowerValidated(lower.test(value)); + setUpperValidated(upper.test(value)); + setNumberValidated(number.test(value)); + setSpecialValidated(special.test(value)); + setLengthValidated(length.test(value)); + + setFormData((prevData) => ({ + ...prevData, + [event.target.name]: event.target.value, + })); + } + + async function submitHandler(event) { + event.preventDefault(); + + if ( + lowerValidated && + upperValidated && + numberValidated && + specialValidated && + lengthValidated + ) { + setLoading(true); + const apiUrl = `${process.env.REACT_APP_BASE_URL}/newPassword/${id}/${token}`; + // const apiUrl = `http://localhost:4000/api/v1/newPassword/${id}/${token} `; + + try { + const response = await axios.post( + apiUrl, + formData + ); + console.log(response); + setLoading(false); + toast.success( + "Password reset successful" + ); + navigate("/login"); + } catch (error) { + console.log(error); + setLoading(false); + toast.error("Failed to reset password"); + } + } else { + toast.error( + "Password must pass all the criteria" + ); + } + } + + return ( + <> + {loading ? ( + + ) : ( +
+
+
+ logo +

+ Connecting You to Your College + Canteens +

+
+
+
+
+
+
+ +
+
+

+ Reset Password +

+

+ Enter new password +

+ +
+ + + setShowPassword( + (prev) => !prev + ) + }> + {showPassword ? ( + + ) : ( + + )} + +
+ + + +
+
+ {lowerValidated ? ( + + + + ) : ( + + + + )} + At least one lowercase letter +
+
+ {upperValidated ? ( + + + + ) : ( + + + + )} + At least one uppercase letter +
+
+ {numberValidated ? ( + + + + ) : ( + + + + )} + At least one number +
+
+ {specialValidated ? ( + + + + ) : ( + + + + )} + At least one special character +
+
+ {lengthValidated ? ( + + + + ) : ( + + + + )} + At least 8 characters +
+
+
+
+ +
+ )} + + ); +} + +export default ResetPassword; diff --git a/src/pages/Signup.jsx b/src/pages/Signup.jsx index e6a6005..8db3c67 100644 --- a/src/pages/Signup.jsx +++ b/src/pages/Signup.jsx @@ -84,9 +84,11 @@ function Signup() { if (lowerValidated && upperValidated && numberValidated && specialValidated && lengthValidated) { if (formData.accountType === "User") { - // const apiUrl = `${process.env.REACT_APP_BASE_URL}/studentSignup`; - const apiUrl = `http://localhost:4000/api/v1/studentSignup`; - + //Loader will show till the api fetching is done as show as promise is resolved the loader will be not shown + setLoading(true); + const apiUrl = `${process.env.REACT_APP_BASE_URL}/studentSignup`; + // const apiUrl = `http://localhost:4000/api/v1/studentSignup`; + axios .post(apiUrl, formData) .then((response) => { @@ -98,6 +100,7 @@ function Signup() { }); } else { const apiUrl = `${process.env.REACT_APP_BASE_URL}/canteenSignup`; + // const apiUrl = `http://localhost:4000/api/v1/canteenSignup`; axios From 30903cf82ffba5b258c693b4b4edc44b540819ee Mon Sep 17 00:00:00 2001 From: "Aditya_Parmar@dev" <105008414+Adityajparmar37@users.noreply.github.com> Date: Sat, 8 Jun 2024 23:10:59 +0530 Subject: [PATCH 2/3] README upaded with .env variable --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 007afdc..17b3dc4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,31 @@
-image +image

Connecting You to Your College Canteens

+ + + + + + + + + + + + + + + + + + + + + +
🌟 Stars🍴 Forks🐛 Issues🔔 Open PRs🔕 Close PRs last commit
StarsForksIssuesOpen Pull RequestsClose Pull RequestsClose Pull Requests
+
+ # Tech Stacks ![](https://img.shields.io/badge/React-61DAFB?style=for-the-badge&logo=react&color=blue) @@ -62,30 +86,37 @@ Welcome to Foodies, your go-to college dining companion! Designed for seamless c ## To get started with contributing to the FoodiesWeb project, follow these steps: -1. **Navigate to the Project Directory:** +1. **Fork and clone the repository** +2. **Navigate to the Project Directory:** ```bash - cd path/to/FoodiesWeb + cd FoodiesWeb ``` -2. **Split Terminal for Backend Setup** +3. **Split Terminal for Backend Setup** -3. **Navigate to the Server Directory:** +4. **Navigate to the Server Directory:** ```bash - cd path/to/FoodiesWeb/server + cd server ``` -4. **Install Dependencies (in both terminals):** +5. **Install Dependencies (in both terminals):** ```bash npm install ``` -5. **Start the Backend Server (in the terminal within the /server directory):**
+ + ### **ENV Variables** + Setup MongoDB local host instance and port in env file in your local device. Default port is 4000 + Sample uri is given below. + ``` + PORT=3000 + DATABASE_URL="http://localhost:21713/foods" + EMAIL="your or website email address to send link" + MAILPASS="mail pass key ( app password)" + ``` + +6. **Start the Backend Server (in the terminal within the /server directory):**
In the terminal where you navigated to the /server directory, run the following command to start the backend server: ```bash nodemon server.js ``` -6. **Navigate to the src (with Backend Running):**
- In the other terminal, run the following command to navigate to the src folder (frontend): - ```bash - cd src - ``` 7. **Start the React App (with Backend Running):**
After navigating run the following command to start the React app with the backend server running successfully: ```bash @@ -158,5 +189,13 @@ To learn React, check out the [React documentation](https://reactjs.org/). -

Thank you for being a part of this project! +

Our Contributors ❤️

+
+

Thank you for being a part of this project!

+ +![Contributors](https://contrib.rocks/image?repo=VanshKing30/FoodiesWeb)
+ + +
+

(Back to top)

From 2d53804eb0462d6a1a0271b84edaa012afb43d2f Mon Sep 17 00:00:00 2001 From: "Aditya_Parmar@dev" <105008414+Adityajparmar37@users.noreply.github.com> Date: Sun, 9 Jun 2024 10:42:21 +0530 Subject: [PATCH 3/3] README file upadted and link to generate app password link added --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 17b3dc4..73d5ed3 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,16 @@ Welcome to Foodies, your go-to college dining companion! Designed for seamless c ``` PORT=3000 DATABASE_URL="http://localhost:21713/foods" - EMAIL="your or website email address to send link" - MAILPASS="mail pass key ( app password)" + EMAIL="The email from which forgot the password email will be sent" + MAILPASS="password for the email ( app password )" ``` + ### **STEP TO GENERATE APP PASSWORD** + 1) Enable 2-step verification if not + **In https://myaccount.google.com/security, do you see 2-step verification set to ON** + + 2) Generate APP PASSWORD by clicking on below link + **https://myaccount.google.com/apppasswords?rapt=AEjHL4PAhcbtFEpLwfNtVix3bfiGe71GdrW_Naiuvp_NVnMZyTd0UR07M2mVnEyWzkw9kB99YVhhfEVtjxTi3QWSZ39biK-zGwnghm0u778vwmlh6TFbmh4** + 6. **Start the Backend Server (in the terminal within the /server directory):**
In the terminal where you navigated to the /server directory, run the following command to start the backend server: