consolidate Role methods roles, applications, and users into one, add query param to allow for pagination and restricting fields

This commit is contained in:
Esco Obong 2015-03-13 11:50:30 -04:00
parent 74018019b4
commit 8cc558a991
4 changed files with 112 additions and 82 deletions

View File

@ -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;
}));
});
};
}
});

View File

@ -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'));

View File

@ -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"
},

View File

@ -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();
});
});
});
});
});
});
})
});