【问题标题】:Loopback: Event resetPasswordRequest not called after reset环回:重置后未调用事件 resetPasswordRequest
【发布时间】:2017-03-25 15:33:42
【问题描述】:

我正在尝试利用 Loopback 上的密码重置过程,因此我可以向用户发送一封包含说明的电子邮件。我创建了一个名为“用户”的自定义模型,它扩展了“用户”。然后我添加了“User.on('resetPasswordRequest'...”,但它永远不会被执行。请检查user.js上的console.log

model-config.json

{
...

  "user": {
    "dataSource": "mysqlDs",
    "public": true,
    "options": {
      "emailVerificationRequired": false
    }
  },
...
}

user.json

{
  "name": "user",
  "base": "User",
  "idInjection": true,
  "properties": {},
  "validations": [],
  "relations": {},
  "acls": [
    {
      "principalType": "ROLE",
      "principalId": "$everyone",
      "accessType": "READ",
      "permission": "ALLOW"
    }
  ],
  "methods": []
}

user.js

module.exports = function(User) {

  console.log('It prints this log here.');

  User.on('resetPasswordRequest', function(info) {

    console.log('But it does not print this log here ever.');

    var url = 'http://www.example.com/reset-password';
    var html = 'Click <a href="' + url + '?access_token=' + info.accessToken.id + '">here</a>';
    loopback.Email.send({
      to: info.email,
      from: 'mail@example.com',
      subject: 'My Subject',
      html: html
    }, function() {
      console.log('> sending password reset email to:', info.email);
      if (err) return console.log('> error sending password reset email');
    });
  });

};

【问题讨论】:

  • 对我来说看起来不错。如何触发事件?你检查了 LoopBack user management example project 吗?重置密码流程是其中的一部分。
  • 嗨@IvanSchwarz,感谢您的帮助。这正是我最初使用的演示。我正在触发 Loopback 创建的 API 面板上的事件。 user.js 文件由 Loopback 执行,因为我可以看到第一个 console.log 在终端上打印。但是 User.on 中的 console.log 永远不会被打印出来。
  • 我刚刚克隆了loopback-getting-started repo,粘贴到你的user 文件中,调整了model-config.jsonconsole.log() 都打印了。我在想……你不是忘了把内置的User 模型隐藏在model-config.json 中吗?您可能会触发内置模型而不是扩展模型的密码重置事件。

标签: loopbackjs strongloop


【解决方案1】:

好的,所以@IvanSschwarz 是对的。非常感谢!我的初始代码是正确的,但它缺少对 model-config.json 的一个小改动:出于某种原因,我需要隐藏 User 模型。所以我也借此机会将我的模型名称从“用户”更改为“成员”,以遵循环回良好实践指南。

   ...
   "User": {
     "dataSource": "mysqlDs",
     "public": false
   },
   "member": {
     "dataSource": "mysqlDs",
     "public": true,
     "options": {
       "emailVerificationRequired": true
     }
   },
   ....

我相信其他建议也可能有效,但我想通过 JSON 扩展 User 模型,并利用来自 Users 模型的内置远程方法 Reset Password。所以谢谢你们!

【讨论】:

【解决方案2】:

这里解释了解决方案: http://loopback.io/doc/en/lb3/Extending-built-in-models.html#setting-up-a-custom-model

所以你需要:

User.setup = function() {
  var User = this;
  // since setup is called for every extended model
  // the extended model will also have the event listener
  User.on('resetPasswordRequest', function() {
    ///Do your stuff here
  });
}

【讨论】:

  • 这看起来是理想的解决方案。但是,该代码永远不会被执行。当我在 User.setup 之前放置一个 console.log 时,它会打印内容。 User.setup 中的 console.log 永远不会被打印出来。只是出于好奇,根据您的建议,完整的 user.js 文件会是什么样子?
  • 嗨@GeoffreyMureithi,我需要设置类似:var User = Model.extends('User'); ?如果是这样,模型是什么?
  • 嗯,需要 var user = Model.extends('User'); 之类的东西
  • 模型应该来自环回对象loopback.Model,并且(我认为)它应该可以通过User.app.Model访问
【解决方案3】:

您不想定义一个远程方法来调用您的代码吗? 这就是我会做的:

user.js

    module.exports = function(User) {

      console.log('It prints this log here.');

      User.resetPasswordRequest = function (info, cb) {

        console.log('But it does not print this log here ever.');

        var url = 'http://www.example.com/reset-password';
        var html = 'Click <a href="' + url + '?access_token=' + info.accessToken + '">here</a>';
        loopback.Email.send({
          to: info.email,
          from: 'mail@example.com',
          subject: 'My Subject',
          html: html
        }, function() {
          console.log('> sending password reset email to:', info.email);
          if (err) {
             cb(err, false);
             return console.log('> error sending password reset email');
          }
          cb(err, true):
        });
      });

    User.remoteMethod('resetPasswordRequest', {
            description: 'Send a mail to an User to permit him to reset his password',
            accepts: {arg: 'info', type: 'object', required: true},
            returns: {arg: 'mailSend', type: 'boolean'},
            http: {verb: 'post'}
        });

};

然后,使用资源管理器或通过 REST 调用 API,同时发布您的 info json,例如:

{
 accessToken: xxx,
 email: xxx
}

别忘了在 user.json 中更新您的 ACL,以便您可以从远程调用该方法:

{
  "name": "user",
  "base": "User",
  "idInjection": true,
  "properties": {},
  "validations": [],
  "relations": {},
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    },
    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW"
    },
    {
      "accessType": "WRITE",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW"
    },
    {
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW",
      "property": "resetPasswordRequest"
    }
  ],
  "methods": []
}

【讨论】:

  • User 基本型号上已经有一个built-in remote method 来请求密码重置。使用POST /users/reset端点应该足够了。
  • 谢谢 F3L1X79 ,但我同意@IvanSchwarz。另外,我相信您的建议中您没有发送正确的密码重置令牌。但无论如何,我尝试实现它并得到:请求 POST /api/users/resetPasswordRequest 的未处理错误:错误:共享类“用户”没有方法处理 POST /resetPasswordRequest
  • 可能是因为名称“resetPasswordRequest”受到保护。我不知道这是一种内置方法。您可能想将名称更改为另一个名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2019-02-01
  • 2018-03-17
相关资源
最近更新 更多