diff --git a/.env b/.env
index 6247272..4ef0c30 100644
--- a/.env
+++ b/.env
@@ -1,3 +1,5 @@
CONNECTION_STRING = 'mongodb+srv://mophoeniiiix:ZK6AdzDw6PbK8YoN@cluster0.ob8d1.mongodb.net/ums?retryWrites=true&w=majority'
secret="this_is_my_jwt_secret"
-PORT=3000
\ No newline at end of file
+PORT=3000
+MAILJET_API_KEY='3509b8424511b49f7f77c97af1e74044'
+MAILJET_API_SECRET='1d3be59ab9ebf2d3c9900fd19d5f13d4'
\ No newline at end of file
diff --git a/controllers/handelCourse.js b/controllers/handelCourse.js
index 83e5fc6..2035f2e 100644
--- a/controllers/handelCourse.js
+++ b/controllers/handelCourse.js
@@ -184,7 +184,6 @@ const enrollInCourse = async (req, res)=>{
// Enroll the student in the course
course.students.push(studentId);
await course.save();
-
// Add the course to the student's enrolled courses
student.enrolledCourses.push(courseId);
await student.save();
diff --git a/controllers/handelUser.js b/controllers/handelUser.js
index d0f7178..ed24f15 100644
--- a/controllers/handelUser.js
+++ b/controllers/handelUser.js
@@ -1,6 +1,8 @@
var jwt = module.require('jsonwebtoken');
const bcrypt = module.require('bcrypt');
const usermodel = module.require("../models/usersModel")
+const crypto = require('crypto');
+const nodemailer = require('nodemailer');
const getall = async (req, res) => {
@@ -35,21 +37,19 @@ const getByid = async (req, res) => {
const updateOne = async (req, res) => {
try {
const { id } = req.params;
- const { password, ...newUpdate } = req.body; // Extract other fields from req.body
+ const { newPassword, ...newUpdate } = req.body; // Extract other fields from req.body
const updateData = { ...newUpdate };
-
+ console.log(req.body)
// Handle password hashing if provided
- if (password) {
- const hashedPassword = await bcrypt.hash(password, 10);
+ if (newPassword) {
+ const hashedPassword = await bcrypt.hash(newPassword, 10);
updateData.password = hashedPassword;
}
- // If an image is provided, handle file upload
if (req.file) {
updateData.image = req.file.path; // Set image path from multer file upload
}
- // Find the user and update
const updatedUser = await usermodel.findByIdAndUpdate(id, updateData, { new: true });
if (!updatedUser) {
@@ -63,6 +63,7 @@ const updateOne = async (req, res) => {
};
+
const createone = async (req, res) => {
try {
// Extract user data from the request body
@@ -199,4 +200,121 @@ const uploadImage = async (req, res) => {
res.status(500).send(err.message);
}
};
-module.exports = { getall, getByid, updateOne,createone,deleteOne,deleteall,login, uploadImage,getAllProfessors }
+
+ const forgotPassword = async (req, res) => {
+ const { email } = req.body;
+
+ if (!email) {
+ return res.status(400).json({ message: "Email is required" });
+ }
+
+ try {
+ const user = await usermodel.findOne({ email });
+
+ if (!user) {
+ return res.status(404).json({ message: "User not found" });
+ }
+
+ const token = crypto.randomBytes(20).toString('hex');
+
+ user.resetPasswordToken = token;
+ user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
+ await user.save();
+
+ const transporter = nodemailer.createTransport({
+ host: 'in.mailjet.com',
+ port: 587,
+ auth: {
+ user: process.env.MAILJET_API_KEY,
+ pass: process.env.MAILJET_API_SECRET,
+ },
+ });
+
+ const resetUrl = `http://localhost:5173/reset-password/${token}`;
+ const mailOptions = {
+ to: user.email,
+ from: 'gamestorrent2015@gmail.com',
+ subject: 'UMS Password Reset',
+ html: `
+
+
+
UMS
+
Password Reset Request [Valid for 1 hour]
+
Dear ${user.name},
+
+ You are receiving this email because we received a request to reset the password for your account.
+
+
+ To complete the process, please click on the link below or copy and paste it into your browser:
+
+
+ ${resetUrl}
+
+
+ If you did not request this change, please ignore this email. Your password will remain unchanged.
+
+
Thank you,
+
UMS Team
+
+
+ `
+ };
+
+ transporter.sendMail(mailOptions, (err) => {
+ if (err) {
+ return res.status(500).json({ message: "Error sending email", error: err.message });
+ }
+ res.status(200).json({ message: "Password reset link sent!" });
+ });
+
+ } catch (error) {
+ res.status(500).json({ message: "Server error, please try again later" });
+ }
+
+};
+const resetPassword = async (req, res) => {
+ const { token } = req.params;
+ const { password } = req.body;
+ if (!password) {
+ return res.status(400).json({ message: "Password is required" });
+ }
+
+ try {
+ const user = await usermodel.findOne({
+ resetPasswordToken: token,
+ resetPasswordExpires: { $gt: Date.now() },
+ });
+
+ if (!user) {
+ return res.status(400).json({ message: "Invalid or expired token" });
+ }
+
+
+ user.password = password;
+ user.resetPasswordToken = undefined;
+ user.resetPasswordExpires = undefined;
+
+ await user.save();
+
+ res.status(200).json({ message: "Password successfully reset!" });
+ } catch (error) {
+ res.status(500).json({ message: "Server error, please try again later" });
+ }
+};
+ const verifyPassword = async (req, res) => {
+ const { password } = req.body;
+ console.log("password is",password)
+ try {
+ const user = await usermodel.findById(req.params.id);
+ if (!user) return res.status(404).send('User not found');
+
+ const isValid = await bcrypt.compare(password, user.password);
+ if (!isValid) return res.status(401).send('passord is not valid');
+
+ res.send( isValid);
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+ }
+
+module.exports = { getall, getByid, updateOne,createone,deleteOne,deleteall,login, uploadImage,getAllProfessors, forgotPassword, resetPassword,verifyPassword }
diff --git a/models/usersModel.js b/models/usersModel.js
index 16f8a92..cd77f89 100644
--- a/models/usersModel.js
+++ b/models/usersModel.js
@@ -43,6 +43,8 @@ const userSchema = new mongoose.Schema({
totalScore: { type: Number, default: 0 },
},
],
+ resetPasswordToken: { type: String },
+ resetPasswordExpires: { type: Date },
});
userSchema.pre("save", async function (next) {
diff --git a/package-lock.json b/package-lock.json
index ab13990..bdff97b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"mongoose": "^8.6.1",
"multer": "^1.4.4",
"multer-gridfs-storage": "^5.0.2",
+ "nodemailer": "^6.9.15",
"nodemon": "^3.1.4",
"uuid": "^10.0.0",
"validator": "^13.12.0"
@@ -595,9 +596,9 @@
}
},
"node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -806,9 +807,9 @@
}
},
"node_modules/express": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
- "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
+ "version": "4.21.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
+ "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
@@ -816,7 +817,7 @@
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.6.0",
+ "cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -1847,6 +1848,15 @@
"webidl-conversions": "^3.0.0"
}
},
+ "node_modules/nodemailer": {
+ "version": "6.9.15",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz",
+ "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==",
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/nodemon": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz",
diff --git a/package.json b/package.json
index d98ef61..b4b2639 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"mongoose": "^8.6.1",
"multer": "^1.4.4",
"multer-gridfs-storage": "^5.0.2",
+ "nodemailer": "^6.9.15",
"nodemon": "^3.1.4",
"uuid": "^10.0.0",
"validator": "^13.12.0"
diff --git a/routes/userRoute.js b/routes/userRoute.js
index f09f23f..12a0246 100644
--- a/routes/userRoute.js
+++ b/routes/userRoute.js
@@ -1,6 +1,6 @@
const upload = require('../Middlewares/uploadConfig');
-const { getall, getByid, updateOne,createone,deleteOne,deleteall,login,uploadImage, getAllProfessors} = module.require("../controllers/handelUser");
+const { getall, getByid, updateOne,createone,deleteOne,deleteall,login,uploadImage, getAllProfessors, forgotPassword, resetPassword,verifyPassword} = module.require("../controllers/handelUser");
const express = module.require('express')
const router=express.Router();
@@ -16,4 +16,8 @@ router.delete('/:id',deleteOne)
router.delete('/',auth,restrict("admin"),deleteall)
router.post('/login',login)
router.post('/uploadUserImage/:id',upload.single('image'),uploadImage);
+router.post('/forgot-password', forgotPassword);
+router.post('/reset-password/:token', resetPassword);
+router.post('/verify/:id',verifyPassword);
+
module.exports=router;