Я создал функцию 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,
}