2023-03-15 16:00:52 +00:00
/ * *
* Copyright ( c ) HashiCorp , Inc .
* SPDX - License - Identifier : MPL - 2.0
* /
2021-12-17 03:44:29 +00:00
/* eslint ember/no-computed-properties-in-native-classes: 'warn' */
2021-05-19 16:43:55 +00:00
import Ember from 'ember' ;
import { inject as service } from '@ember/service' ;
import Component from '@glimmer/component' ;
import { tracked } from '@glimmer/tracking' ;
import { action } from '@ember/object' ;
import { alias } from '@ember/object/computed' ;
import { maybeQueryRecord } from 'vault/macros/maybe-query-record' ;
2021-12-17 03:44:29 +00:00
const getErrorMessage = ( errors ) => {
2022-11-09 23:15:31 +00:00
const errorMessage =
errors ? . join ( '. ' ) || 'Something went wrong. Check the Vault logs for more information.' ;
2021-05-19 16:43:55 +00:00
return errorMessage ;
} ;
export default class SecretDeleteMenu extends Component {
@ service store ;
@ service router ;
@ service flashMessages ;
@ tracked showDeleteModal = false ;
@ maybeQueryRecord (
'capabilities' ,
2021-12-17 03:44:29 +00:00
( context ) => {
2021-05-19 16:43:55 +00:00
if ( ! context . args || ! context . args . modelForData || ! context . args . modelForData . id ) return ;
2022-11-09 23:15:31 +00:00
const [ backend , id ] = JSON . parse ( context . args . modelForData . id ) ;
2021-05-19 16:43:55 +00:00
return {
2021-09-14 18:30:01 +00:00
id : ` ${ backend } /undelete/ ${ id } ` ,
2021-05-19 16:43:55 +00:00
} ;
} ,
'model.id'
)
undeleteVersionPath ;
@ alias ( 'undeleteVersionPath.canUpdate' ) canUndeleteVersion ;
@ maybeQueryRecord (
'capabilities' ,
2021-12-17 03:44:29 +00:00
( context ) => {
2021-05-19 16:43:55 +00:00
if ( ! context . args || ! context . args . modelForData || ! context . args . modelForData . id ) return ;
2022-11-09 23:15:31 +00:00
const [ backend , id ] = JSON . parse ( context . args . modelForData . id ) ;
2021-05-19 16:43:55 +00:00
return {
2021-09-14 18:30:01 +00:00
id : ` ${ backend } /destroy/ ${ id } ` ,
2021-05-19 16:43:55 +00:00
} ;
} ,
'model.id'
)
destroyVersionPath ;
@ alias ( 'destroyVersionPath.canUpdate' ) canDestroyVersion ;
@ maybeQueryRecord (
'capabilities' ,
2021-12-17 03:44:29 +00:00
( context ) => {
2021-05-19 16:43:55 +00:00
if ( ! context . args . model || ! context . args . model . engine || ! context . args . model . id ) return ;
2022-11-09 23:15:31 +00:00
const backend = context . args . model . engine . id ;
const id = context . args . model . id ;
2021-05-19 16:43:55 +00:00
return {
2021-09-14 18:30:01 +00:00
id : ` ${ backend } /metadata/ ${ id } ` ,
2021-05-19 16:43:55 +00:00
} ;
} ,
'model' ,
'model.id' ,
'mode'
)
v2UpdatePath ;
@ alias ( 'v2UpdatePath.canDelete' ) canDestroyAllVersions ;
2021-08-31 15:41:41 +00:00
@ maybeQueryRecord (
'capabilities' ,
2021-12-17 03:44:29 +00:00
( context ) => {
2021-08-31 15:41:41 +00:00
if ( ! context . args . model || context . args . mode === 'create' ) {
return ;
}
2022-11-09 23:15:31 +00:00
const backend = context . args . isV2 ? context . args . model . engine . id : context . args . model . backend ;
const id = context . args . model . id ;
const path = context . args . isV2 ? ` ${ backend } /data/ ${ id } ` : ` ${ backend } / ${ id } ` ;
2021-08-31 15:41:41 +00:00
return {
id : path ,
} ;
} ,
'isV2' ,
'model' ,
'model.id' ,
'mode'
)
secretDataPath ;
@ alias ( 'secretDataPath.canDelete' ) canDeleteSecretData ;
2021-10-12 19:42:04 +00:00
@ maybeQueryRecord (
'capabilities' ,
2021-12-17 03:44:29 +00:00
( context ) => {
2021-10-12 19:42:04 +00:00
if ( ! context . args . model || context . args . mode === 'create' ) {
return ;
}
2022-11-09 23:15:31 +00:00
const backend = context . args . isV2 ? context . args . model . engine . id : context . args . model . backend ;
const id = context . args . model . id ;
const path = context . args . isV2 ? ` ${ backend } /delete/ ${ id } ` : ` ${ backend } / ${ id } ` ;
2021-10-12 19:42:04 +00:00
return {
id : path ,
} ;
} ,
'isV2' ,
'model' ,
'model.id' ,
'mode'
)
secretSoftDataPath ;
@ alias ( 'secretSoftDataPath.canUpdate' ) canSoftDeleteSecretData ;
2021-05-19 16:43:55 +00:00
get isLatestVersion ( ) {
2021-10-12 19:42:04 +00:00
// must have metadata access.
2022-11-09 23:15:31 +00:00
const { model } = this . args ;
2021-05-19 16:43:55 +00:00
if ( ! model ) return false ;
2022-11-09 23:15:31 +00:00
const latestVersion = model . currentVersion ;
const selectedVersion = model . selectedVersion . version ;
2021-05-19 16:43:55 +00:00
if ( latestVersion !== selectedVersion ) {
return false ;
}
return true ;
}
@ action
handleDelete ( deleteType ) {
2021-08-31 15:41:41 +00:00
// deleteType should be 'delete', 'destroy', 'undelete', 'delete-latest-version', 'destroy-all-versions', 'v1'
2021-05-19 16:43:55 +00:00
if ( ! deleteType ) {
return ;
}
if ( deleteType === 'destroy-all-versions' || deleteType === 'v1' ) {
this . args . model . destroyRecord ( ) . then ( ( ) => {
2021-10-12 19:42:04 +00:00
return this . router . transitionTo ( 'vault.cluster.secrets.backend.list-root' ) ;
2021-05-19 16:43:55 +00:00
} ) ;
} else {
2021-10-12 19:42:04 +00:00
// if they do not have read access on the metadata endpoint we need to pull the version from modelForData so they can perform delete and undelete operations
2022-09-13 22:11:08 +00:00
// only perform if no access to metadata otherwise it will only delete latest version for any deleteType === delete
2021-10-12 19:42:04 +00:00
let currentVersionForNoReadMetadata ;
if ( ! this . args . canReadSecretMetadata ) {
currentVersionForNoReadMetadata = this . args . modelForData ? . version ;
}
2021-05-19 16:43:55 +00:00
return this . store
. adapterFor ( 'secret-v2-version' )
2021-10-12 19:42:04 +00:00
. v2DeleteOperation ( this . store , this . args . modelForData . id , deleteType , currentVersionForNoReadMetadata )
2021-12-17 03:44:29 +00:00
. then ( ( resp ) => {
2021-05-19 16:43:55 +00:00
if ( Ember . testing ) {
2021-11-30 22:31:02 +00:00
this . showDeleteModal = false ;
// we don't want a refresh otherwise test loop will rerun in a loop
2021-05-19 16:43:55 +00:00
return ;
}
if ( ! resp ) {
this . showDeleteModal = false ;
this . args . refresh ( ) ;
return ;
}
if ( resp . isAdapterError ) {
const errorMessage = getErrorMessage ( resp . errors ) ;
this . flashMessages . danger ( errorMessage ) ;
} else {
// not likely to ever get to this situation, but adding just in case.
location . reload ( ) ;
}
} ) ;
}
}
}