Various ACL fixes
This commit is contained in:
parent
f08b09823d
commit
4560ec0964
|
@ -162,12 +162,7 @@ app.enableAuth = function() {
|
||||||
var req = ctx.req;
|
var req = ctx.req;
|
||||||
var Model = method.ctor;
|
var Model = method.ctor;
|
||||||
var modelInstance = ctx.instance;
|
var modelInstance = ctx.instance;
|
||||||
var modelId = modelInstance && modelInstance.id;
|
var modelId = modelInstance && modelInstance.id || req.param('id');
|
||||||
|
|
||||||
// TODO(ritch) - this fallback could be less express dependent
|
|
||||||
if(modelInstance && !modelId) {
|
|
||||||
modelId = req.param('id');
|
|
||||||
}
|
|
||||||
|
|
||||||
Model.checkAccess(
|
Model.checkAccess(
|
||||||
req.accessToken,
|
req.accessToken,
|
||||||
|
|
|
@ -95,7 +95,7 @@ AccessToken.findForRequest = function(req, options, cb) {
|
||||||
this.findById(id, function(err, token) {
|
this.findById(id, function(err, token) {
|
||||||
if(err) {
|
if(err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
} else {
|
} else if(token) {
|
||||||
token.validate(function(err, isValid) {
|
token.validate(function(err, isValid) {
|
||||||
if(err) {
|
if(err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
|
@ -105,6 +105,8 @@ AccessToken.findForRequest = function(req, options, cb) {
|
||||||
cb(new Error('Invalid Access Token'));
|
cb(new Error('Invalid Access Token'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
cb();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
var loopback = require('../loopback');
|
var loopback = require('../loopback');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var debug = require('debug')('acl');
|
||||||
|
|
||||||
var role = require('./role');
|
var role = require('./role');
|
||||||
var Role = role.Role;
|
var Role = role.Role;
|
||||||
|
@ -190,6 +191,7 @@ function resolvePermission(acls, req) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
model: req.model,
|
model: req.model,
|
||||||
property: req.property,
|
property: req.property,
|
||||||
|
@ -208,7 +210,7 @@ function resolvePermission(acls, req) {
|
||||||
*
|
*
|
||||||
* @return {Object[]} An array of ACLs
|
* @return {Object[]} An array of ACLs
|
||||||
*/
|
*/
|
||||||
function getStaticACLs(principalType, principalId, model, property, accessType) {
|
function getStaticACLs(model, property, accessType) {
|
||||||
var modelClass = loopback.getModel(model);
|
var modelClass = loopback.getModel(model);
|
||||||
var staticACLs = [];
|
var staticACLs = [];
|
||||||
if (modelClass && modelClass.settings.acls) {
|
if (modelClass && modelClass.settings.acls) {
|
||||||
|
@ -269,7 +271,7 @@ ACL.checkPermission = function (principalType, principalId, model, property, acc
|
||||||
accessType: accessType
|
accessType: accessType
|
||||||
};
|
};
|
||||||
|
|
||||||
var acls = getStaticACLs(principalType, principalId, model, property, accessType);
|
var acls = getStaticACLs(model, property, accessType);
|
||||||
|
|
||||||
var resolved = resolvePermission(acls, req);
|
var resolved = resolvePermission(acls, req);
|
||||||
|
|
||||||
|
@ -355,21 +357,7 @@ ACL.checkAccess = function (context, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var effectiveACLs = [];
|
var effectiveACLs = [];
|
||||||
|
var staticACLs = getStaticACLs(model.modelName, property, accessType);
|
||||||
// Check the LDL ACLs
|
|
||||||
principals.forEach(function(p) {
|
|
||||||
effectiveACLs = effectiveACLs.concat(getStaticACLs(p.principalType, p.principalId, model.modelName, property, accessType));
|
|
||||||
});
|
|
||||||
|
|
||||||
var resolved = resolvePermission(effectiveACLs, req);
|
|
||||||
|
|
||||||
if(resolved && resolved.permission === ACL.DENY) {
|
|
||||||
// Fail fast
|
|
||||||
process.nextTick(function() {
|
|
||||||
callback && callback(null, resolved);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACL.find({where: {model: model.modelName, property: propertyQuery, accessType: accessTypeQuery}}, function (err, acls) {
|
ACL.find({where: {model: model.modelName, property: propertyQuery, accessType: accessTypeQuery}}, function (err, acls) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -377,6 +365,9 @@ ACL.checkAccess = function (context, callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var inRoleTasks = [];
|
var inRoleTasks = [];
|
||||||
|
|
||||||
|
acls = acls.concat(staticACLs);
|
||||||
|
|
||||||
acls.forEach(function (acl) {
|
acls.forEach(function (acl) {
|
||||||
principals.forEach(function (principal) {
|
principals.forEach(function (principal) {
|
||||||
if (principal.principalType === acl.pricipalType && principal.principalId === acl.principalId) {
|
if (principal.principalType === acl.pricipalType && principal.principalId === acl.principalId) {
|
||||||
|
@ -384,11 +375,12 @@ ACL.checkAccess = function (context, callback) {
|
||||||
} else if (acl.principalType === ACL.ROLE) {
|
} else if (acl.principalType === ACL.ROLE) {
|
||||||
inRoleTasks.push(function (done) {
|
inRoleTasks.push(function (done) {
|
||||||
Role.isInRole(acl.principalId,
|
Role.isInRole(acl.principalId,
|
||||||
{principalType: principal.principalType, principalId: acl.principalId, model: model, id: id, property: property},
|
{principalType: principal.principalType, userId: context.userId, principalId: acl.principalId, model: model, id: id, property: property},
|
||||||
function (err, inRole) {
|
function (err, inRole) {
|
||||||
if(!err) {
|
if(!err && inRole) {
|
||||||
effectiveACLs.push(acl);
|
effectiveACLs.push(acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
done(err, acl);
|
done(err, acl);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -429,12 +421,14 @@ ACL.checkAccessForToken = function(token, model, modelId, method, callback) {
|
||||||
var modelCtor = loopback.getModel(model);
|
var modelCtor = loopback.getModel(model);
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
|
userId: token.userId,
|
||||||
principals: principals,
|
principals: principals,
|
||||||
model: model,
|
model: model,
|
||||||
property: method,
|
property: method,
|
||||||
accessType: modelCtor._getAccessTypeForMethod(method),
|
accessType: modelCtor._getAccessTypeForMethod(method),
|
||||||
id: modelId
|
id: modelId
|
||||||
};
|
};
|
||||||
|
|
||||||
ACL.checkAccess(context, function(err, access) {
|
ACL.checkAccess(context, function(err, access) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback && callback(err);
|
callback && callback(err);
|
||||||
|
|
|
@ -161,11 +161,28 @@ Role.registerResolver(Role.OWNER, function(role, context, callback) {
|
||||||
}
|
}
|
||||||
var modelClass = context.model;
|
var modelClass = context.model;
|
||||||
var id = context.id;
|
var id = context.id;
|
||||||
var userId = context.principalId;
|
var userId = context.userId;
|
||||||
isOwner(modelClass, id, userId, callback);
|
isOwner(modelClass, id, userId, callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
function isOwner(modelClass, id, userId, callback) {
|
function isOwner(modelClass, id, userId, callback) {
|
||||||
|
if(!userId) {
|
||||||
|
process.nextTick(function() {
|
||||||
|
callback(null, false);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelClassIsUserClass = modelClass.prototype instanceof loopback.User
|
||||||
|
|| modelClass === loopback.User;
|
||||||
|
|
||||||
|
if(modelClassIsUserClass) {
|
||||||
|
process.nextTick(function() {
|
||||||
|
callback(null, id === userId);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
modelClass.findById(id, function(err, inst) {
|
modelClass.findById(id, function(err, inst) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback && callback(err);
|
callback && callback(err);
|
||||||
|
|
Loading…
Reference in New Issue