From 1e416ad52347212ea46cac21c6b18bf12e27cb04 Mon Sep 17 00:00:00 2001 From: JaberHPranto Date: Fri, 9 Jul 2021 02:21:01 +0600 Subject: [PATCH] user can now reset password from a link given in email --- .../Ecommerce/Screen/ForgetPasswordScreen.js | 52 +++++++++++++ .../Ecommerce/Screen/LoginScreen.js | 5 +- .../Ecommerce/Screen/PasswordResetScreen.js | 76 +++++++++++++++++++ client/src/pages/EcommercePage.js | 4 + server/controller/productController.js | 2 +- server/controller/userController.js | 21 +++-- server/models/userModel.js | 2 +- 7 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 client/src/components/Ecommerce/Screen/ForgetPasswordScreen.js create mode 100644 client/src/components/Ecommerce/Screen/PasswordResetScreen.js diff --git a/client/src/components/Ecommerce/Screen/ForgetPasswordScreen.js b/client/src/components/Ecommerce/Screen/ForgetPasswordScreen.js new file mode 100644 index 0000000..6a138a6 --- /dev/null +++ b/client/src/components/Ecommerce/Screen/ForgetPasswordScreen.js @@ -0,0 +1,52 @@ +import axios from 'axios' +import React, { useState } from 'react' +import { Button, Form } from 'react-bootstrap' +import FormContainer from '../FormContainer' +import Message from '../Message' +import { toastInfoMessage } from '../ToastMessage' + +function ForgetPasswordScreen() { + const [email, setEmail] = useState('') + const [error, setError] = useState('') + + const handleSubmit = async (e) => { + e.preventDefault() + + const config = { + headers: { + 'Content-Type': 'application/json' + } + } + + try { + await axios.post("/api/users/forget-password", { email }, config) + toastInfoMessage("Instructions to reset your password has been sent to your email") + + } catch (error) { + setError(error.response && error.response.data.message ? error.response.data.message : error.message) + setEmail('') + setTimeout(() => { + setError("") + }, 3000); + + } + } + return ( + +

Forget Password ?

+

Enter the email address you used when you joined and we’ll send you instructions to reset your password.

+ {error && {error}} + +
+ + Email Address + setEmail(e.target.value)} /> + + + +
+
+ ) +} + +export default ForgetPasswordScreen diff --git a/client/src/components/Ecommerce/Screen/LoginScreen.js b/client/src/components/Ecommerce/Screen/LoginScreen.js index bdf1dc8..4442e90 100644 --- a/client/src/components/Ecommerce/Screen/LoginScreen.js +++ b/client/src/components/Ecommerce/Screen/LoginScreen.js @@ -43,12 +43,13 @@ function LoginScreen({location,history}) { setEmail(e.target.value)} /> - + Password setPassword(e.target.value)} /> + Forget Password ? - + diff --git a/client/src/components/Ecommerce/Screen/PasswordResetScreen.js b/client/src/components/Ecommerce/Screen/PasswordResetScreen.js new file mode 100644 index 0000000..5143ecf --- /dev/null +++ b/client/src/components/Ecommerce/Screen/PasswordResetScreen.js @@ -0,0 +1,76 @@ +import axios from 'axios' +import React, { useState } from 'react' +import { Button, Form } from 'react-bootstrap' +import FormContainer from '../FormContainer' +import Message from '../Message' +import { toastSuccessMessage } from '../ToastMessage' + +function ForgetPasswordScreen({match,history}) { + const [password, setPassword] = useState('') + const [confirmPassword, setConfirmPassword] = useState('') + const [error, setError] = useState('') + + const clear = (errorText) => { + setPassword("") + setConfirmPassword("") + setTimeout(() => { + setError("") + }, 3000); + return setError(errorText) + } + + const handleSubmit = async (e) => { + e.preventDefault() + + if (password.length < 6) { + return clear("Password must be at least 6 characters") + } + if (password !== confirmPassword) { + return clear("Password doesn't match") + } + + + const config = { + headers: { + 'Content-Type': 'application/json' + } + } + + + try { + await axios.put(`/api/users/reset-password/${match.params.resetToken}`, { password }, config) + toastSuccessMessage("You're password has been updated") + history.push("/") + + } catch (error) { + setError(error.response && error.response.data.message ? error.response.data.message : error.message) + setPassword("") + setConfirmPassword("") + setTimeout(() => { + setError("") + }, 3000); + + } + } + return ( + +

Reset Your Password

+ {error && {error}} +
+ + Password + setPassword(e.target.value)} /> + + + + Retype Password + setConfirmPassword(e.target.value)} /> + + + +
+
+ ) +} + +export default ForgetPasswordScreen diff --git a/client/src/pages/EcommercePage.js b/client/src/pages/EcommercePage.js index e56df99..ac8d218 100644 --- a/client/src/pages/EcommercePage.js +++ b/client/src/pages/EcommercePage.js @@ -4,8 +4,10 @@ import { BrowserRouter as Router, Route } from 'react-router-dom'; import Footer from "../components/Ecommerce/Footer"; import Header from "../components/Ecommerce/Header"; import CartScreen from '../components/Ecommerce/Screen/CartScreen'; +import ForgetPasswordScreen from '../components/Ecommerce/Screen/ForgetPasswordScreen'; import HomeScreen from '../components/Ecommerce/Screen/HomeScreen'; import LoginScreen from '../components/Ecommerce/Screen/LoginScreen'; +import PasswordResetScreen from '../components/Ecommerce/Screen/PasswordResetScreen'; import ProductScreen from '../components/Ecommerce/Screen/ProductScreen'; import ProfileScreen from '../components/Ecommerce/Screen/ProfileScreen'; import RegisterScreen from '../components/Ecommerce/Screen/RegisterScreen'; @@ -23,6 +25,8 @@ function EcommercePage() { + + diff --git a/server/controller/productController.js b/server/controller/productController.js index d8829fc..8ab10cd 100644 --- a/server/controller/productController.js +++ b/server/controller/productController.js @@ -6,7 +6,7 @@ import User from '../models/userModel.js' export const getProducts = asyncHandler(async (req, res) => { // for pagination - const pageSize = 2 + const pageSize = 10 const page = req.query.pageNumber || 1 const keyword = req.query.keyword ? { diff --git a/server/controller/userController.js b/server/controller/userController.js index 37bdc7e..9aa6a23 100644 --- a/server/controller/userController.js +++ b/server/controller/userController.js @@ -111,17 +111,16 @@ export const forgetPassword = async (req, res) => { try { const user = await User.findOne({ email }) - if (!user) - return res.status(404).json({error:"User doesn't exist"}) + if (!user) { + return res.status(404).json({ message: "User doesn't exist" }) + // res.status(404) + // throw new Error("User doesn't exist") + } const resetToken = user.getPasswordResetToken() - - - // user.resetPasswordToken = user.resetPasswordToken - // user.resetPasswordExpire = user.resetPasswordExpire await user.save() - const resetUrl = `http://localhost:3000/forget-password/${resetToken}` + const resetUrl = `http://localhost:3000/reset-password/${resetToken}` const message = `

Plant Land

You have requested a password reset

@@ -142,7 +141,7 @@ export const forgetPassword = async (req, res) => { await user.save() console.log(error); - res.status(500).json("Failed to send email") + res.status(500).json({message: "Failed to send email"}) } res.status(200).json({ message: 'Success',data:"Email Sent"}) @@ -150,7 +149,7 @@ export const forgetPassword = async (req, res) => { } catch (error) { console.log(error); - res.status(404).json({ error: "Forget password failed" }) + res.status(404).json({ message: "Forget password failed" }) } } @@ -164,7 +163,7 @@ export const resetPassword = async (req, res) => { }) if (!user) { - return res.status(400).json({ error: "Invalid Reset Token" }) + return res.status(400).json({ message: "Invalid Reset Token" }) } user.password = req.body.password @@ -177,6 +176,6 @@ export const resetPassword = async (req, res) => { } catch (error) { console.log(error); - res.status(500).json({ error: "Failed to reset password" }) + res.status(500).json({ message: "Failed to reset password" }) } } \ No newline at end of file diff --git a/server/models/userModel.js b/server/models/userModel.js index a5bb7eb..029783e 100644 --- a/server/models/userModel.js +++ b/server/models/userModel.js @@ -43,7 +43,7 @@ userSchema.methods.getPasswordResetToken = function () { // setting a field in user model this.resetPasswordToken = crypto.createHash('sha256').update(resetToken).digest('hex') - this.resetPasswordExpire = Date.now() + 10 * (60 * 1000) + this.resetPasswordExpire = Date.now() + 100 * (60 * 1000) return resetToken