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 🙏

© 2024 – Pkg Stats / Ryan Hefner

voters

v0.1.0

Published

An Access Control Voters module for JS, inspired by Symfony2 Voters (http://symfony.com/doc/current/cookbook/security/voters_data_permission.html)

Downloads

5

Readme

Voters.js

Minimalistic JS implementation of Symfony2 Voters mechanism.

Build Status

Installation

$ npm install voters

What is it?

Voters are simple mechanism which allows you to manage users permissions inside code.

...but we have ACL...

Access Control Lists (e.g. node_acl) are great way of managing user's permissions. However in many cases may be a little bit overwhelming. Their work involves creating roles which are assigned to answer for resources. These roles are assigned to users, which allows you to check whether an individual can perform a particular action. As you can see, there is a lot of relations. It's not huge issue if you have limited number of roles, but may be if your roles depends on resources.

Imagine a simple blog system, where every authenticated user can post a message that is visible to anyone (even anonymous users). In other words, we have 3 roles:

  • USER
  • GUEST
  • ADMINISTRATOR

and 1 resource: MESSAGE.

Now imagine, that users are allowed to remove messages written by them. That's where problem starts to get a little bit tricky. To achieve this with ACL, you need to create special role for every message, i.e. MESSAGE_AUTHOR_#ID (ID is message id), which will allow user to perform deletion only on this message. Ofcourse to achieve this, you still need to create new resource just for thi message, e.g. MESSAGE_#ID. Than you have 3 + n roles, and 1 + n resources (where n is number of messages). It starts to look bad right?

Let's make it even worse! now imagine that authenticated users can post comments to messages, which can be deleted by their authors and parent message author. In this case you have roles:

  • USER
  • GUEST
  • ADMINISTRATOR
  • MESSAGE_AUTHOR_#ID * n (n = number of messages)
  • COMMENT_AUTHOR_#ID * k (k = number of comments)

And resources:

  • MESSAGE
  • COMMENT
  • MESSAGE_#ID * n
  • COMMENT_#ID * k

So it grows bigger and bigger. What is more, some of this relations are hardly cachable, as you have to update them (i.e. you have to add relations between message author and newly added mesasge comments). Now imagine how it grows in your database. Depending on databse engine (MongoDB, SQL etc.) it will probably couse performance issues at some stage ^1. What is more, in most cases it's all duplicated data, as you probably store comment/message author within its entity.

Voters to the rescue!

Voter's allows you to replace this huge amount of data, with simple conditions. It's much simple to write:

return message.author == user ? ALLOW : DENY

isn't it?

Usage

var myCustomVoter = ...; //your voter, more in "Voter creation"

var Voters = require('Voters');
var security = new Voters();
security.registerVoter(myCustomVoter);

//check permissions
security.isAllowed(user, message, 'DELETE', function(err, decision) {
	if(decision) {
    	messages.delete(message);
    }
});

You can register as many voters as you want. If there is more then one voter that supports given permission and resource, decision from voter with higher priority will be given (at least for now, check TODO). However if it cannot make a clear decision (returns Voter.DECISION.ABSTAIN), proccess moves to next voter. Voters priority is determined by order in which they were registered.

Voter creation

Voters are small objects, that encapsulates logic needed to determine if user has permission to given action on resource. It must implements methods:

  • vote: function (user, resource, permission, function(err, decision) ) - determines if user has permission to perform action on resource. Decision should be one of values:

    • Voters.DECISION.ACCESS_GRANTED - allow user
    • Voters.DECISION.ACCESS_DENIED - deny user
    • Voters.DECISION.ACCESS_ABSTAIN - can't make decision

    Arguments:

    	user {Mixed} 
    	resource {Mixed} 
    	permission {Mixed} 
        cb {Function} callback called after decision making
  • supportsResource: function (resource) - return true if Voter supports given resource, false if not

    Arguments:

    	resource {Mixed} resource passed to vote() method
  • supportsPermission: function (permission) - should return boolean value whever Voter can decide about given permission

    Arguments:

        permission {Mixed} permission passed to vote() method

API Doc

You can find complete Api doc here!

To do

  • move from callbacks (everyone knows why) to Promises.
  • implement all strategies defined in Symfony 2. For now, Voters.js uses only "Affirmative" strategy.
  • ready-for-use Voter for node_acl integration with Voters.js