mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-07 11:51:45 +01:00
* VAULT-39898 page scroll locked after discarding * VAULT-39904 update lease duration card text * Ensure ttl fields dont get reset if there are errors * Fix failing tests * VAULT-39900 close the unsaved changes modal if it errors on save * Switch max and lease duration * Refactor modal save/close * Remove promise! * Code cleanup! Co-authored-by: Kianna <30884335+kiannaquach@users.noreply.github.com>
This commit is contained in:
parent
bddc79aeaa
commit
06948c7588
@ -6,16 +6,15 @@
|
||||
@level="mid"
|
||||
@hasBorder={{true}}
|
||||
class="has-padding-m has-top-bottom-margin"
|
||||
data-test-card-container="lease-duration"
|
||||
data-test-card-container="secrets duration"
|
||||
...attributes
|
||||
>
|
||||
<Hds::Text::Display @size="300" @tag="h2" class="has-bottom-margin-s hds-foreground-strong">Lease Duration</Hds::Text::Display>
|
||||
<Hds::Text::Display @size="300" @tag="h2" class="has-bottom-margin-s hds-foreground-strong">Secrets duration</Hds::Text::Display>
|
||||
|
||||
<Hds::Layout::Flex @align="start" @gap="16" class="has-bottom-margin-m">
|
||||
<Hds::Layout::Flex @direction="column" @gap="4">
|
||||
<Hds::Text::Body @size="200" @tag="p">Lease, measured by the “time-to-live” value, defines how long any secret issued
|
||||
by this engine remains valid.</Hds::Text::Body>
|
||||
{{! TODO: Verify what link this is supposed to be }}
|
||||
<Hds::Text::Body @size="200" @tag="p">Time-to-live defines how long secrets issued by this engine remain valid before
|
||||
expiring.</Hds::Text::Body>
|
||||
<Hds::Link::Standalone
|
||||
@icon="external-link"
|
||||
@iconPosition="trailing"
|
||||
@ -26,7 +25,7 @@
|
||||
</Hds::Layout::Flex>
|
||||
|
||||
<Hds::Layout::Flex @direction="column" @gap="24" @isInline="true" class="has-top-padding-s has-bottom-padding-s">
|
||||
<SecretEngine::TtlPickerV2 @model={{@model}} @ttlKey="default_lease_ttl" />
|
||||
<SecretEngine::TtlPickerV2 @model={{@model}} @ttlKey="max_lease_ttl" />
|
||||
<SecretEngine::TtlPickerV2 @model={{@model}} @initialUnit={{@defaultLeaseUnit}} @ttlKey="default_lease_ttl" />
|
||||
<SecretEngine::TtlPickerV2 @model={{@model}} @initialUnit={{@maxLeaseUnit}} @ttlKey="max_lease_ttl" />
|
||||
</Hds::Layout::Flex>
|
||||
</Hds::Card::Container>
|
||||
@ -31,7 +31,12 @@
|
||||
<SecretEngine::Card::Metadata @model={{@model}} class="is-fullwidth" />
|
||||
</LG.Item>
|
||||
<LG.Item @colspan={{1}}>
|
||||
<SecretEngine::Card::LeaseDuration @model={{@model}} class="is-fullwidth" />
|
||||
<SecretEngine::Card::SecretsDuration
|
||||
@model={{@model}}
|
||||
@defaultLeaseUnit={{this.defaultLeaseUnit}}
|
||||
@maxLeaseUnit={{this.maxLeaseUnit}}
|
||||
class="is-fullwidth"
|
||||
/>
|
||||
<SecretEngine::Card::Security @model={{@model}} class="is-fullwidth" />
|
||||
</LG.Item>
|
||||
</Hds::Layout::Grid>
|
||||
@ -61,20 +66,20 @@
|
||||
<br />
|
||||
Would you like to apply them?
|
||||
</M.Body>
|
||||
<M.Footer>
|
||||
<M.Footer as |F|>
|
||||
<Hds::ButtonSet>
|
||||
<Hds::Button
|
||||
type="button"
|
||||
@text="Save changes"
|
||||
data-test-button="save"
|
||||
{{on "click" (perform this.saveGeneralSettings)}}
|
||||
{{on "click" (fn this.closeAndHandle F.close "save")}}
|
||||
/>
|
||||
<Hds::Button
|
||||
type="button"
|
||||
@text="Discard changes"
|
||||
@color="secondary"
|
||||
data-test-button="discard"
|
||||
{{on "click" this.discardChanges}}
|
||||
{{on "click" (fn this.closeAndHandle F.close "discard")}}
|
||||
/>
|
||||
</Hds::ButtonSet>
|
||||
</M.Footer>
|
||||
|
||||
@ -49,6 +49,9 @@ export default class GeneralSettingsComponent extends Component<Args> {
|
||||
@tracked showUnsavedChangesModal = false;
|
||||
@tracked changedFields: string[] = [];
|
||||
|
||||
@tracked defaultLeaseUnit = '';
|
||||
@tracked maxLeaseUnit = '';
|
||||
|
||||
originalModel = JSON.parse(JSON.stringify(this.args.model));
|
||||
|
||||
getUnsavedChanges(newModel: SecretsEngineResource, originalModel: SecretsEngineResource) {
|
||||
@ -183,20 +186,31 @@ export default class GeneralSettingsComponent extends Component<Args> {
|
||||
|
||||
@action
|
||||
closeUnsavedChangesModal() {
|
||||
this.showUnsavedChangesModal = !this.showUnsavedChangesModal;
|
||||
this.showUnsavedChangesModal = false;
|
||||
this.changedFields = [];
|
||||
}
|
||||
|
||||
@action
|
||||
discardChanges() {
|
||||
this.closeUnsavedChangesModal();
|
||||
this.router.transitionTo(this.args?.model?.secretsEngine?.backendConfigurationLink);
|
||||
closeAndHandle(close: () => void, action: 'save' | 'discard') {
|
||||
close();
|
||||
|
||||
if (action === 'save') {
|
||||
this.saveGeneralSettings.perform();
|
||||
}
|
||||
|
||||
if (action === 'discard') {
|
||||
this.router.transitionTo(this.args?.model?.secretsEngine?.backendConfigurationLink);
|
||||
}
|
||||
}
|
||||
|
||||
saveGeneralSettings = task(async (event) => {
|
||||
event.preventDefault();
|
||||
saveGeneralSettings = task(async (event?) => {
|
||||
// event is an optional arg because saveGeneralSettings can be called in the closeAndHandle function.
|
||||
// There are instances where we will save in the modal where that doesn't require an event.
|
||||
if (event) event.preventDefault();
|
||||
|
||||
const { defaultLeaseTime, maxLeaseTime } = this.getFormData();
|
||||
const { defaultLeaseTime, defaultLeaseUnit, maxLeaseTime, maxLeaseUnit } = this.getFormData();
|
||||
this.defaultLeaseUnit = defaultLeaseUnit;
|
||||
this.maxLeaseUnit = maxLeaseUnit;
|
||||
|
||||
if (!this.validateTtl(defaultLeaseTime) || !this.validateTtl(maxLeaseTime)) {
|
||||
this.errorMessage = 'Only use numbers for this setting.';
|
||||
@ -214,11 +228,11 @@ export default class GeneralSettingsComponent extends Component<Args> {
|
||||
});
|
||||
|
||||
this.flashMessages.success('Engine settings successfully updated.');
|
||||
|
||||
this.router.transitionTo(this.args?.model?.secretsEngine?.backendConfigurationLink);
|
||||
} catch (e) {
|
||||
const { message } = await this.api.parseError(e);
|
||||
this.errorMessage = message;
|
||||
this.flashMessages.danger(`Try again or check your network connection. ${message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ interface Args {
|
||||
model: {
|
||||
secretsEngine: SecretsEngineResource;
|
||||
};
|
||||
initialUnit: string;
|
||||
ttlKey: 'default_lease_ttl' | 'max_lease_ttl';
|
||||
}
|
||||
|
||||
@ -66,7 +67,11 @@ export default class TtlPickerV2 extends Component<Args> {
|
||||
} else {
|
||||
const parseDuration = durationToSeconds(ttlValue || '');
|
||||
// if parsing fails leave it empty
|
||||
if (parseDuration === null) return;
|
||||
if (parseDuration === null) {
|
||||
this.time = ttlValue || '';
|
||||
this.selectedUnit = this.args.initialUnit;
|
||||
return;
|
||||
}
|
||||
seconds = parseDuration;
|
||||
}
|
||||
|
||||
@ -87,11 +92,14 @@ export default class TtlPickerV2 extends Component<Args> {
|
||||
|
||||
get formField() {
|
||||
return {
|
||||
label: this.args?.ttlKey === 'default_lease_ttl' ? 'Time-to-live (TTL)' : 'Maximum Time-to-live (TTL)',
|
||||
label:
|
||||
this.args?.ttlKey === 'default_lease_ttl'
|
||||
? 'Default time-to-live (TTL)'
|
||||
: 'Maximum time-to-live (TTL)',
|
||||
helperText:
|
||||
this.args?.ttlKey === 'default_lease_ttl'
|
||||
? 'Standard expiry deadline.'
|
||||
: 'Maximum possible extension for expiry.',
|
||||
? 'How long secrets in this engine stay valid.'
|
||||
: 'Maximum extension for the secrets life beyond default.',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ module('Acceptance | Enterprise | keymgmt-configuration-workflow', function (hoo
|
||||
assert.dom(SELECTORS.versionCard.engineType).hasText(keymgmtType, 'shows keymgmt engine type');
|
||||
assert.dom(GENERAL.cardContainer('metadata')).exists('metadata card exists');
|
||||
assert.dom(GENERAL.inputByAttr('path')).hasValue(`${keymgmtType}/`, 'show path value');
|
||||
assert.dom(GENERAL.cardContainer('lease-duration')).exists('lease-duration card exists');
|
||||
assert.dom(GENERAL.cardContainer('secrets duration')).exists('secrets duration card exists');
|
||||
assert.dom(GENERAL.cardContainer('security')).exists('security card exists');
|
||||
|
||||
// fill in values to tune
|
||||
|
||||
@ -21,12 +21,16 @@ module('Integration | Component | SecretEngine::Card::LeaseDuration', function (
|
||||
test('it shows default and max ttl pickers', async function (assert) {
|
||||
assert.expect(5);
|
||||
await render(hbs`
|
||||
<SecretEngine::Card::LeaseDuration @model={{this.model}} />
|
||||
<SecretEngine::Card::SecretsDuration @model={{this.model}} />
|
||||
`);
|
||||
assert.dom(SELECTORS.ttlPickerV2).exists({ count: 2 });
|
||||
assert.dom(GENERAL.fieldLabelbyAttr('default_lease_ttl')).hasText('Time-to-live (TTL)');
|
||||
assert.dom(GENERAL.fieldLabelbyAttr('max_lease_ttl')).hasText('Maximum Time-to-live (TTL)');
|
||||
assert.dom(GENERAL.helpTextByAttr('default_lease_ttl')).hasText('Standard expiry deadline.');
|
||||
assert.dom(GENERAL.helpTextByAttr('max_lease_ttl')).hasText('Maximum possible extension for expiry.');
|
||||
assert.dom(GENERAL.fieldLabelbyAttr('default_lease_ttl')).hasText('Default time-to-live (TTL)');
|
||||
assert.dom(GENERAL.fieldLabelbyAttr('max_lease_ttl')).hasText('Maximum time-to-live (TTL)');
|
||||
assert
|
||||
.dom(GENERAL.helpTextByAttr('default_lease_ttl'))
|
||||
.hasText('How long secrets in this engine stay valid.');
|
||||
assert
|
||||
.dom(GENERAL.helpTextByAttr('max_lease_ttl'))
|
||||
.hasText('Maximum extension for the secrets life beyond default.');
|
||||
});
|
||||
});
|
||||
@ -48,7 +48,7 @@ module('Integration | Component | SecretEngine::Page::GeneralSettings', function
|
||||
await render(hbs`
|
||||
<SecretEngine::Page::GeneralSettings @model={{this.model}} />
|
||||
`);
|
||||
assert.dom(GENERAL.cardContainer('lease-duration')).exists(`Lease duration card exists`);
|
||||
assert.dom(GENERAL.cardContainer('secrets duration')).exists(`Lease duration card exists`);
|
||||
assert.dom(GENERAL.cardContainer('security')).exists(`Security card exists`);
|
||||
assert.dom(GENERAL.cardContainer('version')).exists(`Version card exists`);
|
||||
assert.dom(GENERAL.cardContainer('metadata')).exists(`Metadata card exists`);
|
||||
|
||||
@ -23,8 +23,8 @@ module('Integration | Component | SecretEngine::TtlPickerV2', function (hooks) {
|
||||
await render(hbs`
|
||||
<SecretEngine::TtlPickerV2 @model={{this.model}} @ttlKey={{this.ttlKey}} />
|
||||
`);
|
||||
assert.dom(GENERAL.fieldLabelbyAttr(this.ttlKey)).hasText('Time-to-live (TTL)');
|
||||
assert.dom(GENERAL.helpTextByAttr(this.ttlKey)).hasText('Standard expiry deadline.');
|
||||
assert.dom(GENERAL.fieldLabelbyAttr(this.ttlKey)).hasText('Default time-to-live (TTL)');
|
||||
assert.dom(GENERAL.helpTextByAttr(this.ttlKey)).hasText('How long secrets in this engine stay valid.');
|
||||
await fillIn(GENERAL.inputByAttr(this.ttlKey), 5);
|
||||
await fillIn(GENERAL.selectByAttr(this.ttlKey), 'm');
|
||||
assert.dom(GENERAL.inputByAttr(this.ttlKey)).hasValue('5');
|
||||
@ -37,8 +37,10 @@ module('Integration | Component | SecretEngine::TtlPickerV2', function (hooks) {
|
||||
await render(hbs`
|
||||
<SecretEngine::TtlPickerV2 @model={{this.model}} @ttlKey={{this.ttlKey}} />
|
||||
`);
|
||||
assert.dom(GENERAL.fieldLabelbyAttr(this.ttlKey)).hasText('Maximum Time-to-live (TTL)');
|
||||
assert.dom(GENERAL.helpTextByAttr(this.ttlKey)).hasText('Maximum possible extension for expiry.');
|
||||
assert.dom(GENERAL.fieldLabelbyAttr(this.ttlKey)).hasText('Maximum time-to-live (TTL)');
|
||||
assert
|
||||
.dom(GENERAL.helpTextByAttr(this.ttlKey))
|
||||
.hasText('Maximum extension for the secrets life beyond default.');
|
||||
await fillIn(GENERAL.inputByAttr(this.ttlKey), 10);
|
||||
await fillIn(GENERAL.selectByAttr(this.ttlKey), 'm');
|
||||
assert.dom(GENERAL.inputByAttr(this.ttlKey)).hasValue('10');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user