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

xpolicy

v0.3.1

Published

Fine-grained access control policy and enforcement for modern applications

Downloads

16

Readme

XPolicy

CI Coverage Status Dependencies License

Fine-grained access control policy and enforcement for modern applications.

XPolicy implements the flexible attribute-based access control model, which encompasses most access control paradigms. The wide range of rules allows you to define and enforce extremely specific policies.

Table of Contents

Quick start

# Install with NPM
npm install xpolicy

# Install with Yarn
yarn add xpolicy
const xp = require('xpolicy');
const { GreaterOrEq, Less, In, StartsWith } = xp.rules;

// Define a policy to enforce.
const policy = new xp.Policy({
  id: 1,
  description: `Allow users and creators to view, like, and comment
    on public videos if their account age is between 0 and 365`,
  effect: xp.effects.Allow,
  subject: {
    username: Any(),
    role: In(['user', 'creator']),
  },
  action: In(['view', 'like', 'comment']),
  resource: StartsWith('videos/public'),
  context: {
    accountAge: And(GreaterOrEq(0), Less(365)),
  },
});

// Create an enforcer and add the policy to it.
const enforcer = new xp.Enforcer();
enforcer.addPolicy(policy);

// Define a desired operation.
const operation = new xp.Operation({
  subject: { username: 'cat', role: 'user' },
  action: 'like',
  resource: 'videos/public/cat-montage',
  context: { accountAge: 101 },
});

// Enforcer will determine whether the operation is allowed
// according to the defined policies.
console.log(enforcer.isAllowed(operation));
// true

Policy

A policy is a set of rules that you want to enforce. You can create and add multiple policies to be enforced.

It contains the following attributes:

| Attribute | Description | | ------------- | ----------------------------------------------------------------------------------------------------- | | id | Required: A unique identifier of the policy. | | description | Optional: A helpful description of the policy. | | subject | Optional: The allowed entity. Can either be a rule or object. | | action | Optional: The allowed action. Can either be a rule or object. | | resource | Optional: The allowed resource. Can either be a rule or object. | | context | Optional: The allowed context. Can either be a rule or object. | | effect | Required: The result if the conditions are met.Can either be effects.Allow or effects.Deny. |

Here is an example policy:

const policy = new xp.Policy({
  id: 1,
  description: `Allow an admin to create, read, update, and delete
    any resource except for permissions if their IP is 0.0.0.0.`,
  subject: Eq('admin'),
  action: In('create', 'read', 'update', 'delete'),
  resource: And(Any(), NotEq('permissions')),
  context: { ip: Eq('0.0.0.0') },
  effect: xp.effects.Allow,
});

See the rules section for more information about composing complex rules.

Enforcer

An enforcer enforces the given policies by deciding whether a desired activity adheres to the policies. Enforcer exposes two methods:

enforcer.addPolicy(yourPolicy)

  • Adds a Policy object to the enforcer. When later authorizing an operation,

enforcer.isAllowed(yourOperation)

  • Returns a boolean of whether the Operation object is allowed based on the enforced policies.

Here is an example usage of enforcer:

const enforcer = new xp.Enforcer();
enforcer.addPolicy(yourPolicy);
enforcer.addPolicy(anotherPolicy);

enforcer.isAllowed(attemptedOperation);

Operation

An operation is an attempted activity that needs to be authorized by the rules defined by one or more policies.

To do this, you construct a new Operation object and check it by calling enforcer.isAllowed(operation). The enforcer will return a boolean value dictating whether the given operation is allowed according to the policies.

Here is an example operation:

const operation = new xp.Operation({
  subject: 'user0',
  action: 'view',
  resource: 'video',
  context: { location: 'USA' },
});

Note that all the properties are optional. However, if the policy contains a property, the corresponding property must be present on the operation, or else it will be rejected.

For example, if the policy contains subject, then the operation must also contain subject, or else it is automatically rejected.

Rules

Rules allow you to impose conditions on the attributes of a desired operation. You can use rules on the subject, action, resource, and context of an operation.

The rules are exposed in the xp.rules object, which contains all of the below rules. For ease of use, you should destructure xp.rules and expose the rules you want to use:

const { Any, Eq, In, Greater, Contains } = xp.rules;

// Now you can call the function directly:
Any();
Greater(10);

Rules can be applied directly or within an object:

// The subject itself has to equal "admin".
subject: Eq('admin');
// The subject has to be an object with a "role" attribute
// that equals "admin".
subject: {
  role: Eq('admin');
}

Both are valid syntaxes and are be enforced accordingly. The choice depends on your use case and desired fidelity of control.

Constant rules

Constant rules always result in the same outcome.

| Rule | Description | Valid Example | | -------- | --------------------- | ----------------------------- | | Any() | Always allow any data | "cats"Any() | | None() | Always deny any data | Nothing will satisfy None() |

* Note that None() does not have much practical use.

Composition rules

Composition rules allow you to combine and modify other rules to form more complex rules.

| Rule | Description | | ----------- | ------------------------------- | | And(a, b) | Both a and b must be true. | | Or(a, b) | Either a or b must be true. | | Not(a) | a must not be true. |

Relational rules

Relational rules allow you to compare pieces of data.

| Rule | Description | Valid Example | | ---------------- | ---------------------------------------------------- | -------------------------- | | Eq(d) | Must strictly equal d | 202Eq(202) | | NotEq(d) | Must strictly not equal d | 200NotEq(300) | | Greater(n) | Must be a number and be greater than n | 201Greater(200) | | Less(n) | Must be a number and be less than n | 200Less(201) | | GreaterOrEq(n) | Must be a number and be greater than or equal to n | 200GreaterOrEq(200) | | LessOrEq(n) | Must be a number and be less than or equal to n | 200LessOrEq(200) |

Array rules

Array rules allow you to compare arrays with elements and arrays with arrays.

| Rule | Description | Valid Example | | ---------- | ----------------------------------------------------- | -------------------------------------- | | In(a) | Must satisfy an element of array a | "zz"In(["yy", "zz"]) | | NotIn(a) | Must not satisfy an element of array a | "ww"NotIn(["yy", "zz"]) | | AllIn(a) | All input elements must satisfy elements of array a | ["zz", "yy"]AllIn(["yy", "zz"]) |

These array rules can be extremely powerful—they not only compare literals to literals but also literals to rules:

In([
  'admin',
  StartsWith('user'), // You can match a rule!
  { firstName: NotEq('hacker') }, // You can match an object with a rule!
]);

In the above In rule, all the following inputs would satisfy it: admin, user123, { firstName: 'goodperson' }.

String rules

String rules allow you to match a subset of a string with another string.

| Rule | Description | Valid Example | | --------------- | ----------------------------- | ----------------------------- | | StartsWith(s) | Must start with the value s | "yolo"StartsWith("yo") | | EndsWith(s) | Must end with the value s | "yolo"EndsWith("lo") | | Contains(s) | Must contain the value s | "yolo"Contains("ol") |