482 lines
11 KiB
JavaScript
482 lines
11 KiB
JavaScript
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,
|
|
};
|