Skip to content

Commit 856cd89

Browse files
author
Tom Kirkpatrick
committed
Only apply filters if there is an ACL in place
1 parent 38693ea commit 856cd89

File tree

1 file changed

+40
-17
lines changed

1 file changed

+40
-17
lines changed

lib/utils.js

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const debug = require('debug')('loopback:componenet:access');
44
const createPromiseCallback = require('loopback-datasource-juggler/lib/utils').createPromiseCallback;
55
const _defaults = require('lodash').defaults;
66
const _get = require('lodash').get;
7-
const Promise = require("bluebird");
7+
const Promise = require('bluebird');
88

99
module.exports = class AccessUtils {
1010
constructor(app, options) {
@@ -57,18 +57,27 @@ module.exports = class AccessUtils {
5757
const currentUser = this.getCurrentUser();
5858

5959
if (currentUser) {
60-
// Do noinvoice if options.skipAccess has been set.
60+
// Do not filter if options.skipAccess has been set.
6161
if (ctx.options.skipAccess) {
6262
debug('skipAccess: true - skipping access filters');
6363
return next();
6464
}
6565

66-
// Do noinvoice if the request is being made against a single model instance.
66+
// Do not filter if the request is being made against a single model instance.
6767
if (_get(ctx.query, 'where.id')) {
6868
debug('looking up by Id - skipping access filters');
6969
return next();
7070
}
7171

72+
// Do not apply filters if no group access acls were applied.
73+
const loopbackContext = this.app.loopback.getCurrentContext();
74+
const groupAccessApplied = loopbackContext && loopbackContext.get('groupAccessApplied') || false;
75+
76+
if (!groupAccessApplied) {
77+
debug('acls not appled - skipping access filters');
78+
return next();
79+
}
80+
7281
debug('%s observe access: query=%s, options=%o, hookState=%o',
7382
Model.modelName, JSON.stringify(ctx.query, null, 4), ctx.options, ctx.hookState);
7483

@@ -259,19 +268,19 @@ module.exports = class AccessUtils {
259268
const Role = this.app.models[this.options.roleModel];
260269

261270
Role.registerResolver(accessGroup, (role, context, cb) => {
262-
const currentUserId = context.accessToken.userId;
271+
const currentUser = this.getCurrentUser();
263272
const roleName = this.extractRoleName(role);
264273
const GroupAccess = this.app.models[this.options.groupAccessModel];
265274
const scope = { };
266275

267276
// Do not allow anonymous users.
268-
if (!currentUserId) {
277+
if (!currentUser) {
269278
debug('access denied for anonymous user');
270279
return process.nextTick(() => cb(null, false));
271280
}
272281

273282
debug(`Role resolver for ${role}: evaluate ${context.model.definition.name} with id: ${context.modelId}` +
274-
` for currentUserId: ${currentUserId}`);
283+
` for currentUser.getId(): ${currentUser.getId()}`);
275284

276285
return Promise.join(this.getCurrentGroupId(context), this.getTargetGroupId(context),
277286
(currentGroupId, targetGroupId) => {
@@ -284,7 +293,10 @@ module.exports = class AccessUtils {
284293
scope.currentGroupId = currentGroupId;
285294
scope.targetGroupId = targetGroupId;
286295
const actions = [ ];
287-
const conditions = { userId: currentUserId, role: roleName };
296+
const conditions = {
297+
userId: currentUser.getId(),
298+
role: roleName
299+
};
288300

289301
conditions[this.options.foreignKey] = currentGroupId;
290302
actions.push(GroupAccess.count(conditions));
@@ -298,24 +310,35 @@ module.exports = class AccessUtils {
298310
return actions;
299311
})
300312
.spread((currentGroupCount, targetGroupCount) => {
313+
let res = false;
314+
301315
if (currentGroupCount === false) {
302316
// No group context was determined, so allow passthrough access.
303-
return cb(null, true);
317+
res = true;
304318
}
305-
const cMember = currentGroupCount > 0;
319+
else {
320+
// Determine grant based on the current/target group context.
321+
res = currentGroupCount > 0;
322+
323+
debug(`user ${currentUser.getId()} ${res ? 'is a' : 'is not a'}` +
324+
`${roleName} of group ${scope.currentGroupId}`);
306325

307-
debug(`user ${currentUserId} ${cMember ? 'is a' : 'is not a'} ${roleName} of group ${scope.currentGroupId}`);
326+
// If it's an attempt to save into a new group, also ensure the user has access to the target group.
327+
if (scope.targetGroupId && scope.targetGroupId !== scope.currentGroupId) {
328+
const tMember = targetGroupCount > 0;
308329

309-
// If it's an attempt to save the item into a new group, also ensure the user has access to the target group.
310-
if (scope.targetGroupId && scope.targetGroupId !== scope.currentGroupId) {
311-
const tMember = targetGroupCount > 0;
330+
debug(`user ${currentUser.getId()} ${tMember ? 'is a' : 'is not a'}` +
331+
`${roleName} of group ${scope.targetGroupId}`);
332+
res = res && tMember;
333+
}
334+
}
312335

313-
debug(`user ${currentUserId} ${tMember ? 'is a' : 'is not a'} ${roleName} of group ${scope.targetGroupId}`);
314-
return cb(null, cMember && tMember);
336+
// Note the fact that we are allowing access due to passing an ACL.
337+
if (res) {
338+
this.app.loopback.getCurrentContext().set('groupAccessApplied', true);
315339
}
316340

317-
// Otherwise, base access on the current group membership only.
318-
return cb(null, cMember);
341+
return cb(null, res);
319342
})
320343
.catch(cb);
321344
});

0 commit comments

Comments
 (0)