rbactl

0.1.0 • Public • Published

rbactl

build coverage version downloads license

rbactl is an easy to use and intuitive role-based access control library for Express apps. The library embraces the unopinionated and minimalist approach of express and can also be used with other frameworks built on top of express. Your app decides how to store and retrieve roles (plus permissions) and the authentication logic. The library only comes in to simplify the process of building your authorization logic.

Repo : GitLab | GitHub

Installation

Use one of the two based on your project's dependency manager.

$ npm install rbactl --save
 
$ yarn add rbactl

Getting started

  1. Install the library.

  2. Define application permissions.

    Permissions can be defined in a single file or directory with each entity having its own file. This does not prevent you from defining it on an object on the fly.

  3. Define application policies.

    Policies can be defined in a single file or directory with each entity having its own file. This does not prevent you from defining it on an object on the fly.

  4. Add or update user and role models.

    The role model should have a property that stores permissions (an array). A relationship should exist such that a user can have many roles and a role can have many users. The user model should have a property or a function that returns the user's list of permissions based on their roles.

  5. Add or update user and role control logic.

    This will allow management of roles and users on the application. It should achieve at least the following:

    • Creation of roles
    • Setting of role permissions
    • Setting of user roles
  6. Add user sign up / creation logic

    This will allow for creation of user accounts.

  7. Create your authentication middleware.

    Ideally, once the middleware identifies the user it should add the user object to the req object.

  8. Create your authorization middleware creator.

    This will take an action and entity and return a middleware function that authorizes the action against the user permissions and system policies.

  9. Apply both the authentication and authorization middleware as required on your routes.

  10. Consider defining an authorization check method, can, on your user model.

    This can prove convenient if you still need to perform an authorization check without necessarily doing it at the routing level.

Quick start

Define permissions
const { parsePermissions } = require('rbactl');
 
const permissions = parsePermissions({
  article: {
    '*': 'Full articles access',
    view: 'View articles',
    create: 'Create articles',
    update: 'Update articles',
    delete: 'Delete articles',
  },
  report: {
    '*': 'Full reports access',
    view: 'View reports',
    create: 'Create reports',
    update: 'Update reports',
    delete: 'Delete reports',
  },
 
  // ... more permissions ...
});

See an actual example of this; mongo or postgres.

See permissions documentation.

Define policies
const policies = {
  article: {
    view: {
      any: [
        'article.view',
        'article.create',
        'article.update',
        'article.delete',
      ],
    },
    create: 'article.create',
    update: 'article.update',
    delete: 'article.delete',
  },
 
  report: {
    view: {
      any: ['report.view', 'report.create', 'report.update', 'report.delete'],
    },
    create: 'report.create',
    update: 'report.update',
    delete: 'report.delete',
  },
 
  // ... more policies ...
};

See an actual example of this; mongo or postgres.

See policies documentation.

Define roles

Ideally, you will have a Role model that has a permissions property (array). This is just a simple static example.

const roles = [
  {
    name: 'Basic',
    permissions: ['article.view'],
  },
 
  {
    name: 'Admin',
    permissions: ['article.create', 'article.update'],
  },
 
  {
    name: 'Super Admin',
    permissions: ['article.*'],
  },
 
  // ... more roles ...
];

See an actual example of this; mongo or postgres.

Define user permissions resolver

The user model should have a relationship with the roles model. This is required to determine the permissions of a user.

const User = {
  // ... other user model logic and properties
 
  /**
   * The definition of this function is down to your persistence
   * system.
   *
   * @returns {Array} 
   */
  getPermissions() {
    let permissions = [];
 
    this.roles.forEach((role) => {
      permissions = permissions.concat(role.permissions);
    });
 
    return permissions;
  },
 
  // ... other user model logic and properties
};

See an actual example of this; mongo or postgres.

Define authentication middleware

This is a tiny snippet of the authorization middleware. It only shows the success case where the user object is added to the req express object.

const authenticate = async (req, res, next) => {
  // other authentication logic
 
  // make user object available to the next handlers
  req.user = authUserObject;
  next();
 
  // other authentication logic
};

See an actual example of this; mongo or postgres.

Define authorization middleware - can
const { createCan } = require('rbactl');
 
const can = createCan(
  // the system policies
  policies,
 
  // user permissions resolver
  async (req) => req.user.getPermissions(),
 
  // unauthorized request handler
  (req, res) => {
    return res.status(403).json({
      message: `You are not authorized to perform this action.`,
    });
  },
 
  // authorization exception handler
  (req, res) => {
    return res.status(500).json({
      message: 'Sorry :( Something bad happened.',
    });
  },
);

See an actual example of this; mongo or postgres.

See authorization documentation.

Protect endpoints
// assuming we have our simple app ...
const app = express();
 
app.get('/article/', authenticate, can('view', 'article'), () => {
  // user is allowed to view list of articles
});
 
app.post('/article/', authenticate, can('create', 'article'), () => {
  // user is allowed to create article
});
 
// ... the same pattern applies for other routes

See an actual example of this; mongo or postgres.

Complete examples

To wrap your head around the entire process carefully go through one or both examples:

These may still not make everything crystal clear. Go through the documentation to understand all key concepts.

Licence

MIT © Mutai Mwiti | GitHub | GitLab

DISCLAIMER: All opinions expressed in this repository are mine and do not reflect any company or organisation I'm involved with.

Package Sidebar

Install

npm i rbactl

Weekly Downloads

1

Version

0.1.0

License

MIT

Unpacked Size

96.4 kB

Total Files

51

Last publish

Collaborators

  • mutaimwiti