/** * Copyright (c) HashiCorp, Inc. * SPDX-License-Identifier: BUSL-1.1 */ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { task } from 'ember-concurrency'; import { waitFor } from '@ember/test-waiters'; import errorMessage from 'vault/utils/error-message'; import type Store from '@ember-data/store'; import type SecretMountPath from 'vault/services/secret-mount-path'; import type FlashMessageService from 'vault/services/flash-messages'; import type VersionService from 'vault/services/version'; import type PkiTidyModel from 'vault/models/pki/tidy'; import type RouterService from '@ember/routing/router-service'; interface Args { autoTidyConfig: PkiTidyModel; tidyStatus: TidyStatusParams; } interface TidyStatusParams { // tidy banner state: string; error: string; message: string; // tidy status time_started: string | null; time_finished: string | null; cert_store_deleted_count: number; revoked_cert_deleted_count: number; missing_issuer_cert_count: number; revocation_queue_deleted_count: number; // enterprise only cross_revoked_cert_deleted_count: number; // enterprise only // tidy settings tidy_cert_store: boolean; tidy_revoked_certs: boolean; tidy_expired_issuers: boolean; safety_buffer: number; tidy_move_legacy_ca_bundle: boolean; issuer_safety_buffer: string; tidy_revocation_queue: boolean; // enterprise only tidy_cross_cluster_revoked_certs: boolean; // enterprise only revocation_queue_safety_buffer: string; // enterprise only } export default class PkiTidyStatusComponent extends Component { @service declare readonly store: Store; @service declare readonly secretMountPath: SecretMountPath; @service declare readonly flashMessages: FlashMessageService; @service declare readonly version: VersionService; @service declare readonly router: RouterService; @tracked tidyOptionsModal = false; @tracked confirmCancelTidy = false; tidyStatusGeneralFields = [ 'time_started', 'time_finished', 'cert_store_deleted_count', 'revoked_cert_deleted_count', 'missing_issuer_cert_count', ]; tidyStatusConfigFields = [ 'tidy_cert_store', 'tidy_revoked_certs', 'safety_buffer', 'pause_duration', 'tidy_expired_issuers', 'tidy_move_legacy_ca_bundle', 'issuer_safety_buffer', ]; // enterprise only crossClusterOperation = { status: ['revocation_queue_deleted_count', 'cross_revoked_cert_deleted_count'], config: ['tidy_revocation_queue', 'tidy_cross_cluster_revoked_certs', 'revocation_queue_safety_buffer'], }; get isEnterprise() { return this.version.isEnterprise; } get tidyState() { return this.args.tidyStatus?.state; } get hasTidyConfig() { return !this.tidyStatusConfigFields.every( (attr) => this.args.tidyStatus[attr as keyof TidyStatusParams] === null ); } get tidyStateAlertBanner() { const tidyState = this.tidyState; switch (tidyState) { case 'Inactive': return { color: 'highlight', title: 'Tidy is inactive', message: this.args.tidyStatus?.message, }; case 'Running': return { color: 'highlight', title: 'Tidy in progress', message: this.args.tidyStatus?.message, shouldShowCancelTidy: true, }; case 'Finished': return { color: 'success', title: 'Tidy operation finished', message: this.args.tidyStatus?.message, }; case 'Error': return { color: 'warning', title: 'Tidy operation failed', message: this.args.tidyStatus?.error, }; case 'Cancelling': return { color: 'warning', title: 'Tidy operation cancelling', icon: 'loading', }; case 'Cancelled': return { color: 'warning', title: 'Tidy operation cancelled', message: 'Your tidy operation has been cancelled. If this was a mistake configure and run another tidy operation.', }; default: return { color: 'warning', title: 'Tidy status not found', message: "The system reported no tidy status. It's recommended to perform a new tidy operation.", }; } } @task @waitFor *cancelTidy() { try { const tidyAdapter = this.store.adapterFor('pki/tidy'); yield tidyAdapter.cancelTidy(this.secretMountPath.currentPath); this.router.transitionTo('vault.cluster.secrets.backend.pki.tidy'); } catch (error) { this.flashMessages.danger(errorMessage(error)); } finally { this.confirmCancelTidy = false; } } }