497 lines
13 KiB
JavaScript
497 lines
13 KiB
JavaScript
// controllers/userController.js
|
|
const User = require("../models/User");
|
|
const Products = require("../models/Product");
|
|
const jwt = require("jsonwebtoken");
|
|
const bcrypt = require("bcrypt");
|
|
const otpGenerator = require("otp-generator");
|
|
const nodemailer = require("nodemailer");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { getUser } = require("../config/getUser");
|
|
// const registerUser = async (req, res) => {
|
|
// try {
|
|
// // Create user in the database
|
|
// const request = req.body; // No need to use await here
|
|
// const UserCount = await User.countDocuments();
|
|
// const existingUser = await User.findOne({ email: request.email });
|
|
|
|
// if (existingUser) {
|
|
// return res.status(400).json({
|
|
// UserCount,
|
|
// success: false,
|
|
// message: 'User With This Email Already Exists',
|
|
// });
|
|
// }
|
|
|
|
// const otp = otpGenerator.generate(6, {
|
|
// upperCaseAlphabets: false,
|
|
// specialChars: false,
|
|
// lowerCaseAlphabets: false,
|
|
// digits: true,
|
|
// });
|
|
// // Create user with the generated OTP
|
|
// const user = await User.create({
|
|
// ...request,
|
|
// otp,
|
|
// role: Boolean(UserCount) ? request.role || 'user' : 'super admin',
|
|
// });
|
|
|
|
// // Generate JWT token
|
|
// const token = jwt.sign(
|
|
// {
|
|
// _id: user._id,
|
|
// // email: user.email,
|
|
// },
|
|
// process.env.JWT_SECRET,
|
|
// {
|
|
// expiresIn: '7d',
|
|
// }
|
|
// );
|
|
// // Path to the HTML file
|
|
// const htmlFilePath = path.join(
|
|
// process.cwd(),
|
|
// 'src/email-templates',
|
|
// 'otp.html'
|
|
// );
|
|
|
|
// // Read HTML file content
|
|
// let htmlContent = fs.readFileSync(htmlFilePath, 'utf8');
|
|
|
|
// // Replace the placeholder with the OTP and user email
|
|
// htmlContent = htmlContent.replace(/<h1>[\s\d]*<\/h1>/g, `<h1>${otp}</h1>`);
|
|
// htmlContent = htmlContent.replace(/usingyourmail@gmail\.com/g, user.email);
|
|
|
|
// // Create nodemailer transporter
|
|
// let transporter = nodemailer.createTransport({
|
|
// service: 'gmail',
|
|
// auth: {
|
|
// user: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
// pass: process.env.EMAIL_PASSWORD, // Your Gmail password
|
|
// },
|
|
// });
|
|
|
|
// // Email options
|
|
// let mailOptions = {
|
|
// from: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
// to: user.email, // User's email
|
|
// subject: 'Verify your email',
|
|
// html: htmlContent, // HTML content with OTP and user email
|
|
// };
|
|
|
|
// // Send email
|
|
// await transporter.sendMail(mailOptions);
|
|
// res.status(201).json({
|
|
// success: true,
|
|
// message: 'Created User Successfully',
|
|
// otp,
|
|
// token,
|
|
// user,
|
|
// });
|
|
// } catch (error) {
|
|
// res.status(500).json({
|
|
// message: error.message,
|
|
// status: 500,
|
|
// });
|
|
// }
|
|
// };
|
|
|
|
const registerUser = async (req, res) => {
|
|
try {
|
|
// Create user in the database
|
|
const request = req.body; // No need to use await here
|
|
const UserCount = await User.countDocuments();
|
|
const existingUser = await User.findOne({ email: request.email });
|
|
|
|
if (existingUser) {
|
|
return res.status(400).json({
|
|
UserCount,
|
|
success: false,
|
|
message: "User With This Email Already Exists",
|
|
});
|
|
}
|
|
|
|
const otp = otpGenerator.generate(6, {
|
|
upperCaseAlphabets: false,
|
|
specialChars: false,
|
|
lowerCaseAlphabets: false,
|
|
digits: true,
|
|
});
|
|
|
|
// Create user with the generated OTP
|
|
const user = await User.create({
|
|
...request,
|
|
otp,
|
|
role: Boolean(UserCount) ? request.role || "user" : "super admin",
|
|
});
|
|
|
|
// Generate JWT token
|
|
const token = jwt.sign(
|
|
{
|
|
_id: user._id,
|
|
},
|
|
process.env.JWT_SECRET,
|
|
{
|
|
expiresIn: "7d",
|
|
}
|
|
);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: "Created User Successfully",
|
|
otp,
|
|
token,
|
|
user,
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
message: error.message,
|
|
status: 500,
|
|
});
|
|
}
|
|
};
|
|
|
|
const loginUser = async (req, res) => {
|
|
try {
|
|
const { email, password } = await req.body;
|
|
const user = await User.findOne({ email }).select("+password");
|
|
|
|
if (user.isVerified === false) {
|
|
return res
|
|
.status(404)
|
|
.json({
|
|
success: false,
|
|
message: "탈퇴한 회원입니다. 관리자에게 문의하세요",
|
|
});
|
|
}
|
|
|
|
if (!user) {
|
|
return res
|
|
.status(404)
|
|
.json({ success: false, message: "User Not Found" });
|
|
}
|
|
|
|
if (!user.password) {
|
|
return res
|
|
.status(404)
|
|
.json({ success: false, message: "User Password Not Found" });
|
|
}
|
|
|
|
const isPasswordMatch = await bcrypt.compare(password, user.password);
|
|
|
|
if (!isPasswordMatch) {
|
|
return res
|
|
.status(400)
|
|
.json({ success: false, message: "Incorrect Password" });
|
|
}
|
|
|
|
const token = jwt.sign(
|
|
{
|
|
_id: user._id,
|
|
email: user.email,
|
|
},
|
|
process.env.JWT_SECRET,
|
|
{
|
|
expiresIn: "7d",
|
|
}
|
|
);
|
|
|
|
const products = await Products.aggregate([
|
|
{
|
|
$match: {
|
|
_id: { $in: user.wishlist },
|
|
},
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: "productreviews",
|
|
localField: "productreviews",
|
|
foreignField: "_id",
|
|
as: "productreviews",
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
averageRating: { $avg: "$productreviews.rating" },
|
|
image: { $arrayElemAt: ["$images", 0] },
|
|
},
|
|
},
|
|
{
|
|
$project: {
|
|
image: { url: "$image.url", blurDataURL: "$image.blurDataURL" },
|
|
name: 1,
|
|
slug: 1,
|
|
colors: 1,
|
|
discount: 1,
|
|
likes: 1,
|
|
priceSale: 1,
|
|
price: 1,
|
|
averageRating: 1,
|
|
vendor: 1,
|
|
shop: 1,
|
|
createdAt: 1,
|
|
},
|
|
},
|
|
]);
|
|
|
|
return res.status(201).json({
|
|
success: true,
|
|
message: "Login Successfully",
|
|
token,
|
|
user: {
|
|
_id: user._id,
|
|
firstName: user.firstName,
|
|
lastName: user.lastName,
|
|
email: user.email,
|
|
cover: user.cover,
|
|
gender: user.gender,
|
|
phone: user.phone,
|
|
address: user.address,
|
|
city: user.city,
|
|
country: user.country,
|
|
zip: user.zip,
|
|
state: user.state,
|
|
about: user.about,
|
|
role: user.role,
|
|
wishlist: products,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, error: error.message });
|
|
}
|
|
};
|
|
|
|
const forgetPassword = async (req, res) => {
|
|
try {
|
|
const request = await req.body;
|
|
const user = await User.findOne({ email: request.email });
|
|
|
|
if (!user) {
|
|
return res
|
|
.status(404)
|
|
.json({ success: false, message: "User Not Found " });
|
|
}
|
|
|
|
const token = jwt.sign({ _id: user._id }, process.env.JWT_SECRET, {
|
|
expiresIn: "7d",
|
|
});
|
|
// Constructing the link with the token
|
|
const resetPasswordLink = `${request.origin}/auth/reset-password/${token}`;
|
|
|
|
// Path to the HTML file
|
|
const htmlFilePath = path.join(
|
|
process.cwd(),
|
|
"src/email-templates",
|
|
"forget.html"
|
|
);
|
|
|
|
// Read HTML file content
|
|
let htmlContent = fs.readFileSync(htmlFilePath, "utf8");
|
|
|
|
// Replace the href attribute of the <a> tag with the reset password link
|
|
// htmlContent = htmlContent.replace(
|
|
// /href="javascript:void\(0\);"/g,
|
|
// `href="${resetPasswordLink}"`
|
|
// )
|
|
htmlContent = htmlContent.replace(
|
|
/href="javascript:void\(0\);"/g,
|
|
`href="${resetPasswordLink}"`
|
|
);
|
|
// Create nodemailer transporter
|
|
let transporter = nodemailer.createTransport({
|
|
service: "gmail",
|
|
auth: {
|
|
user: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
pass: process.env.EMAIL_PASSWORD, // Your Gmail password
|
|
},
|
|
});
|
|
|
|
// Email options
|
|
let mailOptions = {
|
|
from: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
to: user.email, // User's email
|
|
subject: "Verify your email",
|
|
html: htmlContent, // HTML content with OTP and user email
|
|
};
|
|
|
|
// Send email synchronously
|
|
await transporter.sendMail(mailOptions);
|
|
|
|
return res.status(200).json({
|
|
success: true,
|
|
message: "Forgot Password Email Sent Successfully.",
|
|
token,
|
|
});
|
|
} catch (error) {
|
|
return res.status(500).json({ success: false, message: error.message });
|
|
}
|
|
};
|
|
|
|
const resetPassword = async (req, res) => {
|
|
try {
|
|
const { token, newPassword } = await req.body;
|
|
|
|
// Verify the token
|
|
let decoded;
|
|
try {
|
|
decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
} catch (err) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "Invalid Or Expired Token. Please Request A New One.",
|
|
});
|
|
}
|
|
|
|
// Find the user by ID from the token
|
|
const user = await User.findById(decoded._id).select("password");
|
|
|
|
if (!user) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: "User Not Found ",
|
|
});
|
|
}
|
|
if (!newPassword || !user.password) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message:
|
|
"Invalid Data. Both NewPassword And User Password Are Required.",
|
|
});
|
|
}
|
|
|
|
// Check if the new password is the same as the old password
|
|
const isSamePassword = await bcrypt.compare(newPassword, user.password);
|
|
if (isSamePassword) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "New Password Must Be Different From The Old Password.",
|
|
});
|
|
}
|
|
// Update the user's password
|
|
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
|
|
|
await User.findByIdAndUpdate(user._id, {
|
|
password: hashedPassword,
|
|
});
|
|
|
|
return res.status(201).json({
|
|
success: true,
|
|
message: "Password Updated Successfully.",
|
|
user,
|
|
});
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
};
|
|
const verifyOtp = async (req, res) => {
|
|
try {
|
|
const { otp } = req.body;
|
|
const user = await getUser(req, res, "not-verified");
|
|
if (!user) {
|
|
return res
|
|
.status(404)
|
|
.json({ success: false, message: "User Not Found" });
|
|
}
|
|
// Check if OTP has already been verified
|
|
if (user.isVerified) {
|
|
return res
|
|
.status(400)
|
|
.json({ success: false, message: "OTP Has Already Been Verified" });
|
|
}
|
|
|
|
let message = "";
|
|
// Verify the OTP
|
|
if (otp === user.otp) {
|
|
user.isVerified = true;
|
|
await user.save();
|
|
message = "OTP Verified Successfully";
|
|
return res.status(200).json({ success: true, message });
|
|
} else {
|
|
message = "Invalid OTP";
|
|
return res.status(400).json({ success: false, message });
|
|
}
|
|
} catch (error) {
|
|
return res
|
|
.status(500)
|
|
.json({ success: false, message: "Internal Server Error" });
|
|
}
|
|
};
|
|
|
|
const resendOtp = async (req, res) => {
|
|
try {
|
|
const user = await getUser(req, res, "not-verified");
|
|
|
|
if (!user) {
|
|
return res
|
|
.status(404)
|
|
.json({ success: false, message: "User Not Found" });
|
|
}
|
|
if (user.isVerified) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "OTP Has Already Been Verified",
|
|
});
|
|
}
|
|
// Generate new OTP
|
|
const otp = otpGenerator.generate(6, {
|
|
upperCaseAlphabets: false,
|
|
specialChars: false,
|
|
lowerCaseAlphabets: false,
|
|
digits: true,
|
|
});
|
|
// Update the user's OTP
|
|
await User.findByIdAndUpdate(user._id, {
|
|
otp: otp.toString(),
|
|
});
|
|
|
|
// Path to the HTML file
|
|
const htmlFilePath = path.join(
|
|
process.cwd(),
|
|
"src/email-templates",
|
|
"otp.html"
|
|
);
|
|
|
|
// Read HTML file content
|
|
let htmlContent = fs.readFileSync(htmlFilePath, "utf8");
|
|
|
|
// Replace the placeholder with the OTP and user email
|
|
htmlContent = htmlContent.replace(/<h1>[\s\d]*<\/h1>/g, `<h1>${otp}</h1>`);
|
|
htmlContent = htmlContent.replace(/usingyourmail@gmail\.com/g, user.email);
|
|
|
|
// Create nodemailer transporter
|
|
let transporter = nodemailer.createTransport({
|
|
service: "gmail",
|
|
auth: {
|
|
user: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
pass: process.env.EMAIL_PASSWORD, // Your Gmail password
|
|
},
|
|
});
|
|
|
|
// Email options
|
|
let mailOptions = {
|
|
from: process.env.RECEIVING_EMAIL, // Your Gmail email
|
|
to: user.email, // User's email
|
|
subject: "Verify your email",
|
|
html: htmlContent, // HTML content with OTP and user email
|
|
};
|
|
|
|
// Send email
|
|
await transporter.sendMail(mailOptions);
|
|
|
|
// Return the response
|
|
return res.status(200).json({
|
|
success: true,
|
|
message: "OTP Resent Successfully",
|
|
});
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
};
|
|
module.exports = {
|
|
registerUser,
|
|
loginUser,
|
|
forgetPassword,
|
|
resetPassword,
|
|
verifyOtp,
|
|
resendOtp,
|
|
};
|