Skip to content

Commit

Permalink
disable wizard items that user does not have access to
Browse files Browse the repository at this point in the history
  • Loading branch information
andaley committed Jan 24, 2019
1 parent cd7ac9c commit 68e575d
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 10 deletions.
44 changes: 39 additions & 5 deletions ui/app/components/wizard/features-selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,48 @@ import { FEATURE_MACHINE_TIME } from 'vault/helpers/wizard-constants';
export default Component.extend({
wizard: service(),
version: service(),
permissions: service(),

init() {
this._super(...arguments);
this.maybeHideFeatures();
},

maybeHideFeatures() {
let features = this.get('allFeatures');
features.forEach(feat => {
feat.disabled = !this.get(`has${feat.name}Permission`);
});

if (this.get('showReplication') === false) {
let feature = this.get('allFeatures').findBy('key', 'replication');
feature.show = false;
}
},

hasSecretsPermission: computed(function() {
return this.permissions.hasPermission('sys/mounts', 'create');
}),

hasAuthenticationPermission: computed(function() {
return this.permissions.hasPermission('sys/auth', 'create');
}),

hasPoliciesPermission: computed(function() {
return this.permissions.hasPermission('sys/policies/acl', 'list');
}),

hasReplicationPermission: computed(function() {
return this.permissions.hasPermission('sys/mounts', 'create');
}),

hasToolsPermission: computed(function() {
const PATHS = ['sys/wrapping/wrap', 'sys/wrapping/lookup', 'sys/wrapping/unwrap', 'sys/wrapping/rewrap'];
return PATHS.every(path => {
return this.permissions.hasPermission(path, 'update');
});
}),

estimatedTime: computed('selectedFeatures', function() {
let time = 0;
for (let feature of Object.keys(FEATURE_MACHINE_TIME)) {
Expand All @@ -44,15 +74,15 @@ export default Component.extend({
steps: ['Enabling a secrets engine', 'Adding a secret'],
selected: false,
show: true,
permission: 'secrets',
disabled: false,
},
{
key: 'authentication',
name: 'Authentication',
steps: ['Enabling an auth method', 'Managing your auth method'],
selected: false,
show: true,
permission: 'access',
disabled: false,
},
{
key: 'policies',
Expand All @@ -65,23 +95,23 @@ export default Component.extend({
],
selected: false,
show: true,
permission: 'policies',
disabled: false,
},
{
key: 'replication',
name: 'Replication',
steps: ['Setting up replication', 'Your cluster information'],
selected: false,
show: true,
permission: 'status',
disabled: false,
},
{
key: 'tools',
name: 'Tools',
steps: ['Wrapping data', 'Lookup wrapped data', 'Rewrapping your data', 'Unwrapping your data'],
selected: false,
show: true,
permission: 'tools',
disabled: false,
},
];
}),
Expand All @@ -96,6 +126,10 @@ export default Component.extend({
.mapBy('key');
}),

cannotStartWizard: computed('selectedFeatures', function() {
return !this.get('selectedFeatures').length;
}),

actions: {
saveFeatures() {
let wizard = this.get('wizard');
Expand Down
4 changes: 2 additions & 2 deletions ui/app/helpers/has-permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { inject as service } from '@ember/service';

export default Helper.extend({
permissions: service(),
compute([navItem], { routeParams }) {
compute([route], { routeParams, capability }) {
let permissions = this.permissions;
return permissions.hasNavPermission(navItem, routeParams);
return permissions.hasNavPermission(route, routeParams, capability);
},
});
5 changes: 5 additions & 0 deletions ui/app/styles/components/features-selection.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
&.is-active {
box-shadow: 0 0 0 1px $grey-light;
}

&.is-disabled {
background-color: $ui-gray-010;
color: $ui-gray-300;
}
}

.feature-box label {
Expand Down
21 changes: 18 additions & 3 deletions ui/app/templates/components/wizard/features-selection.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@
<h3 class="feature-header">Walk me through setting up:</h3>
<form id="features-form" class="feature-selection" {{action "saveFeatures" on="submit"}}>
{{#each allFeatures as |feature|}}
{{#if (and feature.show (has-permission feature.permission))}}
<div class="feature-box {{if feature.selected 'is-active'}}">
{{#if feature.show}}
<div class="feature-box {{if feature.selected 'is-active'}} {{if feature.disabled 'is-disabled'}}"
data-test-select-input={{true}}>
<div class="b-checkbox">
<input
id="feature-{{feature.key}}"
type="checkbox"
class="styled"
checked={{feature.selected}}
onchange={{action (mut feature.selected) value="target.checked"}}
disabled={{feature.disabled}}
data-test-checkbox={{feature.name}}
/>
<label for="feature-{{feature.key}}">{{feature.name}}</label>
<button type="button" class="button is-ghost icon is-pulled-right" onclick={{action (toggle (concat feature.key "-isOpen") this)}}>
Expand All @@ -29,6 +32,11 @@
@class="has-text-grey auto-width is-paddingless is-flex-column"
/>
</button>
{{#if feature.disabled}}
<Info-Tooltip data-test-tooltip>
You do not have permissions to tour some parts of this feature
</Info-Tooltip>
{{/if}}
</div>
{{#if (get this (concat feature.key "-isOpen"))}}
<ul class="feature-steps">
Expand All @@ -41,7 +49,14 @@
{{/if}}
{{/each}}
<span class="selection-summary">
<button type="submit" class="button is-primary">Start</button>
<button
type="submit"
class="button is-primary"
disabled={{cannotStartWizard}}
data-test-start-button
>
Start
</button>
{{#if selectedFeatures}}
<span class="time-estimate"><ICon @glyph="stopwatch" @class="has-text-grey auto-width is-paddingless is-flex-column"/>About {{estimatedTime}} minutes</span>
{{/if}}
Expand Down
47 changes: 47 additions & 0 deletions ui/tests/integration/components/features-selection-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { create } from 'ember-cli-page-object';
import featuresSelection from 'vault/tests/pages/components/wizard/features-selection';
import hbs from 'htmlbars-inline-precompile';

const component = create(featuresSelection);

module('Integration | Component | features-selection', function(hooks) {
setupRenderingTest(hooks);

hooks.beforeEach(function() {
component.setContext(this);
});

hooks.afterEach(function() {
component.removeContext();
});

test('it disables and enables wizard items according to user permissions', async function(assert) {
const enabled = { Secrets: true, Authentication: false, Policies: true, Tools: false };
await render(
hbs`{{wizard/features-selection hasSecretsPermission=true hasAuthenticationPermission=false hasPoliciesPermission=true}}`
);

component.wizardItems.forEach(i => {
assert.equal(
i.hasDisabledTooltip,
!enabled[i.text],
'shows a tooltip only when the wizard item is not enabled'
);
});
});

test('it disables the start button if no wizard items are checked', async function(assert) {
await render(hbs`{{wizard/features-selection}}`);
assert.equal(component.hasDisabledStartButton, true);
});

test('it enables the start button when user has permission and wizard items are checked', async function(assert) {
await render(hbs`{{wizard/features-selection hasSecretsPermission=true}}`);
await component.selectSecrets();

assert.equal(component.hasDisabledStartButton, false);
});
});
9 changes: 9 additions & 0 deletions ui/tests/pages/components/wizard/features-selection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { collection, isPresent, property, clickable } from 'ember-cli-page-object';

export default {
wizardItems: collection('[data-test-select-input]', {
hasDisabledTooltip: isPresent('[data-test-tooltip]'),
}),
hasDisabledStartButton: property('disabled', '[data-test-start-button]'),
selectSecrets: clickable('[data-test-checkbox=Secrets]'),
};

0 comments on commit 68e575d

Please sign in to comment.