add namespace to path matching algorithm (#13948)

* refact:  namespace should be bound property

* chore: pass bound namespace property in template

* chore: update tests to account for bound namespace refactoring

* test: add test coverage for factoring namespace in path matching algo
This commit is contained in:
Jai
2022-08-01 15:33:47 -04:00
committed by GitHub
parent c182b40408
commit a095225ba7
5 changed files with 108 additions and 8 deletions

View File

@@ -61,15 +61,12 @@ export default class Variable extends AbstractAbility {
?.capabilities?.includes('destroy');
}
@computed('token.selfTokenPolicies.[]', '_namespace')
@computed('token.selfTokenPolicies.[]', 'namespace')
get allPaths() {
return (get(this, 'token.selfTokenPolicies') || [])
.toArray()
.reduce((paths, policy) => {
const matchingNamespace = this._findMatchingNamespace(
get(policy, 'rulesJSON.Namespaces') || [],
this._namespace
);
const matchingNamespace = this.namespace ?? 'default';
const variables = (get(policy, 'rulesJSON.Namespaces') || []).find(
(namespace) => namespace.Name === matchingNamespace

View File

@@ -15,7 +15,7 @@
/>
{{/if}}
<div class="button-bar">
{{#if (can "write variable" path=this.model.absolutePath)}}
{{#if (can "write variable" path=this.model.absolutePath namespace=this.model.namespace)}}
<LinkTo
@route="variables.new"
@query={{hash path=(concat this.model.absolutePath "/")}}

View File

@@ -36,7 +36,7 @@
</div>
<div>
{{#unless this.isDeleting}}
{{#if (can "write variable" path=this.model.path)}}
{{#if (can "write variable" path=this.model.path namespace=this.model.namespace)}}
<div class="two-step-button">
<LinkTo
data-test-edit-button
@@ -50,7 +50,7 @@
</div>
{{/if}}
{{/unless}}
{{#if (can "destroy variable" path=this.model.path)}}
{{#if (can "destroy variable" path=this.model.path namespace=this.model.namespace)}}
<TwoStepButton
data-test-delete-button
@alignRight={{true}}

View File

@@ -62,6 +62,11 @@ module('Acceptance | secure variables', function (hooks) {
defaultScenario(server);
const variablesToken = server.db.tokens.find(SECURE_TOKEN_ID);
window.localStorage.nomadTokenSecret = variablesToken.secretId;
server.db.variables.update({ namespace: 'default' });
const policy = server.db.policies.find('Variable Maker');
policy.rulesJSON.Namespaces[0].SecureVariables.Paths.find(
(path) => path.PathSpec === '*'
).Capabilities = ['list', 'read', 'destroy'];
await Variables.visit();
assert.equal(currentURL(), '/variables');
@@ -480,6 +485,7 @@ module('Acceptance | secure variables', function (hooks) {
policy.rulesJSON.Namespaces[0].SecureVariables.Paths.find(
(path) => path.PathSpec === '*'
).Capabilities = ['list', 'write'];
server.db.variables.update({ namespace: 'default' });
await Variables.visit();
await click('[data-test-file-row]');
// End Test Set-up
@@ -559,6 +565,7 @@ module('Acceptance | secure variables', function (hooks) {
policy.rulesJSON.Namespaces[0].SecureVariables.Paths.find(
(path) => path.PathSpec === '*'
).Capabilities = ['list', 'destroy'];
server.db.variables.update({ namespace: 'default' });
await Variables.visit();
await click('[data-test-file-row]');
// End Test Set-up

View File

@@ -859,4 +859,100 @@ module('Unit | Ability | variable', function (hooks) {
);
});
});
module('#allPaths', function () {
test('it filters by namespace and shows all matching paths on the namespace', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
selfTokenPolicies: [
{
rulesJSON: {
Namespaces: [
{
Name: 'default',
Capabilities: [],
SecureVariables: {
Paths: [{ Capabilities: ['write'], PathSpec: 'foo' }],
},
},
{
Name: 'bar',
Capabilities: [],
SecureVariables: {
Paths: [
{ Capabilities: ['read', 'write'], PathSpec: 'foo' },
],
},
},
],
},
},
],
});
this.owner.register('service:token', mockToken);
this.ability.namespace = 'bar';
const allPaths = this.ability.allPaths;
assert.deepEqual(
allPaths,
[
{
capabilities: ['read', 'write'],
name: 'foo',
},
],
'It should return the exact path match.'
);
});
test('it matches on default if no namespace is selected', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
selfTokenPolicies: [
{
rulesJSON: {
Namespaces: [
{
Name: 'default',
Capabilities: [],
SecureVariables: {
Paths: [{ Capabilities: ['write'], PathSpec: 'foo' }],
},
},
{
Name: 'bar',
Capabilities: [],
SecureVariables: {
Paths: [
{ Capabilities: ['read', 'write'], PathSpec: 'foo' },
],
},
},
],
},
},
],
});
this.owner.register('service:token', mockToken);
this.ability.namespace = undefined;
const allPaths = this.ability.allPaths;
assert.deepEqual(
allPaths,
[
{
capabilities: ['write'],
name: 'foo',
},
],
'It should return the exact path match.'
);
});
});
});