README
Authoritah is an unopinionated, tiny, library for node that provides a
convenient API for scrutinizing an object against a set of rules. This is used
internally at Coding Blocks for the authorization subsystems of various
applications, but is unopinionated enough to be useful in any scenario.
Author
Prajjwal Singh
Usage
Authoritah implements a rule based system, where a rule looks like this:
{
predicate: (x) => { ... },
test: (x) => { ... }
}
Here, both predicate()
and test()
are functions returning booleans. For each
rule where the predicate returns true
for the object under scrutiny(supplied
via respect()
, see below), Authoritah ensures that the corresponding test()
returns a truthy value as well. Note that predicate()
must always be
synchronous.
A sample rule used internally at Coding Blocks looks like this:
const onlyAdminsCanDeleteRecords = {
predicate: (request) => isDeleteRequest(request),
test: (request) => currentUserIsAdmin(),
httpErrorCode: 401,
errorCode: 006
})
First, create a context:
const A = new Authoritah()
To add the rule:
A.addRule(onlyAdminsCanDeleteRecords)
addRule()
also returns a boolean value indicating whether your rule was added
or not.
Finally, ensure every rule passes against object x
with:
A.respect(x)
A.respectAsync(x)
.then(...)
.catch(...)
This returns a boolean indicating whether every rule passed or not.
To check the number of rules that have been added, use A.ruleCount()
.
To clear all existing rules (useful for switching contexts), use
A.clearRules()
.
Example
const Authoritah = require('cb-authoritah') ;
let manBearPig = {
species: "ManBearPig",
manFraction: 0.5,
bearFraction: 0.5,
pigFraction: 0.5
}
let fakeManBearPig = {
species: "ManBearPig",
manFraction: 0.1,
bearFraction: 0.1,
pigFraction: 0.8
}
let notManBearPig = {
species: "NotManBearPig"
}
const A = new Authoritah()
A.addRule({
predicate: (creature) => {
return (creature.species === "ManBearPig")
},
test: (creature) => {
return (
(creature.manFraction === 0.5) &&
(creature.bearFraction === 0.5) &&
(creature.pigFraction === 0.5)
)
},
errorMessage: "That's no ManBearPig!"
})
A.respect(manBearPig)
A.respect(fakeManBearPig)
A.respect(notManBearPig)
A.disrespectedRules(manBearPig)
A.disrespectedRules(fakeManBearPig)
A
.disrespectedRules(fakeManBearPig)[0]
.errorMessage
A.disrespectedRules(notManBearPig)
A.ruleCount()
A.clearRules()
A.ruleCount()
Running Tests
$> yarn test