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'
+ );
});
});