Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/4139.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui/input-variables: Adds the ability to set an input variable as sensitive and hides its value from the list and form
```
68 changes: 47 additions & 21 deletions ui/app/components/project-input-variables/list-item.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<Pds::Input
@type="text"
data-test-input-variables-var-name
required
id="input-variable-name"
placeholder={{t "form.project_variables_settings.variable_name_placeholder"}}
value={{this.variable.name}}
Expand All @@ -28,18 +29,28 @@
<Pds::Input
@type="text"
data-test-input-variables-var-hcl
required
id="input-variable-value"
placeholder={{t "form.project_variables_settings.variable_value_placeholder"}}
value={{this.variable.hcl}}
placeholder={{if
this.writeOnly
(t "form.project_variables_settings.variable_value_placeholder_sensitive")
(t "form.project_variables_settings.variable_value_placeholder")
}}
value={{if this.writeOnly "" this.variable.hcl}}
{{on "input" (pick "target.value" (set this "variable.hcl"))}}
/>
{{else}}
<Pds::Input
@type="text"
id="input-variable-value"
data-test-input-variables-var-str
placeholder={{t "form.project_variables_settings.variable_value_placeholder"}}
value={{this.variable.str}}
required
placeholder={{if
this.writeOnly
(t "form.project_variables_settings.variable_form_placeholder_sensitive")
(t "form.project_variables_settings.variable_value_placeholder")
}}
value={{if this.writeOnly "" this.variable.str}}
{{on "input" (pick "target.value" (set this "variable.str"))}}
/>
{{/if}}
Expand All @@ -49,26 +60,35 @@
data-test-input-variables-toggle-hcl
id="input-variable-hcl"
checked={{this.isHcl}}
{{on "change" (fn this.toggleHcl this.variable)}}>
<label for="input-variable-hcl">HCL</label>
{{on "change" (fn this.toggleHcl this.variable)}}
/>
<label for="input-variable-hcl">HCL</label>
</span>
</div>
<div class="pds-formField__input-inline-toggle">
<Hds::Form::Toggle::Field
data-test-input-variables-toggle-sensitive
checked={{this.isSensitive}}
{{on "change" (fn this.toggleSensitive this.variable)}}
as |F|
>
<F.Label>
{{t "form.project_variables_settings.variable_set_sensitive"}}
</F.Label>
</Hds::Form::Toggle::Field>
</div>
</div>
</fieldset>
<div class="card-footer">
<Pds::ButtonSet>
<Pds::Button
data-test-input-variables-edit-save
@variant="primary"
@type="submit">
<Pds::Button data-test-input-variables-edit-save @variant="primary" @type="submit">
{{t "form.project_variables_settings.button_submit"}}
</Pds::Button>
<Pds::Button
data-test-input-variables-edit-cancel
@variant="secondary"
{{on "click"
(if this.isCreating this.cancelCreate this.cancelEdit)
}}>
{{on "click" (if this.isCreating this.cancelCreate this.cancelEdit)}}
>
{{t "form.project_variables_settings.button_cancel"}}
</Pds::Button>
</Pds::ButtonSet>
Expand All @@ -79,7 +99,13 @@
<div class="variables--list-item">
<span class="variables--list-item-name" data-test-input-variables-var-name>{{this.variable.name}}</span>
<span class="variables--list-item-value" data-test-input-variables-var-value>
{{#if this.isHcl}}
{{#if this.isSensitive}}
<Hds::Badge
data-test-sensitive-var-badge
@icon="eye-off"
@text={{t "form.project_variables_settings.variable_value_placeholder_sensitive"}}
/>
{{else if this.isHcl}}
<b class="badge" data-test-input-variables-list-item-is-hcl>
HCL
</b>
Expand All @@ -89,28 +115,28 @@
{{/if}}
</span>
<Pds::Dropdown @align="right" as |D|>
<D.Trigger
data-test-input-variables-dropdown
@variant="ghost">
<D.Trigger data-test-input-variables-dropdown @variant="ghost">
Actions
</D.Trigger>
<D.Dialog >
<D.Dialog>
<section>
<Pds::Button
data-test-input-variables-dropdown-edit
@variant="secondary"
{{on "click" (fn this.editVariable this.variable)}}>
{{on "click" (fn this.editVariable this.variable)}}
>
Edit
</Pds::Button>
<Pds::Button
data-test-input-variables-dropdown-delete
@variant="warning"
{{on "click" (fn this.deleteVariable this.variable)}}>
{{on "click" (fn this.deleteVariable this.variable)}}
>
Delete
</Pds::Button>
</section>
</D.Dialog>
</Pds::Dropdown>
</div>
{{/if}}
</li>
</li>
14 changes: 12 additions & 2 deletions ui/app/components/project-input-variables/list-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { Project, Variable } from 'waypoint-pb';
import { inject as service } from '@ember/service';
import ApiService from 'waypoint/services/api';

interface VariableArgs {
variable: Variable.AsObject;
Expand All @@ -17,29 +16,35 @@ interface VariableArgs {
}

export default class ProjectInputVariablesListItemComponent extends Component<VariableArgs> {
@service api!: ApiService;
@service('pdsFlashMessages') flashMessages;

initialVariable: Variable.AsObject;
@tracked variable: Variable.AsObject;
@tracked isCreating: boolean;
@tracked isEditing: boolean;
@tracked writeOnly: boolean;

constructor(owner: unknown, args: VariableArgs) {
super(owner, args);
let { variable, isEditing, isCreating } = args;
this.variable = variable;
this.isEditing = isEditing;
this.isCreating = isCreating;
this.writeOnly = false;
this.initialVariable = JSON.parse(JSON.stringify(this.variable));
}

get isHcl(): boolean {
return !!this.variable.hcl;
}

get isSensitive(): boolean {
return !!this.variable.sensitive;
}

storeInitialVariable(): void {
this.initialVariable = JSON.parse(JSON.stringify(this.variable));
this.writeOnly = this.variable.sensitive ? true : false;
}

@action
Expand Down Expand Up @@ -99,4 +104,9 @@ export default class ProjectInputVariablesListItemComponent extends Component<Va
this.variable.str = '';
}
}

@action
toggleSensitive(variable: Variable.AsObject): void {
this.variable.sensitive = !variable.sensitive;
}
}
1 change: 1 addition & 0 deletions ui/app/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export default class ApiService extends Service {
} else {
variable.setStr(v.str);
}
variable.setSensitive(v.sensitive);
return variable;
});
return varProtosList;
Expand Down
1 change: 1 addition & 0 deletions ui/mirage/factories/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default Factory.extend({
afterCreate(project, server) {
server.createList('variable', 2, 'random-str', { project });
server.create('variable', 'random-hcl', { project });
server.create('variable', 'is-sensitive', { project });
},
}),

Expand Down
5 changes: 5 additions & 0 deletions ui/mirage/factories/variable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ export default Factory.extend({
name: () => faker.hacker.noun(),
hcl: () => faker.hacker.adjective(),
}),
'is-sensitive': trait({
name: () => faker.hacker.noun(),
str: () => faker.hacker.adjective(),
sensitive: true,
}),
});
1 change: 1 addition & 0 deletions ui/mirage/models/variable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default Model.extend({

result.setServer();
result.setName(this.name);
result.setSensitive(this.sensitive);
if (this.hcl) {
result.setStr('');
result.setHcl(this.hcl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module('Integration | Component | project-input-variables-list', function (hooks

await render(hbs`<ProjectInputVariables::List @project={{this.project}}/>`);
assert.dom('.variables-list').exists('The list renders');
assert.equal(page.variablesList.length, 3, 'the list contains all variables');
assert.equal(page.variablesList.length, 4, 'the list contains all variables');
assert.notOk(page.variablesList.objectAt(0).isHcl, 'the list contains a string variable');
assert.ok(page.variablesList.objectAt(2).isHcl, 'the list contains a hcl variable');
});
Expand All @@ -51,23 +51,23 @@ module('Integration | Component | project-input-variables-list', function (hooks

await render(hbs`<ProjectInputVariables::List @project={{this.project}}/>`);
assert.dom('.variables-list').exists('The list renders');
assert.equal(page.variablesList.length, 3, 'the list contains all variables');
assert.equal(page.variablesList.length, 4, 'the list contains all variables');
await page.createButton();
assert.ok(page.hasForm, 'Attempt to create: the form appears when the Add Variable button is clicked');
await page.cancelButton();
assert.equal(
page.variablesList.length,
3,
4,
'Attempt to create: the list still has the normal count of variables after cancelling'
);
await page.createButton();
await page.varName('var_name');
await page.varStr('foozbarz');
await page.saveButton();
assert.equal(page.variablesList.length, 4, 'Create Variable: the list has the new variable');
assert.equal(page.variablesList.length, 5, 'Create Variable: the list has the new variable');
await page.variablesList.objectAt(0).dropdown();
await page.variablesList.objectAt(0).dropdownDelete();
assert.equal(page.variablesList.length, 3, 'Delete Variable: the variable has been removed');
assert.equal(page.variablesList.length, 4, 'Delete Variable: the variable has been removed');
});

test('editing variables works', async function (assert) {
Expand Down Expand Up @@ -103,4 +103,29 @@ module('Integration | Component | project-input-variables-list', function (hooks
'the updated variable value is correct'
);
});

test('sensitive variables are hidden in list', async function (assert) {
let dbproj = await this.server.create('project', { name: 'Proj3' });
this.server.create('variable', 'is-sensitive', { project: dbproj });
let project = dbproj.toProtobuf();
this.set('project', project.toObject());

await render(hbs`<ProjectInputVariables::List @project={{this.project}}/>`);

assert.dom('[data-test-sensitive-var-badge]').exists();
});

test('sensitive variables are hidden in forms', async function (assert) {
let dbproj = await this.server.create('project', { name: 'Proj3' });
this.server.create('variable', 'is-sensitive', { project: dbproj });
let project = dbproj.toProtobuf();
this.set('project', project.toObject());

await render(hbs`<ProjectInputVariables::List @project={{this.project}}/>`);

await page.variablesList.objectAt(0).dropdown();
await page.variablesList.objectAt(0).dropdownEdit();

assert.dom('[data-test-input-variables-var-str]').hasAttribute('placeholder', 'sensitive - write only');
});
});
5 changes: 4 additions & 1 deletion ui/translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ form:
variable_name_placeholder: 'var_key'
variable_value: 'Value'
variable_value_placeholder: 'var_value'
variable_set_sensitive: Set as sensitive
variable_value_placeholder_sensitive: 'Sensitive - write only'
variable_form_placeholder_sensitive: 'sensitive - write only'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(suggestion) Have the casing for both be 'Sensitive - write only' so that they match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the way it is in HCP and the accompanying designs so I'm just making them match.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, but we should follow https://design-system-components-hashicorp.vercel.app/content/writing-guidelines in the future to be consistent with casing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joshklekamp or @ryenotbread what do you think? This difference in case is how it works in TFC which is what I modeled ours on.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they should match and they should be sentence cased.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree they should match and be sentence cased.

button_submit: 'Save variable'
button_cancel: 'Cancel'
config_variables_settings:
Expand Down Expand Up @@ -315,7 +318,7 @@ image-ref:
workspace-switcher:
error: Failed to load workspaces

runner-alert:
runner-alert:
title: Remote runner required
description: In order to connect to a repository, you must install a remote runner first.
link: Waypoint Runners documentation