Организация функций контроллера электронной почты в приложении Mern - PullRequest
0 голосов
/ 17 апреля 2020

Я создал функцию emailController и модуль mailer отдельно для отправки электронной почты пользователю. Кроме того, я буду отправлять случайное сообщение каждый день (только если сообщений больше 10) в 9:30 каждый день с помощью node-cron.

Кроме того, receiveNewPassword выглядит как настоящий кошмар, и я хочу сделать это без обратных вызовов, но bcrypt, похоже, не любит async / await. Итак, мне нужно знать, как улучшить его рефакторинг.

Все остальное кажется нормальным?

emailController

const User = require("../models/User")
const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt")
const cron = require("node-cron")
const {
  transporter,
  getResetPasswordURL,
  resetPasswordTemplate,
  confirmationEmailTemplate,
  randomPostTemplate,
} = require("../utils/mailer")

const receiveConfirmationEmail = async (userId) => {
  try {
    const user = await User.findOne({ _id: userId })
    const emailTemplate = confirmationEmailTemplate(user)
    transporter.sendMail(emailTemplate, (err) => {
      if (err) {
        res.status(500).json({ Error: err })
      }
    })
    res.status(200).json({ info: info.response })
  } catch (err) {
    if (err) {
      console.log(err)
    }
  }
}

module.exports = {
  createOneTimeTokenAndSendMail: async (req, res) => {
    const email = req.params.email
    try {
      const user = await User.findOne({ email })
      if (!user) {
        return res.status(404).json({ error: "No user with that email" })
      }
      const hashedPassword = user.password
      const createdAt = user.createdAt
      const userId = user._id
      const secret = hashedPassword + "-" + createdAt
      const token = jwt.sign({ userId }, secret, {
        expiresIn: 60,
      })
      const url = getResetPasswordURL(user, token)
      const emailTemplate = resetPasswordTemplate(user, url)
      transporter.sendMail(emailTemplate, (err, info) => {
        if (err) {
          res.status(500).json({ error: err })
        }
        res.status(200).json({ info: info.response })
      })
    } catch (error) {
      console.log(error)
    }
  },

  receiveNewPassword: (req, res) => {
    const { userId, token } = req.params
    const password = req.body.password
    User.findOne({ _id: userId }, (err, user) => {
      if (err) console.log(err)
      const secret = user.password + "-" + user.createdAt
      const payload = jwt.decode(token, secret)
      if (payload.userId == user.id) {
        bcrypt.genSalt(10, (err, salt) => {
          if (err) console.log(err)
          bcrypt.hash(password, salt, (err, hash) => {
            if (err) console.log(err)
            User.findOneAndUpdate(
              { _id: userId },
              { password: hash },
              (err) => {
                if (err) console.log(err)
                res.status(202).json("password changed")
                receiveConfirmationEmail(userId)
              }
            )
          })
        })
      }
    })
  },

  sendRandomPost: async (req, res) => {
    try {
      const user = await User.findById(req.params.id).populate("posts")
      if (!user) console.log("no user")

      const userPosts = user.posts
      if (userPosts.length < 10) {
        console.log("Sorry, write some more posts")
      } else if (userPosts.length > 10) {
        let postsArray = userPosts.map((item) => {
          return {
            date: item.createdAt,
            title: item.title,
            description: item.description,
          }
        })
        const randomPostObject = postsArray[Math.floor(Math.random() * postsArray.length)]
        const emailTemplate = randomPostTemplate(user,randomPostObject)
        cron.schedule("30 9 * * *", () => { //send email at 9:30 in the morning everyday 
          transporter.sendMail(emailTemplate, (err, info) => {
            if (err) {
              res.json({ err })
            }
            res.json({ info: info.response })
          })
        })
      }
    } catch (error) {
      console.log(error)
    }
  }
}

почта. js

const nodemailer = require("nodemailer")
const nodemailMailGun = require("nodemailer-mailgun-transport")

const auth = {
  auth: {
    api_key: process.env.api_key,
    domain: process.env.domain,
  },
}

let transporter = nodemailer.createTransport(nodemailMailGun(auth))

const getResetPasswordURL = (user, token) => {
  return `http://localhost:3000/update-password/${user._id}/${token}`
}

const resetPasswordTemplate = (user, url) => {
  const from = process.env.EMAIL
  const to = user.email
  const subject = "PASSWORD UPDATE EMAIL"
  const text = "Reset your password"
  const html = `This is your password reset url:

  <a href=${url}>${url}</a>`

  return { from, to, subject, text, html }
}

const confirmationEmailTemplate = (user) => {
  const from = process.env.EMAIL
  const to = user.email
  const subject = "CONFIRMATION EMAIL"
  const text = "Your password has been successfully updated"

  return { from, to, subject, text }
}

const randomPostTemplate = (user, randomPostObject) => {
  const from = process.env.EMAIL
  const to = user.email
  const subject = `Good Morning, ${user.username}, we hope you are doing great`
  const html = `
      <h1>Hello, ${user.username}! These are your posts.</h1>
      <h3>${randomPostObject.title}</h3>
      <h3>${randomPostObject.description}</h3>
    `
  return { from, to, subject, html }
}

module.exports = {
  transporter,
  getResetPasswordURL,
  resetPasswordTemplate,
  confirmationEmailTemplate,
  randomPostTemplate,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...