Meteor: How to assign different roles to users during sign up process
Asked Answered
Z

4

7

I am using the meteor package ian:accounts-ui-bootstrap-3 for accounts and alanning:roles for assigning roles.

On the sign up form I have two options one for Doctor and one for Advisor. I want to assign the selected option as a role to that user. Can someone let me know how to do this?

I have just started learning meteor and don't know much about its flow. I can assign roles to a user if I create the user manually like this:

var adminUser = Meteor.users.findOne({roles:{$in:["admin"]}});

if(!adminUser){

    adminUser = Accounts.createUser({
      email: "[email protected]",
      password: "admin",
      profile: { name: "admin" }
    });
    Roles.addUsersToRoles(adminUser, [ROLES.Admin]);
 }

But I want to assign a roll automatically as a user signs up and select one of the options and that option should be assigned as his role.

Zitella answered 27/5, 2015 at 12:42 Comment(1)
just a word about using profile. it seems like it's not a good idea: see "Dont use profile" in guide.meteor.com/accounts.htmlDieselelectric
W
5

You shouldn't need a hack for this. Instead of using Accounts.onCreateUser you can do it with the following hook on the Meteor.users collection. Something along the lines of the following should work:

Meteor.users.after.insert(function (userId, doc) {
    if (doc.profile.type === "doctor") {
        Roles.addUsersToRoles(doc._id, [ROLES.Doctor])
    } else if (doc.profile.type === "advisor") {
        Roles.addUsersToRoles(doc._id, [ROLES.Advisor])
    }
});
Watthour answered 4/11, 2015 at 12:2 Comment(1)
Maybe important to note that you need meteor add matb33:collection-hooks for this.Joyejoyful
G
1

To get around having to check on login every time it's possible to directly set the roles on the user object instead of using the Roles API.

A hack? Yep, you probably need to make sure the roles have already been added to roles... not sure if there's anything else yet.

if(Meteor.isServer){
  Accounts.onCreateUser(function(options, user){
    if(options.roles){
      _.set(user, 'roles.__global_roles__', ['coach', options.roles]);
    }
    return user;
  });
}

Note: _.set is a lodash method not in underscorejs.

There's no pretty solution because:

  1. There's no server side meteor callback post complete account creation.
    • In onCreateUser the user hasn't been added to the collection.
    • Accounts.createUser's callback is currently only for use on the client. A method could then be used from that callback but it would be insecure to rely on it.
  2. The roles package seems to grab the user from the collection and in onCreateUser it's not there yet.
Glassworks answered 8/9, 2015 at 22:5 Comment(0)
Z
-1

you can use the Accounts.onCreateUser hook to manage that.

Please keep in mind the code below is fairly insecure and you would probably want to do more checking beforehand, otherwise anyone can assign themselves admin. (from docs):

options may come from an untrusted client so make sure to validate any values you read from it.

Accounts.onCreateUser(function (options, user) {
  user.profile = options.profile || {};
  if (_.has(options, 'role')) {
    Roles.addUserToRoles(user._id, options.role);
  }
  return user;
});
Zymolysis answered 27/5, 2015 at 12:51 Comment(2)
thanks for your help. I tried your code but i am not getting 'role' in 'options'. I did console.log(options) and there was no roles field there and that might be reason it is not adding roles. On mongo when i do "db.users.find()" its also not showing roles field. But when i used "Accounts.onLogin" as i share my code below its working perfect. But i want it to work on "Accounts.onCreateUser".Zitella
Roles.addUserToRoles will not work in onCreateUser because the new user has not been added to the Meteor.users collection yet, even though there's a user._id that will be used to do so.Glassworks
Z
-1

Thanks for your response. I tried but it doesn't work for me.

I used Accounts.onLogin hook to to manage this. Below code works for me:

Accounts.onLogin(function (info) {
    var user = info.user;
    if(user.profile.type === "doctor"){
      Roles.addUsersToRoles(user, [ROLES.Doctor])
    }
    else 
      if(user.profile.type === "advisor"){
        Roles.addUsersToRoles(user, [ROLES.Advisor])
        }
    return user;
  });
Zitella answered 27/5, 2015 at 14:9 Comment(2)
This is pretty inefficient because you're doing at least one additional database query per login. What was the issue with @corvid's answer?Resolute
Yes, you are right. I tried @corvid's code but don't know why that didn't work for me. After running his code i was not getting any roles assigned to user.Zitella

© 2022 - 2024 — McMap. All rights reserved.