Невозможно установить заголовки после их отправки клиенту в контроллере аутентификации Node.js (Express) и почтовой программе Node - PullRequest
0 голосов
/ 15 декабря 2018

Я пытаюсь отправить подтверждение по электронной почте, когда пользователь зарегистрируется.Интересен тот факт, что когда я нажимаю кнопку регистрации, она работает, создает пользователя и переходит на страницу, на которой он должен перемещаться.Но он не отправляет подтверждение по электронной почте и в командной строке показывает следующую ошибку: Невозможно установить заголовки после их отправки клиенту

Вот код:

Контроллер аутентификации

 module.exports = {
      async CreateUser(req, res) {
        const schema = Joi.object().keys({
          username: Joi.string()
            .min(4)
            .max(10)
            .required(),
          email: Joi.string()
            .email()
            .required(),
          password: Joi.string()
            .min(5)
            .required(),
        });

        const { error, value } = Joi.validate(req.body, schema);
        if (error && error.details) {
          return res.status(HttpStatus.BAD_REQUEST).json({ msg: error.details })
        }

        const userEmail = await User.findOne({
          email: Helpers.lowerCase(req.body.email)
        });
        if (userEmail) {
          return res
            .status(HttpStatus.CONFLICT)
            .json({ message: 'Email already exist' });
        }

        const userName = await User.findOne({
          username: Helpers.firstUpper(req.body.username)
        });
        if (userName) {
          return res
            .status(HttpStatus.CONFLICT)
            .json({ message: 'Username already exist' });
        }

        return bcrypt.hash(value.password, 10, (err, hash) => {
          if (err) {
            return res
              .status(HttpStatus.BAD_REQUEST)
              .json({ message: 'Error hashing password' });
          }

          const age = moment().diff(moment([value.byear, value.bmonth - 1, value.bday]), 'years');
          const body = {
            username: Helpers.firstUpper(value.username),
            email: Helpers.lowerCase(value.email),
            password: hash,
          };
          User.create(body)
            .then(user => {
              const token = jwt.sign({ data: user }, dbConfig.secret, {
                expiresIn: '5h'
              });
              res.cookie('auth', token);
              res
                .status(HttpStatus.CREATED)
                .json({ message: 'User created successfully', user, token });
                var emailtoken = new emailToken({ _userId: user._id, emailtoken: crypto.randomBytes(16).toString('hex') });
                emailtoken.save(function (err) {
                    if (err) { return res.status(500).send({ msg: err.message }); }
                    var transporter = nodemailer.createTransport({
                        service: 'Sendgrid',
                        auth: { api_key:'api key is here' }
                    });
                    var mailOptions = {
                        from: 'email@email.com',
                        to: user.email, subject: 'Account Verification Token',
                        text: 'Hello,\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + emailtoken.emailtoken
                    }

                    transporter.sendMail(mailOptions, function (err) {
                        if (err) { return res.status(500).send({ msg: err.message }); }
                        res.status(HttpStatus.CREATED).json({ message: 'User created successfully', user, emailtoken }); // or you can send another response as you like here
                    })          
                })
            })
            .catch(err => {
                res
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .json({ message: 'Error occured' });
            });
          });
        },

      async LoginUser(req, res) {
        if (!req.body.username || !req.body.password) {
          return res
            .status(HttpStatus.INTERNAL_SERVER_ERROR)
            .json({ message: 'No empty fields allowed' });
        }

        await User.findOne({ username: Helpers.firstUpper(req.body.username) })
          .then(user => {
            if (!user) {
              return res
                .status(HttpStatus.NOT_FOUND)
                .json({ message: 'Username not found' });
            }

        return bcrypt.compare(req.body.password, user.password).then(result => {
          if (!result) {
            return res
              .status(HttpStatus.INTERNAL_SERVER_ERROR)
              .json({ message: 'Password is incorrect' });
          }
          if (!user.isVerified)
          return res
          .status(HttpStatus.INTERNAL_SERVER_ERROR)
          .json({ message: 'Email is not verified' });


          const token = jwt.sign({ data: user }, dbConfig.secret, {
            expiresIn: '5h'
          });
          res.cookie('auth', token);
          return res
            .status(HttpStatus.OK)
            .json({ message: 'Login successful', user, token });
        });
      })
      .catch(err => {
        return res
          .status(HttpStatus.INTERNAL_SERVER_ERROR)
          .json({ message: 'Error occured' });
      });
  }
};

модель пользователя:

const userSchema = mongoose.Schema({
  username: { type: String },
  email: { type: String },
  isVerified: { type: Boolean, default: false },
  password: { type: String },

модель токена электронной почты

const tokenSchema = new mongoose.Schema({
    _userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
    emailtoken: { type: String, required: true },
    createdAt: { type: Date, required: true, default: Date.now, expires: 43200 }
});

module.exports = mongoose.model('emailToken', tokenSchema);

В соответствии с командной строкой, где-то здесь, в контроллере аутентификации, должно быть что-то не так:

  var transporter = nodemailer.createTransport({
                            service: 'Sendgrid',
                            auth: { api_key:'api key is here' }
                        });
                        var mailOptions = {
                            from: 'email@email.com',
                            to: user.email, subject: 'Account Verification Token',
                            text: 'Hello,\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + emailtoken.emailtoken
                        }

                        transporter.sendMail(mailOptions, function (err) {
                            if (err) { return res.status(500).send({ msg: err.message }); }
                            res.status(HttpStatus.CREATED).json({ message: 'User created successfully', user, emailtoken }); // or you can send another response as you like here
                        })          
                    })
                })

Также во внешнем интерфейсе я использую Angular.Что случилось?Почему он не отправляет электронное письмо и выдает эту странную ошибку?

...