diff --git a/src/accesscontrol.js b/src/accesscontrol.js index 87edfd208..ec71d53c9 100644 --- a/src/accesscontrol.js +++ b/src/accesscontrol.js @@ -60,7 +60,32 @@ function intersectScopes(allowedScopes, wantedScopes) { assert(Array.isArray(allowedScopes), 'Expecting sorted array'); assert(Array.isArray(wantedScopes), 'Expecting sorted array'); - return _.intersection(allowedScopes, wantedScopes); + let wantedScopesMap = new Map(); + let results = []; + + // make a map of scope -> [ subscopes ] + for (let w of wantedScopes) { + let parts = w.split(':'); + let subscopes = wantedScopesMap.get(parts[0]) || new Set(); + subscopes.add(parts[1] || '*'); + wantedScopesMap.set(parts[0], subscopes); + } + + for (let a of allowedScopes) { + let parts = a.split(':'); + let as = parts[1] || '*'; + + let subscopes = wantedScopesMap.get(parts[0]); + if (!subscopes) continue; + + if (subscopes.has('*') || subscopes.has(as)) { + results.push(a); + } else if (as === '*') { + results = results.concat(Array.from(subscopes).map(function (ss) { return `${a}:${ss}`; })); + } + } + + return results; } function validateRoles(roles) { diff --git a/src/test/accesscontrol-test.js b/src/test/accesscontrol-test.js index 9eea9099e..30a6ae1d0 100644 --- a/src/test/accesscontrol-test.js +++ b/src/test/accesscontrol-test.js @@ -34,9 +34,10 @@ describe('access control', function () { expect(accesscontrol.intersectScopes(['cloudron', 'domains' ], ['clients', 'apps'])).to.eql([]); }); - xit('subscopes', function () { + it('subscopes', function () { expect(accesscontrol.intersectScopes(['apps:read' ], ['apps'])).to.eql(['apps:read']); - expect(accesscontrol.intersectScopes(['apps:read','profile','domains'], ['apps','domains:manage','profile'])).to.eql(['apps:read','domains:manage','profile']); + expect(accesscontrol.intersectScopes(['apps:read','domains','profile'], ['apps','domains:manage','profile'])).to.eql(['apps:read','domains:manage','profile']); + expect(accesscontrol.intersectScopes(['apps:read','domains','profile'], ['apps','apps:read'])).to.eql(['apps:read']); }); });