UNPKG

access-mate

Version:

Attribute base access control using o-is for the conditions

121 lines (110 loc) 2.55 kB
'use strict' const oIsDefault = require('./o-is-default') class Policy { constructor(policySet, effect) { this._policySet = policySet this._oIs = policySet._oIs || oIsDefault this._target = [] this._action = [] this._name = null this._condition = [] this._effect = effect || null this._fields = null } _copy() { const copy = new Policy(this._policySet) copy._effect = this._effect copy._action = this._action copy._condition = this._condition copy._target = this._target copy._name = this._name copy._fields = this._fields return copy } _set(key, value) { const copy = this._copy() copy[key] = value return copy } _concat(key, value) { const copy = this._copy() copy[key] = copy[key].concat(value) return copy } target(value) { return this._concat('_target', value) } action(value) { return this._concat('_action', value) } effect(value) { if(value !== 'allow' && value !== 'deny') { throw new Error('Effect "' + value + '" is not valid') } return this._set('_effect', value) } fields(...values) { return this._set('_fields', values) } name(value) { return this._set('_name', value) } allow() { return this._policySet.concat(this).allow() } deny() { return this._policySet.concat(this).deny() } concat(item) { return this._policySet.concat(this, item) } condition(value) { if(value) { return this._set('_condition', value.tests) } else { const o = this._oIs() o._policy = this return o } } toJSON() { return this._policySet.concat(this).toJSON() } static fromJSON(policySet, obj) { const policy = new Policy(policySet, obj.effect) policy._target = obj.target policy._action = obj.action policy._condition = obj.condition policy._name = obj.name policy._fields = obj.fields || null return policy } decision(context) { if(typeof context.action !== 'string') { throw new Error('Action must be a string.') } if(typeof context.target !== 'string') { throw new Error('Target must be a string.') } for(const action of this._action) { for(const target of this._target) { if(context.action === action && context.target === target && this._oIs.test(this._oIs.assertions, context, this._condition)) { switch(this._effect) { case 'allow': return true case 'deny': return false default: throw new Error('Invalid effect "' + this._effect + '"') } } } } } end() { return this._policySet.concat(this) } } module.exports = Policy