Merge branch 'release/1.6.2' into production

This commit is contained in:
Raymond Feng 2014-02-12 11:35:41 -08:00
commit ec3535e550
9 changed files with 113 additions and 56 deletions

View File

@ -305,7 +305,9 @@ app.enableAuth = function() {
next();
}
});
}
this.isAuthEnabled = true;
};
/**
* Initialize an application from an options object or a set of JSON and JavaScript files.
@ -319,7 +321,7 @@ app.enableAuth = function() {
*
* **Options**
*
* - `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files
* - `appRootDir` - _optional_ - the directory to use when loading JSON and JavaScript files
* - `models` - _optional_ - an object containing `Model` definitions
* - `dataSources` - _optional_ - an object containing `DataSource` definitions
*

View File

@ -57,6 +57,11 @@ function createApplication() {
utils.merge(app, proto);
// Create a new instance of models registry per each app instance
app.models = function() {
return proto.models.apply(this, arguments);
};
return app;
}

View File

@ -98,12 +98,13 @@ var crypto = require('crypto');
function generateKey(hmacKey, algorithm, encoding) {
hmacKey = hmacKey || 'loopback';
algorithm = algorithm || 'sha256';
encoding = encoding || 'base64';
algorithm = algorithm || 'sha1';
encoding = encoding || 'hex';
var hmac = crypto.createHmac(algorithm, hmacKey);
var buf = crypto.randomBytes(64);
var buf = crypto.randomBytes(32);
hmac.update(buf);
return hmac.digest('base64');
var key = hmac.digest(encoding);
return key;
}
/**
@ -121,7 +122,7 @@ var Application = loopback.createModel('Application', ApplicationSchema);
Application.beforeCreate = function (next) {
var app = this;
app.created = app.modified = new Date();
app.id = generateKey('id', 'sha1');
app.id = generateKey('id', 'md5');
app.clientKey = generateKey('client');
app.javaScriptKey = generateKey('javaScript');
app.restApiKey = generateKey('restApi');
@ -208,13 +209,18 @@ Application.authenticate = function (appId, key, cb) {
cb && cb(err, null);
return;
}
var matched = null;
['clientKey', 'javaScriptKey', 'restApiKey', 'windowsKey', 'masterKey'].forEach(function (k) {
if (app[k] === key) {
matched = k;
var result = null;
var keyNames = ['clientKey', 'javaScriptKey', 'restApiKey', 'windowsKey', 'masterKey'];
for (var i = 0; i < keyNames.length; i++) {
if (app[keyNames[i]] === key) {
result = {
application: app,
keyType: keyNames[i]
};
break;
}
});
cb && cb(null, matched);
}
cb && cb(null, result);
});
};

View File

@ -117,10 +117,20 @@ Model.setup = function () {
/*!
* Get the reference to ACL in a lazy fashion to avoid race condition in require
*/
var ACL = null;
function getACL() {
return ACL || (ACL = require('./acl').ACL);
}
var _aclModel = null;
Model._ACL = function getACL(ACL) {
if(ACL !== undefined) {
// The function is used as a setter
_aclModel = ACL;
}
if(_aclModel) {
return _aclModel;
}
var aclModel = require('./acl').ACL;
_aclModel = loopback.getModelByType(aclModel);
return _aclModel;
};
/**
* Check if the given access token can invoke the method
@ -137,9 +147,9 @@ function getACL() {
Model.checkAccess = function(token, modelId, method, callback) {
var ANONYMOUS = require('./access-token').ANONYMOUS;
token = token || ANONYMOUS;
var ACL = getACL();
var aclModel = Model._ACL();
var methodName = 'string' === typeof method? method: method && method.name;
ACL.checkAccessForToken(token, this.modelName, modelId, methodName, callback);
aclModel.checkAccessForToken(token, this.modelName, modelId, methodName, callback);
};
/*!
@ -158,7 +168,7 @@ Model._getAccessTypeForMethod = function(method) {
'method is a required argument and must be a RemoteMethod object'
);
var ACL = getACL();
var ACL = Model._ACL();
switch(method.name) {
case'create':

View File

@ -9,35 +9,35 @@
"Platform",
"mBaaS"
],
"version": "1.6.1",
"version": "1.6.2",
"scripts": {
"test": "mocha -R spec"
},
"dependencies": {
"debug": "~0.7.2",
"express": "~3.4.0",
"strong-remoting": "~1.2.1",
"inflection": "~1.2.5",
"passport": "~0.1.17",
"debug": "~0.7.4",
"express": "~3.4.8",
"strong-remoting": "~1.2.4",
"inflection": "~1.2.7",
"passport": "~0.2.0",
"passport-local": "~0.1.6",
"nodemailer": "~0.5.7",
"ejs": "~0.8.4",
"nodemailer": "~0.6.0",
"ejs": "~0.8.5",
"bcryptjs": "~0.7.10",
"underscore.string": "~2.3.3",
"underscore": "~1.5.2",
"underscore": "~1.6.0",
"uid2": "0.0.3",
"async": "~0.2.9"
"async": "~0.2.10"
},
"peerDependencies": {
"loopback-datasource-juggler": "~1.2.13"
"loopback-datasource-juggler": "~1.3.0"
},
"devDependencies": {
"loopback-datasource-juggler": "~1.2.13",
"mocha": "~1.14.0",
"loopback-datasource-juggler": "~1.3.0",
"mocha": "~1.17.1",
"strong-task-emitter": "0.0.x",
"supertest": "~0.8.1",
"chai": "~1.8.1",
"loopback-testing": "~0.1.0"
"supertest": "~0.9.0",
"chai": "~1.9.0",
"loopback-testing": "~0.1.2"
},
"repository": {
"type": "git",

View File

@ -76,10 +76,17 @@ describe('app', function() {
});
});
describe('app.models', function() {
it('is unique per app instance', function() {
var Color = app.model('Color', { dataSource: 'db' });
expect(app.models.Color).to.equal(Color);
var anotherApp = loopback();
expect(anotherApp.models.Color).to.equal(undefined);
});
});
describe('app.boot([options])', function () {
beforeEach(function () {
var app = this.app = loopback();
app.boot({
app: {
port: 3000,
@ -393,6 +400,14 @@ describe('app', function() {
});
});
describe('enableAuth', function() {
it('should set app.isAuthEnabled to true', function() {
expect(app.isAuthEnabled).to.not.equal(true);
app.enableAuth();
expect(app.isAuthEnabled).to.equal(true);
});
});
describe('app.get("/", loopback.status())', function () {
it('should return the status of the application', function (done) {
var app = loopback();

View File

@ -121,7 +121,8 @@ describe('Application', function () {
it('Authenticate with application id & clientKey', function (done) {
Application.authenticate(registeredApp.id, registeredApp.clientKey,
function (err, result) {
assert.equal(result, 'clientKey');
assert.equal(result.application.id, registeredApp.id);
assert.equal(result.keyType, 'clientKey');
done(err, result);
});
});
@ -129,7 +130,8 @@ describe('Application', function () {
it('Authenticate with application id & javaScriptKey', function (done) {
Application.authenticate(registeredApp.id, registeredApp.javaScriptKey,
function (err, result) {
assert.equal(result, 'javaScriptKey');
assert.equal(result.application.id, registeredApp.id);
assert.equal(result.keyType, 'javaScriptKey');
done(err, result);
});
});
@ -137,7 +139,8 @@ describe('Application', function () {
it('Authenticate with application id & restApiKey', function (done) {
Application.authenticate(registeredApp.id, registeredApp.restApiKey,
function (err, result) {
assert.equal(result, 'restApiKey');
assert.equal(result.application.id, registeredApp.id);
assert.equal(result.keyType, 'restApiKey');
done(err, result);
});
});
@ -145,7 +148,8 @@ describe('Application', function () {
it('Authenticate with application id & masterKey', function (done) {
Application.authenticate(registeredApp.id, registeredApp.masterKey,
function (err, result) {
assert.equal(result, 'masterKey');
assert.equal(result.application.id, registeredApp.id);
assert.equal(result.keyType, 'masterKey');
done(err, result);
});
});
@ -153,7 +157,8 @@ describe('Application', function () {
it('Authenticate with application id & windowsKey', function (done) {
Application.authenticate(registeredApp.id, registeredApp.windowsKey,
function (err, result) {
assert.equal(result, 'windowsKey');
assert.equal(result.application.id, registeredApp.id);
assert.equal(result.keyType, 'windowsKey');
done(err, result);
});
});
@ -170,13 +175,14 @@ describe('Application', function () {
describe('Application subclass', function () {
it('should use subclass model name', function (done) {
var MyApp = Application.extend('MyApp');
MyApp.attachTo(loopback.createDataSource({connector: loopback.Memory}));
MyApp.register('rfeng', 'MyApp2',
{description: 'My second mobile application'}, function (err, result) {
var ds = loopback.createDataSource({connector: loopback.Memory});
MyApp.attachTo(ds);
MyApp.register('rfeng', 'MyApp123',
{description: 'My 123 mobile application'}, function (err, result) {
var app = result;
assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application');
assert.equal(app.name, 'MyApp123');
assert.equal(app.description, 'My 123 mobile application');
assert(app.clientKey);
assert(app.javaScriptKey);
assert(app.restApiKey);
@ -184,6 +190,8 @@ describe('Application subclass', function () {
assert(app.masterKey);
assert(app.created);
assert(app.modified);
// Remove all instances from Application model to avoid left-over data
Application.destroyAll(function () {
MyApp.findById(app.id, function (err, myApp) {
assert(!err);
assert(myApp);
@ -196,5 +204,6 @@ describe('Application subclass', function () {
});
});
});
});
});

View File

@ -612,6 +612,16 @@ describe('Model', function() {
}
});
describe('Model._getACLModel()', function() {
it('should return the subclass of ACL', function() {
var Model = require('../').Model;
var acl = ACL.extend('acl');
Model._ACL(null); // Reset the ACL class for the base model
var model = Model._ACL();
assert.equal(model, acl);
});
});
// describe('Model.hasAndBelongsToMany()', function() {
// it("TODO: implement / document", function(done) {
// /* example -

View File

@ -17,7 +17,7 @@ request = require('supertest');
loopback.User.settings.saltWorkFactor = 4;
beforeEach(function () {
app = loopback();
this.app = app = loopback();
// setup default data sources
loopback.setDefaultDataSourceForType('db', {