Skip to content

Commit 5d4a069

Browse files
Merge pull request #3796 from RedisInsight/feature/RI-6004-delete-certificates
[RI-6004] Delete Certificates
2 parents fd15627 + b09dd32 commit 5d4a069

File tree

12 files changed

+546
-10
lines changed

12 files changed

+546
-10
lines changed

redisinsight/ui/src/pages/home/components/database-list-component/DatabasesListWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ const DatabasesListWrapper = ({ width, onEditInstance, editedInstance, onDeleteI
388388
/>
389389
<PopoverDelete
390390
header={formatLongName(instance.name, 50, 10, '...')}
391-
text="will be deleted from Redis Insight."
391+
text="will be removed from Redis Insight."
392392
item={instance.id}
393393
suffix={suffix}
394394
deleting={deletingIdRef.current}

redisinsight/ui/src/pages/home/components/form/TlsDetails.tsx

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { ChangeEvent } from 'react'
1+
import React, { ChangeEvent, useState } from 'react'
22
import {
33
EuiCheckbox,
44
EuiFieldText,
@@ -13,25 +13,76 @@ import {
1313
import cx from 'classnames'
1414
import { FormikProps } from 'formik'
1515

16-
import { validateCertName, validateField } from 'uiSrc/utils'
16+
import { useDispatch } from 'react-redux'
17+
import { validateCertName, validateField, Nullable, truncateText } from 'uiSrc/utils'
18+
import PopoverDelete from 'uiSrc/pages/browser/components/popover-delete/PopoverDelete'
1719

1820
import {
1921
ADD_NEW_CA_CERT,
20-
NO_CA_CERT
22+
NO_CA_CERT,
23+
ADD_NEW,
2124
} from 'uiSrc/pages/home/constants'
2225
import { DbConnectionInfo } from 'uiSrc/pages/home/interfaces'
23-
26+
import { TelemetryEvent, sendEventTelemetry } from 'uiSrc/telemetry'
27+
import { deleteCaCertificateAction } from 'uiSrc/slices/instances/caCerts'
28+
import { deleteClientCertAction } from 'uiSrc/slices/instances/clientCerts'
2429
import styles from '../styles.module.scss'
2530

31+
const suffix = '_tls_details'
32+
2633
export interface Props {
2734
flexGroupClassName?: string
2835
flexItemClassName?: string
2936
formik: FormikProps<DbConnectionInfo>
3037
caCertificates?: { id: string; name: string }[]
3138
certificates?: { id: number; name: string }[]
3239
}
40+
3341
const TlsDetails = (props: Props) => {
42+
const dispatch = useDispatch()
3443
const { flexGroupClassName = '', flexItemClassName = '', formik, caCertificates, certificates } = props
44+
const [activeCertId, setActiveCertId] = useState<Nullable<string>>(null)
45+
46+
const handleDeleteCaCert = (id: string) => {
47+
dispatch(deleteCaCertificateAction(id, () => {
48+
if (formik.values.selectedCaCertName === id) {
49+
formik.setFieldValue(
50+
'selectedCaCertName',
51+
NO_CA_CERT,
52+
)
53+
}
54+
handleClickDeleteCert('CA')
55+
}))
56+
}
57+
58+
const handleDeleteClientCert = (id: string) => {
59+
dispatch(deleteClientCertAction(id, () => {
60+
if (formik.values.selectedTlsClientCertId === id) {
61+
formik.setFieldValue(
62+
'selectedTlsClientCertId',
63+
ADD_NEW,
64+
)
65+
}
66+
handleClickDeleteCert('Client')
67+
}))
68+
}
69+
70+
const handleClickDeleteCert = (certificateType: 'Client' | 'CA') => {
71+
sendEventTelemetry({
72+
event: TelemetryEvent.CONFIG_DATABASES_CERTIFICATE_REMOVED,
73+
eventData: {
74+
certificateType,
75+
},
76+
})
77+
}
78+
79+
const closePopover = () => {
80+
setActiveCertId(null)
81+
}
82+
83+
const showPopover = (id: string) => {
84+
setActiveCertId(`${id}${suffix}`)
85+
}
3586

3687
const optionsCertsCA: EuiSuperSelectOption<string>[] = [
3788
{
@@ -48,6 +99,23 @@ const TlsDetails = (props: Props) => {
4899
optionsCertsCA.push({
49100
value: cert.id,
50101
inputDisplay: cert.name,
102+
dropdownDisplay: (
103+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
104+
<div>{truncateText(cert.name, 25)}</div>
105+
<PopoverDelete
106+
header={cert.name}
107+
text="will be removed from RedisInsight."
108+
item={cert.id}
109+
suffix={suffix}
110+
deleting={activeCertId}
111+
closePopover={closePopover}
112+
updateLoading={false}
113+
showPopover={showPopover}
114+
handleDeleteItem={handleDeleteCaCert}
115+
testid={`delete-ca-cert-${cert.id}`}
116+
/>
117+
</div>
118+
),
51119
})
52120
})
53121

@@ -62,6 +130,23 @@ const TlsDetails = (props: Props) => {
62130
optionsCertsClient.push({
63131
value: `${cert.id}`,
64132
inputDisplay: cert.name,
133+
dropdownDisplay: (
134+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
135+
<div>{truncateText(cert.name, 25)}</div>
136+
<PopoverDelete
137+
header={cert.name}
138+
text="will be removed from RedisInsight."
139+
item={cert.id}
140+
suffix={suffix}
141+
deleting={activeCertId}
142+
closePopover={closePopover}
143+
updateLoading={false}
144+
showPopover={showPopover}
145+
handleDeleteItem={handleDeleteClientCert}
146+
testid={`delete-client-cert-${cert.id}`}
147+
/>
148+
</div>
149+
),
65150
})
66151
})
67152

redisinsight/ui/src/pages/home/components/manual-connection/ManualConnectionWrapper.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { applyTlSDatabase, applySSHDatabase, autoFillFormDetails, getTlsSettings
2727
import {
2828
DEFAULT_TIMEOUT,
2929
SubmitBtnText,
30+
ADD_NEW,
31+
ADD_NEW_CA_CERT,
3032
} from 'uiSrc/pages/home/constants'
3133
import ManualConnectionForm from './manual-connection-form'
3234

@@ -207,7 +209,22 @@ const ManualConnectionWrapper = (props: Props) => {
207209
if (editMode) {
208210
database.id = editedInstance?.id
209211

210-
return getFormUpdates(database, omit(editedInstance, ['id']))
212+
const updatedValues = getFormUpdates(database, omit(editedInstance, ['id']))
213+
214+
// When a new caCert/clientCert is deleted, the editedInstance
215+
// is not updated with the deletion until 'apply' is
216+
// clicked. Once the apply is clicked, the editedInstance object
217+
// that is validated against, still has the older certificates
218+
// attached. Attaching the new certs to the final object helps.
219+
if (values.selectedCaCertName === ADD_NEW_CA_CERT && values.newCaCertName !== '' && values.newCaCertName === editedInstance.caCert?.name) {
220+
updatedValues.caCert = database.caCert
221+
}
222+
223+
if (values.selectedTlsClientCertId === ADD_NEW && values.newTlsCertPairName !== '' && values.newTlsCertPairName === editedInstance?.clientCert?.name) {
224+
updatedValues.clientCert = database.clientCert
225+
}
226+
227+
return updatedValues
211228
}
212229

213230
return removeEmpty(database)

redisinsight/ui/src/pages/rdi/home/instance-list/RdiInstancesListWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ const RdiInstancesListWrapper = ({ width, onEditInstance, editedInstance, onDele
186186
/>
187187
<PopoverDelete
188188
header={formatLongName(instance.name, 50, 10, '...')}
189-
text="will be deleted from RedisInsight."
189+
text="will be removed from RedisInsight."
190190
item={instance.id}
191191
suffix={suffix}
192192
deleting={deleting.id}

redisinsight/ui/src/slices/instances/caCerts.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ const caCertsSlice = createSlice({
3030
state.loading = false
3131
state.error = payload
3232
},
33+
34+
// delete ca certificate
35+
deleteCaCertificate: (state) => {
36+
state.loading = true
37+
state.error = ''
38+
},
39+
deleteCaCertificateSuccess: (state) => {
40+
state.loading = false
41+
},
42+
deleteCaCertificateFailure: (state, { payload }) => {
43+
state.loading = false
44+
state.error = payload
45+
},
3346
},
3447
})
3548

@@ -38,6 +51,10 @@ export const {
3851
loadCaCerts,
3952
loadCaCertsSuccess,
4053
loadCaCertsFailure,
54+
55+
deleteCaCertificate,
56+
deleteCaCertificateSuccess,
57+
deleteCaCertificateFailure,
4158
} = caCertsSlice.actions
4259

4360
// A selector
@@ -66,3 +83,25 @@ export function fetchCaCerts() {
6683
}
6784
}
6885
}
86+
87+
export function deleteCaCertificateAction(id: string, onSuccessAction?: (id: string) => void,) {
88+
return async (dispatch: AppDispatch) => {
89+
dispatch(deleteCaCertificate(id))
90+
91+
try {
92+
const { status } = await apiService.delete(
93+
`${ApiEndpoints.CA_CERTIFICATES}/${id}`
94+
)
95+
96+
if (isStatusSuccessful(status)) {
97+
dispatch(deleteCaCertificateSuccess())
98+
onSuccessAction?.(id)
99+
dispatch(fetchCaCerts())
100+
}
101+
} catch (error) {
102+
const errorMessage = getApiErrorMessage(error)
103+
dispatch(addErrorNotification(error))
104+
dispatch(deleteCaCertificateFailure(errorMessage))
105+
}
106+
}
107+
}

redisinsight/ui/src/slices/instances/clientCerts.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ const clientCertsSlice = createSlice({
3030
state.loading = false
3131
state.error = payload
3232
},
33+
34+
// delete client certificate
35+
deleteClientCert: (state) => {
36+
state.loading = true
37+
state.error = ''
38+
},
39+
deleteClientCertSuccess: (state) => {
40+
state.loading = false
41+
},
42+
deleteClientCertFailure: (state, { payload }) => {
43+
state.loading = false
44+
state.error = payload
45+
},
3346
},
3447
})
3548

@@ -38,6 +51,10 @@ export const {
3851
loadClientCerts,
3952
loadClientCertsSuccess,
4053
loadClientCertsFailure,
54+
55+
deleteClientCert,
56+
deleteClientCertSuccess,
57+
deleteClientCertFailure,
4158
} = clientCertsSlice.actions
4259

4360
// A selector
@@ -67,3 +84,22 @@ export function fetchClientCerts() {
6784
}
6885
}
6986
}
87+
88+
export function deleteClientCertAction(id: string, onSuccessAction?: (id: string) => void,) {
89+
return async (dispatch: AppDispatch) => {
90+
try {
91+
const { status } = await apiService.delete(
92+
`${ApiEndpoints.CLIENT_CERTIFICATES}/${id}`
93+
)
94+
95+
if (isStatusSuccessful(status)) {
96+
dispatch(deleteClientCertSuccess())
97+
onSuccessAction?.(id)
98+
dispatch(fetchClientCerts())
99+
}
100+
} catch (error) {
101+
dispatch(addErrorNotification(error))
102+
dispatch(deleteClientCertFailure(getApiErrorMessage(error)))
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)