无法使用“角色”包向流星添加角色
我正尝试使用Atmosphere中的'角色'包,但无法使用Accounts.onCreateUser(),我可以获得在github上的例子。当我注册一个用户时,我想向他们添加一个角色,当我测试角色是否被分配时,它不会选择它。无法使用“角色”包向流星添加角色
这里是我的代码
/server/users.js
Accounts.onCreateUser(function(options, user){
var role = ['admin'];
Roles.addUsersToRoles(user, role);
return user;
});
/client/page.js
Template.hello.events({
'click input': function() {
var loggedInUser = Meteor.user();
if (Roles.userIsInRole(loggedInUser, ['admin'])) {
console.log("Hi Admin!");
}else{
console.log("Please Log In");
}
}
});
如果你在看代码的Roles
包正在使用你将看到他们使用您传入的user/userId在用户的集合上执行查询(here,从行〜623开始):
Roles
找不到它 try {
if (Meteor.isClient) {
// On client, iterate over each user to fulfill Meteor's
// 'one update per ID' policy
_.each(users, function (user) {
Meteor.users.update({_id: user}, update)
})
} else {
// On the server we can use MongoDB's $in operator for
// better performance
Meteor.users.update(
{_id: {$in: users}},
update,
{multi: true})
}
}
由于onCreateUser
用户对象被插入到收集之前被调用。
为了解决这个问题,您必须等到用户插入到集合中。如果你看看Roles
包,他们的所有例子都显示了这一点。像here,(第二个例子中,添加注释),与许多人一起:
// insert user and retrieve the id
id = Accounts.createUser({
email: user.email,
password: "apple1",
profile: { name: user.name }
});
// now we can verify that the user was inserted and add permissions
if (user.roles.length > 0) {
Roles.addUsersToRoles(id, user.roles);
}
。希望照在你的问题的一些情况。所以基本上只需插入用户,然后添加权限。
我不明白如何将Roles.addUsersToRoles与创建用户时调用的onCreateUser函数进行集成。正如你所做的那样,它在OnCreateUser中被调用时不起作用,就像你找到的那样。但是在用户创建循环中调用addUsersToRoles的示例大多不适用于创建帐户的新用户的正常用例。
相反,我只是做:
Accounts.onCreateUser(function(options, user){
var role = ['admin'];
user.roles = role
return user;
});
要的东西添加到用户的文档已经插入由accounts
包后,尝试这种模式。请注意,您必须输入meteor add random
才能生成userId
,在此情况下这是安全的。
Accounts.onCreateUser(function (options, user) {
// Semantics for adding things to users after the user document has been inserted
var userId = user._id = Random.id();
var handle = Meteor.users.find({_id: userId}, {fields: {_id: 1}}).observe({
added: function() {
Roles.addUsersToRoles(userId, ['admin']);
handle.stop();
handle = null;
}
});
// In case the document is never inserted
Meteor.setTimeout(function() {
if (handle) {
handle.stop();
}
}, 30000);
return user;
});
这比'user.roles = ['admin']'还好,比如dojomouse的答案是什么? – Dan
@dojomouse的答案对“allaning:roles”的工作原理做了假设。如果他们不将角色存储在一个字符串数组中,会怎么样?如果其他一些代码修改角色呢?如果你更新'roles'并且增加了一种方法来做到这一点呢?在对dojomouse解决方案的评论中,你实际上似乎是一个例子,如果你直接修改这个数组,你会100%破坏一些东西。这样,你可以保证只要'addUsersToRoles'不会改变,你就不会去别的东西。 – DoctorPangloss
这比Joe的答案要复杂得多,它不需要手动设置用户ID,添加另一个不必要的依赖关系,或者尽可能多的代码行,尽管它为可能需要的更复杂的功能提供了一个整齐的观察者模式onCreateUser。 –
接受的答案迫使你写通过账户的UI /密码,由流星给出登录逻辑样板代码。 其他答案对基础实现做出了假设,超时解决方案引入了竞争条件。
为什么不能做到这一点:
Accounts.onCreateUser(function(options, user) {
...
Meteor.setTimeout(function() {
Roles.addUsersToRoles(user._id, roles, group);
},0);
...
});
您有效地添加的角色后,不管它是什么触发了onCreateUser通话,并使用alanning的API添加到角色。 (用流星1.0测试,角色1.2。13)
我不想重写Meteor的帐户包提供的逻辑,自己设置ID,或者使用setTimeout。
相反,我有跟踪代码看着Meteor.user()
调用,它返回用户如果登录,如果不是,则返回null。
因此,有效的是,一旦用户登录,此代码将检查是否已分配角色,以及是否未添加角色。
我确实必须使用Meteor方法,因为我不想让角色与客户端混淆,但是您可以更改它。
/* client */
Tracker.autorun(function() {
var user = Meteor.user();
if (user && !Roles.getRolesForUser(user).length) {
Meteor.call('addUserRole', user);
}
});
/* server */
Meteor.methods({
addUserRole: function (user) {
Roles.addUsersToRoles(user, user.profile.edmodo.type);
},
});
我的方式我发现要做到这一点,这很简单。
我传递作用的阵列,所以就用[作用]
在客户端中,当用户注册:
var role = $(event.target).find('#role').val();
/*
* Add account - Client-Side
*/
Accounts.createUser(account, (error) => {
if (error) {
console.log(error);
} else {
// server-side call to add the user to the role
// notice Meteor.userId() and [role]
Meteor.call('assignUserToRole', Meteor.userId(), [role]);
// everything went well, redirect to home
FlowRouter.go('home');
}
});
在我们的流星的方法(我使用lodash相交方法来验证我希望用户选择的角色)
Meteor.methods({
// when a account is created make sure we limit the roles
assignUserToRole: (userId, roles) => {
check(userId, String);
check(roles, Array);
var allowedRoles = ['student', 'parent', 'teacher'];
if (_.intersection(allowedRoles, roles).length > 0) {
Roles.addUsersToRoles(userId, roles, 'user');
} else {
Roles.addUsersToRoles(userId, ['student'], 'user');
}
}
});
这里的问题其实就是要寻找一个后创建用户挂机(其中onCreateUser
不是)。
事实证明,这样的事情存在!它被称为postSignUpHook
。
https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options
我发现这个从这个苏答案:
https://stackoverflow.com/a/34114000/3221576
这是添加角色与样板UserAccounts包创建的用户(即,如果你不是首选方法用Accounts.createUser
滚动你自己)。
UPDATE
最后,我结束了使用matb33:收集钩按本评论:
https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601
只要坚持这些代码在你的Meteor.startup和工作的事情如预期。
这就是我正在寻找的解决方案! – kroe
优秀的答案。我以前见过这个问题,并愿意接受建议。也许只是在文档中特别提到这一点? – alanning
@alanning谢谢!是的,这可能会引起一些混乱。我个人建议在文档中添加一些内容。即使只是在气氛页面上的* client *部分之后添加备注,也可能会捕获这些情况中的一部分。否则,希望人们会开始找到与其相关的SO帖子。 – Firo
更新的文档:https://atmosphere.meteor.com/package/roles – alanning