Merge pull request #69 from strongloop/datasource-auto-wiring
Initial auto wiring for model dataSources
This commit is contained in:
commit
e5a55846e8
|
@ -221,6 +221,9 @@ app.boot = function(options) {
|
|||
app.model(key, obj);
|
||||
});
|
||||
|
||||
// attach models to dataSources by type
|
||||
loopback.autoAttach();
|
||||
|
||||
// require directories
|
||||
var requiredModels = requireDir(path.join(appRootDir, 'models'));
|
||||
}
|
||||
|
|
|
@ -96,6 +96,11 @@ loopback.createDataSource = function (name, options) {
|
|||
ModelCtor.attachTo(ds);
|
||||
return ModelCtor;
|
||||
};
|
||||
|
||||
if(options && options.defaultForType) {
|
||||
loopback.setDefaultDataSourceForType(options.defaultForType, ds);
|
||||
}
|
||||
|
||||
return ds;
|
||||
};
|
||||
|
||||
|
@ -108,7 +113,12 @@ loopback.createDataSource = function (name, options) {
|
|||
*/
|
||||
|
||||
loopback.createModel = function (name, properties, options) {
|
||||
return loopback.Model.extend(name, properties, options);
|
||||
var model = loopback.Model.extend(name, properties, options);
|
||||
|
||||
// try to attach
|
||||
loopback.autoAttachModel(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,6 +183,58 @@ loopback.getModel = function(modelName) {
|
|||
return loopback.Model.modelBuilder.models[modelName];
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the default `dataSource` for a given `type`.
|
||||
*/
|
||||
|
||||
loopback.setDefaultDataSourceForType = function(type, dataSource) {
|
||||
var defaultDataSources = this.defaultDataSources || (this.defaultDataSources = {});
|
||||
|
||||
if(!(dataSource instanceof DataSource)) {
|
||||
dataSource = this.createDataSource(dataSource);
|
||||
}
|
||||
|
||||
defaultDataSources[type] = dataSource;
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default `dataSource` for a given `type`.
|
||||
*/
|
||||
|
||||
loopback.getDefaultDataSourceForType = function(type) {
|
||||
return this.defaultDataSources && this.defaultDataSources[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach any model that does not have a dataSource to
|
||||
* the default dataSource for the type the Model requests
|
||||
*/
|
||||
|
||||
loopback.autoAttach = function() {
|
||||
var models = this.Model.modelBuilder.models;
|
||||
assert.equal(typeof models, 'object', 'Cannot autoAttach without a models object');
|
||||
|
||||
Object.keys(models).forEach(function(modelName) {
|
||||
var ModelCtor = models[modelName];
|
||||
|
||||
if(ModelCtor) {
|
||||
loopback.autoAttachModel(ModelCtor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loopback.autoAttachModel = function(ModelCtor) {
|
||||
if(ModelCtor.autoAttach) {
|
||||
var ds = loopback.getDefaultDataSourceForType(ModelCtor.autoAttach);
|
||||
|
||||
assert(ds instanceof DataSource, 'cannot autoAttach model "' + ModelCtor.modelName
|
||||
+ '". No dataSource found of type ' + ModelCtor.attachTo);
|
||||
|
||||
ModelCtor.attachTo(ds);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Built in models / services
|
||||
*/
|
||||
|
@ -182,3 +244,26 @@ loopback.Email = require('./models/email');
|
|||
loopback.User = require('./models/user');
|
||||
loopback.Application = require('./models/application');
|
||||
loopback.AccessToken = require('./models/access-token');
|
||||
loopback.Role = require('./models/role').Role;
|
||||
loopback.RoleMapping = require('./models/role').RoleMapping;
|
||||
loopback.ACL = require('./models/acl').ACL;
|
||||
loopback.Scope = require('./models/acl').Scope;
|
||||
|
||||
|
||||
/**
|
||||
* Automatically attach these models to dataSources
|
||||
*/
|
||||
|
||||
var dataSourceTypes = {
|
||||
DB: 'db',
|
||||
MAIL: 'mail'
|
||||
};
|
||||
|
||||
loopback.Email.autoAttach = dataSourceTypes.MAIL;
|
||||
loopback.User.autoAttach = dataSourceTypes.DB;
|
||||
loopback.AccessToken.autoAttach = dataSourceTypes.DB;
|
||||
loopback.Role.autoAttach = dataSourceTypes.DB;
|
||||
loopback.RoleMapping.autoAttach = dataSourceTypes.DB;
|
||||
loopback.ACL.autoAttach = dataSourceTypes.DB;
|
||||
loopback.Scope.autoAttach = dataSourceTypes.DB;
|
||||
loopback.Application.autoAttach = dataSourceTypes.DB;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var loopback = require('../loopback');
|
||||
var ModelBuilder = require('loopback-datasource-juggler').ModelBuilder;
|
||||
var modeler = new ModelBuilder();
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
var loopback = require('../');
|
||||
var Token = loopback.AccessToken.extend('MyToken');
|
||||
|
||||
// attach Token to testing memory ds
|
||||
Token.attachTo(loopback.memory());
|
||||
|
||||
describe('loopback.token(options)', function() {
|
||||
beforeEach(createTestingToken);
|
||||
|
||||
|
|
|
@ -14,18 +14,10 @@ function checkResult(err, result) {
|
|||
describe('security scopes', function () {
|
||||
|
||||
it("should allow access to models for the given scope by wildcard", function () {
|
||||
var ds = loopback.createDataSource({connector: loopback.Memory});
|
||||
Scope.attachTo(ds);
|
||||
ACL.attachTo(ds);
|
||||
|
||||
// console.log(Scope.relations);
|
||||
|
||||
Scope.create({name: 'userScope', description: 'access user information'}, function (err, scope) {
|
||||
// console.log(scope);
|
||||
ACL.create({principalType: ACL.SCOPE, principalId: scope.id, model: 'User', property: ACL.ALL,
|
||||
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||
function (err, resource) {
|
||||
// console.log(resource);
|
||||
Scope.checkPermission('userScope', 'User', ACL.ALL, ACL.ALL, checkResult);
|
||||
Scope.checkPermission('userScope', 'User', 'name', ACL.ALL, checkResult);
|
||||
Scope.checkPermission('userScope', 'User', 'name', ACL.READ, checkResult);
|
||||
|
@ -36,13 +28,7 @@ describe('security scopes', function () {
|
|||
|
||||
it("should allow access to models for the given scope", function () {
|
||||
var ds = loopback.createDataSource({connector: loopback.Memory});
|
||||
Scope.attachTo(ds);
|
||||
ACL.attachTo(ds);
|
||||
|
||||
// console.log(Scope.relations);
|
||||
|
||||
Scope.create({name: 'userScope', description: 'access user information'}, function (err, scope) {
|
||||
// console.log(scope);
|
||||
ACL.create({principalType: ACL.SCOPE, principalId: scope.id,
|
||||
model: 'User', property: 'name', accessType: ACL.READ, permission: ACL.ALLOW},
|
||||
function (err, resource) {
|
||||
|
@ -74,7 +60,6 @@ describe('security ACLs', function () {
|
|||
|
||||
it("should allow access to models for the given principal by wildcard", function () {
|
||||
var ds = loopback.createDataSource({connector: loopback.Memory});
|
||||
ACL.attachTo(ds);
|
||||
|
||||
ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL,
|
||||
accessType: ACL.ALL, permission: ACL.ALLOW}, function (err, acl) {
|
||||
|
@ -117,7 +102,6 @@ describe('security ACLs', function () {
|
|||
{principalType: ACL.USER, principalId: 'u001', accessType: ACL.ALL, permission: ACL.ALLOW}
|
||||
];
|
||||
*/
|
||||
ACL.attachTo(ds);
|
||||
|
||||
ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function (err, perm) {
|
||||
assert(perm.permission === ACL.DENY);
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
var loopback = require('../');
|
||||
var MailConnector = loopback.Mail;
|
||||
var MyEmail = loopback.Email.extend('my-email');
|
||||
var assert = require('assert');
|
||||
|
||||
describe('Email and SMTP', function () {
|
||||
var mail = loopback.createDataSource({
|
||||
connector: MailConnector,
|
||||
transports: [
|
||||
{type: 'STUB'}
|
||||
]
|
||||
});
|
||||
|
||||
MyEmail.attachTo(mail);
|
||||
|
||||
it('should have a send method', function () {
|
||||
assert(typeof MyEmail.send === 'function');
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
var loopback = require(('../'));
|
||||
var assert = require('assert');
|
||||
|
||||
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
|
||||
|
||||
var Application = loopback.Application;
|
||||
Application.attachTo(dataSource);
|
||||
|
||||
describe('Application', function () {
|
||||
var registeredApp = null;
|
||||
|
||||
it('Create a new application', function (done) {
|
||||
|
||||
Application.create({owner: 'rfeng', name: 'MyApp1', description: 'My first mobile application'}, function (err, result) {
|
||||
var app = result;
|
||||
assert.equal(app.owner, 'rfeng');
|
||||
|
@ -27,8 +22,7 @@ describe('Application', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Register a new application', function (done) {
|
||||
|
||||
beforeEach(function (done) {
|
||||
Application.register('rfeng', 'MyApp2', {description: 'My second mobile application'}, function (err, result) {
|
||||
var app = result;
|
||||
assert.equal(app.owner, 'rfeng');
|
||||
|
@ -47,7 +41,6 @@ describe('Application', function () {
|
|||
});
|
||||
|
||||
it('Reset keys', function (done) {
|
||||
|
||||
Application.resetKeys(registeredApp.id, function (err, result) {
|
||||
var app = result;
|
||||
assert.equal(app.owner, 'rfeng');
|
||||
|
@ -73,7 +66,6 @@ describe('Application', function () {
|
|||
});
|
||||
|
||||
it('Authenticate with application id & clientKey', function (done) {
|
||||
|
||||
Application.authenticate(registeredApp.id, registeredApp.clientKey, function (err, result) {
|
||||
assert.equal(result, 'clientKey');
|
||||
done(err, result);
|
||||
|
@ -81,7 +73,6 @@ describe('Application', function () {
|
|||
});
|
||||
|
||||
it('Authenticate with application id & javaScriptKey', function (done) {
|
||||
|
||||
Application.authenticate(registeredApp.id, registeredApp.javaScriptKey, function (err, result) {
|
||||
assert.equal(result, 'javaScriptKey');
|
||||
done(err, result);
|
||||
|
@ -116,6 +107,5 @@ describe('Application', function () {
|
|||
done(err, result);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ function checkResult(err, result) {
|
|||
describe('role model', function () {
|
||||
|
||||
it("should define role/role relations", function () {
|
||||
var ds = loopback.createDataSource({connector: 'memory'});
|
||||
Role.attachTo(ds);
|
||||
RoleMapping.attachTo(ds);
|
||||
|
||||
Role.create({name: 'user'}, function (err, userRole) {
|
||||
Role.create({name: 'admin'}, function (err, adminRole) {
|
||||
userRole.principals.create({principalType: RoleMapping.ROLE, principalId: adminRole.id}, function (err, mapping) {
|
||||
|
@ -41,11 +37,6 @@ describe('role model', function () {
|
|||
});
|
||||
|
||||
it("should define role/user relations", function () {
|
||||
var ds = loopback.createDataSource({connector: 'memory'});
|
||||
User.attachTo(ds);
|
||||
Role.attachTo(ds);
|
||||
RoleMapping.attachTo(ds);
|
||||
|
||||
User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) {
|
||||
// console.log('User: ', user.id);
|
||||
Role.create({name: 'userRole'}, function (err, role) {
|
||||
|
@ -75,11 +66,6 @@ describe('role model', function () {
|
|||
});
|
||||
|
||||
it("should support getRoles() and isInRole()", function () {
|
||||
var ds = loopback.createDataSource({connector: 'memory'});
|
||||
User.attachTo(ds);
|
||||
Role.attachTo(ds);
|
||||
RoleMapping.attachTo(ds);
|
||||
|
||||
User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) {
|
||||
// console.log('User: ', user.id);
|
||||
Role.create({name: 'userRole'}, function (err, role) {
|
||||
|
|
|
@ -12,6 +12,21 @@ request = require('supertest');
|
|||
|
||||
beforeEach(function () {
|
||||
app = loopback();
|
||||
|
||||
// setup default data sources
|
||||
loopback.setDefaultDataSourceForType('db', {
|
||||
connector: loopback.Memory
|
||||
});
|
||||
|
||||
loopback.setDefaultDataSourceForType('mail', {
|
||||
connector: loopback.Mail,
|
||||
transports: [
|
||||
{type: 'STUB'}
|
||||
]
|
||||
});
|
||||
|
||||
// auto attach data sources to models
|
||||
loopback.autoAttach();
|
||||
});
|
||||
|
||||
assertValidDataSource = function (dataSource) {
|
||||
|
|
|
@ -8,20 +8,14 @@ var userMemory = loopback.createDataSource({
|
|||
});
|
||||
|
||||
describe('User', function(){
|
||||
|
||||
var mailDataSource = loopback.createDataSource({
|
||||
connector: MailConnector,
|
||||
transports: [{type: 'STUB'}]
|
||||
});
|
||||
User.attachTo(userMemory);
|
||||
AccessToken.attachTo(userMemory);
|
||||
// TODO(ritch) - this should be a default relationship
|
||||
User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'});
|
||||
User.email.attachTo(mailDataSource);
|
||||
|
||||
// allow many User.afterRemote's to be called
|
||||
User.setMaxListeners(0);
|
||||
|
||||
before(function () {
|
||||
debugger;
|
||||
User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'});
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
app.use(loopback.rest());
|
||||
app.model(User);
|
||||
|
|
Loading…
Reference in New Issue