Loopback: How to get all users belong to a specific role?

Created on 16 Jun 2014  路  13Comments  路  Source: strongloop/loopback

What I would like to accomplish is: get all users with the role of 'admin', is there an easier way to do this in loopback?

bug

All 13 comments

app.models.role.findOne({where: {name: 'admin'}, function(err, adminRole) {
  adminRole.users(function(err, users) {
    ...
  });
});

Well, the following code doesn't work

adminRole.users(function(err, users) {
    ...
  });

I changed the code to the following and then get it working correctly.

User.getAdminUsers = function(callback) {
  Role.findOne({where: {name: 'admin'}}, function(err, adminRole) {

    if(adminRole) {
      console.log(adminRole);
      RoleMapping.find({where: {roleId: this.id,
        principalType: RoleMapping.USER}}, function (err, mappings) {
        if (err) {
          callback && callback(err);
          //return;
        }
        var users = mappings.map(function (m) {
          return m.principalId;
        });

        console.log(users);
        callback(null, users);
      });

      /*adminRole.users(function(err, users) {
        if(users) {
          console.log(users);
          callback(null, users);
        } else {
          console.log(err);
          callback(err);
        }
      });*/
    } else {
      console.log(err);
      callback(err);
    }
  });

Actually I am working on a project created via slc lb project myapp, so there is a new roleMapping in the models.json file which extends the RoleMapping model.

Still for your own code I cannot get anything back for the users. and here is the code I tracked down in the node-inspector

// Set up the connection to users/applications/roles once the model
Role.once('dataSourceAttached', function () {
  var roleMappingModel = this.RoleMapping || loopback.getModelByType(RoleMapping);
  Role.prototype.users = function (callback) {
    roleMappingModel.find({where: {roleId: this.id,
      principalType: RoleMapping.USER}}, function (err, mappings) {
      if (err) {
        callback && callback(err);
        return;
      }
      return mappings.map(function (m) {
        return m.principalId;
      });
    });
  };

I guess this issue (#274) might be able to answer why your code doesn't work for me, by the way, I am also using MongoDB as my data source.

Any update on this issue?

Seems there are several open issues with roles not correctly being included with users. The way I ended up making this work was:

server/boot/role-mapping.js

module.exports = function(app) {

  var RoleMapping = app.models.RoleMapping;
  /**
   * Get user ID's by role name
   * @param role
   * @param callback
   */
  RoleMapping.usersIDByRole = function(role, callback){

    RoleMapping.app.models.Role.byName(role, function(err, role){

      if( err || !role ) return callback(err);

      RoleMapping.find({
        where: {
          roleId: role.id,
          principalType: RoleMapping.USER
        }
      }, function(err, mappings){

        if( err ) return callback(err);

        var users = mappings.map(function (m) {
          return m.principalId;
        });

        callback(null, users);
      });

    });

  }

};

Then in my users model common/models/user.js

/**
   * Return users by role
   * @param role
   * @param callback
   */
  User.getUsersByRole = function(role, callback) {

    User.app.models.RoleMapping.usersIDByRole(role, function(err, users) {

      if( err || !users ) return callback(err);

      User.find({
        where : {
          _id : {inq : users}
        }
      }, callback);
    });
  };

@mneil Thanks, your solution is working fine. However in RoleMapping.app.models.Role.byName, the function byName is saying undefined. Hence, I have modified the above portion as follows
RoleMapping.app.models.Role.findOne({where: {name:role}}, function(err, role){ // ... });

Ah yes, sorry @hilarudeensa I didn't define that function in my example.

In ./server/boot/role.js

module.exports = function(app) {

  var Role = app.models.Role;

  /**
   * Get a role by name
   * @param name
   */
  Role.byName = function(name, callback){

    Role.findOne({where: {name: name}}, callback);
  }
}

I also added slightly better error checking to the above examples as I found that it was throwing an exception if I searched for a role that didn't exist. In my case the role should always exist but I have tests for if it doesn't and they were failing without better error checking.

Are you guys still running into issues? Can I close this?

I think you should close this issue. It's related to https://github.com/strongloop/loopback/issues/1441. I was just suggesting a workaround that I used. A couple of the suggestions about coercing the id to a mongo ObjectId in the issue I just linked to really is a better solution though.

@mneil Thanks for the response. Closing.

Please open a new issue if you guys are still running into problems.

Please note that the adminRole.users method used in @raymondfeng's solution is currently broken. I've submitted a simple fix in PR #2742.

Was this page helpful?
0 / 5 - 0 ratings