无法使用“角色”包向带有流星的用户添加角色
Posted
技术标签:
【中文标题】无法使用“角色”包向带有流星的用户添加角色【英文标题】:unable to add roles to user with meteor using 'roles' package 【发布时间】:2014-05-04 04:22:48 【问题描述】:我正在尝试使用 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");
);
【问题讨论】:
【参考方案1】:如果您查看 Roles
包中使用的代码,您会发现它们使用您传入的用户/用户 ID 对用户的集合执行查询(here,从 ~623 行开始):
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
在用户对象插入集合之前被调用(docs:返回的文档直接插入到Meteor.users集合中),Roles
找不到它当它执行查询时。
为了解决这个问题,您必须等到用户被插入到集合中。如果您查看Roles
包,他们的所有示例都显示了这一点。像here,(第二个例子,添加了cmets),还有很多其他的:
// 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);
希望对您的问题有所启发。所以基本上只是插入用户,然后添加权限。
【讨论】:
优秀的答案。我以前见过这个问题,并愿意接受建议。也许只是在文档中特别指出这一点? @alanning 谢谢!是的,这可能会引起一些混乱。我个人建议在文档中添加一些内容。即使只是在气氛页面的 client 部分之后添加注释也可能会捕获其中一些情况。否则,希望人们会开始找到与之相关的 SO 帖子。 使用accounts-ui创建的用户呢? @Dan,@DoctorPangloss 的回答让你使用onCreateUser
,这很方便。我们使用自己的自定义 Meteor 方法来创建用户,因此在我们的应用程序中,我们按照 @Firo 建议的方式进行操作。我添加了一个新函数示例,该函数直接在用户对象 here 上设置角色,但只有角色使用的 db 结构保持不变(正如 DP 在他的一个 cmets 中提到的那样),它才会起作用。跨度>
下一个版本的角色可能会采用一个标志,让您指示用户角色应该直接在用户对象上更新,以便它们可以直接在 onCreateUser 中使用。没有计划什么时候会。【参考方案2】:
我不明白如何将 Roles.addUsersToRoles 与创建用户时调用的 onCreateUser 函数集成。正如您所发现的,当您在 OnCreateUser 中调用它时,它不起作用。但是在用户创建循环中调用 addUsersToRoles 的示例似乎不适用于新用户创建帐户的正常用例。
相反,我只是这样做:
Accounts.onCreateUser(function(options, user)
var role = ['admin'];
user.roles = role
return user;
);
【讨论】:
虽然这适用于角色,但如果您同时拥有角色和组,则它不起作用。通常你会得到这样的东西:"roles" : "__global_roles__" : [ "admin" ] ,
如果'admin'
还没有在roles
集合中,这会起作用吗?这会将其添加到roles
集合中吗?【参考方案3】:
要在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 的回答有什么优势?
@dojomouse 的回答对allaning:roles
的工作方式做出了假设。如果他们不将角色存储在字符串数组中怎么办?如果其他一些代码修改了角色怎么办?如果您更新roles
并且他添加了一种方法来做到这一点怎么办?在对 dojomouse 的解决方案的评论中,您实际上似乎是一个示例,说明如果直接修改此数组,您将 100% 破坏某些东西。这样,您就可以保证,只要addUsersToRoles
没有改变,您就不会再做其他事情了。
这比 Joe 上面的回答复杂得多,它不需要手动设置用户 ID、添加另一个不必要的依赖项或尽可能多的代码行,尽管它提供了一个简洁的观察者模式发布 onCreateUser 可能需要的复杂功能。
当您需要使用组时,此答案有效。 @alanning 在评论 ***.com/questions/22649600/… 中提到的另一个选项不适用于组。【参考方案4】:
接受的答案迫使您为流星通过帐户-ui/密码给出的登录逻辑编写样板代码。 其他答案对底层实现进行了假设,超时解决方案引入了竞争条件。
为什么不这样做:
Accounts.onCreateUser(function(options, user)
...
Meteor.setTimeout(function ()
Roles.addUsersToRoles(user._id, roles, group);
,0);
...
);
您有效地添加角色在之后触发 onCreateUser 调用并使用 alanning 的 api 添加到角色。 (使用流星 1.0 测试,角色 1.2.13)
【讨论】:
这里使用setTimeout()函数有什么意义? 在onCreateUser这一点上,用户实际上并没有被创建。由于 javascript 是一个单线程进程,Meteor.setTimeout
保证其中的函数在创建用户的当前线程之后调用。
我认为Meteor.defer()
比setTimeout
和0
有一些优势,但我不能100% 确定这个优势是什么。 :)
不,Meteor.defer() 只是语法糖,仅此而已。见github.com/meteor/meteor/issues/2176【参考方案5】:
我不想重写 Meteor 的帐户包给出的逻辑,自己设置 ID,或者使用 setTimeout。
相反,我有 Tracker 代码监视 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);
,
);
【讨论】:
【参考方案6】:我发现这样做很简单。
我将角色作为数组传递,所以我使用了 [role]
在客户端,当用户注册时:
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 intersect 方法来验证我希望用户选择的角色)
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');
);
【讨论】:
【参考方案7】:这里的问题实际上归结为寻找 post 创建用户挂钩(onCreateUser
不是)。
原来,这样的东西是存在的!它被称为postSignUpHook
。
https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options
我从这个 SO 答案中找到了这个:
https://***.com/a/34114000/3221576
这是向使用样板 UserAccounts 包创建的用户添加角色的首选方法(即,如果您不使用 Accounts.createUser
滚动自己的角色)。
更新
最终我根据这条评论使用了 matb33:collection-hooks:
https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601
只需将该代码粘贴到您的 Meteor.startup 中,事情就会按预期工作。
【讨论】:
这就是我一直在寻找的解决方案!以上是关于无法使用“角色”包向带有流星的用户添加角色的主要内容,如果未能解决你的问题,请参考以下文章
使用 alanning:roles 构建流星应用程序中的角色管理