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.

644 lines (565 loc) 17.4 kB
var assert = require('assert'); describe('Permission Service', function() { it('should exist', function() { assert.ok(sails.services.permissionservice); assert.ok(global.PermissionService); }); describe('#isForeignObject()', function() { it('should return true if object is not owned by the requesting user', function(done) { var objectNotOwnedByUser = { owner: 2 }; var user = 1; assert.equal(sails.services.permissionservice.isForeignObject(user)(objectNotOwnedByUser), true); done(); }); it('should return false if object is owned by the requesting user', function(done) { var objectOwnedByUser = { owner: 1 }; var user = 1; assert.equal(sails.services.permissionservice.isForeignObject(user)(objectOwnedByUser), false); done(); }); }); describe('#hasForeignObjects()', function() { it('should return true if any object is not owned by the requesting user', function(done) { var objectOwnedByUser = { owner: 1 }; var objectNotOwnedByUser = { owner: 2 }; var user = { id: 1 }; assert.equal(sails.services.permissionservice.hasForeignObjects([objectNotOwnedByUser, objectOwnedByUser], user), true); done(); }); it('should return false if all objects are owned by the requesting user', function(done) { var objectOwnedByUser = { owner: 1 }; var objectOwnedByUser2 = { owner: 1 }; var user = { id: 1 }; assert.equal(sails.services.permissionservice.hasForeignObjects([objectOwnedByUser2, objectOwnedByUser], user), false); done(); }); }); describe('#hasOwnershipPolicy()', function() { it('should return true if object supports ownership policy', function(done) { assert.equal(sails.services.permissionservice.hasOwnershipPolicy({ autoCreatedBy: true }), true); done(); }); it('should return false if object does not support ownership policy', function(done) { assert.equal(sails.services.permissionservice.hasOwnershipPolicy({ autoCreatedBy: false }), false); done(); }); }); describe('#getMethod()', function() { it('should return \'create\' if POST request', function(done) { assert.equal(sails.services.permissionservice.getMethod('POST'), 'create'); done(); }); it('should return \'update\' if PUT request', function(done) { assert.equal(sails.services.permissionservice.getMethod('PUT'), 'update'); done(); }); it('should return \'read\' if GET request', function(done) { assert.equal(sails.services.permissionservice.getMethod('GET'), 'read'); done(); }); it('should return \'delete\' if DELETE request', function(done) { assert.equal(sails.services.permissionservice.getMethod('DELETE'), 'delete'); done(); }); }); describe('#hasPassingCriteria()', function() { it('should return an array of items that don\'t match the given criteria', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { where: { x: 2 } } }]; assert.equal(sails.services.permissionservice.hasPassingCriteria(objects, permissions), false); done(); }); it('should return an array of items that don\'t match the given criteria, if the criteria has many values for the same key', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { where: { x: 2 } } }, { criteria: { where: { x: 3 } } }]; assert.equal(sails.services.permissionservice.hasPassingCriteria(objects, permissions), false); done(); }); it('should return an array of items that don\'t match the given criteria, if the criteria has many values for the same key', function(done) { var objects = { x: 2 }; var permissions = [{ criteria: { where: { x: 2 } } }, { criteria: { where: { x: 3 } } }]; assert(sails.services.permissionservice.hasPassingCriteria(objects, permissions)); done(); }); it('should return an empty array if there is no criteria', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; assert(sails.services.permissionservice.hasPassingCriteria(objects)); done(); }); it('should match without where clause and blacklist', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { blacklist: ['x'] } }]; assert(sails.services.permissionservice.hasPassingCriteria(objects, permissions)); done(); }); it('should match with where clause and attributes', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { where: { x: { '>': 0 } }, blacklist: ['y'] } }]; assert(sails.services.permissionservice.hasPassingCriteria(objects, permissions, { x: 5 })); done(); }); it('should fail with bad where clause and good blacklist', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { where: { x: { '<': 0 } }, blacklist: ['y'] } }]; assert.equal(sails.services.permissionservice.hasPassingCriteria(objects, permissions, { x: 5 }), false); done(); }); it('should fail with good where clause and bad blacklist', function(done) { var objects = [{ x: 1 }, { x: 2 }, { x: 3 }]; var permissions = [{ criteria: { where: { x: { '>': 0 } }, blacklist: ['x'] } }]; assert.equal(sails.services.permissionservice.hasPassingCriteria(objects, permissions, { x: 5 }), false); done(); }); }); describe('#hasUnpermittedAttributes', function() { it('should return true if any of the attributes are in the blacklist', function(done) { var attributes = { ok: 1, fine: 2 }; var blacklist = ["ok", "alright", "fine"]; assert(sails.services.permissionservice.hasUnpermittedAttributes(attributes, blacklist)); done(); }); it('should return true if any attributes are not permitted', function(done) { var attributes = { ok: 1, fine: 2, whatever: 3 }; var blacklist = ["ok", "alright", "fine"]; assert(sails.services.permissionservice.hasUnpermittedAttributes(attributes, blacklist)); done(); }); it('should return false if none of the keys are in the blacklist', function(done) { var attributes = { ok: 1, fine: 2, whatever: 3 }; var blacklist = ["notallowed"]; assert.equal(sails.services.permissionservice.hasUnpermittedAttributes(attributes, blacklist), false); done(); }); it('should return false if there are no attributes', function(done) { var attributes = {}; var blacklist = ["ok", "alright", "fine"]; assert.equal(sails.services.permissionservice.hasUnpermittedAttributes(attributes, blacklist), false); done(); }); it('should return false if blacklist is empty', function(done) { var attributes = { ok: 1, fine: 2, whatever: 3 }; var blacklist = []; assert.equal(sails.services.permissionservice.hasUnpermittedAttributes(attributes, blacklist), false); done(); }); }); describe('role and permission helpers', function() { it('should create a role', function(done) { // make sure there is no existing role with this name Role.find({ name: 'fakeRole' }) .then(function(role) { assert.equal(role.length, 0); // use the helper to create a new role var newRole = { name: 'fakeRole', permissions: [{ model: 'Permission', action: 'delete', relation: 'role', }], users: ['newuser'] }; return sails.services.permissionservice.createRole(newRole); }) .then(function(result) { // make sure the role exists now that we have created it return Role.findOne({ name: 'fakeRole' }); }) .then(function(role) { assert(role && role.id); }) .done(done, done); }); it('should create a permission', function(done) { var permissionModelId; // find any existing permission for this action, and delete it Model.findOne({ name: 'Permission' }).then(function(permissionModel) { permissionModelId = permissionModel.id; return Permission.destroy({ action: 'create', model: permissionModelId, relation: 'role' }); }) .then(function(destroyed) { // make sure we actually destroyed it return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 0); // create a new permission var newPermissions = [{ role: 'fakeRole', model: 'Permission', action: 'create', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }, { role: 'fakeRole', model: 'Role', action: 'update', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }]; return sails.services.permissionservice.grant(newPermissions); }) .then(function(perm) { // verify that it was created return Permission.findOne({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert(permission && permission.id); }) .done(done, done); }); it('should grant a permission directly to a user', function(done) { var permissionModelId; // find any existing permission for this action, and delete it Model.findOne({ name: 'Permission' }).then(function(permissionModel) { permissionModelId = permissionModel.id; return Permission.destroy({ action: 'create', model: permissionModelId, relation: 'role' }); }) .then(function(destroyed) { // make sure we actually destroyed it return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 0); // create a new permission var newPermissions = [{ user: 'admin', model: 'Permission', action: 'create', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }, { user: 'admin', model: 'Role', action: 'update', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }]; return sails.services.permissionservice.grant(newPermissions); }) .then(function(perm) { // verify that it was created return Permission.findOne({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert(permission && permission.id); }) .done(done, done); }); it('should revoke a permission', function(done) { var permissionModelId; // make sure there is already an existing permission for this case Model.findOne({ name: 'Permission' }).then(function(permissionModel) { permissionModelId = permissionModel.id; return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 1); return sails.services.permissionservice.revoke({ user: 'admin', model: 'Permission', relation: 'role', action: 'create' }); }) .then(function() { return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 0); }) .done(done, done); }); it('should not revoke a permission if no user or role is supplied', function(done) { var permissionModelId; var newPermissions = [{ user: 'admin', model: 'Permission', action: 'create', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }, { user: 'admin', model: 'Role', action: 'update', relation: 'role', criteria: { where: { x: 1 }, blacklist: ['y'] } }]; return sails.services.permissionservice.grant(newPermissions) .then(function() { // make sure there is already an existing permission for this case Model.findOne({ name: 'Permission' }).then(function(permissionModel) { permissionModelId = permissionModel.id; return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 1); return sails.services.permissionservice.revoke({ model: 'Permission', relation: 'role', action: 'create' }); }) .catch(function(err) { assert.equal(err.message, 'You must provide either a user or role to revoke the permission from'); }) .then(function() { return Permission.find({ action: 'create', relation: 'role', model: permissionModelId }); }) .then(function(permission) { assert.equal(permission.length, 1); }) .done(done, done); }); }); it('should remove users from a role', function(done) { var user; var ok = User.create({ username: 'test', email: 'testemail@test.test' }); ok = ok.then(function(usr) { user = usr; return PermissionService.addUsersToRole('test', 'admin'); }); ok = ok.then(function (role) { assert(_.contains(_.pluck(role.users, 'id'), user.id)); return PermissionService.removeUsersFromRole('test', 'admin'); }); ok = ok.then(function (role) { assert(!_.contains(_.pluck(role.users, 'id'), user.id)); }) .done(done, done); }); }); //TODO: add unit tests for #findTargetObjects() //TODO: add unit tests for #findModelPermissions() });