Initial auto wiring for model dataSources

This commit is contained in:
Ritchie Martori 2013-11-18 16:13:40 -08:00
parent 9eb44bdb59
commit da0545bed6
8 changed files with 93 additions and 42 deletions

View File

@ -108,7 +108,9 @@ loopback.createDataSource = function (name, options) {
*/ */
loopback.createModel = function (name, properties, options) { loopback.createModel = function (name, properties, options) {
return loopback.Model.extend(name, properties, options); var model = loopback.Model.extend(name, properties, options);
return model;
} }
/** /**
@ -173,6 +175,53 @@ loopback.getModel = function(modelName) {
return loopback.Model.modelBuilder.models[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');
var lb = this;
Object.keys(models).forEach(function(modelName) {
var ModelCtor = models[modelName];
if(ModelCtor.autoAttach) {
var ds = lb.getDefaultDataSourceForType(ModelCtor.autoAttach);
assert(ds instanceof DataSource, 'cannot autoAttach model "' + modelName
+ '". No dataSource found of type ' + ModelCtor.attachTo);
ModelCtor.attachTo(ds);
}
});
}
/* /*
* Built in models / services * Built in models / services
*/ */
@ -182,3 +231,24 @@ loopback.Email = require('./models/email');
loopback.User = require('./models/user'); loopback.User = require('./models/user');
loopback.Application = require('./models/application'); loopback.Application = require('./models/application');
loopback.AccessToken = require('./models/access-token'); loopback.AccessToken = require('./models/access-token');
loopback.Role = require('./models/role');
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.ACL.autoAttach = dataSourceTypes.DB;
loopback.Scope.autoAttach = dataSourceTypes.DB;
loopback.Application.autoAttach = dataSourceTypes.DB;

View File

@ -1,7 +1,7 @@
/** /**
* Module Dependencies. * Module Dependencies.
*/ */
var loopback = require('../loopback');
var ModelBuilder = require('loopback-datasource-juggler').ModelBuilder; var ModelBuilder = require('loopback-datasource-juggler').ModelBuilder;
var modeler = new ModelBuilder(); var modeler = new ModelBuilder();

View File

@ -1,9 +1,6 @@
var loopback = require('../'); var loopback = require('../');
var Token = loopback.AccessToken.extend('MyToken'); var Token = loopback.AccessToken.extend('MyToken');
// attach Token to testing memory ds
Token.attachTo(loopback.memory());
describe('loopback.token(options)', function() { describe('loopback.token(options)', function() {
beforeEach(createTestingToken); beforeEach(createTestingToken);

View File

@ -14,18 +14,10 @@ function checkResult(err, result) {
describe('security scopes', function () { describe('security scopes', function () {
it("should allow access to models for the given scope by wildcard", 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) { 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, ACL.create({principalType: ACL.SCOPE, principalId: scope.id, model: 'User', property: ACL.ALL,
accessType: ACL.ALL, permission: ACL.ALLOW}, accessType: ACL.ALL, permission: ACL.ALLOW},
function (err, resource) { function (err, resource) {
// console.log(resource);
Scope.checkPermission('userScope', 'User', ACL.ALL, ACL.ALL, checkResult); Scope.checkPermission('userScope', 'User', ACL.ALL, ACL.ALL, checkResult);
Scope.checkPermission('userScope', 'User', 'name', ACL.ALL, checkResult); Scope.checkPermission('userScope', 'User', 'name', ACL.ALL, checkResult);
Scope.checkPermission('userScope', 'User', 'name', ACL.READ, 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 () { it("should allow access to models for the given scope", function () {
var ds = loopback.createDataSource({connector: loopback.Memory}); 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) { Scope.create({name: 'userScope', description: 'access user information'}, function (err, scope) {
// console.log(scope);
ACL.create({principalType: ACL.SCOPE, principalId: scope.id, ACL.create({principalType: ACL.SCOPE, principalId: scope.id,
model: 'User', property: 'name', accessType: ACL.READ, permission: ACL.ALLOW}, model: 'User', property: 'name', accessType: ACL.READ, permission: ACL.ALLOW},
function (err, resource) { function (err, resource) {
@ -74,7 +60,6 @@ describe('security ACLs', function () {
it("should allow access to models for the given principal by wildcard", function () { it("should allow access to models for the given principal by wildcard", function () {
var ds = loopback.createDataSource({connector: loopback.Memory}); var ds = loopback.createDataSource({connector: loopback.Memory});
ACL.attachTo(ds);
ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL, ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL,
accessType: ACL.ALL, permission: ACL.ALLOW}, function (err, acl) { 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} {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) { ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function (err, perm) {
assert(perm.permission === ACL.DENY); assert(perm.permission === ACL.DENY);

View File

@ -1,17 +1,8 @@
var loopback = require('../'); var loopback = require('../');
var MailConnector = loopback.Mail;
var MyEmail = loopback.Email.extend('my-email'); var MyEmail = loopback.Email.extend('my-email');
var assert = require('assert'); var assert = require('assert');
describe('Email and SMTP', function () { describe('Email and SMTP', function () {
var mail = loopback.createDataSource({
connector: MailConnector,
transports: [
{type: 'STUB'}
]
});
MyEmail.attachTo(mail);
it('should have a send method', function () { it('should have a send method', function () {
assert(typeof MyEmail.send === 'function'); assert(typeof MyEmail.send === 'function');

View File

@ -27,7 +27,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) { Application.register('rfeng', 'MyApp2', {description: 'My second mobile application'}, function (err, result) {
var app = result; var app = result;

View File

@ -12,6 +12,21 @@ request = require('supertest');
beforeEach(function () { beforeEach(function () {
app = loopback(); 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) { assertValidDataSource = function (dataSource) {

View File

@ -8,20 +8,14 @@ var userMemory = loopback.createDataSource({
}); });
describe('User', function(){ 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 // allow many User.afterRemote's to be called
User.setMaxListeners(0); User.setMaxListeners(0);
// should be able to remove this with autoAttach
User.attachTo(loopback.memory())
AccessToken.attachTo(loopback.memory());
User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'});
beforeEach(function (done) { beforeEach(function (done) {
app.use(loopback.rest()); app.use(loopback.rest());
app.model(User); app.model(User);