UNPKG

sails-permissions-sequelize

Version:

Sequelize version of : Comprehensive user permissions and entitlements system for sails.js and Waterline. Supports user authentication with passport.js, role-based permissioning, object ownership, and row-level security.

240 lines (201 loc) 10.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); 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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _marlinspike = require('marlinspike'); var _marlinspike2 = _interopRequireDefault(_marlinspike); var _distApiModels = require('./dist/api/models'); var _distApiModels2 = _interopRequireDefault(_distApiModels); var permissionPolicies = ['passport', 'sessionAuth', 'ModelPolicy', 'OwnerPolicy', 'PermissionPolicy', 'RolePolicy']; var Permissions = (function (_Marlinspike) { _inherits(Permissions, _Marlinspike); function Permissions(sails) { _classCallCheck(this, Permissions); _get(Object.getPrototypeOf(Permissions.prototype), 'constructor', this).call(this, sails, module); } _createClass(Permissions, [{ key: 'configure', value: function configure() { if (!_lodash2['default'].isObject(sails.config.permissions)) sails.config.permissions = {}; /** * Local cache of Model name -> id mappings to avoid excessive database lookups. */ this.sails.config.blueprints.populate = false; var hook = this; hook.initModels(); var connection, migrate, sequelize; sails.log.verbose('Using connection named ' + sails.config.models.connection); connection = sails.config.connections[sails.config.models.connection]; if (connection == null) { throw new Error('Connection \'' + sails.config.models.connection + '\' not found in config/connections'); } if (connection.options == null) { connection.options = {}; } connection.options.logging = connection.options.logging || sails.log.verbose; //A function that gets executed everytime Sequelize would log something. migrate = sails.config.models.migrate; sails.log.verbose('Migration: ' + migrate); if (connection.url) { sequelize = new Sequelize(connection.url, connection.options); } else { sequelize = new Sequelize(connection.database, connection.user, connection.password, connection.options); } global['sequelize'] = sequelize; var modelDef, modelName, ref; if (err != null) { return next(err); } for (modelName in _distApiModels2['default']) { modelDef = _distApiModels2['default'][modelName]; sails.log.verbose('Loading model \'' + modelDef.globalId + '\''); global[modelDef.globalId] = global['sequelize'].define(modelDef.globalId, modelDef.attributes, modelDef.options); _lodash2['default'].extend(global[modelDef.globalId], modelDef); sails.models[modelDef.globalId.toLowerCase()] = global[modelDef.globalId]; } for (modelName in _distApiModels2['default']) { modelDef = _distApiModels2['default'][modelName]; hook.setAssociation(modelDef); hook.setDefaultScope(modelDef); } if (migrate === 'safe') { return next(); } else { var forceSync = migrate === 'drop'; global['sequelize'].sync({ force: forceSync }).then(function () { return next(); }); } } }, { key: 'initModels', value: function initModels() { if (sails.models === undefined) { sails.models = {}; } } }, { key: 'setAssociation', value: function setAssociation(modelDef) { if (modelDef.associations != null) { sails.log.verbose('Loading associations for \'' + modelDef.globalId + '\''); if (typeof modelDef.associations === 'function') { modelDef.associations(modelDef); } } } }, { key: 'setDefaultScope', value: function setDefaultScope(modelDef) { if (modelDef.defaultScope != null) { sails.log.verbose('Loading default scope for \'' + modelDef.globalId + '\''); var model = global[modelDef.globalId]; if (typeof modelDef.defaultScope === 'function') { var defaultScope = modelDef.defaultScope() || {}; model.addScope('defaultScope', defaultScope, { override: true }); } } } }, { key: 'initialize', value: function initialize(next) { var _this = this; var config = this.sails.config.permissions; this.installModelOwnership(); this.sails.after(config.afterEvent, function () { if (!_this.validateDependencies()) { _this.sails.log.error('Cannot find sails-auth hook. Did you "npm install sails-auth --save"?'); _this.sails.log.error('Please see README for installation instructions: https://github.com/tjwebb/sails-permissions'); return _this.sails.lower(); } if (!_this.validatePolicyConfig()) { _this.sails.log.warn('One or more required policies are missing.'); _this.sails.log.warn('Please see README for installation instructions: https://github.com/tjwebb/sails-permissions'); } }); this.sails.after('hook:sequelize:loaded', function () { //TO CHANGE sails.models.model.count().then(function (count) { if (count === _lodash2['default'].keys(_this.sails.models).length) return next(); return _this.initializeFixtures().then(function () { next(); }); })['catch'](function (error) { _this.sails.log.error(error); next(error); }); }); } }, { key: 'validatePolicyConfig', value: function validatePolicyConfig() { var policies = this.sails.config.policies; return _lodash2['default'].all([_lodash2['default'].isArray(policies['*']), _lodash2['default'].intersection(permissionPolicies, policies['*']).length === permissionPolicies.length, policies.AuthController && _lodash2['default'].contains(policies.AuthController['*'], 'passport')]); } }, { key: 'installModelOwnership', value: function installModelOwnership() { var models = this.sails.models; if (this.sails.config.models.autoCreatedBy === false) return; _lodash2['default'].each(models, function (model) { if (model.autoCreatedBy === false) return; _lodash2['default'].defaults(model.attributes, { createdBy: { model: 'User', index: true }, owner: { model: 'User', index: true } }); }); } /** * Install the application. Sets up default Roles, Users, Models, and * Permissions, and creates an admin user. */ }, { key: 'initializeFixtures', value: function initializeFixtures() { var _this2 = this; var fixturesPath = _path2['default'].resolve(__dirname, '../../../config/fixtures/'); return require(_path2['default'].resolve(fixturesPath, 'model')).createModels().then(function (models) { _this2.models = models; _this2.sails.hooks.permissions._modelCache = _lodash2['default'].indexBy(models, 'identity'); return require(_path2['default'].resolve(fixturesPath, 'role')).create(); }).then(function (roles) { _this2.roles = roles; var userModel = _lodash2['default'].find(_this2.models, { name: 'User' }); return require(_path2['default'].resolve(fixturesPath, 'user')).create(_this2.roles, userModel); }).then(function () { return sails.models.user.findOne({ email: _this2.sails.config.permissions.adminEmail }); }).then(function (user) { _this2.sails.log('sails-permissions: created admin user:', user); user.createdBy = user.id; user.owner = user.id; return user.save(); }).then(function (admin) { return require(_path2['default'].resolve(fixturesPath, 'permission')).create(_this2.roles, _this2.models, admin, _this2.sails.config.permissions); })['catch'](function (error) { _this2.sails.log.error(error); }); } }, { key: 'validateDependencies', value: function validateDependencies() { return !!this.sails.hooks.auth; } }]); return Permissions; })(_marlinspike2['default']); exports['default'] = _marlinspike2['default'].createSailsHook(Permissions); module.exports = exports['default'];