kindergarten
Version:
Kindergarten is a JavaScript library which helps programmers to achieve modular security using sandbox pattern
286 lines (211 loc) • 8.11 kB
JavaScript
;
exports.__esModule = true;
exports.default = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _each = require('lodash/each');
var _each2 = _interopRequireDefault(_each);
var _find = require('lodash/find');
var _find2 = _interopRequireDefault(_find);
var _some = require('lodash/some');
var _some2 = _interopRequireDefault(_some);
var _isEmpty = require('lodash/isEmpty');
var _isEmpty2 = _interopRequireDefault(_isEmpty);
var _HeadGoverness = require('./governesses/HeadGoverness');
var _HeadGoverness2 = _interopRequireDefault(_HeadGoverness);
var _Purpose = require('./Purpose');
var _Purpose2 = _interopRequireDefault(_Purpose);
var _AllowedMethodsService = require('./utils/AllowedMethodsService');
var _AllowedMethodsService2 = _interopRequireDefault(_AllowedMethodsService);
var _utils = require('./utils');
var _errors = require('./errors');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* The definition of Sandbox class.
* The sandbox is place where children can play governed by a governess.
*/
var Sandbox = function () {
/**
* Create a new empty sandbox.
*/
function Sandbox() {
var child = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$governess = _ref.governess,
governess = _ref$governess === undefined ? new _HeadGoverness2.default() : _ref$governess,
_ref$perimeters = _ref.perimeters,
perimeters = _ref$perimeters === undefined ? [] : _ref$perimeters;
_classCallCheck(this, Sandbox);
this.child = child;
if (!(0, _utils.isGoverness)(governess)) {
try {
var Governess = governess;
governess = new Governess();
} catch (ignore) {
// ignore...
}
}
this.governess = governess;
this._perimeters = [];
if (!(0, _isEmpty2.default)(perimeters)) {
this.loadPerimeter.apply(this, _toConsumableArray(perimeters));
}
}
/**
* The getter of the governess.
*/
_createClass(Sandbox, [{
key: 'guard',
value: function guard() {
var _governess;
return (_governess = this.governess).guard.apply(_governess, arguments);
}
/**
* Load perimeters.
* Returns the count of addded perimeters.
*/
}, {
key: 'loadPerimeter',
value: function loadPerimeter() {
var _this = this;
var counter = 0;
for (var _len = arguments.length, perimeters = Array(_len), _key = 0; _key < _len; _key++) {
perimeters[_key] = arguments[_key];
}
(0, _each2.default)(perimeters, function (perimeter) {
// Sandbox only accepts perimeters
if (!(0, _utils.isPerimeter)(perimeter)) {
throw new _errors.ArgumentError('Module must be instance of Kindergarten.Perimeter.');
}
// Skip if sandbox already have the perimeter
if (_this.hasPerimeter(perimeter)) return;
// If perimeter has a governess, then she has to learn the rules as well
if ((0, _utils.isGoverness)(perimeter.governess)) {
perimeter.governess.learnRules(perimeter);
}
// Governess that used when checking rules through purpose
if (!perimeter.purposeGoverness) {
perimeter.purposeGoverness = new _this.governess.constructor();
perimeter.purposeGoverness.learnRules(perimeter);
}
// The governess of a sandbox must know all the rules
_this.governess.learnRules(perimeter);
perimeter.sandbox = _this;
_this._perimeters.push(perimeter);
// Make sure the purpose is available on Sandbox
_this._extendPurpose(perimeter);
++counter;
});
return counter;
}
/**
* Alias for loadPerimeter
*/
}, {
key: 'loadModule',
value: function loadModule() {
return this.loadPerimeter.apply(this, arguments);
}
/**
* Return all loaded perimeters
*/
}, {
key: 'getPerimeters',
value: function getPerimeters() {
return this._perimeters || [];
}
/**
* Return perimeter by a purpose or null.
*/
}, {
key: 'getPerimeter',
value: function getPerimeter(purpose) {
var perimeter = (0, _find2.default)(this.getPerimeters(), function (p) {
return p.purpose === purpose;
});
return (0, _utils.isPerimeter)(perimeter) ? perimeter : null;
}
/**
* Return true if sandbox already contains a perimeter.
*/
}, {
key: 'hasPerimeter',
value: function hasPerimeter(perimeter) {
var purpose = (0, _utils.isPerimeter)(perimeter) ? perimeter.purpose : perimeter;
return (0, _some2.default)(this.getPerimeters(), function (p) {
return p.purpose === purpose;
});
}
/**
* Return true if allowed to do action on target.
*/
}, {
key: 'isAllowed',
value: function isAllowed() {
var _governess2;
return (_governess2 = this.governess).isAllowed.apply(_governess2, arguments);
}
/**
* Return true if not allowed to do action on target.
*/
}, {
key: 'isNotAllowed',
value: function isNotAllowed() {
var _governess3;
return (_governess3 = this.governess).isNotAllowed.apply(_governess3, arguments);
}
/**
* Expose the purpose of a perimeter, make sure the purpose of the perimeter
* is available on this sandbox.
* This method is used internally by Sandbox and shouldn't be used
* externally.
*/
}, {
key: '_extendPurpose',
value: function _extendPurpose(perimeter) {
var name = perimeter.purpose;
var allowedMethodsService = new _AllowedMethodsService2.default(this);
if (allowedMethodsService.isRestricted(name)) {
throw new _errors.RestrictedMethodError('Cannot expose purpose ' + name + ' to sandbox. Restricted method name.');
}
this[name] = (0, _utils.isPurpose)(this[name]) ? this[name] : new _Purpose2.default(name, this);
this[name]._loadPerimeter(perimeter);
}
/**
* Make sure governess know all the rules from all loaded perimeters.
* This method is used internally by Sandbox and shouldn't be used
* externally.
*/
}, {
key: '_learnRules',
value: function _learnRules() {
var _this2 = this;
(0, _each2.default)(this.getPerimeters() || [], function (perimeter) {
return _this2.governess.learnRules(perimeter);
});
}
}, {
key: 'governess',
get: function get() {
return this._governess;
}
/**
* The setter of the governess.
* Make sure new governess learn all the rules when governess is set.
*/
,
set: function set(value) {
if (!(0, _utils.isGoverness)(value)) {
throw new _errors.NoGovernessError();
}
// if governess is null perimeter will use the governess of it's sandbox
this._governess = value;
// New governess must know all the rules (if any)
this._learnRules();
return value;
}
}]);
return Sandbox;
}();
exports.default = Sandbox;