Skip to content

Commit 98eed72

Browse files
committed
Merge pull request #2628 from benkroeger/master
Fix acl related model resolution Close #2628
2 parents cc95860 + 4ff9a4c commit 98eed72

File tree

5 files changed

+53
-10
lines changed

5 files changed

+53
-10
lines changed

common/models/acl.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,9 @@ module.exports = function(ACL) {
395395
*/
396396

397397
ACL.checkAccessForContext = function(context, callback) {
398-
var registry = this.registry;
398+
var self = this;
399+
self.resolveRelatedModels();
400+
var roleModel = self.roleModel;
399401

400402
if (!(context instanceof AccessContext)) {
401403
context = new AccessContext(context);
@@ -418,10 +420,8 @@ module.exports = function(ACL) {
418420
var req = new AccessRequest(modelName, property, accessType, ACL.DEFAULT, methodNames);
419421

420422
var effectiveACLs = [];
421-
var staticACLs = this.getStaticACLs(model.modelName, property);
423+
var staticACLs = self.getStaticACLs(model.modelName, property);
422424

423-
var self = this;
424-
var roleModel = registry.getModelByType(Role);
425425
this.find({ where: { model: model.modelName, property: propertyQuery,
426426
accessType: accessTypeQuery }}, function(err, acls) {
427427
if (err) {
@@ -508,10 +508,10 @@ module.exports = function(ACL) {
508508
ACL.resolveRelatedModels = function() {
509509
if (!this.roleModel) {
510510
var reg = this.registry;
511-
this.roleModel = reg.getModelByType(loopback.Role);
512-
this.roleMappingModel = reg.getModelByType(loopback.RoleMapping);
513-
this.userModel = reg.getModelByType(loopback.User);
514-
this.applicationModel = reg.getModelByType(loopback.Application);
511+
this.roleModel = reg.getModelByType('Role');
512+
this.roleMappingModel = reg.getModelByType('RoleMapping');
513+
this.userModel = reg.getModelByType('User');
514+
this.applicationModel = reg.getModelByType('Application');
515515
}
516516
};
517517

test/access-control.integration.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,34 @@ describe('access control - integration', function() {
142142
});
143143

144144
describe('/banks', function() {
145+
var SPECIAL_USER = { email: '[email protected]', password: 'test' };
146+
147+
// define dynamic role that would only grant access when the authenticated user's email is equal to
148+
// SPECIAL_USER's email
149+
150+
before(function() {
151+
var roleModel = app.registry.getModel('Role');
152+
var userModel = app.registry.getModel('user');
153+
154+
roleModel.registerResolver('$dynamic-role', function(role, context, callback) {
155+
if (!(context && context.accessToken && context.accessToken.userId)) {
156+
return process.nextTick(function() {
157+
callback && callback(null, false);
158+
});
159+
}
160+
var accessToken = context.accessToken;
161+
userModel.findById(accessToken.userId, function(err, user) {
162+
if (err) {
163+
return callback(err, false);
164+
}
165+
if (user && user.email === SPECIAL_USER.email) {
166+
return callback(null, true);
167+
}
168+
return callback(null, false);
169+
});
170+
});
171+
});
172+
145173
lt.beforeEach.givenModel('bank');
146174

147175
lt.it.shouldBeAllowedWhenCalledAnonymously('GET', '/api/banks');
@@ -163,6 +191,7 @@ describe('access control - integration', function() {
163191
lt.it.shouldBeDeniedWhenCalledAnonymously('DELETE', urlForBank);
164192
lt.it.shouldBeDeniedWhenCalledUnauthenticated('DELETE', urlForBank);
165193
lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'DELETE', urlForBank);
194+
lt.it.shouldBeAllowedWhenCalledByUser(SPECIAL_USER, 'DELETE', urlForBank);
166195

167196
function urlForBank() {
168197
return '/api/banks/' + this.bank.id;

test/fixtures/access-control/common/models/bank.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
"permission": "ALLOW",
2323
"principalType": "ROLE",
2424
"principalId": "$everyone"
25+
},
26+
{
27+
"accessType": "WRITE",
28+
"permission": "ALLOW",
29+
"principalType": "ROLE",
30+
"principalId": "$dynamic-role"
2531
}
2632
],
2733
"properties": {}

test/fixtures/access-control/server/server.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55

66
var loopback = require('../../../..');
77
var boot = require('loopback-boot');
8-
var app = module.exports = loopback({ localRegistry: true });
8+
var app = module.exports = loopback({
9+
localRegistry: true,
10+
loadBuiltinModels: true,
11+
});
912
var errorHandler = require('strong-error-handler');
13+
1014
boot(app, __dirname);
1115

1216
var apiPath = '/api';

test/fixtures/user-integration-app/server/server.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55

66
var loopback = require('../../../../index');
77
var boot = require('loopback-boot');
8-
var app = module.exports = loopback({ localRegistry: true });
8+
var app = module.exports = loopback({
9+
localRegistry: true,
10+
loadBuiltinModels: true,
11+
});
912
var errorHandler = require('strong-error-handler');
13+
1014
app.enableAuth();
1115
boot(app, __dirname);
1216
app.use(loopback.token({ model: app.models.AccessToken }));

0 commit comments

Comments
 (0)