How to setup permissions and roles on NodeJS

At aercolino/mean-app you’ll see a partially developed NodeJS app. I’m still working on it, but I’ve recently added a permission model that works with permissions like this:

{[ .anybody_canEdit_theirStuff | 1.hilite(=javascript=) ]}

I like it because it’s quite clean and very self-documenting. I personally find it very frustrating that permissions use to be buried into code in many places and need always some computer guy to translate them into business terms.

The name / value pair above completely defines a permission. The name is not only an English description but also active code to be interpreted by the model using the value. The name is SUBJECT + ACTION + OBJECT and the value should contain descriptors for each of those parts.

Notice that the meaning of all those parts comes from their descriptors in the value. For example, there is no conventional meaning assigned to the ´canEdit´ action except for it to be matched against the action passed to the Can function. Compare with this:

{[ .anAdmin_canDo_everything | 1.hilite(=javascript=) ]}

And here are some console logs just to see how it works.

Screen Shot 2015-12-16 at 12.48.40

What do you think? 🙂


To illustrate how to use these permissions I’m going to implement a use case where a developer wants to check permissions before allowing updates to models. I’m going to only show needed changes to existing files: the complete files are in the repository on GitHub.

Load the Can function

File ´/server/start.js´: Make the permission model available to the app. The ´Can´ function returns a promise which will be resolved with the first matching permission name or ´false´.

{[ .=start.js= | 1.hilite(=javascript=) ]}

Add support for the Can function

File ´/server/app/shared/CRUD.controller.js´ (old): This is how the ´Update´ function looked like before adding a check for verifying whether the update is allowed or not.

{[ .=function Update old= | 1.hilite(=javascript=) ]}

File ´/server/app/shared/CRUD.controller.js´ (new): This is how the ´Update´ function looks like after adding a check for verifying whether the update is allowed or not.

{[ .=function Update new= | 1.hilite(=javascript=) ]}

Instead of directly calling the ´Can´ function from the ´Update´ function, I prefer to call it from an ´AllowUpdate´ method, optionally defined on the model. This solution is much more flexible because it allows to easily tell apart when a check is required and when it is not: if the ´AllowUpdate´ is defined, it will be used, otherwise the update will take place straight away. Additionally, this solution decouples the permissions functionality from the (shared) CRUD functionality, enabling the developer to allow an update or not for whatever reason, not necessarily by checking a permission.

Notice that:

  1. I had to wrap the call to ´FilterFields(…)´ (which is the updating block) into a local function so that it can be called after the check or immediately.
  2. The ´AllowUpdate´ result could be a promise or not, and ´Promise.resolve(self.AllowUpdate(item, req))´ takes care of that.
  3. The ´AllowUpdate´ arguments could be a subject and an object, i.e. a user and an item, thus mimicking the arguments for the descriptors of the permissions. I decided instead to pass the item and the request.
    1. The order is important for highlighting that this is not (necessarily) related to a permission.
    2. The request carries the session, whose current user is the big deal.
  4. The error we signal when the update is not allowed is independent from the permission model: We just say that the ´AllowUpdate´ check failed.

Call the Can function

File ´/server/app/components/users/user.controller.js (old)´: This is how the ´User´ controller looked like before adding an ´AllowUpdate´ method.

{[ .=user.controller.js old= | 1.hilite(=javascript=) ]}

Notice that if no ´AllowUpdate´ method was necessary, this code would still work perfectly well with the permission setup I’m describing here.

File ´/server/app/components/users/user.controller.js (new)´: This is how the ´User´ controller looks like after adding an ´AllowUpdate´ method.

{[ .=user.controller.js new= | 1.hilite(=javascript=) ]}

Notice how I take advantage of the resolved value to ´´ about the matching permission right here, while the ´AllowUpdate´ result is going to be taken into account from the shared CRUD controller code.


File ´/server/app/components/permissions/permissions.js´: Here is where the available permissions are listed. This is an example with all the different shapes (hopefully). Add and remove as needed.

{[ .=permissions.js= | 1.hilite(=javascript=) ]}

