Skip to content

Commit

Permalink
user can now reset password from a link given in email
Browse files Browse the repository at this point in the history
  • Loading branch information
JaberHPranto committed Jul 8, 2021
1 parent 217b8c7 commit 1e416ad
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 15 deletions.
52 changes: 52 additions & 0 deletions client/src/components/Ecommerce/Screen/ForgetPasswordScreen.js
Original file line number Diff line number Diff line change
@@ -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 (
<FormContainer>
<h1 className='py-2'>Forget Password ?</h1>
<p className='mb-5'>Enter the email address you used when you joined and we’ll send you instructions to reset your password.</p>
{error && <Message variant='danger'>{error}</Message>}

<Form onSubmit={handleSubmit}>
<Form.Group controlId="email" className='mb-3 mt-5'>
<Form.Label>Email Address</Form.Label>
<Form.Control type="email" placeholder="Enter email" value={email} onChange={(e)=> setEmail(e.target.value)} />
</Form.Group>

<Button type='submit' variant='primary' className="auth-btn" >Submit</Button>
</Form>
</FormContainer>
)
}

export default ForgetPasswordScreen
5 changes: 3 additions & 2 deletions client/src/components/Ecommerce/Screen/LoginScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ function LoginScreen({location,history}) {
<Form.Control type="email" placeholder="Enter email" value={email} onChange={(e)=> setEmail(e.target.value)} />
</Form.Group>

<Form.Group controlId="password" className='mb-4'>
<Form.Group controlId="password" className='mb-1'>
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Enter password" value={password} onChange={(e)=> setPassword(e.target.value)} />
</Form.Group>
<Link to ="/forget-password" >Forget Password ?</Link>

<Button type='submit' variant='primary' className="auth-btn mb-2" >Sign In</Button>
<Button type='submit' variant='primary' className="auth-btn mb-2 mt-4" >Sign In</Button>
</Form>

<Row>
Expand Down
76 changes: 76 additions & 0 deletions client/src/components/Ecommerce/Screen/PasswordResetScreen.js
Original file line number Diff line number Diff line change
@@ -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 (
<FormContainer>
<h2 className='py-3 text-center'>Reset Your Password</h2>
{error && <Message variant='danger'>{error}</Message>}
<Form onSubmit={handleSubmit}>
<Form.Group controlId="password" className='mb-3'>
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Enter password" value={password} onChange={(e)=> setPassword(e.target.value)} />
</Form.Group>

<Form.Group controlId="confirmPassword" className='mb-4'>
<Form.Label>Retype Password</Form.Label>
<Form.Control type="password" placeholder="Confirm Password" value={confirmPassword} onChange={(e)=> setConfirmPassword(e.target.value)} />
</Form.Group>

<Button type='submit' variant='primary' className="auth-btn" >Submit</Button>
</Form>
</FormContainer>
)
}

export default ForgetPasswordScreen
4 changes: 4 additions & 0 deletions client/src/pages/EcommercePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -23,6 +25,8 @@ function EcommercePage() {
<Route path="/page/:pageNumber" component={HomeScreen} />
<Route path="/login" component={LoginScreen} />
<Route path="/register" component={RegisterScreen} />
<Route path="/forget-password" component={ForgetPasswordScreen} />
<Route path="/reset-password/:resetToken" component={PasswordResetScreen} />
<Route path="/profile" component={ProfileScreen} />
<Route path="/product/:id" component={ProductScreen} />
<Route path="/cart/:id?" component={CartScreen} />
Expand Down
2 changes: 1 addition & 1 deletion server/controller/productController.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? {
Expand Down
21 changes: 10 additions & 11 deletions server/controller/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = `
<h1> Plant Land </h1>
<h2>You have requested a password reset</h2>
Expand All @@ -142,15 +141,15 @@ 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"})


} catch (error) {
console.log(error);
res.status(404).json({ error: "Forget password failed" })
res.status(404).json({ message: "Forget password failed" })
}
}

Expand All @@ -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
Expand All @@ -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" })
}
}
2 changes: 1 addition & 1 deletion server/models/userModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 1e416ad

Please sign in to comment.