Skip to content

Commit b39b853

Browse files
committed
commit reset password client and server
1 parent 9b39c78 commit b39b853

File tree

8 files changed

+161
-10
lines changed

8 files changed

+161
-10
lines changed

client/src/Pages/Reset.js

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,82 @@
1-
import { useContext } from 'react'
2-
import { Link } from 'react-router-dom'
1+
import { useContext, useState } from 'react'
2+
import { Link, useNavigate } from 'react-router-dom'
33
import loginimg from '../assets/forgot.png'
44
import '../css/login.css'
55
import { AppContext } from '../App'
6+
import toast, { Toaster } from 'react-hot-toast';
7+
import axios from 'axios'
8+
import { url } from '../baseurl'
9+
610

711
export const Reset = () => {
812
const context = useContext(AppContext)
13+
const navigate = useNavigate()
14+
const [otp, setOpt] = useState('')
15+
const [email, setEmail] = useState('')
16+
const [pass, setPass] = useState('')
17+
918

19+
async function sendOtp() {
20+
if (!email)
21+
toast.error("Email required", {
22+
style: {
23+
fontSize: '12px'
24+
}
25+
})
26+
const resp = await axios.put(`${url}/user/password/otp`, {
27+
email
28+
})
29+
if (resp.data.status) {
30+
toast.success("OTP sent", {
31+
style: {
32+
fontSize: '12px'
33+
}
34+
})
35+
}
36+
}
37+
async function changePass() {
38+
if (!email)
39+
toast.error("Email required", {
40+
style: {
41+
fontSize: '12px'
42+
}
43+
})
44+
if (!pass)
45+
toast.error("Password required", {
46+
style: {
47+
fontSize: '12px'
48+
}
49+
})
50+
if (!otp)
51+
toast.error("OTP required", {
52+
style: {
53+
fontSize: '12px'
54+
}
55+
})
56+
await axios.put(`${url}/user/verifyotp`, {
57+
email, password: pass, otp
58+
}).then(() => navigate('/login'))
59+
}
1060
return (
1161
<div className="containerlogin">
62+
<Toaster />
1263
<div className="leftlogin">
13-
<img style={{ marginTop: '-40px', minWidth: '400px', zIndex: '-99',width:'85%' }} src={loginimg} alt="" />
64+
<img style={{ marginTop: '-40px', minWidth: '400px', zIndex: '-99', width: '85%' }} src={loginimg} alt="" />
1465
</div>
1566
<div className="rightlogin">
1667
<div className="headerlogin">
1768
<h1 className='hrespreset'>
1869
Reset Password
1970
</h1>
20-
<p style={{ marginTop: '-10px', marginBottom: '5px' ,fontSize:'14px',marginLeft:'5px',minWidth:'320px'}}>Remember your password <Link to="/login" style={{ color: 'rgb(109 109 109)', textDecoration: 'none', marginBottom: '-2.5px', marginLeft: '3px' }}> Login here</Link></p>
71+
<p style={{ marginTop: '-10px', marginBottom: '5px', fontSize: '14px', marginLeft: '5px', minWidth: '320px' }}>Remember your password <Link to="/login" style={{ color: 'rgb(109 109 109)', textDecoration: 'none', marginBottom: '-2.5px', marginLeft: '3px' }}> Login here</Link></p>
72+
</div>
73+
<div className="same-line" style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', width: '325px', marginTop: '20px', }}>
74+
<input value={email} onChange={e => setEmail(e.target.value)} type="email" placeholder='Enter email' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', paddingLeft: '14px', width: '78%' }} />
75+
<button onClick={() => sendOtp()} style={{ fontFamily: 'Poppins', color: context.dark ? 'black' : 'white', border: 'none', outline: 'none', background: context.dark ? 'white' : 'rgb(66 66 66)', cursor: 'pointer', fontWeight: 'bold', borderRadius: '5px', height: '45px', width: '21%', marginLeft: '8px' }}>OTP</button>
2176
</div>
22-
<input type="email" placeholder='Enter email' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} />
23-
<input type="password" placeholder='Enter new password' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} />
24-
<button style={{ fontFamily: 'Poppins', width: '320px', color: context.dark ? 'black' : 'white', border: 'none', outline: 'none', background: context.dark ? 'white' : 'rgb(66 66 66)', height: '44px', borderRadius: '5px', cursor: 'pointer', marginTop: '20px', fontWeight: 'bold' }} variant="outlined">Done</button>
77+
<input value={otp} onChange={e => setOpt(e.target.value)} type="text" placeholder='Enter OTP' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} />
78+
<input value={pass} onChange={e => setPass(e.target.value)} type="password" placeholder='Enter new password' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} />
79+
<button onClick={() => changePass()} style={{ fontFamily: 'Poppins', width: '320px', color: context.dark ? 'black' : 'white', border: 'none', outline: 'none', background: context.dark ? 'white' : 'rgb(66 66 66)', height: '44px', borderRadius: '5px', cursor: 'pointer', marginTop: '20px', fontWeight: 'bold' }} variant="outlined">Done</button>
2580
</div>
2681
</div>
2782
)

