UI: VAULT-12357 VAULT-12356 Add PKI Beta tag and Modal (#18761)

* Initial beta modal set up

* Add back to old pki from engine

* Remove commented out code

* Add stylesheet and tests!

* Address feedback!

* Add id to input
This commit is contained in:
Kianna 2023-01-20 12:02:13 -08:00 committed by GitHub
parent 3762cfaf0a
commit 748f1b5395
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 209 additions and 2 deletions

View File

@ -73,6 +73,7 @@ export default class App extends Application {
],
externalRoutes: {
secrets: 'vault.cluster.secrets.backends',
secretsListRoot: 'vault.cluster.secrets.backend.list-root',
},
},
},

View File

@ -18,6 +18,11 @@
min-width: 0;
width: 12px;
}
&.is-success {
background-color: $green-100;
color: $green-700;
}
}
.tag.is-outlined {

View File

@ -25,6 +25,84 @@
<h1 class="title is-3">
<Icon @name={{@model.icon}} @size="24" class="has-text-grey-light" />
{{@model.id}}
{{#if this.isPki}}
{{#if @isEngine}}
<span>
<LinkToExternal @route="secretsListRoot" class="tag is-borderless is-underline" data-test-new-pki-beta-button>
<Icon @name="arrow-left" />
Return to old PKI
</LinkToExternal>
</span>
{{else}}
{{#if this.shouldHidePkiBetaModal}}
<LinkTo @route="vault.cluster.secrets.backend.pki.overview" class="tag is-success is-borderless">
<Icon @name="key" />
New PKI UI available
</LinkTo>
{{else}}
<button
type="button"
class="tag is-success is-v-centered text-button is-underline"
{{on "click" (action (mut this.modalOpen) true)}}
data-test-old-pki-beta-button
>
<Icon @name="key" />
New PKI UI available
</button>
<Modal
@title="New PKI Beta"
@onClose={{action (mut this.modalOpen) false}}
@isActive={{this.modalOpen}}
@showCloseButton={{true}}
>
<section class="modal-card-body">
The new PKI beta includes, among other things:
<ul class="bullet">
<li>Multiple issuers can now be generated and managed in the UI.</li>
<li>Non-disruptive root rotation: quickly rotate a root within the UI without disrupting issuance.</li>
<li>UI upgrades: smoother configuration, an overview page, and more certificate information.</li>
</ul>
<br />
You will always be able to return to this version.
<br />
<br />
You can also copy the following URL and bookmark it to always go to the beta version:
<br />
<code class="has-text-danger has-background-white-bis">
{{this.windowOrigin}}/ui/vault/secrets/{{@model.id}}/pki/overview
</code>
<br />
<br />
<Input
id="hide-beta-modal"
@type="checkbox"
@checked={{this.hidePkiBetaModal}}
{{on "change" this.toggleHidePkiBetaModal}}
/>
<label class="has-text-weight-semibold" for="hide-beta-modal">
Don't show me this again
</label>
</section>
<footer class="modal-card-foot modal-card-foot-outlined">
<button type="button" class="button is-primary" {{on "click" this.transitionToNewPki}}>
Go to beta
</button>
<button
type="button"
class="button is-secondary"
{{on "click" (fn (mut this.modalOpen) false)}}
data-test-cancel-pki-beta-modal
>
Cancel
</button>
</footer>
</Modal>
{{/if}}
{{/if}}
{{/if}}
{{#if this.isKV}}
<span class="tag" data-test-kv-version-badge>
Version
@ -32,6 +110,7 @@
</span>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
{{#if options.tabs}}

View File

@ -1,3 +1,7 @@
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import localStorage from 'vault/lib/local-storage';
import Component from '@glimmer/component';
/**
@ -23,7 +27,36 @@ import Component from '@glimmer/component';
*/
export default class SecretListHeader extends Component {
@service router;
@tracked hidePkiBetaModal = false;
get isKV() {
return ['kv', 'generic'].includes(this.args.model.engineType);
}
get isPki() {
return this.args.model.engineType === 'pki';
}
get shouldHidePkiBetaModal() {
return localStorage.getItem('hidePkiBetaModal');
}
get windowOrigin() {
return window.location.origin;
}
@action
transitionToNewPki() {
this.router.transitionTo('vault.cluster.secrets.backend.pki.overview', this.args.model.engineType);
}
@action
toggleHidePkiBetaModal() {
this.hidePkiBetaModal = !this.hidePkiBetaModal;
this.hidePkiBetaModal
? localStorage.setItem('hidePkiBetaModal', true)
: localStorage.removeItem('hidePkiBetaModal');
}
}

View File

@ -23,7 +23,7 @@ export default class PkiEngine extends Engine {
'version',
'wizard',
],
externalRoutes: ['secrets'],
externalRoutes: ['secrets', 'secretsListRoot'],
};
}

View File

@ -1,6 +1,6 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { render, click } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { supportedSecretBackends } from 'vault/helpers/supported-secret-backends';
import { setupMirage } from 'ember-cli-mirage/test-support';
@ -23,8 +23,10 @@ module('Integration | Component | secret-list-header', function (hooks) {
<SecretListHeader
@model={{this.model}}
/>
<div id="modal-wormhole"></div>
`);
const selector = '[data-test-kv-version-badge]';
if (['kv', 'generic'].includes(type)) {
assert
.dom(selector)
@ -37,4 +39,91 @@ module('Integration | Component | secret-list-header', function (hooks) {
}
}
});
test('it should render new pki beta button and remain the same for other engines', async function (assert) {
const backends = supportedSecretBackends();
const numExpects = backends.length + 1;
assert.expect(numExpects);
this.server.post('/sys/capabilities-self', () => {});
for (const type of backends) {
const data = this.server.create('secret-engine', 2, { type });
this.model = mirageToModels(data);
await render(hbs`
<SecretListHeader
@model={{this.model}}
/>
<div id="modal-wormhole"></div>
`);
const oldPkiBetaButtonSelector = '[data-test-old-pki-beta-button]';
const oldPkiBetaModalSelector = '[data-test-modal-background="New PKI Beta"]';
if (type === 'pki') {
assert.dom(oldPkiBetaButtonSelector).hasText('New PKI UI available');
await click(oldPkiBetaButtonSelector);
assert.dom(oldPkiBetaModalSelector).exists();
} else {
assert
.dom(oldPkiBetaButtonSelector)
.doesNotExist(`Version badge does not render for ${type} engine type`);
}
}
});
test('it should render return to old pki from new pki', async function (assert) {
const backends = supportedSecretBackends();
assert.expect(backends.length);
this.server.post('/sys/capabilities-self', () => {});
for (const type of backends) {
const data = this.server.create('secret-engine', 2, { type });
this.model = mirageToModels(data);
await render(hbs`
<SecretListHeader
@model={{this.model}}
@isEngine={{true}}
/>
<div id="modal-wormhole"></div>
`);
const newPkiButtonSelector = '[data-test-new-pki-beta-button]';
if (type === 'pki') {
assert.dom(newPkiButtonSelector).hasText('Return to old PKI');
} else {
assert.dom(newPkiButtonSelector).doesNotExist(`No return to old pki exists`);
}
}
});
test('it should show the pki modal when New PKI UI available button is clicked', async function (assert) {
const backends = supportedSecretBackends();
const numExpects = backends.length + 1;
assert.expect(numExpects);
this.server.post('/sys/capabilities-self', () => {});
for (const type of backends) {
const data = this.server.create('secret-engine', 2, { type });
this.model = mirageToModels(data);
await render(hbs`
<SecretListHeader
@model={{this.model}}
/>
<div id="modal-wormhole"></div>
`);
const oldPkiButtonSelector = '[data-test-old-pki-beta-button]';
const cancelPkiBetaModal = '[data-test-cancel-pki-beta-modal]';
if (type === 'pki') {
await click(oldPkiButtonSelector);
assert.dom('.modal.is-active').exists('Pki beta modal is open');
await click(cancelPkiBetaModal);
assert.dom('.modal').exists('Pki beta modal is closed');
} else {
assert.dom(oldPkiButtonSelector).doesNotExist(`No return to old pki exists`);
}
}
});
});