npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

permission-middleware

v0.0.1

Published

A simple permission middleware for Express applications.

Readme

permission-middleware Codeship Status for mkretschek/permission-middleware

NPM version Coverage Status

A simple permissions middleware for Express applications which helps you to define and organize your application's access permissions.

This will, however, make no assumptions about how to store, retrieve and associate those permissions to a given target (user, client, app, etc.).

Installation

As usual:

npm install permission-middleware --save

Usage

permission-middleware works with 3 fundamental components to handle permissions:

  • permission types: used to create permission instances (see below). Every permission type must know how to get a permission set (from the request) for the agent trying to access the URI.

  • permission instances: defines a permission, knows how to test a a request to see if the agent is allowed to access the requested resource.

  • permission sets: a set of permissions a specific agent has;

Permission types

Permission types are subclasses of the Permission class. To create a new type you may use Permission.create() or just create a new class that inherits from Permission using your inheritance method of choice.

NOTE: Permission.create() is aliased as a middleware property for easy access:

var permission = require('permission-middleware');
assert.equal(permission.create, permission.Permission.create);

It's usually a good idea to create one type for each agent that can perform actions on your system (such as users, applications, services, etc).

var Permission = require('permission-middleware').Permission;

var UserPermission = Permission.create(function (req) {
  // Return the permission set for the current user (assumes `req.user`
  // will be set already). The permission set tells which permissions the
  // user has. See more about permission sets below.
  return req.user && req.user.permissions;
});

NOTE: Permission must be subclassed as it doesn't know how to retrieve a permission set from the request.

Permission instances

They define a specific permission and how to test a request to see if the involved agents have permission to access its underlying resources.

var permissions = {
  // Code 1 and NOT allowed by default  
  CREATE:   new UserPermission(1, false),
  
  // Code 2 and allowed by default
  READ:     new UserPermission(2, true),
  
  // Code 3 and NOT allowed by default
  UPDATE:   new UserPermission(3, false),
  
  // Code 4 and NOT allowed by default
  DELETE:   new UserPermission(4, false)
};

NOTE: permission codes must be unique, i.e. you cannot have two permissions with the same code (even if they have different types).

The examples above do a very simple verification. If no verification function is provided, the middleware will just check if the permission is listed in the permission set retrieved from the request. If you need more complex permissions (i.e. checking if the user is allowed to read a specific post), you can pass a verification function when creating the permission:

permissions.Post = {
  READ:     new UserPermission(5, false, function (req) {
    var post = req.post;
    // A user can read a post if...
    return post.public ||                             // ...the post is public
      post.owner === req.user.id ||                   // ...he owns it
      post.colaborators.indexOf(req.user.id) !== -1;  // ...he contributes to it
  }),
  
  DELETE:   new UserPermission(6, false, function (req) {
    var post = req.post;
    return req.user.isAdmin || post.owner = req.user.id;
  }),
  
  ...
};

Permission sets

Permission sets define the permissions an agent has. An agent can be any entity able to perform actions on the system, such as a user, a client or application, another service, etc...

A permission set is just a map binding permission codes to a boolean indicating whether the permission is granted or not:

{
    1 : true,   // Grants the CREATE permission
    2 : false,  // Revokes the READ permission
    5 : true    // Grants the READ Post permission
}

NOTE: keep in mind that, if the user does not have a permission explicitly set in the permission set, it will get the default value for that permission (as defined by the permission instance).

The permission types should know how to retrieve those sets from the request object, extracting them from a user, application or any other agent to whom the permission is applied.

Example

Here goes a complete example of how to set permissions to read, write and delete posts from a blog. First we define the permission types:

var express = require('express');
var permission = require('permission-middleware');

var UserPermission = permission.create(function (req) {
  return req.user && req.user.permissions || {};
});

var ClientPermission = permission.create(function (req) {
  return req.client && req.client.permissions || {};
});

var PostPermission = permission.create(function (req) {
  var post = req.post;
  var user = req.user;
  
  return post && user && post.permissions[user.id] || {};
});

Then we define the permissions themselves:

var permissions = {};

// Basic user permissions
permissions.User = {
  READ:   new UserPermission(11, true),
  WRITE:  new UserPermission(12, false),
  DELETE: new UserPermission(13, false)
};


// Basic client permissions
permissions.Client = {
  READ:   new ClientPermission(21, true),
  WRITE:  new ClientPermission(22, true),
  DELETE: new ClientPermission(23, true)
};


// Slightly more complex post-specific permissions
permissions.Post = {
  READ:   new PostPermission(31, false, function (req) {
    var post = req.post;
    var user = req.user;
    
    return post && (
      (post.public && post.published) ||
      post.author === user.id ||
      post.contributors.indexOf(user.id) !== -1
    );
  }),
  
  EDIT:  new PostPermission(32, false, function (req) {
    var post = req.post;
    var user = req.user;
    return post.owner === user.id || post.contributors.indexOf(user.id);
  }),
  
  DELETE: new PostPermission(33, false, function (req) {
    var post = req.post;
    var user = req.user;
    return post && user && (post.owner === user.id || user.admin);
  })
};


// Composite permissions (combine multiple permissions)
var READ_POST = permission.all(
  permissions.Client.READ,
  permissions.User.READ,
  permissions.Post.READ
);

var CREATE_POST = permission.all(
  permissions.Client.WRITE,
  permissions.User.WRITE
);

var EDIT_POST = permission.all(
  permissions.Client.WRITE,
  permissions.User.WRITE,
  permissions.Post.EDIT
);

var DELETE_POST = permission.all(
  permissions.Client.DELETE,
  permissions.User.DELETE,
  permissions.Post.DELETE
);

Before we can use these permissions, we must define some middlewares that insert the data we need in the request, such as client, user and post data:

function setUser(req, res, next) {
  if (req.query.userId) {
    req.user = getUser(req.query.userId);
  }
  next();
}

function setClient(req, res, next) {
  if (req.header.accessToken) {
    req.client = getClient(req.header.accessToken);
    if (req.client) {
      next();
    } else {
      res.sendStatus(400); // BAD REQUEST
    }
  }
}


var app = express();

app
  .use(setClient)
  .use(setUser)
  .param('postSlug', function (req, res, next, slug) {
    req.post = getPost(slug);
    if (req.post) {
      next();
    } else {
      res.sendStatus(404); // NOT FOUND
    }
  });

And, finally, we use our permissions with the permission middleware:

app
  .post('/post', permission(CREATE_POST), function (req, res) {
    createPost(req.body);
    res.sendStatus(200);
  });
  
app.route('/post/:postSlug')
  .get(permission(READ_POST), function (req, res) {
    // At this point we know the post exists and the current user and client
    // are authorized to read it...
    res.send(req.post);
  })
  
  .put(permission(EDIT_POST), function (req, res) {
    updatePost(req.body);
    res.sendStatus(200);
  })
  
  .del(permission(DELETE_POST), function (req, res) {
    deletePost(req.post.id);
    res.sendStatus(200);
  });

Contributing

Feel free to submit pull requests for this project. It may take some days for me to review them, but I'll do that.

License

This project is released under the MIT license.