Coder Social home page Coder Social logo

seeden / rbac Goto Github PK

View Code? Open in Web Editor NEW
978.0 32.0 101.0 581 KB

Hierarchical Role Based Access Control for NodeJS

License: MIT License

JavaScript 100.00%
rbac role-based-access-control role permissions authentication auth authorization javascript

rbac's Introduction

RBAC

(Hierarchical Role Based Access Control)

NPM version build status Test coverage Gitter chat

RBAC is the authorization library for NodeJS.

๐ŸŽ‰ We have supported DynamoDB storage now by implementation of dynamoose.

Motivation

I needed hierarchical role based access control for my projects based on ExpressJS. I had one requirement. This structure must be permanently stored in various storages. For example in memory or Mongoose. Because there is a lot of options for storing of data and many of them are asynchronous. I created asynchronous API. Please, if you found any bug or you need custom API, create an issue or pull request.

Documentation

Read more about API in documentation

Support us

Star this project on GitHub.

Install

npm install rbac

Usage

import { RBAC } from 'rbac'; // ES5 var RBAC = require('rbac').default;
const rbac = new RBAC({
  roles: ['superadmin', 'admin', 'user', 'guest'],
  permissions: {
    user: ['create', 'delete'],
    password: ['change', 'forgot'],
    article: ['create'],
    rbac: ['update'],
  },
  grants: {
    guest: ['create_user', 'forgot_password'],
    user: ['change_password'],
    admin: ['user', 'delete_user', 'update_rbac'],
    superadmin: ['admin'],
  },
});

await rbac.init();

Usage with express

import express from 'express';
import { RBAC } from 'rbac';
import secure from 'rbac/controllers/express';

// your custom controller for express
function adminController(req, res, next) {
  res.send('Hello admin');
}

const app = express();
const rbac = new RBAC({
  roles: ['admin', 'user'],
});

await rbac.init();

// setup express routes
app.use('/admin', secure.hasRole(rbac, 'admin'), adminController);

Check permissions

const can = await rbac.can('admin', 'create', 'article');
if (can) {
  console.log('Admin is able create article');
}

// or you can use instance of admin role
const admin = await rbac.getRole('admin');
if (!admin) {
  return console.log('Role does not exists');
}

const can = await admin.can('create', 'article');
if (can) {
  console.log('Admin is able create article');    
}

Mongoose user model

Please take a look on plugin mongoose-hrbac

Build documentation

npm run doc

Running Tests

npm run test

Build

npm run build

Credits

License

The MIT License (MIT)

Copyright (c) 2016-2018 Zlatko Fedor [email protected]

rbac's People

Contributors

at0g avatar fnky avatar johnny-y-wang avatar markherhold avatar rajan-goswami avatar seeden avatar suntopo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rbac's Issues

Browser support?

This library is for node but we used it in browser as well.

The only issue we have is that currently library supposed to work on node@6+ and up and as result some of the code throws errors in older browsers (IE, etc) since it contains new ES6 syntax.

I think it can be configured to support browsers by few lines of code in .babelrc.
I can create PR for that

Confused about grants

Hi guys, In the sample code we have:

import RBAC from 'rbac'; // ES5 var RBAC = require('rbac').default;
const rbac = new RBAC({
  roles: ['superadmin', 'admin', 'user', 'guest'],
  permissions: {
    user: ['create', 'delete'],
    password: ['change', 'forgot'],
    article: ['create'],
    rbac: ['update']
  },
  grants: {
    guest: ['create_user', 'forgot_password'],
    user: ['change_password'],
    admin: ['user', 'delete_user', 'update_rbac'], 
    superadmin: ['admin']
  }
}, function(err, rbacInstance) {
  if (err) {
    throw err;
  }
});

So what does 'user' in admin: ['user', 'delete_user', 'update_rbac'] mean? It allows admins to create_user also, right? The following code does NOT work as I think.

rbac.can("admin", "create", "user", (err, can) => {
	if (can) {
		console.log("Granted"); // expected to have this printed out, but it's NOT
	}
});

Would you please tell me what wrong is?

`@babel/polyfill` is deprecated

During install dependencies I got such an error:

npm WARN deprecated @babel/[email protected]: ๐Ÿšจ As of Babel 7.4.0, this
npm WARN deprecated package has been deprecated in favor of directly
npm WARN deprecated including core-js/stable (to polyfill ECMAScript
npm WARN deprecated features) and regenerator-runtime/runtime
npm WARN deprecated (needed to use transpiled generator functions):
npm WARN deprecated 
npm WARN deprecated   > import "core-js/stable";
npm WARN deprecated   > import "regenerator-runtime/runtime";

a error

