如何仅注册邀请?

问题描述:

使用流星帐户(和accounts-ui)是否有一种简单的方法可以仅让新用户注册邀请?例如通过提供邀请链接或邀请代码。如何仅注册邀请?

我可以在流星文档中找到的唯一相关事项是Meteor.sendEnrollmentEmail,但它不能解决我的问题。

您可以使用内置软件包来做到这一点,但我发现它更简单,更强大,可以实现简单的实现。

你需要:

  • 创建一个集合,例如UserInvitations遏制邀请成为用户。
  • 制作UserInvitations创建UI /插入使用meteor mongo
  • 使用iron-router或类似创建一个路由一些,如:

    Router.map -> 
        @route 'register', 
        path: '/register/:invitationId' 
        template: 'userRegistration' 
        data: -> 
         return { 
         invitationId: @params.invitationId 
         } 
        onBeforeAction: -> 
         if Meteor.userId()? 
         Router.go('home') 
         return 
    
  • userRegistration表单提交 - 调用

    Accounts.createUser({invitationId: Template.instance().data.invitationId /*,.. other fields */}) 
    
  • 在服务器上,使Accounts.onCreateUser挂钩从o经过invitationId ptions用户

    Accounts.onCreateUser(function(options, user){ 
        user.invitationId = options.invitationId 
        return user; 
    }); 
    
  • 此外,在服务器上做出Accounts.validateNewUser钩检查invitationId并标记邀请为使用

    Accounts.validateNewUser(function(user){ 
        check(user.invitationId, String); 
        // validate invitation 
        invitation = UserInvitations.findOne({_id: user.invitationId, used: false}); 
        if (!invitation){ 
        throw new Meteor.Error(403, "Please provide a valid invitation"); 
        } 
        // prevent the token being re-used. 
        UserInvitations.update({_id: user.invitationId, used: false}, {$set: {used: true}}); 
    
        return true 
    }); 
    

现在,只有具有有效的未使用的用户invitationId可以注册。

编辑:2014年10月 - 更新使用流星0.9.x版本的API

+0

感谢您概述此实现。我希望有一个内置的选项,但会自行实施。 – Tobold

要使用内置的东西做到这一点,你们可以一起现有Accounts.sendEnrollmentEmail下探 - 但它是一个小比给出的其他解决方案更复杂。

使用下面的示例代码,调用enroll方法,例如:

Meteor.call('enroll', 'john.smith', '[email protected]', {name: 'John Smith'}); 

然后流星会向用户发送电子邮件的链接(你可以配置Accounts.emailTemplates模板)

当他们点击链接,流星调用传递给Accounts.onEnrollmentLink的函数 - 在这种情况下,您可以将它们带到密码设置页面;但你必须用他们的done回调。

修改下面的代码,它代表INSERT XXX HERE;那么在您的代码中,如果用户取消,请致电SomeGlobalEnrollmentObjectThing.cancel();如果他们提交新的密码,请拨打SomeGlobalEnrollmentObjectThing.complete(theUsersNewPassword)

if (Meteor.isServer){ 
    Meteor.methods({ 
    "enroll": function(username, email, profile){ 
     var userId; 
     check(username, String); 
     check(email, String); // Or email validator 
     check(profile, { 
     name: String 
     }); // your own schema 

     // check that the current user is privileged (using roles package) 
     if (!Roles.isInRole(this.userId, 'admin')){ 
     throw new Meteor.Error(403); 
     } 

     userId = Accounts.createUser({ 
     username: username, 
     email: email, 
     profile: profile 
     }); 

     Accounts.sendEnrollmentEmail(userId); 

    } 
    }); 
} else { 
    // uses `underscore`, `reactive-var` and `tracker` packages 

    function Enrollment(){ 
    this.computation = null; 
    this.token = new ReactiveVar(null); 
    this.password = new ReactiveVar(null); 
    this.cancelled = new ReactiveVar(false); 
    this.done = null; 
    this._bind(); 
    } 

    _.extend(Enrollment.prototype, { 

    _bind: function(){ 
     Accounts.onEnrollmentLink(_.bind(this.action, this)); 
    }, 

    reset: function(){ 
     this.token.set(null); 
     this.password.set(null); 
     this.cancelled.set(false); 
     this.done = null; 
     if (this.computation !== null){ 
     this.computation.stop(); 
     this.computation = null; 
     } 
    }, 

    cancel: function(){ 
     this.cancelled.set(true); 
    }, 

    complete: function(password){ 
     this.password.set(password); 
    }, 

    action: function(token, done){ 
     this.reset(); 
     this.token.set(token); 
     this.done = done; 
     this.computation = Tracker.autorun(_.bind(this._computation, this)); 
     // --- INSERT REDIRECT LOGIC HERE [TAKE TO PASSWORD SETUP PAGE]--- // 
    }, 

    _computation: function(){ 
     var password; 
     if (this.cancelled.get()){ 
     this.reset(); 
     this.done(); 
     // --- INSERT REDIRECT LOGIC HERE [USER CANCELLED]--- // 
     } else { 
     password = this.password.get(); 
     if (password !== null){ 
      Accounts.resetPassword(this.token.get(), password, _.bind(this._complete, this)); 
     } 
     } 
    }, 

    _complete: function(err){ 
     // TODO - check if we were reset before callback completed 
     this.reset(); 
     this.done(); 
     if (err){ 
     // --- INSERT REDIRECT LOGIC HERE [RESET FAILED] --- // 
     } else { 
     // --- INSERT REDIRECT LOGIC HERE [SUCCESS] --- // 
     } 
    } 
    }); 

    SomeGlobalEnrollmentObjectThing = new Enrollment(); 
} 

我已经创建了一个specific solution to this,因为所有其他解决方案,只允许你明确地创建基于密码的帐户。t3db0t:accounts-invite包允许任何服务创建帐户,只要您允许它们,例如使用“接受邀请”路线。 Live demo here