如何在 Loopback 中使用 checkAccessForContext
How to use checkAccessForContext in Loopback
我有
common/models/list.json
...
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "find"
},
{
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "create"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
...
当我使用 id
1 执行 GET /lists/{id}
时(我的令牌是此列表的所有者),我的列表有 200 个响应。没关系。
但是,当我在应用程序中拨打电话时
app.models.ACL.checkAccessForContext({
principals: [{
type: 'ROLE',
id: '$owner'
}],
model: 'List',
id: 1,
property: '*',
accessType: 'READ'
}, (error, request) => {
console.log(request);
});
我有 request.permission === 'DENY'
。为什么会这样?
我通过了正确的校长吗?
感谢您的帮助。
你的代码没问题。这是一个bug(#2153) in loopback. I have made a pull request。现在你可以 monkey-patch 方法,直到错误修复被合并:
const { AccessRequest } = require('loopback/lib/access-context');
ACL.resolvePermission = function resolvePermission(acls, req) {
if (!(req instanceof AccessRequest)) {
req = new AccessRequest(req);
}
// Sort by the matching score in descending order
acls = acls.sort(function(rule1, rule2) {
return ACL.getMatchingScore(rule2, req) - ACL.getMatchingScore(rule1, req);
});
var permission = ACL.DEFAULT;
var score = 0;
for (var i = 0; i < acls.length; i++) {
var candidate = acls[i];
score = ACL.getMatchingScore(candidate, req);
if (score < 0) {
// the highest scored ACL did not match
break;
}
if (!req.isWildcard()) {
// We should stop from the first match for non-wildcard
permission = candidate.permission;
break;
} else {
if (req.exactlyMatches(candidate)) {
permission = candidate.permission;
break;
}
// For wildcard match, find the strongest permission
var candidateOrder = AccessContext.permissionOrder[candidate.permission];
var permissionOrder = AccessContext.permissionOrder[permission];
if (candidateOrder > permissionOrder) {
permission = candidate.permission;
//@issuehere
break; //This is the fix
}
}
}
if (debug.enabled) {
debug('The following ACLs were searched: ');
acls.forEach(function(acl) {
acl.debug();
debug('with score:', acl.score(req));
});
}
var res = new AccessRequest(req.model, req.property, req.accessType,
permission || ACL.DEFAULT);
return res;
};
我有
common/models/list.json
...
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "find"
},
{
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "create"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
...
当我使用 id
1 执行 GET /lists/{id}
时(我的令牌是此列表的所有者),我的列表有 200 个响应。没关系。
但是,当我在应用程序中拨打电话时
app.models.ACL.checkAccessForContext({
principals: [{
type: 'ROLE',
id: '$owner'
}],
model: 'List',
id: 1,
property: '*',
accessType: 'READ'
}, (error, request) => {
console.log(request);
});
我有 request.permission === 'DENY'
。为什么会这样?
我通过了正确的校长吗?
感谢您的帮助。
你的代码没问题。这是一个bug(#2153) in loopback. I have made a pull request。现在你可以 monkey-patch 方法,直到错误修复被合并:
const { AccessRequest } = require('loopback/lib/access-context');
ACL.resolvePermission = function resolvePermission(acls, req) {
if (!(req instanceof AccessRequest)) {
req = new AccessRequest(req);
}
// Sort by the matching score in descending order
acls = acls.sort(function(rule1, rule2) {
return ACL.getMatchingScore(rule2, req) - ACL.getMatchingScore(rule1, req);
});
var permission = ACL.DEFAULT;
var score = 0;
for (var i = 0; i < acls.length; i++) {
var candidate = acls[i];
score = ACL.getMatchingScore(candidate, req);
if (score < 0) {
// the highest scored ACL did not match
break;
}
if (!req.isWildcard()) {
// We should stop from the first match for non-wildcard
permission = candidate.permission;
break;
} else {
if (req.exactlyMatches(candidate)) {
permission = candidate.permission;
break;
}
// For wildcard match, find the strongest permission
var candidateOrder = AccessContext.permissionOrder[candidate.permission];
var permissionOrder = AccessContext.permissionOrder[permission];
if (candidateOrder > permissionOrder) {
permission = candidate.permission;
//@issuehere
break; //This is the fix
}
}
}
if (debug.enabled) {
debug('The following ACLs were searched: ');
acls.forEach(function(acl) {
acl.debug();
debug('with score:', acl.score(req));
});
}
var res = new AccessRequest(req.model, req.property, req.accessType,
permission || ACL.DEFAULT);
return res;
};