UNPKG

kindergarten

Version:

Kindergarten is a JavaScript library which helps programmers to achieve modular security using sandbox pattern

286 lines (211 loc) 8.11 kB
'use strict'; 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;