Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

functional-acl

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

functional-acl - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

lib/express.js

36

package.json
{
"name": "functional-acl",
"version": "0.3.1",
"version": "0.4.0",
"description": "A functional implementation of access control lists (ACLs)",
"main": "index.js",
"main": "lib",
"files": [
"lib"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "babel --out-dir . src/",
"watch": "npm run build -- --watch",
"prepublish": "npm run build",
"build": "babel --out-dir lib/ src/",
"example:express": "babel-node examples/express.js",
"example:simple": "babel-node examples/index.js",
"example:express": "babel-node examples/express.js"
"lint": "eslint src/",
"prepublish": "npm run validate && npm run build",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"test": "mocha --require babel-register src/**/*.test.js",
"tdd": "npm run test -- -w",
"validate": "npm run lint && npm run test",
"watch": "npm run build -- --watch"
},

@@ -19,6 +26,19 @@ "author": "Paul 'opatut' Bienkowski <npm@opatut.de>",

"babel-cli": "^6.1.4",
"babel-eslint": "^6.0.4",
"babel-preset-es2015": "^6.1.4",
"babel-preset-stage-0": "^6.1.2",
"express": "^4.13.3"
"babel-register": "^6.9.0",
"eslint": "^2.11.1",
"eslint-config-wish-technology": "^2.3.0",
"eslint-plugin-babel": "^3.2.0",
"eslint-plugin-flow-vars": "^0.4.0",
"eslint-plugin-import": "^1.8.1",
"eslint-plugin-jsx-a11y": "^1.2.2",
"eslint-plugin-mocha": "^2.2.0",
"eslint-plugin-react": "^5.1.1",
"express": "^4.13.3",
"mocha": "^2.5.3",
"power-assert": "^1.4.1",
"semantic-release": "^4.3.5"
}
}

@@ -7,5 +7,11 @@ # Functional Access Control Lists (node-functional-acl)

