简体   繁体   English

无法使用'roles'包向meteor用户添加角色

[英]unable to add roles to user with meteor using 'roles' package

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. 我正在尝试使用Atmosphere上提供的“角色”包但我无法使用Accounts.onCreateUser(),我可以在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 /server/users.js

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

/client/page.js /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");
    }
  }
});

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): 如果您查看Roles包中使用的代码,您将看到他们使用您传入的user / userId对用户的集合执行查询( 此处 ,从第〜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. 由于在将用户对象插入集合之前调用onCreateUserdocs将返回的文档直接插入到Meteor.users集合中 ),因此Roles在执行查询时无法找到它。

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. 如果你看一下Roles包,他们的所有例子都会显示出来。 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. 所以基本上只需插入用户然后添加权限。

To add things to a user document after it has been inserted by the accounts package, try this pattern. 要在accounts包插入用户文档后将其添加到用户文档,请尝试此模式。 Note, you must meteor add random in order to generate a userId , which is safe to do in this context. 注意,你必须使用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;
});

I don't understand how to integrate Roles.addUsersToRoles with the onCreateUser function called when a user is created. 我不明白如何将Roles.addUsersToRoles与创建用户时调用的onCreateUser函数集成。 It doesn't work when it's called within OnCreateUser as you've done, as you've found. 正如您所发现的那样,当您在OnCreateUser中调用它时,它不起作用。 But the example case of calling addUsersToRoles within a user creation loop doesn't seem applicable to the normal use case of a new user creating an account. 但是在用户创建循环中调用addUsersToRoles的示例情况似乎不适用于创建帐户的新用户的正常用例。

Instead, I just do: 相反,我只是这样做:

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

The accepted answer forces you to write boilerplate code for login logic given by meteor through accounts-ui/password. 接受的答案强制您编写由meteor通过accounts-ui / password给出的登录逻辑的样板代码。 The other answers make assumptions about the underlying implementation and the timeout solution introduces a race condition. 其他答案对底层实现做出假设,超时解决方案引入竞争条件。

Why not do this: 为什么不这样做:

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

You effectively add the role after whatever it is that triggered the onCreateUser call and use alanning's api to add to roles. 您可以在触发onCreateUser调用的任何内容之后有效地添加角色并使用alanning的api添加到角色。 (Tested with meteor 1.0, roles 1.2.13) (测试流星1.0,角色1.2.13)

The issue here really comes down to looking for a post create user hook (which onCreateUser is not). 这里的问题实际上归结为寻找post create用户钩子( onCreateUser不是)。

It turns out, such a thing exists! 事实证明,存在这样的事情! It's called the postSignUpHook . 它被称为postSignUpHook

https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options

I found this from this SO answer: 我从这个答案中找到了这个:

https://stackoverflow.com/a/34114000/3221576 https://stackoverflow.com/a/34114000/3221576

This is the preferred method for adding roles to a user created with the boilerplate UserAccounts package (ie if you're not rolling your own with Accounts.createUser ). 这是向使用样板UserAccounts包创建的用户添加角色的首选方法(即,如果您不使用Accounts.createUser滚动自己的角色)。

UPDATE UPDATE

Ultimately I ended up using matb33:collection-hooks as per this comment: 最终我最终使用matb33:collection-hooks根据这个评论:

https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601 https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601

Just stick that code in your Meteor.startup and things work as expected. 只需将该代码粘贴在Meteor.startup中即可按预期工作。

I didn't want to rewrite logic given by Meteor's accounts packages, set the ID myself, or use setTimeout. 我不想重写Meteor的帐户包给出的逻辑,自己设置ID,或者使用setTimeout。

Instead I have Tracker code watching the Meteor.user() call, which returns the user if logged in and null if not. 相反,我有跟踪器代码观察Meteor.user()调用,如果登录则返回用户,否则返回null。

So, effectively, once a user has logged in, this code will check to see if they've been assigned a role and if they haven't add them. 因此,实际上,一旦用户登录,此代码将检查他们是否已被分配角色以及他们是否未添加角色。

I did have to use a Meteor method because I don't want roles to be messed with client side, but you can change that. 我确实必须使用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);
  },
});

I way I found to do this and it's pretty simple. 我的方式我发现这样做,这很简单。

I am passing role as an array, so I used [role] 我作为一个数组传递角色,所以我用[角色]

On client-side, when the user signs up: 在客户端,当用户注册时:

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

In our meteor methods (I am using lodash intersect method to verify the role I want user to choose) 在我们的流星方法中(我使用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');
      }
    }
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM