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);
isPublic = config.public !== false;
} else {
assert(Model.prototype instanceof loopback.Model,
assert(Model.prototype instanceof registry.Model,
'Model must be a descendant of loopback.Model');
}
@ -320,6 +320,7 @@ app.dataSources = app.datasources = {};
app.enableAuth = function() {
var remotes = this.remotes();
var app = this;
remotes.before('**', function(ctx, next, method) {
var req = ctx.req;
@ -327,6 +328,12 @@ app.enableAuth = function() {
var modelInstance = ctx.instance;
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) {
// Pause the request before checking access
// See https://github.com/strongloop/loopback-storage-service/issues/7
@ -344,8 +351,15 @@ app.enableAuth = function() {
} else if(allowed) {
next();
} 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);
}
}

View File

@ -81,13 +81,38 @@ describe('app.enableAuth()', function() {
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)
.del('/tests/123')
.expect(401)
.set('authorization', this.token.id)
.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) {
@ -99,12 +124,19 @@ function createTestingToken(done) {
});
}
function createTestAppAndRequest(testToken, done) {
var app = createTestApp(testToken, done);
function createTestAppAndRequest(testToken, settings, done) {
var app = createTestApp(testToken, settings, done);
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();
app.use(loopback.cookieParser('secret'));
@ -125,7 +157,11 @@ function createTestApp(testToken, done) {
app.use(loopback.rest());
app.enableAuth();
var TestModel = loopback.PersistedModel.extend('test', {}, {
Object.keys(appSettings).forEach(function(key){
app.set(key, appSettings[key]);
});
var modelOptions = {
acls: [
{
principalType: "ROLE",
@ -135,8 +171,14 @@ function createTestApp(testToken, done) {
property: 'removeById'
}
]
};
Object.keys(modelSettings).forEach(function(key){
modelOptions[key] = modelSettings[key];
});
var TestModel = loopback.PersistedModel.extend('test', {}, modelOptions);
TestModel.attachTo(loopback.memory());
app.model(TestModel);