Here is a bunch of things to know about permissions.

  • ´Translators canTranslate DocumentsNeedingTranslation´
    • A permission name is a sentence SUBJECT + ACTION + OBJECT.
    • An action must begin with ´can´.
    • An actor is either a subject or an object.
    • Actors starting with an uppercase letter are role names.
    • Roles are defined by instances of the ´Role´ model, thus they cannot be defined in the permission value.
  • ´Translators canTranslate documentsNeedingTranslation´
    • Actors starting with a lowercase letter are item names.
    • Items must be defined by descriptors in the permission value.
    • A descriptor can be a hash with a ´model´ string and a ´restriction´ function.
    • The corresponding actor must then be an item of the given model, which also satisfies the given restriction.
    • The restriction function always gets two arguments: the subject item and the object item, in this order.
    • An underscore in the signature means that the corresponding item is not relevant. (by convention)
    • The name of an argument should always be whatever makes the most sense for self documentation.
    • Permissions can overlap with each other, like this permission overlaps with the previous one. They’re not nice, one is probably superfluous, but the permission model gets happily along with them.
  • ´anybody canEdit TheirStuff´
  • ´anybody canEdit theirStuff´
    • A descriptor can be a model string. The corresponding actor must then be an item of the given model.
    • A descriptor can contain a ´model´ RegEx. The corresponding actor must then be an item of a matching model.
    • As a policy, to keep things simple, a RegEx R (fully) matches a string S if
      • ´S.replace(R, ”) === ”´
    • The descriptor of the item ´theirStuff´ is an implementation of Duck Typing.
    • Compare the descriptor of the item ´theirStuff´ with the role ´TheirStuff´ and its setup below.
  • ´anAdmin canDo everything´
    • Actions can be defined by RegEx descriptors in the permission value.
    • A match-all RegEx for the action and the object makes this permission VERY generic.

Role and Permission Models

Role Model

File ´/server/app/components/roles/role.model.js´: This is the role model.

{[ .=role.model.js= | 1.hilite(=javascript=) ]}

Here is a bunch of things to know about the permission model.

  • The model must be a string, even when it should be a RegEx.
    • To differentiate a RegEx string from a non-RegEx string, wrap it into slashes (with optional modifiers at the end).
    • In other words, the string to use for a RegEx is its source with properly escaped backslashes.
  • If the restriction R is a JSON object, then an item I of the model M has this role if
    • ´M.count(Extend({_id: I._id}, R)) === 1´.
    • R is considered like Mongoose / MongoDB criteria.
  • If the restriction R is a non-empty string, then an item I of the model M has this role if
    • ´R(subject, object) == true´.
    • R is considered like a function name.
    • The function name can contain dots.
    • If the function name is a (static) method of an unavailable Model, it will be automatically required.
  • If the restriction R is FALSEy, then an item I of the model M has this role if
    • ´item.roles.indexOf(name) > -1´.
    • This is the case corresponding to a classical ´Role´ model, where a given role is associated to a given user by adding the role name to the user roles.
  • If the restriction R is TRUEy, then each item I of the model M has this role.
    • This role acts like an alias of the model.
    • The usefulness of this case is still unknown…

Their Stuff

Here is how the role ´TheirStuff´ I used in a permission above could be implemented.

{[ .TheirStuff | 1.hilite(=javascript=) ]}

File ´/server/app/components/users/user.model.js´: This is the user model, after adding both the instance method ´isAdmin´ the static method ´owns´ used before and right above respectively.

{[ .=User.owns= | 1.hilite(=javascript=) ]}

Permission Model

File ´/server/app/components/permissions/permission.model.js´: This is the permission model.

I’m not going to illustrate its supporting functions (peruse them here, if you like), but here is its main code.

{[ .=permission.model.js main= | 1.hilite(=javascript=) ]}

Here is a bunch of things to know about the permission model.

  • When the permission model is required the permissions list is loaded and compiled.
  • The compilation process builds a structure that the global ´Can´ function will later use.
  • A permission answers a ´Can´ question if their actions, subjects, and objects respectively match each other.
  • Permissions are selected, sorted, chained, and then all checked in turn, one after the other.
  • Sorting is based on a very rough complexity measure, detected during compilation.
  • As soon as a full match is found, the ´Can´ function immediately resolves with the permission name.
  • If no full match exists, then the ´Can´ function finally resolves with a ´false´.


How to support promised predicates in Array find

I’m building ACL support in NodeJS. For example, I’ll allow to write:

{[ .can-example | 1.hilite(=javascript=) ]}

For any given action, my ´Can´ function must check a list of permissions. If one matches, then the action ´Can´ asks for is granted, otherwise (no permission exists) it’s denied. Of course I’m only interested in the first permission to match, and to allow for optimizations, I want permissions to be checked in the order I provide.

It’s easy to see that my problem is solved by the Array.prototype.find method. The problem I have, though, is that it only works with immediate predicates, but my checks can entail both immediate and promised predicates. For example, I allow predicates to access the database.

I googled my problem and found this StackOverflow page. Bergi’s answer gives both recursive and non-recursive solutions. (Side note. There was a time when recursive was opposed to iterative. With promises, that’s no longer the case. In fact, the non-recursive solution is a chain of ´catch´ handlers. An iteration is used to build the chain but promises themselves, throwing exceptions, control the iteration.) Benjamin Gruenbaum’s answer gives a recursive solution.

Here are their issues.

  1. The predicate is hacky because it signals a ´false´ by throwing an exception.
  2. The promise management is hacky because (a) it must cater for the predicate with ´.catch()´, and (b) it signals the “not found” outcome with ´reject()´.
  3. The promise management and the predicate are very coupled.
  4. The contract is different from that of the Array.prototype.find method.

