使用Meteor帐户(和accounts-ui
)是否有一种简单的方法来仅提出新的用户注册邀请? 例如,通过提供邀请链接或邀请代码。
我在Meteor文档中找到的唯一相关内容是Meteor.sendEnrollmentEmail,但它并没有解决我的问题。
您可以使用内置程序包执行此操作,但我发现滚动简单实现更简单,更强大。
你需要:
UserInvitations
以包含成为用户的邀请。 meteor mongo
创建UI以进行UserInvitations
/插入一些 使用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
挂钩,将invitationId
从选项传递给用户
Accounts.onCreateUser(function(options, user){ user.invitationId = options.invitationId return user; });
此外,在服务器上创建Accounts.validateNewUser
挂钩以检查invitationId
并将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月 - 更新为使用meteor 0.9.x API
要使用内置的东西,您可以将现有的Accounts.sendEnrollmentEmail
连接在一起 - 但是它比给出的其他解决方案稍微复杂一些。
使用下面的示例代码,调用enroll
方法:
Meteor.call('enroll', 'john.smith', '[email protected]', {name: 'John Smith'});
然后Meteor会向用户发送一个链接(您可以使用Accounts.emailTemplates
配置模板)
当他们点击链接时,meteor调用传递给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();
}