unable to add roles to user with meteor using 'roles' package

user1627990 picture user1627990 · Mar 26, 2014 · Viewed 8.8k times · Source

I'm trying to use the 'roles' package available on Atmosphere but I can't get it to work with Accounts.onCreateUser(), I can get the example on github. When I register a user, I want to add a role to them, when I test whether the role is assigned, it's not picking it up.

Here's my code

/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");
    }
  }
});

Answer

Firo picture Firo · Mar 26, 2014

If you look at the code being used in the Roles package you will see that they use your passed in user/userId to perform a query on the user's collection (here, starting at line ~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})
  }
}

Since onCreateUser is called before the user object is inserted into the collection (docs: The returned document is inserted directly into the Meteor.users collection), Roles cannot find it when it performs the query.

In order to fix this you must wait until the user is inserted into the collection. If you look at the Roles package all of their examples show this. Like here, (second example, comments added), along with many others:

// 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);
}

Hope that shines some light on your issue. So basically just insert the user and then add the permissions after.