So I came up with this one.

{[ .ArrayFind | 1.hilite(=javascript=) ]}

Apart from being a global function instead of an Array instance method, the contract is exactly the same as that of the Array.prototype.find method.

  1. The only hack I used is to immediately exit when an element is found instead of continuing until the end of the ´.then()´ chain. But how I implemented it is both robust (as in Robustness) and hidden (as in Information Hiding). To make sure I do not mistake a rightful exception with my hack, I throw my own fake exception which is a wrapper around the found element. Thus, my fake exception is caught by the last ´.catch()´ and the element is returned.
  2. The predicate can be both immediate or a promise, thanks to ´Promise.resolve(Predicate…)´. If it’s immediate, it can throw an exception if it has to, not if it doesn’t hold true. If it’s a promise, it can reject() if it has to, not if it doesn’t hold true.


Here are some examples.

{[ .predicates | 1.hilite(=javascript=) ]}

The result is a promise

Here is how ArrayFind compares to Array.prototype.find when no exceptions are thrown:

VM834:3 -- 1
VM834:3 -- 13
VM834:3 -- 5
VM834:3 -- 4

ArrayFind([1,13,5,4,7], ImmediatePredicate)
VM834:3 -- 1
VM834:3 -- 13
VM834:3 -- 5
VM834:3 -- 4
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

Of course the result is a Promise instead of the found element, but we can append additional handlers, like

ArrayFind([1,13,5,4,7], ImmediatePredicate)

VM834:3 -- 1
VM834:3 -- 13
VM834:3 -- 5
VM834:3 -- 4
VM880:4 4
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

An exception makes the promise reject

Here is how ArrayFind compares to Array.prototype.find when an exception is thrown:

VM834:3 -- 1
VM834:3 -- 3
VM834:4 Uncaught dirty

ArrayFind([1,3,5,4,7], ImmediatePredicate)

VM834:3 -- 1
VM834:3 -- 3
VM925:7 dirty
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

Immediate and promised predicates work equally well

Here you can see how ArrayFind supports at the same time immediate and promised predicates:

ArrayFind([1,13,5,4,7], MixedPredicate)

VM834:3 -- 1
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
VM834:12 -- 13
VM834:3 -- 5
VM834:3 -- 4
VM955:4 4

ArrayFind([1,3,5,4,7], MixedPredicate)

VM834:3 -- 1
VM834:3 -- 3
VM974:7 dirty
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

ArrayFind([1,12,5,4,7], MixedPredicate)

VM834:3 -- 1
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
VM834:12 -- 12
VM975:7 dirty

You can’t appreciate from the output above, but the immediate predicate really outputs immediately. 🙂

Also notice that in the second to last example the warned ´dirty´ comes from the immediate predicate because 3 < 10, while in the last example it comes from the promised predicate because 12 >= 10.

How to customize MorganJS

MorganJS is easy to install and works nicely out of the box.

{[.old-setup | 1.hilite(=javascript=) ]}

Here is what it looks like. Highlighted HTTP status codes are quite useful.

Screen Shot 2015-11-08 at 14.44.07

Thankfully, it’s possible to customize MorganJS by adding tokens, which are template symbols, like this:

{[ .current-user | 1.hilite(=javascript=) ]}

which can be later used like this:

{[ .middle-setup | 1.hilite(=javascript=) ]}

to produce something like this:

Screen Shot 2015-11-08 at 14.52.16

Uh-oh!! Where are my colors?

I delve into MorganJS code…

{[ .morgan | 1.hilite(=javascript=) ]}

As you may have noticed, the above code is hard to understand and quite hard-coded too.

  • Hard-coded because, even if the ´dev´ template is documented as ´:method :url :status :response-time ms – :res[content-length]´, it’s really embedded into the code and mixed up with extraneous bits rather than being declared into some option and used like any other MorganJS template is.
  • Hard to understand because the function object is being used as a cache for its own executions which entail a compilation step whose raison d’être I still have to grasp. I could be wrong, but this one could be a clear example of over-engineering.

However my biggest disappointment was that there is no way of reusing the colored ´:status´ token nor the coloring functionality, neither directly, by calling a method, nor indirectly, by copy-pasting some code. A total fail. 🙁

Googling “terminal colors” I eventually got to this Unix StackExchange answer, which I used to write this:

{[ .color-factory | 1.hilite(=javascript=) ]}

A nice collateral about my ´ColorFactory´ function is that I can use it also in the console like this:

{[ .console-log | 1.hilite(=javascript=) ]}

to get something like this:

Screen Shot 2015-11-08 at 16.12.17

Finally, I was able to customize Morgan with this:

{[ .morgan-factory | 1.hilite(=javascript=) ]}

and use it like this:

{[ .new-setup | 1.hilite(=javascript=) ]}

to get something like this:

Screen Shot 2015-11-08 at 16.51.54