9

我想知道是否有人愿意提供一个流星垫或代码示例,以在 Meteor 中正确使用上面列出的方法之一(使用铁:路由器)。我很难理解这些方法究竟是如何与我的应用程序交互的,而且这些方法似乎足够新,以至于没有太多关于如何正确使用它们的好的文档。谢谢!

http://docs.meteor.com/#/full/Accounts-onResetPasswordLink

4

4 回答 4

15

好的,所以我将在这里发布我最终学习和做的事情,以便其他人可以将其用作参考。我也会尽力解释正在发生的事情。

从其他评论中可以看出,传递给 Accounts.on****Link 回调的“完成”函数是让我绊倒的主要部分。这个函数只做一件事——重新启用自动登录。值得注意的是,“完成”功能/自动登录是核心“帐户”包之一的一部分,不能修改。'autoLogin' 用于一种特殊情况:用户 A 尝试在用户 B 当前登录的计算机上重置他或她的密码。如果用户 A 在提交新密码之前退出重置密码流程,则用户 B 将保持登录状态in. 如果用户 A 完成重置密码流程,则用户 B 将注销,用户 A 会登录。

在 accounts-ui 包中用于处理“完成”的模式,以及我最终所做的,将“完成”分配给一个变量,然后可以将其传递给您的模板事件处理函数,并在您的重置密码逻辑完成后运行. 此变量分配需要在 Accounts.on****Link 回调中完成,但回调可以放置在任何顶级客户端代码中(只需确保正确分配变量的范围)。我只是把它放在我的 reset_password_template.js 文件的开头(到目前为止,我只这样做是为了重置密码,但模式应该是相似的):

客户端/reset_password_template.js:

// set done as a variable to pass
var doneCallback;

Accounts.onResetPasswordLink(function(token, done) {
  Session.set('resetPasswordToken', token);  // pull token and place in a session variable, so it can be accessed later 
  doneCallback = done;  // Assigning to variable
});

使用这些 on****Link 回调的另一个挑战是了解您的应用如何“知道”回调已被触发,以及应用需要做什么。由于 iron:router 与 Meteor 紧密集成,很容易忘记它是一个单独的包。重要的是要记住,这些回调是为独立于 Iron:router 而编写的。这意味着当单击发送到您的电子邮件的链接时,您的应用程序将在根级别 ('/') 加载。

***旁注 - StackOverflow 上还有其他一些答案,它们提供了与 Iron:router 集成的方法,并为每个链接加载特定路由。对我来说,这些模式的问题是它们看起来有点老套,不符合“流星”的方式。更重要的是,如果核心 Meteor 团队决定改变这些注册链接的路径,这些路径就会中断。我尝试调用 Router.go('path'); 在 on****Link 回调中,但由于某种原因,这在 Chrome 和 Safari 中不起作用。我很想有一种方法来处理这些电子邮件链接中的每一个的特定路由,从而消除不断设置和清除会话变量的需要,但我想不出一个好的解决方案。

无论如何,正如@stubailo 在他的回答中描述的那样,您的应用程序已加载(在根级别),并触发了回调。触发回调后,您就设置了会话变量。您可以使用此会话变量使用以下模式在根级别加载适当的模板:

client/home.html(或您的登录页面模板)