when use 'const rbac = new RBAC({
roles: ['admin', 'user']
}, (err, rbac) => {
if (err) throw err;
// setup express routes
app.use('/admin', secure.hasRole(rbac, 'admin'), adminController);
});'
return a reeor 'RBAC is not a constructor'?

WebError is not a constructor

When using with the Express controller, like this:

import RBAC from 'rbac'
import secure from 'rbac/controllers/express'

const rbac = new RBAC({ roles, permissions, grants }, (err, rbac) => {
  app.use('/test', secure.hasRole('admin'), (req, res) => {
    res.send({ success: true })
  })
})

Since I don't yet use any user system (don't have req.user set) I expect WebError to handle the error as as implemented in the controller.

However, I get the following error

TypeError: WebError is not a constructor
   at /home/project/node_modules/rbac/controllers/express.js:19:19
   at Layer.handle [as handle_request] (/home/project/node_modules/express/lib/router/layer.js:95:5)
   at trim_prefix (/home/project/node_modules/express/lib/router/index.js:312:13)
   at /home/project/node_modules/express/lib/router/index.js:280:7
   at Function.process_params (/home/project/node_modules/express/lib/router/index.js:330:12)
   at next (/home/project/node_modules/express/lib/router/index.js:271:10)
   at cors (/home/project/node_modules/cors/lib/index.js:179:7)
   at /home/project/node_modules/cors/lib/index.js:229:17
   at originCallback (/home/project/node_modules/cors/lib/index.js:218:15)
   at /home/project/node_modules/cors/lib/index.js:223:13
   at optionsCallback (/home/project/node_modules/cors/lib/index.js:204:9)
   at corsMiddleware (/home/project/node_modules/cors/lib/index.js:209:7)
   at Layer.handle [as handle_request] (/home/project/node_modules/express/lib/router/layer.js:95:5)
   at trim_prefix (/home/project/node_modules/express/lib/router/index.js:312:13)
   at /home/project/node_modules/express/lib/router/index.js:280:7
   at Function.process_params (/home/project/node_modules/express/lib/router/index.js:330:12)
   at next (/home/project/node_modules/express/lib/router/index.js:271:10)
   at methodOverride (/home/project/node_modules/method-override/index.js:65:14)
   at Layer.handle [as handle_request] (/home/project/node_modules/express/lib/router/layer.js:95:5)
   at trim_prefix (/home/project/node_modules/express/lib/router/index.js:312:13)
   at /home/project/node_modules/express/lib/router/index.js:280:7
   at Function.process_params (/home/project/node_modules/express/lib/router/index.js:330:12)

I use Express 4.14.0

Use of role topic

Hi. Repositories using topic role are mostly repositories for ansible roles. Using it on this repository may attract attention from wrong group.

Would you like to remove it?

role is not a GitHub featured topic, so it's use if free. I am not demanding, but just want to raise this in case it is something you were not aware and would like to change.

Error on readme example

Hi
I am trying to use this library but running the README example I get this error from the Memory storage

You can grant yourself admin

This is the setup configuration

{
        roles: ['superadmin', 'admin', 'user', 'guest'],
        permissions: {
            user: ['create', 'delete'],
            password: ['change', 'forgot'],
            article: ['create'],
            rbac: ['update']
        },
        grants: {
            guest: ['create_user', 'forgot_password'],
            user: ['change_password'],
            admin: ['user', 'delete_user', 'update_rbac'],
            superadmin: ['admin']
        }
    }

Is it a bug or an issue on my side?

I had hit also One of item is undefined which is not really easy to understand, what does it means?

Thanks!

Issue using rbac.getRole

When I use rbac.getRole, each time I get the following error.

/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/rbac/lib/base.js:19
        return cb(null, this);  
               ^
