Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sails-permissions

Package Overview
Dependencies
Maintainers
1
Versions
83
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sails-permissions - npm Package Compare versions

Comparing version 0.10.17 to 0.10.19

api/policies/PermissionPolicy.js

43

api/hooks/permissions-api/index.js

@@ -14,6 +14,8 @@ module.exports = function (sails) {

initialize: function (next) {
installModelOwnership(sails.models);
sails.after('hook:orm:loaded', function () {
sails.log('initializing sails-permissions...');
var models = _.filter(sails.controllers, function (controller, name) {
var sailsModels = _.filter(sails.controllers, function (controller, name) {
var model = sails.models[name];

@@ -26,4 +28,4 @@ return model && model.globalId && model.identity;

var count = models ? models.length : 0;
if (count < models.length) {
sails.log('Expecting', models.length, 'models, found', count);
if (count < sailsModels.length) {
sails.log('Expecting', sailsModels.length, 'models, found', count);
sails.log('Installing fixtures');

@@ -33,3 +35,2 @@ return initializeFixtures(next);

logModelOwnership(models);
next();

@@ -94,2 +95,15 @@ })

function logModelOwnership (models) {
var missingOwner = _.filter(models, function (model) {
return _.isUndefined(sails.models[model.identity].attributes.owner);
});
var warnings = _.difference(_.pluck(missingOwner, 'name'), ignoreModels);
if (warnings.length) {
sails.log.warn('these models do not support ownership, and are unusable by the permissions-api:', warnings);
}
}
function installModelOwnership (models) {
if (sails.config.permissions.enableOwnership === false) return;
var ignoreModels = [

@@ -103,11 +117,16 @@ 'BackboneModel',

];
var missingOwner = _.filter(models, function (model) {
return _.isUndefined(sails.models[model.identity].attributes.owner);
_.each(models, function (model) {
if (model.enableOwnership === false) return;
if (_.contains(ignoreModels, model.globalId)) return;
sails.log('enabling ownership on', model.globalId);
_.defaults(model.attributes, {
owner: {
model: 'User',
index: true,
notNull: true
}
});
});
var warnings = _.difference(_.pluck(missingOwner, 'name'), ignoreModels);
if (warnings.length) {
sails.log.warn('the following models do not support ownership:', warnings);
}
sails.log.warn('these models do not support the permissions-api');
}

@@ -17,2 +17,4 @@ /**

enableOwnership: false,
attributes: {

@@ -19,0 +21,0 @@ name: {

@@ -40,13 +40,34 @@ var EventEmitter = require('events').EventEmitter;

/**
* @param action.method
* @param action.attribute
* @param ownership
* @param method
*
* permission.grant is a permission mapping for a particular model, e.g.
* {
* owner: {
* '*': true
* },
* role: {
* '*': true,
* update: false
* },
* none: {
* // '*': false by default
* }
*
* }
*/
permits: function (action) {
return _.find([ 'owner', 'role', 'others' ], function (ownership) {
return this.grant[ownership][action.attribute][action.method];
}, this);
permits: function (ownership, method) {
var permittedOwnership = _.dot(this.grant, [ ownership, '*' ]);
var permittedMethod = _.dot(this.grant, [ ownership, action ]);
return permittedMethod || (permittedOwnership && permittedMethod !== false);
}
},
beforeValidate: function (permission, next) {
/**
* Perform deep-validation of grant object
*/
afterValidate: function (permission, next) {
_.isObject(permission.grant) || (permission.grant = { });
_.defaults(permission.grant, {

@@ -60,6 +81,6 @@ owner: { },

var valid = _.similar(Permission.grantTemplate, permission.grant, emitter);
emitter.on('invalid:keys', function (error) {
emitter.once('invalid:keys', function (error) {
next(new Error('the grant object is missing a required key'));
});
emitter.on('invalid:value', function (error) {
emitter.once('invalid:value', function (error) {
next(new Error('grant key ' + error.key + ' is invalid'));

@@ -66,0 +87,0 @@ });

@@ -19,3 +19,4 @@ /**

index: true,
notNull: true
notNull: true,
unique: true
},

@@ -58,3 +59,3 @@ children: {

grant: function (permissions) {
var grant = PermissionService.createGrant(permisisons);
var grant = PermissionService.createGrant(permissions);

@@ -95,7 +96,6 @@ return Permission

return permission.permits(action.method, action.attribute);
return permission.permits(action);
});
}
},
}
};

@@ -10,4 +10,65 @@ var _ = require('lodash');

via: 'users'
},
/**
* Returns this user's ownership relation to an object. If the user owns the
* specified object directly, return 'owner'. If the user shares a
* role with the owner, return 'role'. If the user is not the owner
* and has no roles in common with the owner of the object, then return
* 'none'.
*
* @return Promise that resolves to 0, 1, or -1
*/
getOwnershipRelation: function (object) {
if (!object.owner) {
return -1;
}
if (object.owner === this.id) {
return 0;
}
// query roles for this and object.owner and see if there are any in
// common
User.findOne(this.id).populate('roles').bind(this)
.then(function (user) {
this.roles = user.roles;
return User.findOne(object.owner).populate('roles');
})
.then(function (owner) {
var intersection = _.intersection(
_.pluck(this.roles, 'id'),
_.pluck(owner.roles, 'id')
);
if (intersection.length > 0) {
return 1;
}
else {
return -1;
}
});
}
},
/**
* Attach default Role to a new User
*/
afterCreate: function (_user, next) {
var user;
sails.log('user afterCreate');
User.findOne(_user.id)
.populate('roles')
.then(function (_user) {
user = _user;
return Role.findOne({ name: 'registered' });
})
.then(function (role) {
user.roles.add(role.id);
return user.save();
})
.then(function (updatedUser) {
sails.log('role "registered" attached to user', user.username);
next();
})
.catch(next);
}
});

@@ -0,1 +1,3 @@

var actionUtil = require('sails/lib/hooks/blueprints/actionUtil');
/**

@@ -5,16 +7,19 @@ * Query the Model that is being acted upon, and set it on the req object.

module.exports = function ModelPolicy (req, res, next) {
var modelName = ModelService.getTargetModelName(req);
req.options.modelName = actionUtil.parseModel(req).identity;
Model.findOne({ identity: modelName })
if (_.contains(sails.config.permissions.ignoreOwnership, req.options.modelName)) {
req.options.ignoreOwnership = true;
return next();
}
Model.findOne({ identity: req.options.modelName })
.then(function (model) {
if (_.isObject(model)) {
// TODO probably only one of these is needed
req.model = model;
next();
if (!_.isObject(model)) {
return next(new Error('Model definition not found: '+ req.options.modelName));
}
else {
next(new Error('Model definition not found in datastore: '+ modelName));
}
req.model = model;
next();
})
.catch(next);
};
/**
* Ensure that the 'owner' property of an Object is set upon creation.
*
* @param {Object} req
* @param {Object} res
* @param {Function} next
*/
module.exports = function OwnerPolicy (req, res, next) {
if (!req.user || !req.user.id) next(new Error('req.user is not set'));
if (!req.user || !req.user.id) return next(new Error('req.user is not set'));
req.owner = req.user.id;
sails.log(req.query);
sails.log(req.params);
// set owner on newly created object
if (req.options.action === 'create') {
if (req.options.modelName === 'user') {
req.body = req.body || { };
req.body.owner = req.owner;
req.body.id = req.user.id;
req.query.id = req.user.id;
if (!_.isEmpty(req.params.id) && req.params.id != req.user.id) {
return res.send(400, 'you cannot query another user');
}
}
else if (!req.options.ignoreOwnership) {
req.body = req.body || { };
req.body.owner = req.user.id;
req.query.owner = req.user.id;
req.params.owner = req.user.id;
}
next();
/*
User.findOne(req.user.id)
.populate('roles')
.then(function (user) {
if (!user) {
return next(new Error('could not find user with id "' + req.user.id + '" in database'));
}
req.owner = user;
next();
})
.catch(next);
*/
};
var pluralize = require('pluralize');
module.exports = {
/**
* Return the type of model acted upon by this request.
*/
getTargetModelName: function (req) {

@@ -5,0 +8,0 @@ if (_.isString(req.options.alias)) {

@@ -0,5 +1,13 @@

global._ = require('lodash');
global._.mixin(require('a.b'));
module.exports.permissions = {
adminEmail: process.env.ADMIN_EMAIL,
adminPassword: process.env.ADMIN_PASSWORD
adminPassword: process.env.ADMIN_PASSWORD,
ignoreOwnership: [
'model',
'backbonemodel'
]
};

@@ -14,6 +14,8 @@ module.exports = require('sails-generate-entities')({

'config/permissions.js'
'config/permissions.js',
'config/blueprints.js'
],
classes: [
'api/services/ModelService.js'
'api/services/ModelService.js',
'api/services/PermissionService.js'
],

@@ -23,4 +25,5 @@ functions: [

'api/policies/ModelPolicy.js',
'api/policies/OwnerPolicy.js'
'api/policies/OwnerPolicy.js',
'api/policies/PermissionPolicy.js'
]
});
{
"name": "sails-permissions",
"version": "0.10.17",
"version": "0.10.19",
"description": "Comprehensive sails.js user permission/privilege framework that allows granting and restricting access to models and attributes based on object ownership and relationships with other users and roles",

@@ -38,2 +38,3 @@ "main": "index.js",

"dependencies": {
"a.b": "^1.0.1",
"bluebird": "^2.3.6",

@@ -40,0 +41,0 @@ "congruence": "^1.6.4",

@@ -49,14 +49,5 @@ # <img src="http://cdn.tjw.io/images/sails-logo.png" height='43px' />-permissions

### 3. extend models to support ownership
Currently, sails-permissions does not validated the permissions of associations. Until this
is implemented, ensure that `sails.config.blueprints.populate` is set to `false`.
#### api/models/Foo.js
```js
var Foo = {
// model definition
};
_.merge(Foo, require('sails-permissions/src/models/HasOwner.js'));
module.exports = Foo;
```
## License

@@ -63,0 +54,0 @@ MIT

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc