From 2f2e0184bb57996c0e94955173d6dc6556ff30bf Mon Sep 17 00:00:00 2001 From: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Date: Wed, 14 Feb 2024 11:04:20 -0800 Subject: [PATCH] UI: Fix copy button for PKI ca_chain certificate card (#25399) * use format-copy-value helper for copy text in Hds::Copy::Button * delete helper and revert masked input * update certificate card to format to string * add test * add changelog; --- changelog/25399.txt | 3 ++ ui/app/styles/helper-classes/layout.scss | 2 +- .../addon/components/certificate-card.hbs | 6 +-- .../core/addon/components/certificate-card.js | 29 +++++++++---- .../components/page/pki-issuer-details.hbs | 2 +- .../components/certificate-card-test.js | 43 ++++++++++++++----- 6 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 changelog/25399.txt diff --git a/changelog/25399.txt b/changelog/25399.txt new file mode 100644 index 0000000000..d0b6405cc5 --- /dev/null +++ b/changelog/25399.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Fix PKI ca_chain display so value can be copied to clipboard +``` diff --git a/ui/app/styles/helper-classes/layout.scss b/ui/app/styles/helper-classes/layout.scss index 544c34fa0d..fa654da798 100644 --- a/ui/app/styles/helper-classes/layout.scss +++ b/ui/app/styles/helper-classes/layout.scss @@ -77,7 +77,7 @@ } .is-medium-width { - width: calc($desktop / 3); + width: calc($desktop / 2.5); } .is-medium-height { diff --git a/ui/lib/core/addon/components/certificate-card.hbs b/ui/lib/core/addon/components/certificate-card.hbs index 044067b817..d9ac86f556 100644 --- a/ui/lib/core/addon/components/certificate-card.hbs +++ b/ui/lib/core/addon/components/certificate-card.hbs @@ -14,7 +14,7 @@

- {{this.format}} + {{this.certLabel}}

{{@data}} @@ -24,9 +24,9 @@
\ No newline at end of file diff --git a/ui/lib/core/addon/components/certificate-card.js b/ui/lib/core/addon/components/certificate-card.js index 03e8baf39a..f7dd8ff4bd 100644 --- a/ui/lib/core/addon/components/certificate-card.js +++ b/ui/lib/core/addon/components/certificate-card.js @@ -17,24 +17,35 @@ import Component from '@glimmer/component'; * * ``` * @param {string} data - the data to be displayed in the component (usually in PEM or DER format) - * @param {boolean} isPem - optional argument for if the data is required to be in PEM format (and should thus have the PEM Format label) + * @param {boolean} [isPem] - optional argument for if the data is required to be in PEM format (and should thus have the PEM Format label) */ export default class CertificateCardComponent extends Component { - // Returns the format the data is in: PEM, DER, or no format if no data is provided - get format() { + get certLabel() { if (!this.args.data) return ''; - let value; - if (typeof this.args.data === 'object') { - value = this.args.data[0]; - } else { - value = this.args.data; - } + const value = Array.isArray(this.args.data) ? this.args.data[0] : this.args.data; if (value.substring(0, 11) === '-----BEGIN ' || this.args.isPem === true) { return 'PEM Format'; } return 'DER Format'; } + + get copyValue() { + const { data } = this.args; + if (!data) return data; + const type = Array.isArray(data) ? 'array' : typeof data; + switch (type) { + case 'string': + return data; + case 'array': + return data.join('\n'); + case 'object': + // unlikely for certificates but just in case + return JSON.stringify(data); + default: + return data.toString(); + } + } } diff --git a/ui/lib/pki/addon/components/page/pki-issuer-details.hbs b/ui/lib/pki/addon/components/page/pki-issuer-details.hbs index 35a88266ba..5924d9f959 100644 --- a/ui/lib/pki/addon/components/page/pki-issuer-details.hbs +++ b/ui/lib/pki/addon/components/page/pki-issuer-details.hbs @@ -116,7 +116,7 @@ @value={{get @issuer attr.name}} @formatDate={{if attr.options.formatDate "MMM d yyyy HH:mm:ss a zzzz"}} @alwaysRender={{true}} - @addCopyButton={{(eq attr.name "issuerId")}} + @addCopyButton={{eq attr.name "issuerId"}} /> {{/if}} {{/each}} diff --git a/ui/tests/integration/components/certificate-card-test.js b/ui/tests/integration/components/certificate-card-test.js index 3d16b68cff..6680047654 100644 --- a/ui/tests/integration/components/certificate-card-test.js +++ b/ui/tests/integration/components/certificate-card-test.js @@ -7,8 +7,7 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'vault/tests/helpers'; import { render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; -import { rootPem } from 'vault/tests/helpers/pki/values'; -import { rootDer } from 'vault/tests/helpers/pki/values'; +import { rootPem, rootDer } from 'vault/tests/helpers/pki/values'; const SELECTORS = { label: '[data-test-certificate-label]', @@ -31,35 +30,57 @@ module('Integration | Component | certificate-card', function (hooks) { }); test('it renders with an example PEM Certificate', async function (assert) { - const certificate = rootPem; - this.set('certificate', certificate); + this.certificate = rootPem; await render(hbs``); assert.dom(SELECTORS.label).hasText('PEM Format', 'The label text is PEM Format'); - assert.dom(SELECTORS.value).hasText(certificate, 'The data rendered is correct'); + assert.dom(SELECTORS.value).hasText(this.certificate, 'The data rendered is correct'); assert.dom(SELECTORS.icon).exists('The certificate icon exists'); assert.dom(SELECTORS.copyButton).exists('The copy button exists'); + assert + .dom(SELECTORS.copyButton) + .hasAttribute('data-test-copy-button', this.certificate, 'copy value is the same as data'); }); test('it renders with an example DER Certificate', async function (assert) { - const certificate = rootDer; - this.set('certificate', certificate); + this.certificate = rootDer; await render(hbs``); assert.dom(SELECTORS.label).hasText('DER Format', 'The label text is DER Format'); - assert.dom(SELECTORS.value).hasText(certificate, 'The data rendered is correct'); + assert.dom(SELECTORS.value).hasText(this.certificate, 'The data rendered is correct'); assert.dom(SELECTORS.icon).exists('The certificate icon exists'); assert.dom(SELECTORS.copyButton).exists('The copy button exists'); + assert + .dom(SELECTORS.copyButton) + .hasAttribute('data-test-copy-button', this.certificate, 'copy value is the same as data'); }); test('it renders with the PEM Format label regardless of the value provided when @isPem is true', async function (assert) { - const certificate = 'example-certificate-text'; - this.set('certificate', certificate); + this.certificate = 'example-certificate-text'; await render(hbs``); assert.dom(SELECTORS.label).hasText('PEM Format', 'The label text is PEM Format'); - assert.dom(SELECTORS.value).hasText(certificate, 'The data rendered is correct'); + assert.dom(SELECTORS.value).hasText(this.certificate, 'The data rendered is correct'); + }); + + test('it renders with an example CA Chain', async function (assert) { + this.caChain = [ + '-----BEGIN CERTIFICATE-----\nMIIDIDCCA...\n-----END CERTIFICATE-----\n', + '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBA...\n-----END RSA PRIVATE KEY-----\n', + ]; + + await render(hbs``); + + assert.dom(SELECTORS.label).hasText('PEM Format', 'The label text is PEM Format'); + assert.dom(SELECTORS.value).hasText(this.caChain.join(','), 'The data rendered is correct'); assert.dom(SELECTORS.icon).exists('The certificate icon exists'); assert.dom(SELECTORS.copyButton).exists('The copy button exists'); + assert + .dom(SELECTORS.copyButton) + .hasAttribute( + 'data-test-copy-button', + this.caChain.join('\n'), + 'copy value is array converted to a string' + ); }); });