diff --git a/changelog/22502.txt b/changelog/22502.txt new file mode 100644 index 000000000..b9d21c2ce --- /dev/null +++ b/changelog/22502.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: KV View Secret card will link to list view if input ends in "/" +``` \ No newline at end of file diff --git a/ui/app/components/get-credentials-card.js b/ui/app/components/get-credentials-card.js index 60ff42e33..ddb432eb7 100644 --- a/ui/app/components/get-credentials-card.js +++ b/ui/app/components/get-credentials-card.js @@ -32,18 +32,38 @@ export default class GetCredentialsCard extends Component { @tracked role = ''; @tracked secret = ''; + constructor() { + super(...arguments); + this.secret = this.args?.initialValue || ''; + } + + get buttonText() { + if (this.args.type === 'secret') { + if (this.secret.endsWith('/')) { + return 'View list'; + } + return 'View secret'; + } + return 'Get credentials'; + } + get buttonDisabled() { return !this.role && !this.secret; } @action - transitionToCredential() { + transitionToCredential(evt) { + evt.preventDefault(); const role = this.role; const secret = this.secret; if (role) { this.router.transitionTo('vault.cluster.secrets.backend.credentials', role); } if (secret) { + if (secret.endsWith('/')) { + this.router.transitionTo('vault.cluster.secrets.backend.list', secret); + return; + } this.router.transitionTo('vault.cluster.secrets.backend.show', secret); } } diff --git a/ui/app/templates/components/get-credentials-card.hbs b/ui/app/templates/components/get-credentials-card.hbs index 563a5d862..916345403 100644 --- a/ui/app/templates/components/get-credentials-card.hbs +++ b/ui/app/templates/components/get-credentials-card.hbs @@ -1,4 +1,4 @@ -
+

{{@title}}

@@ -11,6 +11,7 @@ @id="search-input-{{@type}}" @onChange={{this.handleInput}} @placeholder={{@placeholder}} + @initialValue={{@initialValue}} data-test-search-roles /> {{else}} @@ -25,13 +26,7 @@ data-test-search-roles /> {{/if}} -
\ No newline at end of file diff --git a/ui/app/templates/vault/cluster/secrets/backend/list.hbs b/ui/app/templates/vault/cluster/secrets/backend/list.hbs index e4e314f94..06e4bd11b 100644 --- a/ui/app/templates/vault/cluster/secrets/backend/list.hbs +++ b/ui/app/templates/vault/cluster/secrets/backend/list.hbs @@ -26,10 +26,10 @@ @renderInputSearch={{true}} @title="View secret" @searchLabel="Secret path" - @subText="Type the path of the secret you want to read" + @subText="Type the path of the secret you want to view. Include a trailing slash to navigate to the list view." @placeholder="secret/" - @backend="kv" @type="secret" + @initialValue={{this.baseKey.id}} /> @@ -143,7 +143,7 @@ `); assert.dom('[data-test-get-credentials]').isDisabled(); + assert.dom('[data-test-get-credentials]').hasText('Get credentials', 'Button has default text'); }); test('it shows button that can be clicked to credentials route when an item is selected', async function (assert) { @@ -89,6 +90,7 @@ module('Integration | Component | get-credentials-card', function (hooks) { ); await typeIn('[data-test-search-roles] input', 'test'); assert.dom('[data-test-get-credentials]').isEnabled('submit button enables after typing input text'); + assert.dom('[data-test-get-credentials]').hasText('View secret', 'Button has view secret CTA'); await click('[data-test-get-credentials]'); assert.propEqual( this.router.transitionTo.lastCall.args, @@ -96,4 +98,44 @@ module('Integration | Component | get-credentials-card', function (hooks) { 'transitionTo is called with correct route and secret name' ); }); + + test('it prefills input if initialValue has value', async function (assert) { + await render( + hbs`` + ); + assert + .dom('[data-test-component="search-select"]') + .doesNotExist('does not render search select component'); + assert.dom('[data-test-search-roles] input').hasValue('hello/', 'pre-fills search input'); + assert.dom('[data-test-get-credentials]').isEnabled('submit button is enabled at render'); + assert.dom('[data-test-get-credentials]').hasText('View list', 'Button has list CTA'); + await typeIn('[data-test-search-roles] input', 'test'); + assert + .dom('[data-test-get-credentials]') + .hasText('View secret', 'Button has view secret CTA after input'); + await click('[data-test-get-credentials]'); + assert.propEqual( + this.router.transitionTo.lastCall.args, + ['vault.cluster.secrets.backend.show', 'hello/test'], + 'transitionTo is called with correct route and secret name' + ); + }); + + test('it goes to list route if input ends in / and type=secret', async function (assert) { + await render( + hbs`` + ); + assert + .dom('[data-test-component="search-select"]') + .doesNotExist('does not render search select component'); + await typeIn('[data-test-search-roles] input', 'test/'); + assert.dom('[data-test-get-credentials]').hasText('View list', 'submit button has list CTA'); + assert.dom('[data-test-get-credentials]').isEnabled('submit button is enabled at render'); + await click('[data-test-get-credentials]'); + assert.propEqual( + this.router.transitionTo.lastCall.args, + ['vault.cluster.secrets.backend.list', 'test/'], + 'transitionTo is called with correct route and secret name' + ); + }); });