Skip to content

Commit

Permalink
backport of commit 88ed074 (#23263)
Browse files Browse the repository at this point in the history
Co-authored-by: claire bontempo <[email protected]>
  • Loading branch information
1 parent 9e00b34 commit f8da51c
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 28 deletions.
3 changes: 3 additions & 0 deletions changelog/23260.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: Adds warning before downloading KV v2 secret values
```
4 changes: 4 additions & 0 deletions ui/lib/core/addon/components/download-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { assert } from '@ember/debug';
* @param {function} [fetchData] - function that fetches data and returns download content
* @param {string} [extension='txt'] - file extension, the download service uses this to determine the mimetype
* @param {boolean} [stringify=false] - argument to stringify the data before passing to the File constructor
* @param {callback} [onSuccess] - callback from parent to invoke if download is successful
*/

export default class DownloadButton extends Component {
Expand Down Expand Up @@ -73,6 +74,9 @@ export default class DownloadButton extends Component {
try {
this.download.miscExtension(this.filename, this.content, this.extension);
this.flashMessages.info(`Downloading ${this.filename}`);
if (this.args.onSuccess) {
this.args.onSuccess();
}
} catch (error) {
this.flashMessages.danger(errorMessage(error, 'There was a problem downloading. Please try again.'));
}
Expand Down
44 changes: 34 additions & 10 deletions ui/lib/core/addon/components/masked-input.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,9 @@
</CopyButton>
{{/if}}
{{#if @allowDownload}}
<DownloadButton
class="button download-button"
@filename={{or @name "secret-value"}}
@data={{@value}}
@stringify={{true}}
aria-label="Download secret value"
>
<Icon @name="download" />
</DownloadButton>
<button type="button" class="button download-button" {{on "click" (fn (mut this.modalOpen) true)}}>
<Icon data-test-download-icon @name="download" />
</button>
{{/if}}
<button
onclick={{this.toggleMask}}
Expand All @@ -66,4 +60,34 @@
>
<Icon @name={{if this.showValue "eye" "eye-off"}} />
</button>
</div>
</div>

{{! CONFIRM DOWNLOAD MODAL }}
{{#if @allowDownload}}
<Modal
@title="Download secret value?"
@onClose={{action (mut this.modalOpen) false}}
@isActive={{this.modalOpen}}
@type="warning"
>
<section class="modal-card-body">
This download is
<strong>unencrypted</strong>. Are you sure you want to download this secret data as plaintext?
</section>
<footer class="modal-card-foot modal-card-foot-outlined">
<DownloadButton
class="button is-primary"
@filename={{or @name "secret-value"}}
@data={{@value}}
@stringify={{true}}
aria-label="Download secret value"
@onSuccess={{fn (mut this.modalOpen) false}}
>
Download
</DownloadButton>
<button type="button" class="button is-secondary" {{on "click" (fn (mut this.modalOpen) false)}}>
Cancel
</button>
</footer>
</Modal>
{{/if}}
2 changes: 2 additions & 0 deletions ui/lib/core/addon/components/masked-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import autosize from 'autosize';
* @param name {String} - The key correlated to the value. Used for the download file name.
* @param [onChange=Callback] {Function|action} - Callback triggered on change, sends new value. Must set the value of @value
* @param [allowCopy=false] {bool} - Whether or not the input should render with a copy button.
* @param [allowDownload=false] {bool} - Renders a download button that prompts a confirmation modal to download the secret value
* @param [displayOnly=false] {bool} - Whether or not to display the value as a display only `pre` element or as an input.
*
*/
export default class MaskedInputComponent extends Component {
textareaId = 'textarea-' + guidFor(this);
@tracked showValue = false;
@tracked modalOpen = false;

constructor() {
super(...arguments);
Expand Down
25 changes: 11 additions & 14 deletions ui/tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,27 @@

<html>
<head>
<meta charset="utf-8">
<meta charset="utf-8" />
<title>Vault Tests</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

{{content-for "head"}}
{{content-for "test-head"}}
{{content-for "head"}} {{content-for "test-head"}}

<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
<link rel="stylesheet" href="{{rootURL}}assets/vault.css">
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css" />
<link rel="stylesheet" href="{{rootURL}}assets/vault.css" />
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css" />

{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
{{content-for "head-footer"}} {{content-for "test-head-footer"}}
</head>
<body>
{{content-for "body"}}
{{content-for "test-body"}}
{{content-for "body"}} {{content-for "test-body"}}

<div id="qunit"></div>
<div id="qunit-fixture">
<div id="ember-testing-container">
<div id="ember-testing"></div>
<div id="modal-wormhole"></div>
</div>
</div>

Expand All @@ -38,7 +36,6 @@
<script src="{{rootURL}}assets/vault.js"></script>
<script src="{{rootURL}}assets/tests.js"></script>

{{content-for "body-footer"}}
{{content-for "test-body-footer"}}
{{content-for "body-footer"}} {{content-for "test-body-footer"}}
</body>
</html>
14 changes: 10 additions & 4 deletions ui/tests/integration/components/masked-input-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, focus, triggerKeyEvent, typeIn, fillIn } from '@ember/test-helpers';
import { render, focus, triggerKeyEvent, typeIn, fillIn, click } from '@ember/test-helpers';
import { create } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
Expand Down Expand Up @@ -51,8 +51,14 @@ module('Integration | Component | masked input', function (hooks) {
});

test('it renders a download button when allowDownload is true', async function (assert) {
await render(hbs`<MaskedInput @allowDownload={{true}} />`);
assert.ok(component.downloadButtonIsPresent);
await render(hbs`<MaskedInput @allowDownload={{true}} /> <div id="modal-wormhole"></div>
`);
assert.ok(component.downloadIconIsPresent);

await click('[data-test-download-icon]');
assert.ok(component.downloadButtonIsPresent, 'clicking download icon opens modal with download button');

assert;
});

test('it shortens all outputs when displayOnly and masked', async function (assert) {
Expand Down Expand Up @@ -116,7 +122,7 @@ module('Integration | Component | masked input', function (hooks) {
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
assert.ok(component.downloadButtonIsPresent);
assert.ok(component.downloadIconIsPresent);
assert.dom('[data-test-button="toggle-masked"]').exists('shows toggle mask button');

await component.toggleMasked();
Expand Down
1 change: 1 addition & 0 deletions ui/tests/pages/components/masked-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { clickable, isPresent } from 'ember-cli-page-object';
export default {
textareaIsPresent: isPresent('[data-test-textarea]'),
copyButtonIsPresent: isPresent('[data-test-copy-button]'),
downloadIconIsPresent: isPresent('[data-test-download-icon]'),
downloadButtonIsPresent: isPresent('[data-test-download-button]'),
toggleMasked: clickable('[data-test-button="toggle-masked"]'),
copyValue: clickable('[data-test-copy-button]'),
Expand Down

0 comments on commit f8da51c

Please sign in to comment.