@spacl/core
TypeScript icon, indicating that this package has built-in type declarations

1.2.1 • Public • Published

@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.

Versions

Current Tags

VersionDownloads (Last 7 Days)Tag
1.2.11latest

Version History

VersionDownloads (Last 7 Days)Published
1.2.11
1.2.00
1.1.60
1.1.40
1.1.30
1.1.20
1.1.10
1.1.00
1.0.00

Package Sidebar

Install

npm i @spacl/core

Weekly Downloads

1

Version

1.2.1

License

ISC

Unpacked Size

26.6 kB

Total Files

15

Last publish

Collaborators

  • cptpackrat