client/src/Pages/Signup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const Signup = () => {
6060
<p style={{ marginTop: '-10px', marginBottom: '5px' ,fontSize:'14px',marginLeft:'5px',minWidth:'320px'}}>Already have an account <Link to="/login" style={{ color: 'rgb(109 109 109)', textDecoration: 'none', marginBottom: '-2.5px', marginLeft: '3px' }}> Login here</Link></p>
6161
</div>
6262
<input type="email" placeholder='Enter email' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} value={email} onChange={(e) => setemail(e.target.value)} />
63-
<input type="text" placeholder='Enter username' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} value={username} onChange={(e) => setusername(e.target.value)} />
63+
<input type="text" placeholder='Enter Name' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} value={username} onChange={(e) => setusername(e.target.value)} />
6464
<input type="password" placeholder='Enter password' style={{ background: context.dark ? 'rgb(66 66 66)' : 'rgb(248 248 248)', height: '47px', outline: 'none', border: 'none', borderRadius: '5px', color: 'inherit', width: '325px', marginTop: '20px', paddingLeft: '14px' }} value={password} onChange={(e) => setPassword(e.target.value)} />
6565
<button onClick={signup} style={{ fontFamily: 'Poppins', width: '325px', color: context.dark ? 'black' : 'white', border: 'none', outline: 'none', background: context.dark ? 'white' : 'rgb(66 66 66)', height: '44px', borderRadius: '5px', cursor: 'pointer', marginTop: '20px', fontWeight: 'bold', marginBottom: '25px' }} variant="outlined">Register</button>
6666
</div>

server/models/Otp.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const mongoose = require('mongoose')
2+
3+
const otpSchema = new mongoose.Schema({
4+
email: {
5+
type: String,
6+
required: true,
7+
unique:true
8+
},
9+
otp: {
10+
type: String,
11+
required: true
12+
},
13+
expiry:{
14+
type:Date,
15+
required:true
16+
}
17+
})
18+
19+
const otpModel = new mongoose.model('otp',otpSchema);
20+
21+
module.exports = { otpModel }

server/package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"express": "^4.18.1",
1818
"markdown-to-text": "^0.1.1",
1919
"mongoose": "^6.5.3",
20+
"nodemailer": "^6.7.8",
2021
"uuid": "^8.3.2"
2122
}
2223
}

server/routes/user.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
const router = require('express').Router()
22
const { UserModel } = require('../models/User')
33
const { v4: idnot } = require('uuid')
4-
const { hash } = require('../utils/passwordhash')
5-
const { paginate } = require('../utils/paginate')
4+
const { hash, verify } = require('../utils/passwordhash')
5+
const { otpModel } = require('../models/Otp')
6+
const { main } = require('../utils/mail')
7+
const {AddMinutesToDate}=require('../utils/date')
8+
69

710
router.get('/:uid', async (req, res) => {
811
try {
@@ -14,6 +17,36 @@ router.get('/:uid', async (req, res) => {
1417

1518
})
1619

20+
router.put('/password/otp', async (req, res) => {
21+
const { email } = req.body
22+
const otp = Math.ceil(Math.random() * 1000000).toString()
23+
const hashedOtp=await hash(otp)
24+
const find = await otpModel.findOne({ email })
25+
if (!find) {
26+
const newotp = new otpModel({
27+
email, otp:hashedOtp,expiry:AddMinutesToDate(new Date(),5)
28+
})
29+
await newotp.save()
30+
} else {
31+
await otpModel.updateOne({ email }, { otp:hashedOtp,expiry:AddMinutesToDate(new Date(),5) })
32+
}
33+
await main(otp, email)
34+
res.send({ status: true })
35+
})
36+
37+
router.put('/verifyotp', async (req, res) => {
38+
const { otp, email, password } = req.body
39+
const otpdata=await otpModel.findOne({ email })
40+
if(otpdata.otp<new Date()) return res.status(401).send({ message: "Wrong otp" });
41+
const valid = await verify(otpdata.otp, otp)
42+
if (!valid) {
43+
return res.status(401).send({ message: "Wrong otp" });
44+
}
45+
const result = await UserModel.updateOne({ email }, { password: await hash(password) })
46+
if(result.modifiedCount===0) return res.send({message:'No account found'})
47+
if (result) res.send({ message: "done" })
48+
})
49+
1750
router.get('/followers/:uid', async (req, res) => {
1851
try {
1952
const user = await UserModel.findOne({ uid: req.params.uid })

server/utils/date.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function AddMinutesToDate(date, minutes) {
2+
return new Date(date.getTime() + minutes * 60000);
3+
}
4+
module.exports={AddMinutesToDate}

server/utils/mail.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const nodemailer = require("nodemailer");
2+
3+
async function main(otp, email) {
4+
5+
let transporter = nodemailer.createTransport({
6+
service: 'gmail',
7+
auth: {
8+
user: `${process.env.email}`,
9+
pass: `${process.env.password}`,
10+
},
11+
});
12+
13+
let info = await transporter.sendMail({
14+
from: 'CatchBlog',
15+
to: [`${email}`],
16+
subject: "Reset Password || OTP",
17+
text: `otp=${otp}`
18+
});
19+
20+
console.log("Message sent: %s", info.messageId);
21+
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
22+
}
23+
module.exports = { main }

0 commit comments

Comments
 (0)