diff --git a/ui/app/components/dashboard/quick-actions-card.hbs b/ui/app/components/dashboard/quick-actions-card.hbs index 4c06e0316f..2e81fba965 100644 --- a/ui/app/components/dashboard/quick-actions-card.hbs +++ b/ui/app/components/dashboard/quick-actions-card.hbs @@ -97,7 +97,7 @@ @icon="chevron-right" @iconPosition="trailing" @text="Enable a secrets engine" - @route="vault.cluster.settings.mount-secret-backend" + @route="vault.cluster.secrets.mounts" /> {{/if}} diff --git a/ui/app/components/dashboard/secrets-engines-card.hbs b/ui/app/components/dashboard/secrets-engines-card.hbs index 728c523c53..36f4553829 100644 --- a/ui/app/components/dashboard/secrets-engines-card.hbs +++ b/ui/app/components/dashboard/secrets-engines-card.hbs @@ -87,7 +87,7 @@ @icon="chevron-right" @iconPosition="trailing" @text="Enable a secrets engine" - @route="vault.cluster.settings.mount-secret-backend" + @route="vault.cluster.secrets.mounts" /> {{/if}} diff --git a/ui/app/components/secret-engine/list.hbs b/ui/app/components/secret-engine/list.hbs index 96db6fe0ac..c94d1ded79 100644 --- a/ui/app/components/secret-engine/list.hbs +++ b/ui/app/components/secret-engine/list.hbs @@ -4,12 +4,7 @@ }}
- +
diff --git a/ui/app/components/sidebar/nav/cluster.hbs b/ui/app/components/sidebar/nav/cluster.hbs index da4c9dedbd..b2435eea86 100644 --- a/ui/app/components/sidebar/nav/cluster.hbs +++ b/ui/app/components/sidebar/nav/cluster.hbs @@ -9,7 +9,7 @@ diff --git a/ui/app/controllers/vault/cluster/secrets/mounts/index.js b/ui/app/controllers/vault/cluster/secrets/mounts/index.js new file mode 100644 index 0000000000..7051a5afe7 --- /dev/null +++ b/ui/app/controllers/vault/cluster/secrets/mounts/index.js @@ -0,0 +1,37 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { service } from '@ember/service'; +import Controller from '@ember/controller'; +import { action } from '@ember/object'; +import { supportedSecretBackends } from 'vault/helpers/supported-secret-backends'; +import engineDisplayData from 'vault/helpers/engines-display-data'; + +const SUPPORTED_BACKENDS = supportedSecretBackends(); + +export default class SecretMountsController extends Controller { + @service router; + + @action + onMountSuccess(type, path, useEngineRoute = false) { + let transition; + if (SUPPORTED_BACKENDS.includes(type)) { + const engineInfo = engineDisplayData(type); + if (useEngineRoute) { + transition = this.router.transitionTo( + `vault.cluster.secrets.backend.${engineInfo.engineRoute}`, + path + ); + } else { + // For keymgmt, we need to land on provider tab by default using query params + const queryParams = engineInfo.type === 'keymgmt' ? { tab: 'provider' } : {}; + transition = this.router.transitionTo('vault.cluster.secrets.backend.index', path, { queryParams }); + } + } else { + transition = this.router.transitionTo('vault.cluster.secrets.backends'); + } + return transition.followRedirects(); + } +} diff --git a/ui/app/router.js b/ui/app/router.js index b8b9bb64ab..b681781c7f 100644 --- a/ui/app/router.js +++ b/ui/app/router.js @@ -174,6 +174,10 @@ Router.map(function () { }); }); this.route('secrets', function () { + this.route('mounts', function () { + // TODO: Revisit path on create once components are separated - should we specify selected type or just keep it generic as /create? + this.route('create', { path: '/:mount_type/create' }); + }); this.route('backends', { path: '/' }); this.route('backend', { path: '/:backend' }, function () { this.mount('kmip'); diff --git a/ui/app/routes/vault/cluster/secrets/mounts/index.ts b/ui/app/routes/vault/cluster/secrets/mounts/index.ts new file mode 100644 index 0000000000..b3c83ff835 --- /dev/null +++ b/ui/app/routes/vault/cluster/secrets/mounts/index.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from '@ember/routing/route'; +import { service } from '@ember/service'; +import SecretsEngineForm from 'vault/forms/secrets/engine'; +import Router from 'vault/router'; + +import type { ModelFrom } from 'vault/vault/route'; + +export type MountSecretBackendModel = ModelFrom; + +export default class VaultClusterSecretsMountsIndexRouter extends Route { + @service declare router: Router; + + model() { + const defaults = { + config: { listing_visibility: false }, + kv_config: { + max_versions: 0, + cas_required: false, + delete_version_after: undefined, + }, + options: { version: 2 }, + }; + return new SecretsEngineForm(defaults, { isNew: true }); + } +} diff --git a/ui/app/templates/vault/cluster/secrets/mounts/index.hbs b/ui/app/templates/vault/cluster/secrets/mounts/index.hbs new file mode 100644 index 0000000000..0ecd0436a8 --- /dev/null +++ b/ui/app/templates/vault/cluster/secrets/mounts/index.hbs @@ -0,0 +1,7 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{! TODO: Copied from existing component, to be replaced by new parent component in separate ticket - VAULT-37522 }} + \ No newline at end of file diff --git a/ui/tests/acceptance/enterprise-transform-test.js b/ui/tests/acceptance/enterprise-transform-test.js index d08f4b337f..ae88509a95 100644 --- a/ui/tests/acceptance/enterprise-transform-test.js +++ b/ui/tests/acceptance/enterprise-transform-test.js @@ -100,7 +100,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { }); test('it can create a transformation and add itself to the role attached', async function (assert) { - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await click('[data-test-mount-type="transform"]'); await fillIn(GENERAL.inputByAttr('path'), backend); @@ -152,7 +152,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { test('it can create a role and add itself to the transformation attached', async function (assert) { const roleName = 'my-role'; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await mountBackend('transform', backend); // create transformation without role @@ -192,7 +192,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { test('it adds a role to a transformation when added to a role', async function (assert) { const roleName = 'role-test'; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await mountBackend('transform', backend); const transformation = await newTransformation(backend, 'b-transformation', true); @@ -204,7 +204,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { test('it shows a message if an update fails after save', async function (assert) { const roleName = 'role-remove'; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await mountBackend('transform', backend); // Create transformation @@ -242,7 +242,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { test('it allows creation and edit of a template', async function (assert) { const templateName = 'my-template'; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await mountBackend('transform', backend); await click('[data-test-secret-list-tab="Templates"]'); @@ -284,7 +284,7 @@ module('Acceptance | Enterprise | Transform secrets', function (hooks) { test('it allows creation and edit of an alphabet', async function (assert) { const alphabetName = 'vowels-only'; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); const backend = `transform-${uuidv4()}`; await mountBackend('transform', backend); await click('[data-test-secret-list-tab="Alphabets"]'); diff --git a/ui/tests/acceptance/secrets/backend/aws/aws-configuration-test.js b/ui/tests/acceptance/secrets/backend/aws/aws-configuration-test.js index 2f60a027ad..a7ecb9a8b3 100644 --- a/ui/tests/acceptance/secrets/backend/aws/aws-configuration-test.js +++ b/ui/tests/acceptance/secrets/backend/aws/aws-configuration-test.js @@ -55,7 +55,7 @@ module('Acceptance | aws | configuration', function (hooks) { test('it should prompt configuration after mounting the aws engine', async function (assert) { const path = `aws-${this.uid}`; // in this test go through the full mount process. Bypass this step in later tests. - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await mountBackend('aws', path); await click(SES.configTab); assert.dom(GENERAL.emptyStateTitle).hasText('AWS not configured'); diff --git a/ui/tests/acceptance/secrets/backend/azure/azure-configuration-test.js b/ui/tests/acceptance/secrets/backend/azure/azure-configuration-test.js index e49413a81c..3257b10543 100644 --- a/ui/tests/acceptance/secrets/backend/azure/azure-configuration-test.js +++ b/ui/tests/acceptance/secrets/backend/azure/azure-configuration-test.js @@ -41,7 +41,7 @@ module('Acceptance | Azure | configuration', function (hooks) { test('it should prompt configuration after mounting the azure engine', async function (assert) { const path = `azure-${this.uid}`; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await mountBackend(this.type, path); assert.strictEqual( diff --git a/ui/tests/acceptance/secrets/backend/gcp/gcp-configuration-test.js b/ui/tests/acceptance/secrets/backend/gcp/gcp-configuration-test.js index 32d4fd50f3..0235e4d6c1 100644 --- a/ui/tests/acceptance/secrets/backend/gcp/gcp-configuration-test.js +++ b/ui/tests/acceptance/secrets/backend/gcp/gcp-configuration-test.js @@ -42,7 +42,7 @@ module('Acceptance | GCP | configuration', function (hooks) { }); test('it should prompt configuration after mounting the GCP engine', async function (assert) { - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await mountBackend(this.type, this.path); assert.strictEqual( diff --git a/ui/tests/acceptance/secrets/backend/ssh/configuration-test.js b/ui/tests/acceptance/secrets/backend/ssh/configuration-test.js index 31676dbf94..87bc1663f4 100644 --- a/ui/tests/acceptance/secrets/backend/ssh/configuration-test.js +++ b/ui/tests/acceptance/secrets/backend/ssh/configuration-test.js @@ -30,7 +30,7 @@ module('Acceptance | ssh | configuration', function (hooks) { test('it should prompt configuration after mounting ssh engine', async function (assert) { const sshPath = `ssh-${this.uid}`; // in this test go through the full mount process. Bypass this step in later tests. - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await mountBackend('ssh', sshPath); await click(SES.configTab); assert.dom(GENERAL.emptyStateTitle).hasText('SSH not configured'); diff --git a/ui/tests/acceptance/secrets/backend/totp/key-test.js b/ui/tests/acceptance/secrets/backend/totp/key-test.js index b092725829..8b41b22b9d 100644 --- a/ui/tests/acceptance/secrets/backend/totp/key-test.js +++ b/ui/tests/acceptance/secrets/backend/totp/key-test.js @@ -56,7 +56,7 @@ module('Acceptance | totp key backend', function (hooks) { await login(); // Setup TOTP engine - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await mountBackend('totp', this.mountPath); }); diff --git a/ui/tests/acceptance/settings-test.js b/ui/tests/acceptance/settings-test.js index 3d800cdfcb..7d88483237 100644 --- a/ui/tests/acceptance/settings-test.js +++ b/ui/tests/acceptance/settings-test.js @@ -28,13 +28,9 @@ module('Acceptance | secret engine mount settings', function (hooks) { const path = `settings-path-${this.uid}`; // mount unsupported backend - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); - assert.strictEqual( - currentURL(), - '/vault/settings/mount-secret-backend', - 'navigates to the mount secret backend page' - ); + assert.strictEqual(currentURL(), '/vault/secrets/mounts', 'navigates to the mount secret backend page'); await click(MOUNT_BACKEND_FORM.mountType(type)); await fillIn(GENERAL.inputByAttr('path'), path); await click(GENERAL.button('Method Options')); @@ -58,7 +54,7 @@ module('Acceptance | secret engine mount settings', function (hooks) { const type = 'ldap'; const path = `ldap-${this.uid}`; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await runCmd(mountEngineCmd(type, path), false); await visit('/vault/secrets'); await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), path); @@ -77,7 +73,7 @@ module('Acceptance | secret engine mount settings', function (hooks) { const type = 'ssh'; const path = `ssh-${this.uid}`; - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await runCmd(mountEngineCmd(type, path), false); await visit('/vault/secrets'); await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), path); diff --git a/ui/tests/acceptance/settings/mount-secret-backend-test.js b/ui/tests/acceptance/settings/mount-secret-backend-test.js index 2a0dfffbd8..6c60619194 100644 --- a/ui/tests/acceptance/settings/mount-secret-backend-test.js +++ b/ui/tests/acceptance/settings/mount-secret-backend-test.js @@ -60,7 +60,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { const maxTTLHours = 300; await page.visit(); - assert.strictEqual(currentRouteName(), 'vault.cluster.settings.mount-secret-backend'); + assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.mounts.index'); await click(MOUNT_BACKEND_FORM.mountType('kv')); await fillIn(GENERAL.inputByAttr('path'), path); await click(GENERAL.button('Method Options')); @@ -81,11 +81,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { await page.visit(); - assert.strictEqual( - currentRouteName(), - 'vault.cluster.settings.mount-secret-backend', - 'navigates to mount page' - ); + assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.mounts.index', 'navigates to mount page'); await click(MOUNT_BACKEND_FORM.mountType('kv')); await fillIn(GENERAL.inputByAttr('path'), path); await click(GENERAL.button('Method Options')); @@ -100,7 +96,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { test('it sets the max ttl after pki chosen, resets after', async function (assert) { await page.visit(); - assert.strictEqual(currentRouteName(), 'vault.cluster.settings.mount-secret-backend'); + assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.mounts.index'); await click(MOUNT_BACKEND_FORM.mountType('pki')); assert.dom('[data-test-input="config.max_lease_ttl"]').exists(); assert @@ -131,7 +127,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { await page.visit(); - assert.strictEqual(currentRouteName(), 'vault.cluster.settings.mount-secret-backend'); + assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.mounts.index'); await mountBackend('kv', path); await page.secretList(); await settled(); @@ -139,7 +135,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { await mountBackend('kv', path); await waitFor('[data-test-message-error-description]'); assert.dom('[data-test-message-error-description]').containsText(`path is already in use at ${path}`); - assert.strictEqual(currentRouteName(), 'vault.cluster.settings.mount-secret-backend'); + assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.mounts.index'); await page.secretList(); await settled(); @@ -361,7 +357,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) { ); await login(secretsAdminToken); - await visit('/vault/settings/mount-secret-backend'); + await visit('/vault/secrets/mounts'); await click(MOUNT_BACKEND_FORM.mountType(engine)); await fillIn(GENERAL.inputByAttr('path'), path); await click(GENERAL.button('Method Options')); diff --git a/ui/tests/pages/settings/mount-secret-backend.js b/ui/tests/pages/settings/mount-secret-backend.js index daccb572f6..caf3c299de 100644 --- a/ui/tests/pages/settings/mount-secret-backend.js +++ b/ui/tests/pages/settings/mount-secret-backend.js @@ -8,7 +8,7 @@ import { settled } from '@ember/test-helpers'; import { mountBackend } from 'vault/tests/helpers/components/mount-backend-form-helpers'; export default create({ - visit: visitable('/vault/settings/mount-secret-backend'), + visit: visitable('/vault/secrets/mounts'), version: fillable('[data-test-input="options.version"]'), setMaxVersion: fillable('[data-test-input="kv_config.max_versions"]'), maxTTLVal: fillable('[data-test-ttl-value="Max Lease TTL"]'),