2014-03-26 214 views
12

我正尝试使用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"); 
    } 
    } 
}); 

回答

12

如果你在看代码的Roles包正在使用你将看到他们使用您传入的user/userId在用户的集合上执行查询(here,从行〜623开始):

(:返回的文档直接插入收集Meteor.users docs),当它执行查询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); 
} 

。希望照在你的问题的一些情况。所以基本上只需插入用户,然后添加权限。

+0

优秀的答案。我以前见过这个问题,并愿意接受建议。也许只是在文档中特别提到这一点? – alanning

+0

@alanning谢谢!是的,这可能会引起一些混乱。我个人建议在文档中添加一些内容。即使只是在气氛页面上的* client *部分之后添加备注,也可能会捕获这些情况中的一部分。否则,希望人们会开始找到与其相关的SO帖子。 – Firo

+0

更新的文档:https://atmosphere.meteor.com/package/roles – alanning

5

我不明白如何将Roles.addUsersToRoles与创建用户时调用的onCreateUser函数进行集成。正如你所做的那样,它在OnCreateUser中被调用时不起作用,就像你找到的那样。但是在用户创建循环中调用addUsersToRoles的示例大多不适用于创建帐户的新用户的正常用例。

相反,我只是做:

Accounts.onCreateUser(function(options, user){ 
    var role = ['admin']; 
    user.roles = role 
    return user; 
}); 
+1

虽然这适用于角色,但如果您同时拥有角色和组,则不起作用。通常情况下,你会得到这样的:' “角色”:{ \t \t “__global_roles__”: \t \t \t “管理员” \t \t] \t}, ' – d4nyll

+0

将这项工作,如果''admin''还没有在角色集合中?这会将它添加到角色集合吗? – Dan

9

要的东西添加到用户的文档已经插入由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; 
}); 
+0

这比'user.roles = ['admin']'还好,比如dojomouse的答案是什么? – Dan

+1

@dojomouse的答案对“allaning:roles”的工作原理做了假设。如果他们不将角色存储在一个字符串数组中,会怎么样?如果其他一些代码修改角色呢?如果你更新'roles'并且增加了一种方法来做到这一点呢?在对dojomouse解决方案的评论中,你实际上似乎是一个例子,如果你直接修改这个数组,你会100%破坏一些东西。这样,你可以保证只要'addUsersToRoles'不会改变,你就不会去别的东西。 – DoctorPangloss

+0

这比Joe的答案要复杂得多,它不需要手动设置用户ID,添加另一个不必要的依赖关系,或者尽可能多的代码行,尽管它为可能需要的更复杂的功能提供了一个整齐的观察者模式onCreateUser。 –

5

接受的答案迫使你写通过账户的UI /密码,由流星给出登录逻辑样板代码。 其他答案对基础实现做出了假设,超时解决方案引入了竞争条件。

为什么不能做到这一点:

Accounts.onCreateUser(function(options, user) { 
 

 
    ... 
 

 
    Meteor.setTimeout(function() { 
 
     Roles.addUsersToRoles(user._id, roles, group); 
 
    },0); 
 
    ... 
 
    
 
});

您有效地添加的角色后,不管它是什么触发了onCreateUser通话,并使用alanning的API添加到角色。 (用流星1.0测试,角色1.2。13)

+0

这里使用setTimeout()函数的相关性是什么? – jlouzado

+1

在onCreateUser的时候,用户还没有真正创建过。由于javascript是一个单线程的进程,因此'Meteor.setTimeout'保证内部函数在用户创建的当前线程之后被调用*。 – Joe

+1

我觉得'Meteor.defer()'比'setTimeout'和'0'有一些优势,但我不能100%确定它的优点。 :) – chmac

1

我不想重写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); 
    }, 
}); 
0

我的方式我发现要做到这一点,这很简单。

我传递作用的阵列,所以就用[作用]

在客户端中,当用户注册:

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'); 
     } 
    } 
    }); 
2

这里的问题其实就是要寻找一个创建用户挂机(其中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和工作的事情如预期。

+0

这就是我正在寻找的解决方案! – kroe