const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js"); const User = require("../Models/user.model.js"); const { uploadOnCloudinary } = require("../Utils/cloudinary.js"); const sendEmail = require("../Utils/sendmail.js"); const crypto = require("crypto"); const jwt = require("jsonwebtoken"); const sha1 = require("sha1"); const axios = require("axios"); // Register or Sign up new User -- Done const registerUser = catchAsyncErrors(async (req, res) => { const { name, email, password, role } = req.body; // Strong password policy const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/; if (!strongPasswordRegex.test(password)) { return res.status(400).json({ success: false, message: "Password must be at least 8 characters long and include uppercase, lowercase, number, and special character." }); } // Check for data breach with haveibeenpwned.com const hashed = sha1(password).toUpperCase(); const prefix = hashed.slice(0, 5); const suffix = hashed.slice(5); const response = await axios.get(`https://api.pwnedpasswords.com/range/${prefix}`); if (response.data.includes(suffix)) { return res.status(400).json({ success: false, message: "This password has appeared in a data breach. Please choose a different one." }); } const user = await User.create({ name, email, password, role, }); if (!user) { return res.status(500).json({ success: false, message: "User not created something went wrong.", }); } return res.status(200).json({ success: true, message: "User is registered successfully", data: user, }); }); // Login user in our web app -- Done const loginUser = catchAsyncErrors(async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) { return res.status(404).json({ success: false, message: "User not found", }); } const checkUser = await user.isPasswordCorrect(password); if (!checkUser) { return res.status(500).json({ success: false, message: "Password is incorrect", }); } const token = await user.generateRefreshToken(); if (!token) { return res.status(500).json({ success: false, message: "token not created something went wrong.", }); } user.password = null; return res .status(200) .cookie("uid", token, { httpOnly: true, // Prevent access from JavaScript (recommended for security) secure: false, // ⚠️ Set to `false` for localhost sameSite: "Lax", // Use "Lax" instead of "None" for better compatibility path: "/", expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days }) .json({ success: true, message: "User is successfully logged in.", data: user, }); }); // Logout user in our web app -- Done const logoutUser = catchAsyncErrors(async (req, res) => { return res .clearCookie(process.env.TOKEN_NAME, { path: "/", sameSite: "None", secure: process.env.NODE_ENV === "production", httpOnly: true, expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), }) .status(201) .json({ success: true, message: "User is logged out successfully", }); }); // -- DONE const intializeUser = catchAsyncErrors(async (req, res) => { const tokenValue = req.cookies[process.env.TOKEN_NAME]; // console.log("I am the one who is doing this : ", tokenValue); if (!tokenValue) { return res.status(404).json({ success: false, message: "User is not logged in.", }); } try { const payload = await jwt.verify( tokenValue, process.env.REFRESH_TOKEN_SECRET ); if (!payload) { return res.status(404).json({ success: false, message: "Something went wrong", }); } const user = await User.findById(payload._id).select("-password"); return res.status(200).json({ success: true, message: "User data get successfully", data: user, }); } catch (error) { return res.status(404).json({ success: false, message: "Something went wrong", }); } }); // Update user deatails -- ADMIN const updateUserDetails = catchAsyncErrors(async (req, res) => { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ success: true, message: "User not found", }); } const { name, email } = req.body; const updateUser = await User.findByIdAndUpdate(req.params.id, { $set: { name: name, email: email, }, }).select("-password"); return res.status(200).json({ success: true, message: "User is updated successfully", data: updateUser, }); }); // forget password -- Done const forgetPassword = catchAsyncErrors(async (req, res) => { const { email } = req.body; const user = await User.findOne({ email }); if (!user) { return res.status(404).json({ success: false, message: "User not found ", }); } // get reset password const resetToken = await user.getResetPassword(); await user.save({ validateBeforeSave: false }); /*const resetPasswordUrl = `${req.protocol}://${req.get( "host" )}/api/v1/password/reset/${resetToken}`;*/ const resetPasswordUrl = `${process.env.FRONTEND_URI}/user/api/v1/password/reset/${resetToken}`; const message = `Your password token is :-\n\n${resetPasswordUrl}\n\nIf you are not requested this email then please ingore this mail.`; try { await sendEmail({ email: user.email, subject: "MentorFlux password recovery", message: message, }); return res.status(200).json({ success: true, message: `Email sent to ${email} successfully`, }); } catch (error) { user.resetPasswordToken = undefined; user.resetPasswordExpiry = undefined; await user.save({ validateBeforeSave: false }); return res.status(500).json({ success: false, message: "Something went wrong ", error: error, }); } }); // reset users password -- DONE const resetPassword = catchAsyncErrors(async (req, res) => { const token = req.params.token; const { password, confirmPassword } = req.body; //console.log("My password is :", password); //console.log("My confirmPassword is :", confirmPassword); //console.log("My token is :", token); const resetPasswordToken = await crypto .createHash("sha256") .update(token) .digest("hex"); const user = await User.findOne({ resetPasswordToken, resetPasswordExpiry: { $gte: Date.now() }, }); if (!user) { return res.status(401).json({ success: false, message: "Reset Password token is invalid or has been expired", }); } if (password !== confirmPassword) { return res.status(401).json({ success: false, message: "Please enter password and confirm password", }); } user.password = password; user.resetPasswordToken = undefined; user.resetPasswordExpiry = undefined; //console.log("To check the user ", user); await user.save(); return res.status(200).json({ success: true, message: "Password changed successfully", }); }); // get user personal details const getUserDetails = catchAsyncErrors(async (req, res) => { const user = await User.findById(req.user._id); if (!user) { return res.status(500).json({ success: false, message: "Something went wrong ", }); } return res.status(200).json({ success: true, message: "User details are fetched successfully", data: user, }); }); // Update users password const updatePassword = catchAsyncErrors(async (req, res) => { const { password, oldPassword, confirmPassword } = req.body; const user = await User.findById(req.user._id); const isPasswordMatched = await user.isPasswordCorrect(oldPassword); if (!user) { return res.status(500).json({ success: false, message: "User not found", }); } if (!isPasswordMatched) { return res.status(500).json({ success: false, message: "Old password is incorrect.Please enter correct password ", }); } if (password !== confirmPassword) { return res.status(500).json({ success: false, message: "Password and Confirm password should be same.", }); } user.password = password; await user.save({ validateBeforeSave: false }); return res.status(200).json({ success: true, message: "Password upadated successfully", }); }); // update personal details const updatePersonalDetails = catchAsyncErrors(async (req, res) => { const { name, email } = req.body; const user = await User.findByIdAndUpdate(req.user._id, { $set: { name, email, }, }); if (!user) { return res.status(500).json({ success: false, message: "Something went wrong", }); } return res.status(200).json({ success: true, message: "User details updated successfully", data: user, }); }); // Get all users details -- ADMIN const getAllusersDetail = catchAsyncErrors(async (req, res) => { const users = await find(); return res.status(200).json({ success: true, message: "All user fetch successfully", data: users, }); }); // get single user details const getSingaluserDetail = catchAsyncErrors(async (req, res) => { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ success: false, message: "User not found", }); } }); // upadate user Role -- ADMIN const updateUserRole = catchAsyncErrors(async (req, res) => { const { name, email, role } = req.body; const user = await User.findByIdAndUpdate(req.params.id, { $set: { name, email, role, }, }); if (!user) { return res.status(500).json({ success: false, message: "Something went wrong", }); } return res.status(200).json({ success: true, message: "User Role updated successfully", data: user, }); }); // Delete user -- ADMIN const DeleteUser = catchAsyncErrors(async (req, res) => { const user = await User.findByIdAndDelete(req.params.id); if (!user) { return res.status(404).json({ success: false, message: "User does not exist", }); } return res.status(200).json({ success: true, message: "User deleted successfully", data: user, }); }); // update avatar -- user const updateAvatar = catchAsyncErrors(async (req, res) => { //console.log("Our file is : ", req.file.path); if (!req.file.path) { res.status(500).json({ success: false, message: "Avatar not uploaded on cloudinary.", }); } const avatarUrl = await uploadOnCloudinary(req.file.path); if (!avatarUrl) { return res.status(500).json({ success: false, message: "Avatar not uploaded on cloudinary.", }); } //console.log("Avatar url is : ", avatarUrl); //console.log("our user is : ", req.user); const user = await User.findByIdAndUpdate(req.user._id, { $set: { avatar: avatarUrl, }, }); if (!user) { return res.status(404).json({ success: false, message: "User not found.", }); } return res.status(200).json({ success: true, message: "Avatar updated successfully.", data: user, }); }); module.exports = { registerUser, loginUser, logoutUser, updateUserDetails, forgetPassword, resetPassword, getUserDetails, updatePassword, updatePersonalDetails, updateUserRole, DeleteUser, intializeUser, updateAvatar, };