mongoose-rbac

Role-based access control for mongoose apps.

mongoose-rbac

Role-based access control for mongoose apps.

npm install mongoose-rbac --save

mongoose-rbac gives you the building blocks to lock down your app with role-based access control and gets out of your way.

Generally, you will want to do the following:

  1. Create a Permission for each action you desire to control. A Permission consists of a subject and an action.
  2. Create a Role for each role you wish to assign. A Role only requires a unique name.
  3. Assign the desired set of permissions to each role.
  4. Use the mongoose-rbac plugin in your user schema.

Following is a typical example. Let's imagine we are managing a blog with users, preferences, posts and comments. First, we will define our permissions and roles:

// permissions.js 
 
var rbac = require('mongoose-rbac')
  , Permission = rbac.Permission
  , Role = rbac.Role
  , permissions;
 
permissions = [
    { subject: 'Post', action: 'create' }
  , { subject: 'Post', action: 'read' }
  , { subject: 'Post', action: 'update' }
  , { subject: 'Post', action: 'delete' }
  , { subject: 'Comment', action: 'create' }
  , { subject: 'Comment', action: 'read' }
  , { subject: 'Comment', action: 'update' }
  , { subject: 'Comment', action: 'delete' }
  , { subject: 'Preference', action: 'create' }
  , { subject: 'Preference', action: 'read' }
  , { subject: 'Preference', action: 'update' }
  , { subject: 'Preference', action: 'delete' }
];
 
Permission.create(permissions, function (err) {
  var perms, admin, developer, readonly;
 
  perms = Array.prototype.slice.call(arguments, 1);
 
  admin = new Role({ name: 'admin' });
  admin.permissions = perms;
  admin.save(function (erradmin) {
    developer = new Role({ name: 'developer' });
    developer.permissions = perms.slice(0, 7);
    developer.save(function (errdeveloper) {
      readonly = new Role({ name: 'readonly' });
      readonly.permissions = [perms[1], perms[5], perms[9]];
      readonly.save(function (errreadonly) {
        // ... 
      });
    });
  });
});

Alternatively we can use init to easily bootstrap roles and permissions:

// permissions.js 
 
var rbac = require('mongoose-rbac');
 
rbac.init({
  admin: [
    ['create', 'Post'],
    ['read', 'Post'],
    ['update', 'Post'],
    ['delete', 'Post']
  ],
  readonly: [
    // we can also specify permissions as an object 
    { action: 'read', subject: 'Post' }
  ]
}, function (erradminreadonly) {
  console.log(admin);
  /*
    { __v: 1,
      name: 'admin',
      _id: 513c14dbc90000d10100004e,
      permissions: [ 513c14dbc90000d101000044,
        513c14dbc90000d101000045,
        513c14dbc90000d101000046,
        513c14dbc90000d101000047 ] }
  */
  console.log(readonly);
  /*
    { __v: 1,
      name: 'readonly',
      _id: 513c14dbc90000d10100004f,
      permissions: [ 513c14dbc90000d101000045 ] }
  */
});

Next, we will enhance our user model with the mongoose-rbac plugin:

// user.js 
 
var mongoose = require('mongoose')
  , rbac = require('mongoose-rbac')
  , UserSchema
  , User;
 
UserSchema = mongoose.Schema({
  username: String,
  passwordHash: String
});
 
UserSchema.plugin(rbac.plugin);
 
module.exports = mongoose.model('User', UserSchema);

Finally, we can assign roles to our users and control their access to system resources:

var User = require('user')
  , user;
 
user = new User({ username: 'hercules' });
user.save();
 
user.addRole('admin', function (err) {});
 
user.hasRole('admin', function (errisAdmin) {
  console.log(isAdmin); // true 
});
 
user.can('create', 'Post', function (errcan) {
  if (can) {
    // ok 
  }
  else {
    // insufficient privileges 
  }
});
 
user.canAny([['read', 'Post'], ['create', 'Post']], function (errcanReadOrCreate) {
  if (canReadOrCreate) {
    // ok 
  }
  else {
    // insufficient privileges 
  }
});
 
user.removeRole('admin', function (err) {});

Check if the model has the given role.

  • role String or Role
  • callback(err, bool) Function

Add the given role to the model.

  • role String or Role
  • callback(err) Function

Remove the given role from the model.

  • role String or Role
  • callback(err) Function

Check if the model has the given permisison.

  • action String
  • subject String
  • callback(err, bool) Function

Check if the model has any of the given permissions.

  • actionsAndSubjects Array (of [String, String])
  • callback(err, bool) Function

Check if the model has all of the given permissions.

  • actionsAndSubjects Array (of [String, String])
  • callback(err, bool) Function

To run the tests, clone the repository and install the dev dependencies:

git clone git://github.com/bryandragon/mongoose-rbac.git
cd mongoose-rbac && npm install
make test

MIT