Sindbad~EG File Manager

Current Path : /home/infinitibizsol/autocrm.infinitibizsol.com/controllers/
Upload File :
Current File : /home/infinitibizsol/autocrm.infinitibizsol.com/controllers/authController.js

const brcrypt = require("bcrypt");
const db = require("../models");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const nodemailer = require("nodemailer");
const { Op } = require("sequelize");
const {
  generateResetPasswordPlainTextEmail,
  generateResetPasswordHtmlEmail,
  generatePlainTextEmail,
  generateHtmlEmail,
} = require("../constants/emailTemplate");

function getTokenExpiration(token) {
  try {
    const decodedToken = jwt.decode(token);
    if (decodedToken && decodedToken.exp) {
      const expirationDate = decodedToken.exp * 1000;
      return expirationDate;
    } else {
      throw new NotFoundError("No expiration time found in token.");
    }
  } catch (error) {
    throw new CustomAPIError(error.message);
  }
}

async function doSubscriptionOnSignup(user_id) {
  // Set start_date as the current date
  const start_date = new Date();
  // Set expiration_date as one month from the current date
  const expirationDate = new Date();
  expirationDate.setMonth(expirationDate.getMonth() + 1);
  const expiration_date = expirationDate;

  const data = {
    user_id: user_id,
    auctioneer_id: 2,
    start_date: start_date,
    last_payment_date: expiration_date,
    // expiration_date: expiration_date,
  };

  await db.tblUserSubAuctioneer.create(data);
}

