From a9603f6c83d6dbbb637d500f9e7add5cf65a47cd Mon Sep 17 00:00:00 2001 From: Kianna <30884335+kiannaquach@users.noreply.github.com> Date: Tue, 8 Aug 2023 09:31:16 -0700 Subject: [PATCH] UI: [VAULT-17035 VAULT-17038 VAULT-17039] Dashboard Quick Actions card (#21929) Co-authored-by: clairebontempo@gmail.com --- .../dashboard/quick-actions-card.js | 146 ++++++++++++++++++ .../dashboard/quick-actions-card.hbs | 63 ++++++++ ui/app/templates/vault/cluster/dashboard.hbs | 2 +- .../secrets/backend/database/secret-test.js | 1 + .../dashboard/quick-actions-card-test.js | 132 ++++++++++++++++ 5 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 ui/app/components/dashboard/quick-actions-card.js create mode 100644 ui/app/templates/components/dashboard/quick-actions-card.hbs create mode 100644 ui/tests/integration/components/dashboard/quick-actions-card-test.js diff --git a/ui/app/components/dashboard/quick-actions-card.js b/ui/app/components/dashboard/quick-actions-card.js new file mode 100644 index 000000000000..6652c98d532b --- /dev/null +++ b/ui/app/components/dashboard/quick-actions-card.js @@ -0,0 +1,146 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { inject as service } from '@ember/service'; + +/** + * @module DashboardQuickActionsCard + * DashboardQuickActionsCard component allows users to see a list of secrets engines filtered by + * kv, pki and database and perform certain actions based on the type of secret engine selected + * + * @example + * ```js + * + * ``` + */ + +const QUICK_ACTION_ENGINES = ['pki', 'kv', 'database']; + +export default class DashboardQuickActionsCard extends Component { + @service router; + + @tracked selectedEngine; + @tracked selectedAction; + @tracked mountPath; + @tracked paramValue; + + get actionOptions() { + switch (this.selectedEngine) { + case 'kv': + return ['Find KV secrets']; + case 'database': + return ['Generate credentials for database']; + case 'pki': + return ['Issue certificate', 'View certificate', 'View issuer']; + default: + return []; + } + } + + get searchSelectParams() { + switch (this.selectedAction) { + case 'Find KV secrets': + return { + title: 'Secret Path', + subText: 'Path of the secret you want to read, including the mount. E.g., secret/data/foo.', + buttonText: 'Read secrets', + model: 'secret-v2', + route: 'vault.cluster.secrets.backends.show', + }; + case 'Generate credentials for database': + return { + title: 'Role to use', + buttonText: 'Generate credentials', + model: 'database/role', + route: 'vault.cluster.secrets.backend.credentials', + }; + case 'Issue certificate': + return { + title: 'Role to use', + placeholder: 'Type to find a role', + buttonText: 'Issue leaf certificate', + model: 'pki/role', + route: 'vault.cluster.secrets.backend.pki.roles.role.generate', + }; + case 'View certificate': + return { + title: 'Certificate serial number', + placeholder: '33:a3:...', + buttonText: 'View certificate', + model: 'pki/certificate/base', + route: 'vault.cluster.secrets.backend.pki.certificates.certificate.details', + }; + case 'View issuer': + return { + title: 'Issuer', + placeholder: 'Type issuer name or ID', + buttonText: 'View issuer', + model: 'pki/issuer', + nameKey: 'issuerName', + route: 'vault.cluster.secrets.backend.pki.issuers.issuer.details', + }; + default: + return { + placeholder: 'Please select an action above', + buttonText: 'Select an action', + model: '', + }; + } + } + + get filteredSecretEngines() { + return this.args.secretsEngines.filter((engine) => QUICK_ACTION_ENGINES.includes(engine.type)); + } + + get mountOptions() { + return this.filteredSecretEngines.map((engine) => { + const { id, type } = engine; + return { name: id, type, id }; + }); + } + + @action + handleSearchEngineSelect([selection]) { + this.selectedEngine = selection?.type; + this.mountPath = selection?.id; + // reset tracked properties + this.selectedAction = null; + this.paramValue = null; + } + + @action + setSelectedAction(selectedAction) { + this.selectedAction = selectedAction; + this.paramValue = null; + } + + @action + handleActionSelect(val) { + if (Array.isArray(val)) { + this.paramValue = val[0]; + } else { + this.paramValue = val; + } + } + + @action + navigateToPage() { + let searchSelectParamRoute = this.searchSelectParams.route; + + // kv has a special use case where if the paramValue ends in a '/' you should + // link to different route + if (this.selectedEngine === 'kv') { + searchSelectParamRoute = + this.paramValue && this.paramValue[this.paramValue?.length - 1] === '/' + ? 'vault.cluster.secrets.backend.list' + : 'vault.cluster.secrets.backend.show'; + } + + this.router.transitionTo(searchSelectParamRoute, this.mountPath, this.paramValue); + } +} diff --git a/ui/app/templates/components/dashboard/quick-actions-card.hbs b/ui/app/templates/components/dashboard/quick-actions-card.hbs new file mode 100644 index 000000000000..d019a71c79a3 --- /dev/null +++ b/ui/app/templates/components/dashboard/quick-actions-card.hbs @@ -0,0 +1,63 @@ +

Quick actions

+ +
+

Secrets engines

+ +
+ +{{#if this.selectedEngine}} +

Action

+