diff --git a/backend/middleware/fetchuser.js b/backend/middleware/fetchuser.js index d3e6820..7e5085f 100644 --- a/backend/middleware/fetchuser.js +++ b/backend/middleware/fetchuser.js @@ -3,7 +3,7 @@ const dotenv = require('dotenv'); dotenv.config(); -const JWT_SECRET = process.env.JWT_SECRET; +const JWT_SECRET = "isadvn2hjk23h4h&%@(jhhj"; const fetchuser = async (req, res, next) => { const token = await req.header('auth-token'); diff --git a/backend/models/DeleteAccount.js b/backend/models/DeleteAccount.js new file mode 100644 index 0000000..d9fdc27 --- /dev/null +++ b/backend/models/DeleteAccount.js @@ -0,0 +1,15 @@ +const mongoose = require('mongoose'); +const { Schema } = require('mongoose'); + +const daSchema = new Schema({ + email: { + type: String, + required: true + }, + token: { + type: String, + required: true + } +}, {timestamps: true}); + +module.exports = mongoose.model('daccount', daSchema); \ No newline at end of file diff --git a/backend/routes/auth.js b/backend/routes/auth.js index fb4e365..c49056f 100644 --- a/backend/routes/auth.js +++ b/backend/routes/auth.js @@ -2,6 +2,8 @@ const express = require('express'); const router = express.Router(); const dotenv = require('dotenv'); const UserSchema = require('../models/User'); +const NoteSchema = require('../models/Notes'); +const daSchema = require('../models/DeleteAccount'); const { body, validationResult } = require('express-validator'); var bcrypt = require('bcryptjs'); var jwt = require('jsonwebtoken'); @@ -470,6 +472,141 @@ router.put('/login/changepassword', } catch (error) { return res.status(500).send("Internal Server Error"); } - }) +}); + + + + + + + + + + + +// Route 10: Deleting a user's account: DELETE: http://localhost:8181/api/auth/deleteaccount. Login Required +router.delete('/deleteaccount', fetchuser, async (req, res) => { + + try { + const theUser = await UserSchema.findById(req.user.id); + if (!theUser) { + return res.status(404).json({ error: "User not Found" }); + } + + const daToken = uuidv4(); + + // Pushing the token with email in the DB + await daSchema.create({ + email: theUser.email, + token: daToken + }); + + // Sending the email with the Delete Account link in it + const transporter = nodemailer.createTransport({ + service: 'hotmail', + auth: { + user: "abhinandanwadhwa5@outlook.com", + pass: "Abhi1311" + } + }); + + const options = { + from: "abhinandanwadhwa5@outlook.com", + to: theUser.email, + subject: 'Delete Noteslify Account', + html: `You are receiving this email because you(maybe someone else) wanted to delete your account permanently.\nIf it was not you, ignore this email.If you requested to delete your account, please go to the following link: Click Here` + }; + + transporter.sendMail(options, (err, info) => { + if (err) { + console.log(err); + return res.status(400).json({ error: "Internal Server Error!" }); + } + console.log(info.response); + res.status(200).json({ success: "An Email has been sent to your mail account for confirmation" }); + }); + + + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal Server Error" }); + } + + +}); + + + + + + + + + + + +// Route 11: Getting a specific daEntry: GET: http://localhost:8181/api/auth/getdatoken. Login Required +router.get('/getdatoken/:id', fetchuser, async (req, res) => { + try { + const token = await daSchema.findOne({ token: req.params.id }); + const theUser = await UserSchema.findById(req.user.id); + + if (!token) { + return res.status(404).json({ error: "No such token found" }); + } + if (theUser.email !== token.email) { + return res.status(403).json({ error: "You cannot access some other person's token" }); + } + + res.status(200).json(token); + + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal Server Error" }); + } + + +}); + + + + + + + + + + + +// Route 12: Deleting the user permanently: GET: http://localhost:8181/api/auth/deletepermanently/:id. Login Required +router.delete('/permanentlydelete/:id/:email', async (req, res) => { + try { + const token = await daSchema.findOne({ token: req.params.id }); + const theUser = await UserSchema.findOne({ email: req.params.email }); + + let checkHash = await bcrypt.compare(req.body.password, theUser.password); + if (!checkHash) { + return res.status(403).json({ error: "Wrong Password!" }); + } + + if (!token) { + return res.status(404).json({ error: "No such token found" }); + } + if (theUser.email !== token.email) { + return res.status(403).json({ error: "You cannot access some other person's token" }); + } + + await NoteSchema.deleteMany({ authorId: theUser.id }); + await theUser.delete(); + + res.status(200).json({ success: "The user has been deleted successfully!!" }); + + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal Server Error" }); + } +}); + + -module.exports = router; +module.exports = router; \ No newline at end of file diff --git a/frontend/src/App.js b/frontend/src/App.js index a8a2ac4..dcbfeeb 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -14,6 +14,7 @@ import ErrorPage from './components/Error/ErrorPage'; import AOS from "aos"; import "aos/dist/aos.css"; import { useEffect } from 'react'; +import Deleteaccount from './components/DeleteAccount/Deleteaccount'; function App() { useEffect(() => { @@ -36,6 +37,7 @@ function App() { } /> } /> } /> + } /> ); diff --git a/frontend/src/components/Account/Account.js b/frontend/src/components/Account/Account.js index 7678aa0..fd93f68 100644 --- a/frontend/src/components/Account/Account.js +++ b/frontend/src/components/Account/Account.js @@ -76,6 +76,28 @@ const Account = () => { } }; + + const deleteAccount = async () => { + if (window.confirm("Are you sure you want to delete your account?")) { + const authtoken = sessionStorage.getItem('auth-token'); + const response = await fetch('http://localhost:8181/api/auth/deleteaccount', { + method: "DELETE", + headers: { + 'Content-Type': 'application/json', + 'auth-token': authtoken + } + }); + const json = await response.json(); + console.log(json); + if (json.success) { + toast.success(json.success); + } + else { + toast.error(json.error); + } + } + } + return ( <> @@ -172,8 +194,22 @@ const Account = () => { Change Password + + { + deleteAccount(); + }} + className="add-box" + > + + + + Delete Account + + + diff --git a/frontend/src/components/DeleteAccount/Deleteaccount.js b/frontend/src/components/DeleteAccount/Deleteaccount.js new file mode 100644 index 0000000..cae5733 --- /dev/null +++ b/frontend/src/components/DeleteAccount/Deleteaccount.js @@ -0,0 +1,82 @@ +import React, { useEffect, useState } from 'react' +import { Helmet } from 'react-helmet'; +import { Link, useNavigate, useParams } from 'react-router-dom'; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; + +const Deleteaccount = () => { + const [password, setPassword] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const { token, email } = useParams(); + + const navigate = useNavigate(); + + useEffect(() => { + + }, []); + + + const deletePermanently = async (e) => { + e.preventDefault(); + + const response = await fetch(`http://localhost:8181/api/auth/permanentlydelete/${token}/${email}`, { + method: "DELETE", + headers: { + 'Content-Type': 'application/json' + }, body: JSON.stringify({ password: password }) + }); + const json = await response.json(); + if (json.success) { + localStorage.removeItem('auth-token'); + toast.success(json.success); + setTimeout(() => { + navigate('/login'); + }, 2000); + } + else { + toast.error(json.error); + } + } + return ( + <> + {/* + setPassword(e.target.value)} type="password" /> + Delete Permanently + + */} + + + + Noteslify | Delete Account + + + + Delete User? + + Please confirm your password to delete your account permanently + + + + + setPassword(e.target.value)} required="required" placeholder="Confirm Password"> + + + {!isLoading && } + {isLoading && } + + + + Remember Your Password? Login + + + + + + > + ) +} + +export default Deleteaccount \ No newline at end of file
Change Password
Delete Account
Please confirm your password to delete your account permanently
Remember Your Password? Login