const loginController = async (req, res) => {
  try {
      
    let { business_email, password } = req.body;

    // Convert email to lowercase
    business_email = business_email.toLowerCase();
    let [result] = await db.tblUser.findAll({
      where: {
        business_email: business_email,
      },
    });
    // return res.json({ data: result });
    if (!result) {
      return res
        .status(404)
        .json({ status: 404, message: "Invalid Credentials." });
    }

    const isMatched = await brcrypt.compare(password, result.password);
    if (!isMatched) {
      return res
        .status(403)
        .json({ status: 403, message: "Invalid Credentials." });
    }

    let token = await jwt.sign(
      { business_email: result.business_email, user_id: result.user_id },
      process.env.JWT_KEY,
      { expiresIn: "12h" }
    );
    
    const expirationTime = getTokenExpiration(token);

    const {
      resetPasswordToken,
      password: newPassword,
      resetPasswordExpires,
      ...formattedData
    } = result.dataValues;

    return res.json({
      status: 200,
      message: "Success",
      data: [
        {
            expirationTime, 
            token,
          ...formattedData,
        },
      ],
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const signupController = async (req, res) => {
  try {
    let { business_email, password } = req.body;
    // Convert email to lowercase
    business_email = business_email.toLowerCase();

    const salt = await brcrypt.genSalt(10);
    const hashedPassword = await brcrypt.hash(password, salt);

    // Check if email already exists in the database
    let result = await db.tblUser.findAll({
      where: { business_email: business_email },
    });

    if (result.length > 0) {
      return res.status(402).json({
        status: 402,
        message: "The email address is already in use!",
      });
    }

    // Create a new user with the hashed password and lowercase email
    result = await db.tblUser.create({
      ...req.body,
      password: hashedPassword,
      business_email: business_email, // Make sure email is stored as lowercase
    });

    await doSubscriptionOnSignup(result.user_id);

    let token = await jwt.sign(
      { business_email: result.business_email, userId: result.user_id },
      process.env.JWT_KEY,
      { expiresIn: "12h" }
    );
    
    const expirationTime = getTokenExpiration(token);

    const {
      resetPasswordToken,
      password: newPassword,
      resetPasswordExpires,
      ...formattedData
    } = result.dataValues;

    return res.json({
      status: 200,
      message: "Success",
      data: [{ expirationTime,token, ...formattedData }],
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const updateUserPassword = async (req, res) => {
  try {
    let { userId, newPassword } = req.body;

    if (newPassword) {
      const salt = await brcrypt.genSalt(10);
      const encrypPassword = await brcrypt.hash(newPassword, salt);
      req.body.password = encrypPassword;
      let result = await db.tblUser.update(req.body, {
        where: { user_id: userId },
      });
      return res
        .status(200)
        .json({ status: 200, message: "password updated successfully." });
    } else {
      return res.json({ status: 400, message: "newpassword undefined" });
    }
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const validPassword = (password, storedHash) => {
  return brcrypt.compareSync(password, storedHash);
};

function getTranperter() {
  try {
    const transporter = nodemailer.createTransport({
      host: process.env.MAIL_SERVER_HOST, // Replace with your mail server host from cPanel
      port: 465, // Secure SMTP port number provided by your hosting (commonly 465 or 587)
      // secure: true, // True for 465, false for other ports
      secureConnection: true,
      debug: true,
      auth: {
        user: process.env.EMAIL_USERNAME, // The email account you created in cPanel
        pass: process.env.EMAIL_PASSWORD, // Email account password
      },
    });

    return transporter;
  } catch (error) {
    console.log(error);
  }
}
// Helper functions for password hashing
const generateHash = (password) => {
  return brcrypt.hashSync(password, brcrypt.genSaltSync(8), null);
};

const forgotPassword = async (req, res) => {
  let { business_email } = req.body;
  business_email = business_email?.toLowerCase();
  let transporter;
  if (!transporter) {
    try {
      transporter = getTranperter();
    } catch (error) {
      return res.status(500).json({
        status: 500,
        message: "Failed to send email due to internal error",
        error,
      });
    }
  }

  try {
    const user = await db.tblUser.findOne({
      where: { business_email: business_email },
    });

    if (!user) {
      return res.status(400).json({
        status: 400,
        message: "No account with that email address exists.",
      });
    }

    // user.resetPasswordToken = token;
    // user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

       // Generate token
    const token = crypto.randomBytes(20).toString("hex");
    const tokenExpier = new Date();
    tokenExpier.setMinutes(tokenExpier.getMinutes() + 15); //expires within 15 minutes

    user.resetPasswordToken = token;
    user.resetPasswordExpires = tokenExpier; // 15 mins

    await user.save();

    const emailContentPlainText = generateResetPasswordPlainTextEmail(
      token,
      "password"
    );
    const emailContentHtml = generateResetPasswordHtmlEmail(token, "password");

    const mailOptions = {
      to: user.business_email,
      from: process.env.EMAIL_USERNAME,
      subject: "Password Reset Confirmation",
      text: emailContentPlainText,
      html: emailContentHtml,
    };
    transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        return res.status(500).json({ error, info });
      }
      transporter.close();
      return res.json({
        status: 200,
        message: "Success",
        data: {
          notification: `An e-mail has been sent to ${user.business_email} with further instructions.`,
          token: token,
        },
      });
    });
  } catch (error) {
    return res.status(500).json(error.message);
  }
};

const forgotOrUpdateEmail = async (req, res) => {
  let { business_email } = req.body;
  business_email = business_email?.toLowerCase();
  let transporter;
  if (!transporter) {
    try {
      transporter = getTranperter();
    } catch (error) {
      return res.status(500).json({
        status: 500,
        message: "Failed to send email due to internal error",
        error,
      });
    }
  }
  const otp = Math.floor(1000 + Math.random() * 90000);

  const otpExpier = new Date();
  otpExpier.setMinutes(otpExpier.getMinutes() + 15); //expires within 15 minutes
  try {
    const user = await db.tblUser.findOne({
      where: { business_email: business_email },
    });

    if (!user) {
      return res.status(400).json({
        status: 400,
        message: "No account with that email address exists.",
      });
    }

    user.resetPasswordToken = otp;
    user.resetPasswordExpires = otpExpier; // 15 min timeout

    await user.save();
    const emailContentPlainText = generatePlainTextEmail(otp, "email");
    const emailContentHtml = generateHtmlEmail(otp, "email");

    // text: `Your OTP (It is expired after 1 min) : ${token}`,
    const mailOptions = {
      to: user.business_email,
      from: process.env.EMAIL_USERNAME,
      subject: "Email Reset/Update Confirmation",
      text: emailContentPlainText,
      html: emailContentHtml,
    };
    transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        return res.status(500).json({ error, info });
      }
      transporter.close();
      return res.json({
        status: 200,
        message: "Success",
        data: {
          notification: `Your OTP send to email ${user.business_email} with further instructions.`,
          otp: otp,
        },
      });
    });
  } catch (error) {
    return res.status(500).json(error.message);
  }
};

const resetPasswordViaToken = async (req, res) => {
  const { token, newPassword } = req.body;
  try {
    const user = await db.tblUser.findOne({
      where: {
        resetPasswordToken: token,
        resetPasswordExpires: { [Op.gt]: Date.now() },
      },
    });

    if (!user) {
      return res.status(400).json({
        status: 400,
        message: "Token is invalid or has expired.",
      });
    }

    user.password = generateHash(newPassword);
    user.resetPasswordToken = null;
    user.resetPasswordExpires = null;

    await user.save();
    res.status(200).json({
      status: 200,
      message: "Success! Your password has been changed.",
    });
  } catch (error) {
    res.status(500).send(error.message);
  }
};

const resetEmailViaOTP = async (req, res) => {
  const { otp, confirmEmail } = req.body;

  try {
    const user = await db.tblUser.findOne({
      where: {
        resetPasswordToken: otp,
        resetPasswordExpires: { [Op.gt]: Date.now() },
      },
    });

    if (!user) {
      return res.status(400).json({
        status: 400,
        message: "OTP is invalid or has expired.",
      });
    }

    user.business_email = confirmEmail;
    user.resetPasswordToken = null;
    user.resetPasswordExpires = null;

    await user.save();
    res.status(200).json({
      status: 200,
      message: "Success! Your email has been updated successfully.",
    });
  } catch (error) {
    res.status(500).send(error.message);
  }
};

const validateOTPOrToken = async (req, res) => {
  const { token } = req.body;
  try {
    const user = await db.tblUser.findOne({
      where: {
        resetPasswordToken: token,
        resetPasswordExpires: { [Op.gt]: Date.now() },
      },
    });

    if (!user) {
      return res.status(400).json({
        status: 400,
        message: "Token is invalid or has expired.",
      });
    }

    return res.status(200).json({
      status: 200,
      message: "Success! valid Token.",
    });
  } catch (error) {
    res.status(500).send(error.message);
  }
};

module.exports = {
  loginController,
  signupController,
  updateUserPassword,
  forgotPassword,
  resetPasswordViaToken,
  forgotOrUpdateEmail,
  resetEmailViaOTP,
  validateOTPOrToken,
};

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists