secure-mern
Version:
A lightweight yet powerful npm package to enhance security in MERN stack applications. Built with enterprise-grade architecture in mind, secure-mern helps you integrate essential security features with minimal configuration.
370 lines (293 loc) • 14 kB
JavaScript
const User = require("../models/User");
const Role = require("../models/Role");
const UserOTP = require("../models/UserOTP")
const bcrypt = require("bcrypt");
const generateToken = require("../utils/generateToken");
const crypto = require('crypto')
const sendEmail = require("../utils/emailTransporter");
const jwt = require('jsonwebtoken')
const authContorller = {
register: async (req, res) => {
try {
const { username, email, password } = req.body
const checkuser = await User.findOne({
$or: [
{ username: username },
{ email: email }
]
})
if (checkuser) {
return res.json({ success: false, message: 'User Already in Database' })
}
const hashpass = await bcrypt.hash(password, 10)
const getroleid = await Role.findOne({ name: 'guest' })
const createuser = new User({
username: username,
email: email,
password: hashpass,
role: getroleid._id
})
const resultcreateuser = await createuser.save()
if (resultcreateuser) {
const checkotp = await UserOTP.findOne({ email: email })
if (checkotp) {
return res.json({ success: false, message: 'User Already Reqeust OTP, Please wait and try agin later' })
}
function generateOTP(length = 8) {
return crypto
.randomBytes(length)
.toString('base64')
.replace(/[^a-zA-Z0-9]/g, '')
.slice(0, length);
}
const otp = generateOTP();
await sendEmail({
to: email,
subject: "Email Verification Code",
html: `
<div style="font-family: Arial, sans-serif; line-height: 1.6; max-width: 600px; margin: auto; border: 1px solid #eee; padding: 20px; border-radius: 8px;">
<h2 style="color: #333;">Hello ${username},</h2>
<p>Thank you for registering. To complete your email verification, please use the code below:</p>
<div style="font-size: 24px; font-weight: bold; background-color: #f2f2f2; padding: 10px 20px; text-align: center; border-radius: 6px; color: #2c3e50; letter-spacing: 2px;">
${otp}
</div>
<p style="margin-top: 20px;">This code is valid for the next 10 minutes. Please do not share it with anyone.</p>
<p>Best regards,<br><strong>Hotel Team</strong></p>
</div>
`,
});
const hashotp = await bcrypt.hash(otp, 10)
const createotprecode = new UserOTP({
email: email,
otp: hashotp
})
const resultcreateotp = await createotprecode.save()
if (resultcreateotp) {
const token = generateToken(
{
email: email,
otp: otp
},
'15min'
);
return res.json({ success: true, token: token, message: "Registation Success, Verification Email send to your email" })
}
else {
return res.json({ success: false, message: "Internal Server Error" })
}
}
else {
return res.json({ success: false, message: "Internal Server Error While creating User" })
}
}
catch (err) {
console.log(err)
}
},
veriftEamilOTP: async (req, res) => {
try {
const token = req.header("Authorization")?.replace("Bearer ", "");
if (!token) return res.status(401).json({ message: "Access denied. No token provided." });
let decoded;
try {
decoded = jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired. Please log in again." });
}
return res.status(400).json({ message: "Invalid token." });
}
const user = await User.findOne({ email: decoded.email }).select("-password");
if (!user) return res.status(404).json({ message: "User not found" });
const checkotprecode = await UserOTP.findOne({ email: decoded.email });
if (!checkotprecode) {
return res.status(404).json({ message: "OTP Record Not found" });
}
const { otp } = req.body;
const otpcheck = await bcrypt.compare(otp, checkotprecode.otp);
if (!otpcheck) {
return res.status(404).json({ message: "OTP does not match" });
}
const updateuser = await User.findOneAndUpdate(
{ email: decoded.email },
{ $set: { isEmailVerified: true } },
{ new: true }
);
if (updateuser) {
const deleteotp = await UserOTP.findOneAndDelete({ email: decoded.email });
if (deleteotp) {
return res.json({ success: true, message: "Email Verification Successful" });
}
} else {
return res.status(500).json({ success: false, message: "Internal Server Error" });
}
} catch (err) {
console.log(err);
return res.status(500).json({ message: "Something went wrong" });
}
},
login: async (req, res) => {
try {
const {
email,
password
} = req.body
const checkuser = await User.findOne({ email: email })
if (!checkuser) {
return res.json({ success: false, message: "User Not in Database" })
}
const checkpass = await bcrypt.compare(password, checkuser.password)
if (!checkpass) {
return res.json({ success: false, message: "Password Not Match" })
}
if (checkuser.isEmailVerified === false) {
return res.json({ success: false, message: "Your email is not Verify..." })
}
if (checkuser.isActive === false) {
return res.json({ success: false, message: "Your Account is not Active..." })
}
const getuserrole = await Role.findById(checkuser.role)
const token = generateToken(
{
id: checkuser._id,
email: checkuser.email,
username: checkuser.username,
role: getuserrole.name
},
'1d'
);
return res.json({ success: true, token: token, message: "Login Success" })
}
catch (err) {
console.log(err)
}
},
passwordforget_emailverify: async (req, res) => {
try {
const { email } = req.body
const checkemail = await User.findOne({ email: email })
if (!checkemail) {
return res.json({ success: false, message: "Email Address Cannot Found,.. Please check the email Address and Try Again" })
}
const checkotp = await UserOTP.findOne({ email: email })
if (checkotp) {
return res.json({ success: false, message: 'User Already Reqeust OTP, Please wait and try agin later' })
}
function generateOTP(length = 8) {
return crypto
.randomBytes(length)
.toString('base64')
.replace(/[^a-zA-Z0-9]/g, '')
.slice(0, length);
}
const otp = generateOTP();
await sendEmail({
to: email,
subject: "Password Reset Code",
html: `
<div style="font-family: Arial, sans-serif; line-height: 1.6; max-width: 600px; margin: auto; border: 1px solid #eee; padding: 20px; border-radius: 8px;">
<h2 style="color: #333;">Hello ${checkemail.username},</h2>
<p>For your Password Reset, please use the code below:</p>
<div style="font-size: 24px; font-weight: bold; background-color: #f2f2f2; padding: 10px 20px; text-align: center; border-radius: 6px; color: #2c3e50; letter-spacing: 2px;">
${otp}
</div>
<p style="margin-top: 20px;">This code is valid for the next 10 minutes. Please do not share it with anyone.</p>
<p>Best regards,<br><strong>Hotel Team</strong></p>
</div>
`,
});
const hashotp = await bcrypt.hash(otp, 10)
const createotprecode = new UserOTP({
email: email,
otp: hashotp
})
const resultcreateotp = await createotprecode.save()
if (resultcreateotp) {
const token = generateToken(
{
id: checkemail._id,
email: checkemail.email,
},
'15min'
);
return res.json({ success: true, token: token, message: "Password Reset Code has been send to email, check the emails" })
}
else {
return res.json({ success: false, message: "Internal Server Error" })
}
}
catch (err) {
console.log(err)
}
},
checkpassword_resetotp: async (req, res) => {
try {
const token = req.header("Authorization")?.replace("Bearer ", "");
if (!token) return res.status(401).json({ message: "Access denied. No token provided." });
let decoded;
try {
decoded = jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired. Please log in again." });
}
return res.status(400).json({ message: "Invalid token." });
}
const user = await User.findOne({ email: decoded.email }).select("-password");
if (!user) return res.status(404).json({ message: "User not found" });
const checkotprecode = await UserOTP.findOne({ email: decoded.email });
if (!checkotprecode) {
return res.status(404).json({ message: "OTP Record Not found" });
}
const { otp } = req.body
const checkotp = await bcrypt.compare(otp, checkotprecode.otp)
if (!checkotp) {
return res.json({ success: false, message: "OTP not Match, Please check the OTP" })
}
const deleteotprecode = await UserOTP.findOneAndDelete({ email: decoded.email })
if (deleteotprecode) {
return res.json({ success: false, message: "OTP Verification Successfull" })
}
else {
return res.json({ success: false, message: "Internal Server Error" })
}
}
catch (err) {
console.log(err)
}
},
updaete_password: async (req, res) => {
try {
const token = req.header("Authorization")?.replace("Bearer ", "");
if (!token) return res.status(401).json({ message: "Access denied. No token provided." });
let decoded;
try {
decoded = jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired. Please log in again." });
}
return res.status(400).json({ message: "Invalid token." });
}
console.log("Decoded Token:", decoded);
const user = await User.findOne({ email: decoded.email }).select("-password");
if (!user) return res.status(404).json({ message: "User not found" });
const { new_password } = req.body;
const hashpass = await bcrypt.hash(new_password, 10);
const updatedUser = await User.findOneAndUpdate(
{ email: decoded.email },
{ $set: { password: hashpass } },
{ new: true }
);
if (updatedUser) {
return res.json({ success: true, message: "Password updated successfully." });
} else {
return res.status(500).json({ success: false, message: "Internal server error." });
}
} catch (err) {
console.error(err);
return res.status(500).json({ message: "Server error." });
}
}
}
module.exports = authContorller;