From 8cc558a991d915be8483c7c61abc7d91cf1d53bc Mon Sep 17 00:00:00 2001 From: Esco Obong Date: Fri, 13 Mar 2015 11:50:30 -0400 Subject: [PATCH] consolidate Role methods roles, applications, and users into one, add query param to allow for pagination and restricting fields --- common/models/role.js | 95 ++++++++++++++++++++++++------------------- lib/builtin-models.js | 8 ++-- package.json | 1 + test/role.test.js | 90 +++++++++++++++++++++++----------------- 4 files changed, 112 insertions(+), 82 deletions(-) diff --git a/common/models/role.js b/common/models/role.js index c3b996a1..b8f36317 100644 --- a/common/models/role.js +++ b/common/models/role.js @@ -6,6 +6,10 @@ var async = require('async'); var AccessContext = require('../../lib/access-context').AccessContext; var RoleMapping = loopback.RoleMapping; +var Role = loopback.Role; +var User = loopback.User; +var Application = loopback.Application; + assert(RoleMapping, 'RoleMapping model must be defined before Role model'); /** @@ -29,57 +33,66 @@ module.exports = function(Role) { // Set up the connection to users/applications/roles once the model Role.once('dataSourceAttached', function() { var roleMappingModel = this.RoleMapping || loopback.getModelByType(RoleMapping); + var principalTypesToModels = {}; + + principalTypesToModels[RoleMapping.USER] = User; + principalTypesToModels[RoleMapping.APPLICATION] = Application; + principalTypesToModels[RoleMapping.ROLE] = Role; + + Object.keys(principalTypesToModels).forEach(function(principalType){ + var model = principalTypesToModels[principalType]; + var pluralName = model.pluralModelName.toLowerCase(); + /** + * Fetch all users assigned to this role + * @function Role.prototype#users + * @param {object} [query] query object passed to model find call + * @param {Function} [callback] + */ + /** + * Fetch all applications assigned to this role + * @function Role.prototype#applications + * @param {object} [query] query object passed to model find call + * @param {Function} [callback] + */ + /** + * Fetch all roles assigned to this role + * @function Role.prototype#roles + * @param {object} [query] query object passed to model find call + * @param {Function} [callback] + */ + Role.prototype[pluralName] = function(query, callback) { + listByPrincipalType(model, principalType, query, callback); + } + }); /** - * Fetch the ids of all users assigned to this role - * @param {Function} callback + * Fetch all models assigned to this role + * @param {*} model model type to fetch + * @param {String} [principalType] principalType used in the rolemapping for model + * @param {object} [query] query object passed to model find call + * @param {Function} [callback] */ - Role.prototype.users = function(callback) { + function listByPrincipalType(model, principalType, query, callback) { + if (callback === undefined) { + callback = query; + query = {}; + } + roleMappingModel.find({ - where: {roleId: this.id, principalType: RoleMapping.USER} + where: {roleId: this.id, principalType: principalType} }, function(err, mappings) { + var ids; if (err) { return callback(err); } - callback(null, mappings.map(function(m) { + ids = mappings.map(function(m) { return m.principalId; - })); + }); + query.where = query.where || {}; + query.where.id = {inq: ids}; + model.find(query, callback); }); - }; - - /** - * Fetch the ids of all applications assigned to this role - * @param {Function} callback - */ - Role.prototype.applications = function(callback) { - roleMappingModel.find({ - where: {roleId: this.id, principalType: RoleMapping.APPLICATION} - }, function(err, mappings) { - if (err) { - return callback(err); - } - callback(null, mappings.map(function(m) { - return m.principalId; - })); - }); - }; - - /** - * Fetch the ids of all roles assigned to this role - * @param {Function} callback - */ - Role.prototype.roles = function(callback) { - roleMappingModel.find({ - where: {roleId: this.id, principalType: RoleMapping.ROLE} - }, function(err, mappings) { - if (err) { - return callback(err); - } - callback(null, mappings.map(function(m) { - return m.principalId; - })); - }); - }; + } }); diff --git a/lib/builtin-models.js b/lib/builtin-models.js index 2a346d3e..4a986e8f 100644 --- a/lib/builtin-models.js +++ b/lib/builtin-models.js @@ -13,6 +13,10 @@ module.exports = function(loopback) { require('../common/models/access-token.json'), require('../common/models/access-token.js')); + loopback.User = createModel( + require('../common/models/user.json'), + require('../common/models/user.js')); + loopback.RoleMapping = createModel( require('../common/models/role-mapping.json'), require('../common/models/role-mapping.js')); @@ -29,10 +33,6 @@ module.exports = function(loopback) { require('../common/models/scope.json'), require('../common/models/scope.js')); - loopback.User = createModel( - require('../common/models/user.json'), - require('../common/models/user.js')); - loopback.Change = createModel( require('../common/models/change.json'), require('../common/models/change.js')); diff --git a/package.json b/package.json index 2e065bad..b932f7f8 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "loopback-datasource-juggler": "^2.19.1", "loopback-testing": "^1.1.0", "mocha": "^2.1.0", + "sinon": "^1.13.0", "strong-task-emitter": "^0.0.6", "supertest": "^0.15.0" }, diff --git a/test/role.test.js b/test/role.test.js index f10a1c33..d0cc3586 100644 --- a/test/role.test.js +++ b/test/role.test.js @@ -1,4 +1,5 @@ var assert = require('assert'); +var sinon = require('sinon'); var loopback = require('../index'); var Role = loopback.Role; var RoleMapping = loopback.RoleMapping; @@ -209,49 +210,64 @@ describe('role model', function() { }); - it('should fetch all user ids assigned to the role', function(done) { - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { - Role.create({name: 'userRole'}, function(err, role) { - role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { - role.users(function(err, users) { - assert(!err); - assert.equal(users.length, 1); - assert.equal(users[0], user.id); - done(); - }); - }); - }); - }); - }); + describe('listByPrincipalType', function(){ + var sandbox; - it('should fetch all application ids assigned to the role', function(done) { - Application.create({name: 'New App'}, function(err, application) { - Role.create({name: 'applicationRole'}, function(err, role) { - role.principals.create({principalType: RoleMapping.APPLICATION, principalId: application.id}, function(err, p) { - role.applications(function(err, applications) { - assert(!err); - assert.equal(applications.length, 1); - assert.equal(applications[0], application.id); - done(); - }); - }); - }); + beforeEach(function(){ + sandbox = sinon.sandbox.create(); }); - }); - it('should fetch all role ids assigned to the role', function(done) { - Role.create({name: 'New Role'}, function(err, newRole) { - Role.create({name: 'applicationRole'}, function(err, role) { - role.principals.create({principalType: RoleMapping.ROLE, principalId: newRole.id}, function(err, p) { - role.roles(function(err, roles) { - assert(!err); - assert.equal(roles.length, 1); - assert.equal(roles[0], newRole.id); - done(); + afterEach(function(){ + sandbox.restore(); + }); + + it('should fetch all models assigned to the role', function(done) { + var principalTypesToModels = {}; + var runs = 0; + var mappings; + + principalTypesToModels[RoleMapping.USER] = User; + principalTypesToModels[RoleMapping.APPLICATION] = Application; + principalTypesToModels[RoleMapping.ROLE] = Role; + + mappings = Object.keys(principalTypesToModels); + + mappings.forEach(function(principalType){ + var Model = principalTypesToModels[principalType]; + Model.create({name:"test", email:'x@y.com', password: 'foobar'}, function(err, model){ + Role.create({name:'testRole'}, function(err, role){ + role.principals.create({principalType: principalType, principalId: model.id}, function(err, p){ + var pluralName = Model.pluralModelName.toLowerCase(); + role[pluralName](function(err, models){ + assert(!err); + assert.equal(models.length, 1); + if (++runs === mappings.length) { + done(); + } + }); + }); + }) + }) + }); + }); + + it('should apply query', function(done) { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { + Role.create({name: 'userRole'}, function(err, role) { + role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { + var query = {fields:['id','name']}; + sandbox.spy(User, 'find'); + role.users(query, function(err, users) { + assert(!err); + assert.equal(users.length, 1); + assert.equal(users[0].id, user.id); + assert(User.find.calledWith(query)); + done(); + }); }); }); }); }); - }); + }) });