Skip to content

Commit

Permalink
Implement 'Remove hold' option
Browse files Browse the repository at this point in the history
The option 6 on revokation reasons
refers to the 'Certificate hold' one.
When selecting this option, the 'Remove
hold' option should be enabled in the UI
to allow users to enable again the
given certificate.

Signed-off-by: Carla Martinez <[email protected]>
  • Loading branch information
carma12 committed Nov 3, 2023
1 parent f228839 commit 6977131
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 7 deletions.
45 changes: 38 additions & 7 deletions src/components/Form/IpaCertificates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ModalWithTextAreaLayout from "../layouts/ModalWithTextAreaLayout";
import DeletionConfirmationModal from "../modals/DeletionConfirmationModal";
import CertificatesInformationModal from "../modals/CertificatesInformationModal";
import RevokeCertificate from "../modals/RevokeCertificate";
import RemoveHoldCertificate from "../modals/RemoveHoldCertificate";
// Components
import SecondaryButton from "../layouts/SecondaryButton";
// RTK
Expand Down Expand Up @@ -48,12 +49,6 @@ export interface CertificateData {
certInfo: Certificate;
}

interface DN {
c: string;
cn: string;
o: string;
}

export interface DictWithName {
key: string | React.ReactNode;
name: string;
Expand Down Expand Up @@ -183,6 +178,16 @@ const IpaCertificates = (props: PropsToIpaCertificates) => {
return false;
};

// Check if the certificate can be removed from hold
// - i.e.: certificate has been revoked with CRL reason #6: 'Certificate hold'
const canHoldBeRemoved = (idx: number) => {
const cert: CertificateData = certificatesList[idx];
if (cert.certInfo.revocation_reason !== undefined) {
return cert.certInfo.revocation_reason === 6;
}
return false;
};

// Function to get the dropdown items (based on 'idx')
const getDropdownItems = (idx: number) => {
return [
Expand Down Expand Up @@ -215,7 +220,12 @@ const IpaCertificates = (props: PropsToIpaCertificates) => {
>
Revoke
</DropdownItem>,
<DropdownItem key="remove-hold" component="button" isDisabled>
<DropdownItem
key="remove-hold"
component="button"
isDisabled={!canHoldBeRemoved(idx)}
onClick={() => onRemoveHoldCertificate(idx)}
>
Remove hold
</DropdownItem>,
<DropdownSeparator key="separator" />,
Expand Down Expand Up @@ -487,6 +497,21 @@ const IpaCertificates = (props: PropsToIpaCertificates) => {
setIsRevokeModalOpen(false);
};

// 'REMOVE HOLD' OPTION
const [isRemoveHoldModalOpen, setIsRemoveHoldModalOpen] =
React.useState(false);

const onRemoveHoldCertificate = (idx: number) => {
// Track index of the selected certificate
setIdxSelected(idx);
// show revoke modal
setIsRemoveHoldModalOpen(true);
};

const onCloseRemoveHoldModal = () => {
setIsRemoveHoldModalOpen(false);
};

// Render component
return (
<>
Expand Down Expand Up @@ -587,6 +612,12 @@ const IpaCertificates = (props: PropsToIpaCertificates) => {
onClose={onCloseRevokeModal}
onRefresh={props.onRefresh}
/>
<RemoveHoldCertificate
certificate={certificatesList[idxSelected]}
isOpen={isRemoveHoldModalOpen}
onClose={onCloseRemoveHoldModal}
onRefresh={props.onRefresh}
/>
</>
)}
</>
Expand Down
97 changes: 97 additions & 0 deletions src/components/modals/RemoveHoldCertificate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";
// PatternFly
import { Button } from "@patternfly/react-core";
// Modals
import InformationModalLayout from "../layouts/InformationModalLayout";
// Components
import TextLayout from "../layouts/TextLayout";
// Hooks
import useAlerts from "src/hooks/useAlerts";
// Data types
import { CertificateData } from "../Form/IpaCertificates";
// Utils
import { parseDn } from "src/utils/utils";
// RPC
import {
ErrorResult,
useRemoveHoldCertificateMutation,
} from "src/services/rpc";

interface PropsToRemoveHoldCertificate {
certificate: CertificateData;
isOpen: boolean;
onClose: () => void;
onRefresh: () => void;
}

const RemoveHoldCertificate = (props: PropsToRemoveHoldCertificate) => {
// Alerts to show in the UI
const alerts = useAlerts();

// Prepare "cert_remove_hold" API call
const [certRemoveHold] = useRemoveHoldCertificateMutation();

const onRemoveHold = () => {
// Prepare payload
const serialNumber = props.certificate.certInfo.serial_number;
const cacn = props.certificate.certInfo.cacn;
const payload = [serialNumber, cacn];

// Perform the API call
certRemoveHold(payload).then((response) => {
if ("data" in response) {
if (response.data.result) {
// Close modal
props.onClose();
// Set alert: success
alerts.addAlert(
"remove-hold-certificate-success",
"Certificate hold removed",
"success"
);
} else if (response.data.error) {
// Set alert: error
const errorMessage = response.data.error as ErrorResult;
alerts.addAlert(
"remove-hold-certificate-error",
errorMessage.message,
"danger"
);
}
// Refresh data to show new changes in the UI
props.onRefresh();
}
});
};

const infoModalActions = [
<Button key="remove-hold" variant="danger" onClick={onRemoveHold}>
Remove hold
</Button>,
<Button key="close" variant="link" onClick={props.onClose}>
Close
</Button>,
];

const contentMessage = (
<TextLayout>Do you want to remove the certificate hold?</TextLayout>
);

return (
<>
<alerts.ManagedAlerts />
<InformationModalLayout
title={
"Certificate for " + parseDn(props.certificate.certInfo.issuer).cn
}
variant="medium"
actions={infoModalActions}
isOpen={props.isOpen}
onClose={props.onClose}
content={contentMessage}
/>
</>
);
};

export default RemoveHoldCertificate;
17 changes: 17 additions & 0 deletions src/services/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,22 @@ export const api = createApi({
});
},
}),
removeHoldCertificate: build.mutation<FindRPCResponse, any[]>({
query: (payload) => {
const params = [
[payload[0]],
{
cacn: payload[1],
version: API_VERSION_BACKUP,
},
];

return getCommand({
method: "cert_remove_hold",
params: params,
});
},
}),
}),
});

Expand All @@ -442,4 +458,5 @@ export const {
useRemoveCertificateMutation,
useGetCertificateAuthorityQuery,
useRevokeCertificateMutation,
useRemoveHoldCertificateMutation,
} = api;

0 comments on commit 6977131

Please sign in to comment.