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

face-control

v1.1.0

Published

Intelligent access management for express.js

Downloads

22

Readme

Face Control

Codeship NPM License

Face Control is an opinionated access control middleware for Express. It is heavily inspired by authorized, but also provides a more intelligent way to perform permission checks.

Getting Started

Installation

Installing the module is fairly straightforward:

$ npm install face-control --save

Basics

In this section, I will describe basic ideas behind Face Control by giving an example of space fleet permission hierarchy.

Scope

A scope is a domain that contains various roles. For instance, a spaceship captain's ship:captain role is only valid on his ship, therefore ship is the scope and captain is the role contained in that scope.

In order to minimize the number of database round-trips, Face Control gives you an option to tie a scope to a URL parameter via a hint. For instance, when a fleet scope is requested, and URL contains :shipId parameter, it will automagically see that it can first retrieve the ship scope, then from ship.fleetId extract the fleet scope.

/* https://galactic-federation.net/ship/:shipId */

/* Teaches Face Control how to find the ship info */
FaceControl.scope('ship', { hint: 'shipId' }, async req => db.ships.find(req.params.shipId));

/* Teaches Face Control how to find fleet info from ship info */
FaceControl.scope('fleet', { hint: 'shipId', deps: 'ship' }, async req => {

  /* Since 'ship' is a dependency, it will be stored here */
  const ship = req.$fc_cache$.ship;

  /* Find the 'fleet' based on the ship */
  return db.fleets.find(ship.fleetId);

});

As you can see, hint tells Face Control to use the provided callback when there is a :shipId specified, while deps tells it that it needs to retrieve ship info before trying to find out what fleet it is from.

Of course, you can provide multiple hinted callbacks for the same scope. In that case, Face Control will find the most appropriate callback to use.

/* https://galactic-federation.net/fleet/:fleetId */

/* Teaches Face Control how to find the fleet info from :fleetId */
FaceControl.scope('fleet', { hint: 'fleetId' }, ...);

Role

A role signifies a set of actions a person is allowed to perform. Roles can be global or tied to a specific scope. It's magic, isn't it?


FaceControl.role('ship:captain', function(entity, role, request) {

  /* When the role `captain` is used without scope, it makes no sense */
  if (!entity) { throw new Error('Captain must have a ship!'); }

  /* Now, we can check if the person IS a captain */
  if (!request.user.isCaptain) { return false; }

  /* Here we can check if the user is the captain of THE ship */
  if (entity.id !== request.user.shipId) { return false; }

  /* Welcome, captain! */
  return true;

});

Action

Action is essentially a set of roles that are allowed to perform a certain action. For instance, self-destruct action should only be executed by ship:captain or fleet:admiral. So, here we go:

FaceControl.action('self-destruct', [ 'ship:captain', 'fleet:admiral' ]);

Imply

Let's say we want fleet:admiral to be able to do anything a ship:captain is able to. Writing both roles in every action makes configuration a tangled mess. Instead, you can just say 'let fleet admiral automatically have ship captain powers'!

FaceControl.imply('fleet:admiral', [ 'ship:captain' ]);

After this, when defining actions you only need to specify ship:captain, and the rest is handled for you.

Middleware

So, after going through all the trouble teaching Face Control all fine details of your permission hierarchy, putting it to use is incredibly simple:

app.use(FaceControl('ship:captain', 'hangar:technician'));

And that's it! Face Control will do the rest.

License

MIT