Merge branch 'master' into 2.0

Conflicts:
	test/access-token.test.js
This commit is contained in:
Miroslav Bajtoš 2014-06-16 10:20:22 +02:00
commit 56c7a6b3c5
2 changed files with 64 additions and 8 deletions

View File

@ -141,7 +141,7 @@ app.model = function (Model, config) {
configureModel(Model, config, this); configureModel(Model, config, this);
isPublic = config.public !== false; isPublic = config.public !== false;
} else { } else {
assert(Model.prototype instanceof loopback.Model, assert(Model.prototype instanceof registry.Model,
'Model must be a descendant of loopback.Model'); 'Model must be a descendant of loopback.Model');
} }
@ -320,6 +320,7 @@ app.dataSources = app.datasources = {};
app.enableAuth = function() { app.enableAuth = function() {
var remotes = this.remotes(); var remotes = this.remotes();
var app = this;
remotes.before('**', function(ctx, next, method) { remotes.before('**', function(ctx, next, method) {
var req = ctx.req; var req = ctx.req;
@ -327,6 +328,12 @@ app.enableAuth = function() {
var modelInstance = ctx.instance; var modelInstance = ctx.instance;
var modelId = modelInstance && modelInstance.id || req.param('id'); var modelId = modelInstance && modelInstance.id || req.param('id');
var modelSettings = Model.settings || {};
var errStatusCode = modelSettings.aclErrorStatus || app.get('aclErrorStatus') || 401;
if(!req.accessToken){
errStatusCode = 401;
}
if(Model.checkAccess) { if(Model.checkAccess) {
// Pause the request before checking access // Pause the request before checking access
// See https://github.com/strongloop/loopback-storage-service/issues/7 // See https://github.com/strongloop/loopback-storage-service/issues/7
@ -344,8 +351,15 @@ app.enableAuth = function() {
} else if(allowed) { } else if(allowed) {
next(); next();
} else { } else {
var e = new Error('Access Denied');
e.statusCode = 401; var messages = {
403:'Access Denied',
404: ('could not find a model with id ' + modelId),
401:'Authorization Required'
};
var e = new Error(messages[errStatusCode] || messages[403]);
e.statusCode = errStatusCode;
next(e); next(e);
} }
} }

View File

@ -81,13 +81,38 @@ describe('app.enableAuth()', function() {
beforeEach(createTestingToken); beforeEach(createTestingToken);
it('should prevent remote method calls if the accessToken doesnt have access', function (done) { it('prevents remote call with 401 status on denied ACL', function (done) {
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.del('/tests/123') .del('/tests/123')
.expect(401) .expect(401)
.set('authorization', this.token.id) .set('authorization', this.token.id)
.end(done); .end(done);
}); });
it('prevent remote call with app setting status on denied ACL', function (done) {
createTestAppAndRequest(this.token, {app:{aclErrorStatus:403}}, done)
.del('/tests/123')
.expect(403)
.set('authorization', this.token.id)
.end(done);
});
it('prevent remote call with app setting status on denied ACL', function (done) {
createTestAppAndRequest(this.token, {model:{aclErrorStatus:404}}, done)
.del('/tests/123')
.expect(404)
.set('authorization', this.token.id)
.end(done);
});
it('prevent remote call if the accessToken is missing and required', function (done) {
createTestAppAndRequest(null, done)
.del('/tests/123')
.expect(401)
.set('authorization', null)
.end(done);
});
}); });
function createTestingToken(done) { function createTestingToken(done) {
@ -99,12 +124,19 @@ function createTestingToken(done) {
}); });
} }
function createTestAppAndRequest(testToken, done) { function createTestAppAndRequest(testToken, settings, done) {
var app = createTestApp(testToken, done); var app = createTestApp(testToken, settings, done);
return request(app); return request(app);
} }
function createTestApp(testToken, done) { function createTestApp(testToken, settings, done) {
done = arguments[arguments.length-1];
if(settings == done) settings = {};
settings = settings || {};
var appSettings = settings.app || {};
var modelSettings = settings.model || {};
var app = loopback(); var app = loopback();
app.use(loopback.cookieParser('secret')); app.use(loopback.cookieParser('secret'));
@ -125,7 +157,11 @@ function createTestApp(testToken, done) {
app.use(loopback.rest()); app.use(loopback.rest());
app.enableAuth(); app.enableAuth();
var TestModel = loopback.PersistedModel.extend('test', {}, { Object.keys(appSettings).forEach(function(key){
app.set(key, appSettings[key]);
});
var modelOptions = {
acls: [ acls: [
{ {
principalType: "ROLE", principalType: "ROLE",
@ -135,8 +171,14 @@ function createTestApp(testToken, done) {
property: 'removeById' property: 'removeById'
} }
] ]
};
Object.keys(modelSettings).forEach(function(key){
modelOptions[key] = modelSettings[key];
}); });
var TestModel = loopback.PersistedModel.extend('test', {}, modelOptions);
TestModel.attachTo(loopback.memory()); TestModel.attachTo(loopback.memory());
app.model(TestModel); app.model(TestModel);