> An ACL specifies which users or system processes are granted access to objects, as well as what operations are allowed on given objects. Each entry in a typical ACL specifies a subject and an operation.
> An ACL specifies which users or system processes are granted access to
> objects, as well as what operations are allowed on given objects. Each entry
> in a typical ACL specifies a subject and an operation.
Functional ACL are an implementation of this concept with functional programming. It makes heavy use of [higher-order functions](https://en.wikipedia.org/wiki/Higher-order_function) as [predicates](https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)) to model user permissions.
Functional ACL are an implementation of this concept with functional
programming. It makes heavy use of [higher-order
functions](https://en.wikipedia.org/wiki/Higher-order_function) as
[predicates](https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)) to
model user permissions.

@@ -29,3 +35,4 @@ #### What it is not

An object that describes the situation you are checking permissions for. This usually contains one or more of:
An object that describes the situation you are checking permissions for. This
usually contains one or more of:

@@ -39,3 +46,4 @@ * the acting user (*user* / *subject*)

A function that checks whether the context (or part of it) matches a certain condition. Returns true or false. Examples:
A function that checks whether the context (or part of it) matches a certain
condition. Returns true or false. Examples:

@@ -48,5 +56,12 @@ * `admins = (context) => context.user.isAdmin`

A function that returns one of `true` (allow), `false` (deny) or `null` (proceed with next rule) for a context. These rules can be easily built from predicates using the `allow(...predicates)` and `deny(...predicates)` functions. They require all predicates to match on the context for the rule to match, and then return the appropriate boolean value, or `null` if any of the predicates does not match.
A function that returns one of `true` (allow), `false` (deny) or `null`
(proceed with next rule) for a context. These rules can be easily built from
predicates using the `allow(...predicates)` and `deny(...predicates)`
functions. They require all predicates to match on the context for the rule to
match, and then return the appropriate boolean value, or `null` if any of the
predicates does not match.
Multiple rules can be combined using the `build(...rules)` function. These are then tested in order, the first rule that matches decides the result (`true` or `false`). If no rule matches, the combined rule returns `null`.
Multiple rules can be combined using the `combineRules(...rules)` function.
These are then tested in order, the first rule that matches decides the result
(`true` or `false`). If no rule matches, the combined rule returns `null`.

@@ -56,34 +71,58 @@ ## API

#### `not(predicate) => predicate`
Create a predicate that matches if the original predicate did not match.
#### `invert(rule) => rule`
Create a rule that allows if the original rule would deny, and vice versa. Does
not decide if the original rule wouldn't.
#### `always() => true`
Predicate that always matches.
#### `never() => false`
Predicate that never matches.
#### `all(...predicates) => predicate`
Create a predicate that matches if all predicates match.
#### `any(...predicates) => predicate`
Create a predicate that matches if at least one of the predicates matches.
#### `none(...predicates) => predicate`
Create a predicate that matches if none of the predicates matches
#### `allow(predicate) => rule`
Create a rule that returns true if the predicate matches.
#### `deny(predicate) => rule`
Create a rule that returns false if the predicate matches.
#### `build(...rules) => rule`
Create a rule that returns the result of the first matching rule, or null if none matches
#### `combineRules(...rules) => rule`
Create a rule that returns the result of the first matching rule, or null if
none matches
#### `forceDecisionIf(predicate, rule, undecidedResult = false) => rule`
Create a rule that is triggered only if the predicate matches, and if the rule
does not decide, return the `undecidedResult`.
#### `enforce(rule, context) => undefined`
Throws an `ACLRejectionError` if the `rule` rejects the `context`, or does not decide on the `context` (i.e. returns `null`).
Instead of a `try/catch` switch, you can manually check a rule simply by calling it with a context (it is a function after all, hence this package's name). This would look something like:
Throws an `ACLRejectionError` if the `rule` rejects the `context`, or does not
decide on the `context` (i.e. returns `null`).
const myRule = build(...);
Instead of a `try/catch` switch, you can manually check a rule simply by
calling it with a context (it is a function after all, hence this package's
name). This would look something like:
const myRule = combineRules(...);
const myContext = { user: ..., operation: ..., foo: ... };

@@ -100,3 +139,3 @@

import {build, deny, allow} from '../src';
import {combineRules, deny, allow} from '../src';

@@ -108,3 +147,3 @@ const admins = ({user}) => user && user.isAdmin;

const restricted = build(
const restricted = combineRules(
deny(guests), // guests may not ever read

@@ -116,10 +155,12 @@ allow(admins), // admins may do everything

// now you can check permissions simply by calling
const allowed = restricted({ user: someUser, operation: someOperation });
const context = {user: myUser, operation: 'read'};
const allowed = restricted(context);
// or enforce a permission (throw ACLRejectedError otherwise)
enforce(restricted(...));
enforce(restricted, context);
## Express middleware
There is a helper in `functional-acl/express` that creates a customized middleware factory. Sounds complicated? It's not! Here we go:
There is a helper in `functional-acl/express` that creates a customized
middleware factory. Sounds complicated? It's not! Here we go:

@@ -145,11 +186,19 @@ import aclExpress from 'functional-acl/express';

Used to derive a partial context from the request. This can for example be used to supply the current user in the context. Make sure to plug in an authorization middleware (such as *passport*) somewhere, so you can access the user (e.g. `req.user`) here.
Used to derive a partial context from the request. This can for example be used
to supply the current user in the context. Make sure to plug in an
authorization middleware (such as *passport*) somewhere, so you can access the
user (e.g. `req.user`) here.
#### `createDirectContext: (...args) => context`
Used to extract a partial context from the arguments passed into the resulting middleware after the rule. In the example above, there is only one expected argument after the rule, which is the `operation`. This is then merged into the context at the key `operation`. You can see the value `'read'` being passed in for the example route.
Used to extract a partial context from the arguments passed into the resulting
middleware after the rule. In the example above, there is only one expected
argument after the rule, which is the `operation`. This is then merged into the
context at the key `operation`. You can see the value `'read'` being passed in
for the example route.
#### `onDeny: (rule, context, req, res, next) => undefined`
Used by the default *applyRule* as an error handler. Defaults to throwing an `ACLRejectionError`.
Used by the default *applyRule* as an error handler. Defaults to throwing an
`ACLRejectionError`.

@@ -160,2 +209,4 @@ #### `applyRule: (rule, directContext, extractedContext, req, res, next) => undefined`

By default, it builds a context from the direct and extracted partial contexts (direct context overwrites extracted context) and applies the rule on it. If that fails, `onDeny` is called.
By default, it builds a context from the direct and extracted partial contexts
(direct context overwrites extracted context) and applies the rule on it. If
that fails, `onDeny` is called.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc