UI/fix kv data cache (#14489)
* KV fetches recent version on every page, no longer disallow new version without metadata access * Don't flash no read permissions warning * Send noMetadataVersion on destroy if version is undefined * test coverage * add changelog, fix tests * Fix failing test
This commit is contained in:
parent
50a9dedbcb
commit
ecd4c1e514
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
ui: Fixes caching issue on kv new version create
|
||||
```
|
|
@ -149,6 +149,7 @@ export default ApplicationAdapter.extend({
|
|||
} else if (deleteType === 'soft-delete') {
|
||||
return this.softDelete(backend, path, version);
|
||||
} else {
|
||||
version = version || currentVersionForNoReadMetadata;
|
||||
return this.deleteByDeleteType(backend, path, deleteType, version);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -248,20 +248,7 @@ export default Route.extend(UnloadModelRoute, {
|
|||
if (modelType === 'secret-v2') {
|
||||
// after the the base model fetch, kv-v2 has a second associated
|
||||
// version model that contains the secret data
|
||||
|
||||
// if no read access to metadata, return current Version from secret data.
|
||||
if (!secretModel.currentVersion) {
|
||||
let adapter = this.store.adapterFor('secret-v2-version');
|
||||
try {
|
||||
secretModel.currentVersion = await adapter.getSecretDataVersion(backend, secret);
|
||||
} catch {
|
||||
// will get error if you have deleted the secret
|
||||
// if this is the case do nothing
|
||||
}
|
||||
secretModel = await this.fetchV2Models(capabilities, secretModel, params);
|
||||
} else {
|
||||
secretModel = await this.fetchV2Models(capabilities, secretModel, params);
|
||||
}
|
||||
}
|
||||
return {
|
||||
secret: secretModel,
|
||||
|
|
|
@ -152,13 +152,13 @@
|
|||
<form onsubmit={{action "createOrUpdateKey" "edit"}}>
|
||||
<div class="box is-sideless is-fullwidth is-marginless padding-top">
|
||||
<MessageError @model={{@modelForData}} @errorMessage={{this.error}} />
|
||||
{{#unless @canReadSecretData}}
|
||||
{{#if (eq @canReadSecretData false)}}
|
||||
<AlertBanner
|
||||
@type="warning"
|
||||
@message="You do not have read permissions. If a secret exists here creating a new secret will overwrite it."
|
||||
data-test-warning-no-read-permissions
|
||||
/>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
<NamespaceReminder @mode="edit" @noun="secret" />
|
||||
{{#if this.isCreateNewVersionFromOldVersion}}
|
||||
<div class="form-section">
|
||||
|
|
|
@ -92,12 +92,15 @@
|
|||
{{#let (concat "vault.cluster.secrets.backend." (if (eq @mode "show") "edit" "show")) as |targetRoute|}}
|
||||
{{#if @isV2}}
|
||||
<ToolbarLink
|
||||
@params={{array targetRoute @model.id (query-params version=@modelForData.version)}}
|
||||
{{! Always create new version from latest if no metadata read access }}
|
||||
@params={{array
|
||||
targetRoute
|
||||
@model.id
|
||||
(query-params version=(if @model.canReadMetadata @modelForData.version ""))
|
||||
}}
|
||||
@data-test-secret-edit="true"
|
||||
@replace={{true}}
|
||||
@type="add"
|
||||
@disabled={{@model.failedServerRead}}
|
||||
@disabledTooltip="Metadata read access is required to create new version"
|
||||
>
|
||||
Create new version
|
||||
</ToolbarLink>
|
||||
|
|
|
@ -86,14 +86,13 @@ export const testAliasDeleteFromForm = async function (name, itemType, assert) {
|
|||
`${itemType}: navigates to edit on create`
|
||||
);
|
||||
await page.editForm.delete();
|
||||
await settled();
|
||||
await page.editForm.waitForConfirm();
|
||||
await page.editForm.confirmDelete();
|
||||
await settled();
|
||||
assert.ok(
|
||||
aliasIndexPage.flashMessage.latestMessage.startsWith('Successfully deleted'),
|
||||
`${itemType}: shows flash message`
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
currentRouteName(),
|
||||
'vault.cluster.access.identity.aliases.index',
|
||||
|
|
|
@ -607,11 +607,22 @@ module('Acceptance | secrets/secret/create', function (hooks) {
|
|||
await assert
|
||||
.dom('[data-test-value-div="secret-key"]')
|
||||
.exists('secret view page and info table row with secret-key value');
|
||||
// create new version should be disabled with no metadata read access
|
||||
assert.dom('[data-test-secret-edit]').hasClass('disabled', 'Create new version action is disabled');
|
||||
assert
|
||||
.dom('[data-test-popup-menu-trigger="version"]')
|
||||
.doesNotExist('the version drop down menu does not show');
|
||||
|
||||
// Create new version
|
||||
assert.dom('[data-test-secret-edit]').doesNotHaveClass('disabled', 'Create new version is not disabled');
|
||||
await click('[data-test-secret-edit]');
|
||||
|
||||
// create new version should not include version in the URL
|
||||
assert.equal(
|
||||
currentURL(),
|
||||
`/vault/secrets/${enginePath}/edit/${secretPath}`,
|
||||
'edit route does not include version query param'
|
||||
);
|
||||
// Update key
|
||||
await editPage.secretKey('newKey');
|
||||
await editPage.secretValue('some-value');
|
||||
await editPage.save();
|
||||
assert.dom('[data-test-value-div="newKey"]').exists('Info row table exists at newKey');
|
||||
|
||||
// check metadata tab
|
||||
await click('[data-test-secret-metadata-tab]');
|
||||
|
@ -683,8 +694,9 @@ module('Acceptance | secrets/secret/create', function (hooks) {
|
|||
await settled(); // eslint-disable-line
|
||||
await click('[data-test-secret-tab]');
|
||||
await settled(); // eslint-disable-line
|
||||
let text = document.querySelector('[data-test-empty-state-title]').innerText.trim();
|
||||
assert.equal(text, 'Version 1 of this secret has been permanently destroyed');
|
||||
assert
|
||||
.dom('[data-test-empty-state-title]')
|
||||
.includesText('Version 1 of this secret has been permanently destroyed');
|
||||
});
|
||||
|
||||
test('version 2 with policy with only delete option does not show modal and undelete is an option', async function (assert) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { clickable, fillable, attribute } from 'ember-cli-page-object';
|
||||
import { waitFor } from '@ember/test-helpers';
|
||||
import fields from '../form-field';
|
||||
|
||||
export default {
|
||||
|
@ -13,4 +14,10 @@ export default {
|
|||
submit: clickable('[data-test-identity-submit]'),
|
||||
delete: clickable('[data-test-confirm-action-trigger]'),
|
||||
confirmDelete: clickable('[data-test-confirm-button]'),
|
||||
waitForConfirm() {
|
||||
return waitFor('[data-test-confirm-button]');
|
||||
},
|
||||
waitForFlash() {
|
||||
return waitFor('[data-test-flash-message-body]');
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue