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

@spacl/core

v1.2.1

Published

Simple path-based access control.

Downloads

4

Readme

@spacl/core

npm version pipeline status coverage status standard-js

Simple path-based access control.

Installation

npm install @spacl/core

Additional Packages

This package contains only the core implementation; while it can be used standalone it was intended to be paired with one or more of the following companion packages:

Documentation

API documentation is available here.

Introduction

SPACL policies provide a declarative method of granting users permission to perform specific actions on specific paths within a hierarchy. A policy is made up of one or more rules, each of which declares a set of allowed and/or denied actions for a single path specification.

import { Rule, Policy } from '@spacl/core'

/* Create a policy describing a standard user who can
   view other user's profiles, and edit their own. */
const user = Policy.for('user',
  Rule.for('/user/+').allow('get'),
  Rule.for('/user/:name').allow('put'))

/* Create a derived policy describing an admin user who
   can also create, edit and delete any user's profile,
   but for safety reasons, cannot delete themselves. */
const admin = user.clone('admin').push(
  Rule.for('/user/+').allow('put', 'post', 'delete'),
  Rule.for('/user/:name').deny('delete'))

These policies can then be queried to see what access they grant for a particular combination of path, action, and optional query context, e.g. user name associated with the request). The response to a query can be true (explicitly allowed), false (explicitly denied) or null (implicitly denied; not governed by this policy).

/* Query context for our hypothetical user, 'foo'. */
const ctx = { name: 'foo' }

/* What can 'foo' access if they are granted 'user' rights? */
user.query('/user/foo', 'get',    ctx) /* true; explicitly allowed */
user.query('/user/foo', 'put',    ctx) /* true; explicitly allowed */
user.query('/user/foo', 'delete', ctx) /* null; implicitly denied */
user.query('/user/bar', 'get',    ctx) /* true; explicitly allowed */
user.query('/user/bar', 'put',    ctx) /* null; implicitly denied */
user.query('/user/bar', 'delete', ctx) /* null; implicitly denied */

/* Alternatively, what if 'foo' is granted 'admin' rights? */
admin.query('/user/foo', 'get',    ctx) /* true; explicitly allowed */
admin.query('/user/foo', 'put',    ctx) /* true; explicitly allowed */
admin.query('/user/foo', 'delete', ctx) /* false; explicitly denied */
admin.query('/user/bar', 'get',    ctx) /* true; explicitly allowed */
admin.query('/user/bar', 'put',    ctx) /* true; explicitly allowed */
admin.query('/user/bar', 'delete', ctx) /* true; explicitly allowed */

Path Specifications

Each rule in a policy is associated with a path specification, and will only apply to queries matching that specification. A path specification can be either an explicit, literal path, or a pattern matching multiple paths. The following substitutions can be used to represent one or more whole path segments:

  • + - Match-one wildcard; accepts exactly one path segment.
  • * - Match-many wildcard; accepts one or more path segments.
  • ++ - Match-one-or-none wildcard; accepts zero or one path segments.
  • ** - Match-many-or-none wildcard; accepts zero or more path segments.
  • :<prop> - Capture segment; accepts exactly one path segment matching the value of the named property within the current query context.

Substitutions can be combined as needed and placed anywhere within a path specification, not just at the end. Here are some basic examples:

  • /user/foo - Matches the exact path /user/foo.
  • /user/+ - Matches any path immediately under /user, e.g. /user/foo or /user/bar.
  • /user/* - Matches any path at any depth under /user, e.g. /user/foo or /user/bar/boo/baz.
  • /user/**/admin - Matches any path at any depth under /user, provided the final path segment is admin, e.g. /user/foo/admin.
  • /user/:id - Matches any path immediately under /user, provided the final path segment is equal to the value of the property id within the current query context, e.g. /user/foo given a query context of { id: 'foo' }.

Implicit Denial

Policies and rules are deny-by-default; if no rule within a policy applies to a particular combination of path and action, that combination is considered to be implicitly denied. By extension, an empty policy grants no permissions.

Explicit Denial

Policies and rules prioritise explicit denials; if multiple rules within a policy apply to a particular combination of path and action and one of them explicitly denies access that rule will override all others, regardless of their order within the policy.