NodeJS Express сброс пароля в MVC - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь настроить маршрут сброс пароля внутри приложения моего узла, который предполагает отправку пользователю электронного письма со ссылкой для сброса пароля.

Проблема, с которой я сталкиваюсь, заключается в том, что я получаю сообщение об ошибке TypeError: cannot read property json of undefined. Насколько я понимаю, это означает, что я неправильно передаю email в свой код на стороне сервера.

У меня проблемы с поиском точного места моей ошибки. Я следовал этому примеру , однако я изменил его на более MVC-архитектуру. Это означает, что я разделил код Node на service и controller .

Вот мой код ReactJS:

    class PasswordResetComponent extends Component { 
        constructor(props){
            super(props);
            this.state = {
                email:'',
                showError:false,
                messageFromServer:''
            }
        }
        handleChange = name => event => {
            this.setState({ 
                [name]: event.target.value 
            });
        }
        sendEmail = e => {
            e.preventDefault();
            if(this.state.email == ' '){
                this.setState({
                    showError: false,
                    messageFromServer:' ',
                });
            }else{
                (async () => {
                    const rawResponse = await fetch(process.env.REACT_APP_SERVER_URI + '/user/password-reset', {
                      method: 'POST',
                      body: this.state.email
                    });
                    const response = await rawResponse.json();
                    console.log(response)
                  })();
            }
        }
        render(){
            console.log(this.state.email)
            const {email, messageFromServer, showError, showNullError} = this.state;
            return(
            <div className="container-fluid no-gutters page-login">
                <div className="row">
                    <div className="login-wrapper">
                        <form onSubmit={this.sendEmail} method="POST">
                            <div className="form-row">
                                <div className="form-group col-md-12">
                                    <input type="email" name="email" className="form-control" value={email} onChange={this.handleChange('email')} placeholder="Email" required/>
                                </div>
                            </div>
                                <button type="submit" className="btn btn-primary btn-lg btn-block">Send Confirmation</button>
                        </form>

                        <Link to="/login"><button className="mt-4 btn btn-info">Back to Login</button></Link>
                    </div>
                </div>
            </div>
            );
        }
    }

Внутри моего кода React мне удается успешно распечатать значение this.state.email, означающее, что оно должно проходить нормально. Я также получаю статус 200 по запросу.

Вот мой сервис для сброса пароля:

   exports.passwordResetService = async function(email,res, req){
      try{
        User.findOne({
          email: email
        }).then(user => {
            if( user == null){
              res.json('email not in db');
            }else{
              const token = crypto.randomBytes(20).toString('hex');
              console.log(token);
              user.update({
                resetPasswordToken: token,
                resetPasswordExpires: Date.now() + 360000,
              });

              const transporter = nodemailer.createTransport({
                  service: 'gmx',
                  host: 'mail.gmx.com',
                  port: 587,
                  secure: true,
                  auth: {
                    user: `${process.env.EMAIL_ADDRESS}`,
                    pass: `${process.env.EMAIL_PASSWORD}`,
                  },
              });

              const mailOptions = {
                from:'testaccount9909@gmx.com',
                to: `${user.email}`,
                subject: `Password Reset Email Broh'`,
                text:
                `Please click the following link to reset your account's password:`+
                `http://localhost:3003/reset/${token}\n\n`+
                `If you simply ignore the link, your password will remain unchanged!`
              }
              console.log('sending email...');
              transporter.sendMail(mailOptions, function(err, response){
                if(err){
                  console.error('there was an error: ', err);
                } else {
                  console.log('here is the resposne:', response);
                  res.status(200).json('recovery email sent');
                }
              })

            }
        }).catch(error =>
          console.log(error)
        );
      }catch(e){
        throw Error("And Error occured while resetting the password");
      }
    }

Вот мой контроллер для сброса пароля:

exports.passwordReset = async function(req, res, next){
  try{
    let passwordResetValue = await UserService.passwordResetService(req.body.email);
    return res.status(200).json({status:200, data: passwordResetValue, error:"false", message:"Password reset email has been sent!"})
  }catch(e){
    console.log(e, "Wopsie wopsie email reset error!");
    res.status(400);
  }
};

Место, где я получаю ошибку, находится внутри Сервиса , более конкретно:

    if( user == null){
      res.json('email not in db');
    }

Почему я не передаю электронную почту пользователя службе NodeJS?

1 Ответ

1 голос
/ 09 апреля 2019

Причина, по которой вы получаете cannot read property json of undefined, заключается в том, что res недоступен для passwordResetService, поскольку вы не передали его из обратного вызова маршрута и поскольку это не промежуточное ПО

Поскольку все этовы делаете с passwordResetService, сделав некоторую проверку и отправив электронное письмо, вы можете внести несколько изменений в свой код, например:

// Since you want to send the some success message, you can make a promise wrapper
// to return a promise which you can later await to get status or failure
function mailSender(mailOptions) {
  return new Promise((resolve, reject) => {
    transporter.sendMail(mailOptions, function(err, response){
      if(err){
        // could just reject(err) instead
        reject('there was an error: ', err);
      } else {
        console.log('here is the resposne:', response);
        resolve('recovery email sent');
      }
    });
  });
}

exports.passwordResetService = async function(email){
  let mailStatus;
  try{
    const user = User.findOne({ email });

    if (user === null) {
      return ({ message: "email not in db" });
    }

    const token = crypto.randomBytes(20).toString('hex');
    console.log(token);
    user.update({
      resetPasswordToken: token,
      resetPasswordExpires: Date.now() + 360000,
    });

    const transporter = nodemailer.createTransport({
      service: 'gmx',
      host: 'mail.gmx.com',
      port: 587,
      secure: true,
      auth: {
        user: `${process.env.EMAIL_ADDRESS}`,
        pass: `${process.env.EMAIL_PASSWORD}`,
      },
    });

    const mailOptions = {
      from:'testaccount9909@gmx.com',
      to: `${user.email}`,
      subject: `Password Reset Email Broh'`,
      text:
      `Please click the following link to reset your account's password:`+
      `http://localhost:3003/reset/${token}\n\n`+
      `If you simply ignore the link, your password will remain unchanged!`
    }

    console.log('sending email...');
    // wait for promise to resolve, if promise is rejected, catch block will catch the error
    mailStatus = await mailSender(mailOptions);
  } catch(e) {
    throw Error("And Error occured while resetting the password");
  }
  return mailStatus;
}
...