TypeError: undefined is not a function
    at Role.Base (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/rbac/lib/base.js:19:10)
    at new Role (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/rbac/lib/role.js:16:7)
    at convertToInstance (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/rbac/lib/storage/mongoose.js:44:10)
    at Promise.<anonymous> (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/rbac/lib/storage/mongoose.js:182:12)
    at Promise.<anonymous> (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
    at Promise.emit (events.js:107:17)
    at Promise.emit (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
    at Promise.fulfill (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
    at /Users/bibeksubedi/Personal/Projects/usermodule/node_modules/mongoose/lib/query.js:1400:13
    at model.Document.init (/Users/bibeksubedi/Personal/Projects/usermodule/node_modules/mongoose/lib/document.js:250:11)

My suspect is in mongoose.js at line 44, where Role constructor is called without callback.

Express example

Do you have an example of how you are using the Express controller in an application?

Thanks in advance.

Problems with tests

When running npm test:

  • mocha is not found (see #15 )
  • once mocha is installed, all tests pass on the first run
  • running npm test again causes an error from mongoose storage due to a unique key already existing... adding an appropriate before or after hook to clean the DB should fix it.

How to do RBAC with account, organization, user, membership, role structure?

Hi,

I'm implementing a new model for accounts and users in our application. We're now extending it so that users have roles in organizations ("teams)". So I might be an admin on one team and a user on another. I also see the use for having roles that are a step above all teams, where they are admins over all teams (might be called "Superadmin").

Basically what we want is a model that is modular enough so that we can cover a lot of cases.

Here's an outline of what I'm building:

        _____________
        |           |
        |  account  |
        |___________|
              |
        --------------
        |            | 
_____________     _____________     _____________
|           |     |           |     |           |
|   users   |     |   teams   | --- |   roles   |
|___________|     |___________|     |___________|
                        | 
                 ________________
                 |              |     
                 |  memberships |
                 |______________|

And then I might have these tables:

Users

name             account
----------------------------------------------------------
John             Foo
Mark             Foo
Sarah            Foo
Sam              Foo
Anna             Bar
Dom              Bar

Memberships

account          team            user          role
----------------------------------------------------------
Foo              -               John          Superadmin
Foo              Sales           Mark          Admin
Foo              Support         Mark          Admin
Foo              Sales           Sarah         User
Foo              Support         Sam           User
Bar              A               Anna          User
Bar              A               Dom           User

Roles

role             account         team          permissions
----------------------------------------------------------
Superadmin       Foo             -             ['users:create', 'users:read', 'users:remove', 'roles:create', 'roles:read']
Admin            Foo             Sales         ['users:create', 'users:read', 'users:remove', 'roles:create', 'roles:read']
User             Foo             Sales         ['users:read', 'deals:read', 'deals:create', 'deals:remove']
User             Foo             Support       ['users:read', 'tickets:read', 'tickets:create', 'tickets:remove']
User             Bar             A             ['users:read']
Admin            Bar             A             ['users:create', 'users:read', 'users:remove', 'roles:create', 'roles:read']

Can you see this kind of model working with you library?

Sorry for posting this as an issue, but maybe you can see how you can extend your library further if needed.

WebError is not a contructor

Hi,
i get this error using rbac with express

TypeError: WebError is not a constructor
    at /home/nicknaso/Desktop/pippo/node_modules/rbac/controllers/express.js:53:19
    at Layer.handle [as handle_request] (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/route.js:131:13)
    at Route.dispatch (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/layer.js:95:5)
    at /home/nicknaso/Desktop/pippo/node_modules/express/lib/router/index.js:277:22
    at Function.process_params (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/index.js:330:12)
    at next (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/index.js:271:10)
    at jsonParser (/home/nicknaso/Desktop/pippo/node_modules/body-parser/lib/types/json.js:103:7)
    at Layer.handle [as handle_request] (/home/nicknaso/Desktop/pippo/node_modules/express/lib/router/layer.js:95:5)

I checked the module internally and in the controller rbac/controllers/express.js and web-error module is imported as repoterd below:

var WebError = require('web-error');

instead in your git repo it's imported in this way:

var WebError = require('web-error').default;

I think you need to redeploy the module on npm.

Check permission but always getting false

 var rbac = new RBAC({
      roles: ["superadmin", "admin", "user", "guest"],
      permissions: {
        user: ["create", "delete"],
        password: ["change", "forgot"],
        article: ["create"],
        rbac: ["update"],
      },
      grants: {
        guest: ["create_user", "forgot_password"],
        user: ["change_password"],
        admin: ["user", "delete_user", "update_rbac"],
        superadmin: ["admin"],
      },
    });
    await rbac.init();
  let permission = await  rbac.can("admin", "create", "artical")

Get permission as always false
I don't know what is missing the above code.

License File

Can you add an official license file. Just having in readme is not sufficient

This project is alive?

I like this dependency, but I see that issues already opened without replying, the last commit in the code was last year (b863a46) and I saw an issue where they were working on version 5 since 2018 (#38). I am worried about implementing this dependency and that it is abandoned the project.

Fix eslint errors

You are using eslint for code style checking but it turns out that you have a lot of errors.

Just checkout out the project and tried npm run eslint:

โœ– 124 problems (123 errors, 1 warning)
  71 errors and 0 warnings potentially fixable with the `--fix` option.

I think code style check should report no errors and should be also executed in CI

Problem when using with express

Hi @seeden
I run the sample code,and I got an error:
TypeError: WebError is not a function

my code:

var rbac = new RBAC({
  roles: ['admin', 'user']
}, function(err, rbac)  {
  if (err) throw err;

// setup express routes
  app.use('/admin', secure.hasRole(rbac, 'admin'), adminController);
});

where is req.user.hasRole defined at?

I 'd like to use the this rbac in express, but the method hasRole in rbac/controllers/express.js
row 56 , the req.user.hasRole, I have no idea that where it define the hasRole method in req.user

req.user.hasRole(rbac, name, function(err, has) {
      if(err) {
        return next(err);
      }

Is it the callback result of passport middleware?

RBAC is not a constructor

v.5.0.3

var RBAC = require('rbac');

return

{ __esModule: true,
  RBAC: [Function: RBAC],
  Base: [Function: Base],
  Role: [Function: Role],
  Permission: [Function: Permission],
  Storage: [Function: Storage],
  Memory: [Function: Memory] }

in doc you wrote
var RBAC = require('rbac').default

Where is default key?
var RBAC = require('rbac').default
return undefined and bellow
RBAC is not a constructor

Permission.isValidName

Is it necessary to be so restrictive on the Role.isValidName method?

I'd like to dynamically create roles at run time using the UUID of a resource, but the isValidName fails due to the hyphens.

eg.

rbac.createRole(`foo-${doc.id}`, ...);

Cannot call method 'getRBAC' of undefined

Test the Usage example code of README:

var RBAC = require('rbac');

var _rbac = new RBAC();

var roles = ['superadmin', 'admin', 'user', 'guest'];
var permissions = [
    ['create', 'article'],
    ['delete', 'user']
];

_rbac.create(roles, permissions, function (err, response) {
    if (err) {
        throw err; //process error
    }

    //get admin role
    var admin = response.roles.admin;

    //get delete user permission
    var deleteUser = response.permissions.delete_user;

    //assign delete user permission to the admin
    admin.grant(deleteUser, function (err, granted) {
        if (err) throw err; //process error

        if (granted) {
            console.log('Admin can delete user');
        }
    });
});

get the following errors:

TypeError: Cannot call method 'getRBAC' of undefined
    at RBAC.grant (/Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/lib/rbac.js:72:38)
    at Role.grant (/Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/lib/role.js:23:17)
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/modules/rbac/rbac_example_0.js:21:11
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/lib/rbac.js:253:11
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:632:17
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:157:25
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:629:21
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:632:17
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:157:25
    at /Users/hezhiqiang/PhpstormProjects/console_admin_server/node_modules/rbac/node_modules/async/lib/async.js:629:21

hasRole method for an array or alternative method

Can you support one of multiple methods hasRoleOf type Array? If its a dynamic Role ID, I want to support an array so one of n number of role types. If not, can we have a lookup function that gets any number of roles and does a for loop from the database based on some type of criteria?

NodeJS support

Thanks for your open source!
Can this library support other nodeJS? Like Eggjs and not just express.

What's the storage?

It will store the data in mongodb ?
So, how to set the mongodb connecting configuration?
Can I store the data in mysql ?

Issue in getScope API

Hi Zlatko Fedor,

I have used your module in the following way (code snippet provided below) to implement role based access. I have encountered an issue in the file https://github.com/seeden/rbac/blob/master/dist/rbac.js
on line number 580. When I call the getScope API, items object is null for all other roles. I was able to use the module by replacing the old format of for loop by the new for loop
line 580 - as of today: for (var i = 0; i < items.length; i++)
line 580 - which I suggest: for(var i in items)

Request you to please review this issue and the suggested. I am trying to use this brilliant module in an application. Please let me know your response on this. Below is the code snippet of how I am using the module. Please let me know in case the usage is incorrect.

var RBAC = require('rbac');
var secure = require('rbac/controllers/express');

//create a new RBAC object
var rbac = new RBAC({
    roles        : ['superadmin', 'admin', 'user', 'guest'],
    permissions  : {
        user     : ['create', 'delete'],
        password : ['change', 'forgot'],
        article  : ['create'],
        rbac     : ['update']
    },
    grants: {
        guest: ['create_user', 'forgot_password'],
        user: ['change_password'],
        admin: ['user', 'delete_user', 'update_rbac', 'create_article'],
        superadmin: ['admin']
    }
}, function(err, rbac) {

    if(err) {
        throw err;
                                }

                app.use(function(req, res, next){
                req.user = rbac;
                req.user.getScope('admin', function(err, permissions){
                                for(var i in permissions){
                                                var containsFlag= false;
                                                if(permissions[i]==='create_article'){
                                                                containsFlag = true;
                                                                break;
                                                }
                                }
                                if(containsFlag){
                                                res.send('Hello Admin!!');
                                                }else{
                                                res.send('Access Denied!');
                                                }
                });
});
                //set up express routes
                    app.use('/admin', secure.hasRole(rbac, 'admin'), adminController);
});

In case you have any queries, please write back to me.

Thanks and Regards,
Hrishekesh

rbac.getRoles() crash

TypeError: _this6.items.reduce is not a function

Maybe this is because the type of memory.items is Object, not Array

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.