{{#unless resetPasswordToken}}
  {{> home_template}}
{{else}}
  {{> reset_password_template}}
{{/unless}}

有了这个,你需要在你的 reset_password_template.js 文件和 home.js 中处理一些事情:

客户端/home.js

// checks if the 'resetPasswordToken' session variable is set and returns helper to home template
Template.home.helpers({
  resetPasswordToken: function() {
    return Session.get('resetPasswordToken');
  }
});

客户端/reset_password_template.js

// if you have links in your template that navigate to other parts of your app, you need to reset your session variable before navigating away, you also need to call the doneCallback to re-enable autoLogin
Template.reset_password_template.rendered = function() {
  var sessionReset = function() {
    Session.set('resetPasswordToken', '');
    if (doneCallback) {
      doneCallback();
    }    
  }

  $("#link-1").click(function() {
    sessionReset();
  });

  $('#link2').click(function() {
    sessionReset();
  });
}

Template.reset_password_template.events({
  'submit #reset-password-form': function(e) {
    e.preventDefault();

    var new_password = $(e.target).find('#new-password').val(), confirm_password = $(e.target).find('#confirm-password').val();

    // Validate passwords
    if (isNotEmpty(new_password) && areValidPasswords(new_password, confirm_password)) {
      Accounts.resetPassword(Session.get('resetPasswordToken'), new_password, function(error) {
        if (error) {
          if (error.message === 'Token expired [403]') {
            Session.set('alert', 'Sorry, this link has expired.');
          } else {
            Session.set('alert', 'Sorry, there was a problem resetting your password.');          
          }
        } else {
          Session.set('alert', 'Your password has been changed.');  // This doesn't show. Display on next page
          Session.set('resetPasswordToken', '');
          // Call done before navigating away from here
          if (doneCallback) {
            doneCallback();
          }
          Router.go('web-app');
        }
      });
    }

    return false;
  }
});

希望这对尝试构建自己的自定义身份验证表单的其他人有所帮助。其他答案中提到的软件包在许多情况下都很棒,但有时您需要通过软件包无法获得的额外自定义。

于 2015-01-13T13:54:43.763 回答
6

我写了这个方法,所以希望我可以举一个很好的例子来说明如何使用它。

它旨在与Accounts.sendResetPasswordEmailAccounts.resetPasswordhttp://docs.meteor.com/#/full/accounts_sendresetpasswordemailhttp://docs.meteor.com/#/full/accounts_resetpassword)结合使用。

基本上,假设您想实现自己的帐户 UI 系统,而不是使用accounts-ui包或类似的。如果你想拥有一个密码重置系统,你需要三件事:

  1. 一种使用密码重置链接发送电子邮件的方法
  2. 一种了解用户何时单击重置链接的方法
  3. 一种实际重置密码的方法

以下是流程的工作方式:

  1. 用户单击您页面上的“重置密码”链接
  2. 您找出是哪个用户(可能通过让他们输入他们的电子邮件地址),然后致电Accounts.sendResetPasswordEmail
  3. 用户点击刚刚收到的电子邮件中的重置密码链接
  4. 您的应用程序已加载并注册回调Accounts.onResetPasswordLink
  5. 调用回调是因为 URL 中有一个带有密码重置令牌的特殊片段
  6. 此回调可以显示一个特殊的 UI 元素,要求用户输入他们的新密码
  7. Accounts.resetPassword应用程序使用令牌和新密码调用
  8. 现在用户已登录并且他们有一个新密码

这有点复杂,因为它是可能的最先进和自定义的流程。如果您不想弄乱所有这些回调和方法,我建议您使用现有的帐户 UI 包之一,例如accounts-uihttps://atmospherejs.com/ian/accounts-ui-bootstrap-3

对于一些示例代码,请查看accounts-ui包的代码:https ://github.com/meteor/meteor/blob/devel/packages/accounts-ui-unstyled/login_buttons_dialogs.js

于 2015-01-12T18:59:35.787 回答
1

根据文档:

您可以使用以下函数构建您自己的用户界面,或使用 accounts-ui 包来包含用于基于密码登录的交钥匙用户界面。

因此,这些回调用于滚动您自己的自定义解决方案。但是,我建议使用以下软件包之一,而accounts-entry是我的首选解决方案:

于 2015-01-12T18:41:34.957 回答
0

这个问题已经过去一年了,但我刚刚提出了同样的问题。按照您的解决方案,我发现您可以使用Session路由器中的变量和onAfterAction钩子来实现相同的目的,但使用路由:

Router.route('/', {
  name: 'homepage',
  action: function() {
    if (Session.get('resetPasswordToken')) {
      this.redirect('resetPassword', {token: Session.get('resetPasswordToken')});
    } else {
      this.render('home');
    }
  }
});

Router.route('/password/reset/:token', {
  name: 'resetPassword',
  action: function () {
    this.render('resetPassword');
  },
  data: function() {
    return {token: this.params.token};
  },
  onAfterAction: function () {
    Session.set('resetPasswordToken', '');
  }
});

当然,您还需要:

Accounts.onResetPasswordLink(function(token, done){
  Session.set('resetPasswordToken', token);
  doneResetPassword = done;
});
于 2016-02-20T17:04:45.217 回答