mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 05:28:51 +00:00
Address PR suggestions
This commit is contained in:
@@ -117,10 +117,10 @@ export const useUpdateRenewalConfig = () => {
|
||||
object,
|
||||
TUpdateRenewalConfigDTO
|
||||
>({
|
||||
mutationFn: async ({ certificateId, renewBeforeDays, disableAutoRenewal }) => {
|
||||
mutationFn: async ({ certificateId, renewBeforeDays, enableAutoRenewal }) => {
|
||||
const { data } = await apiRequest.patch<{ message: string; renewBeforeDays?: number }>(
|
||||
`/api/v3/certificates/${certificateId}/config`,
|
||||
{ renewBeforeDays, disableAutoRenewal }
|
||||
{ renewBeforeDays, enableAutoRenewal }
|
||||
);
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -16,8 +16,8 @@ export type TCertificate = {
|
||||
extendedKeyUsages: CertExtendedKeyUsage[];
|
||||
renewBeforeDays?: number;
|
||||
renewedBy?: string;
|
||||
renewedFromId?: string;
|
||||
renewedById?: string;
|
||||
renewedFromCertificateId?: string;
|
||||
renewedByCertificateId?: string;
|
||||
renewalError?: string;
|
||||
};
|
||||
|
||||
@@ -67,6 +67,6 @@ export type TRenewCertificateResponse = {
|
||||
export type TUpdateRenewalConfigDTO = {
|
||||
certificateId: string;
|
||||
renewBeforeDays?: number;
|
||||
disableAutoRenewal?: boolean;
|
||||
enableAutoRenewal?: boolean;
|
||||
projectSlug: string;
|
||||
};
|
||||
|
||||
+23
-7
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
@@ -7,6 +7,7 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
||||
import { useProject } from "@app/context";
|
||||
import { useUpdateRenewalConfig } from "@app/hooks/api";
|
||||
import { useGetCertificateProfileById } from "@app/hooks/api/certificateProfiles";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const DEFAULT_RENEWAL_BEFORE_DAYS = 20;
|
||||
@@ -64,7 +65,8 @@ const RenewalConfigForm = ({
|
||||
}) => (
|
||||
<form onSubmit={onSubmit}>
|
||||
<FormControl
|
||||
label="Renewal Days Before Expiration"
|
||||
label="Auto-renew days before expiry"
|
||||
isError={Boolean(errors.renewBeforeDays)}
|
||||
errorText={errors.renewBeforeDays?.message}
|
||||
className="mb-6"
|
||||
>
|
||||
@@ -111,10 +113,24 @@ export const CertificateManageRenewalModal = ({ popUp, handlePopUpToggle }: Prop
|
||||
ttlDays?: number;
|
||||
notAfter: string;
|
||||
renewalError?: string;
|
||||
renewedFromId?: string;
|
||||
renewedById?: string;
|
||||
renewedFromCertificateId?: string;
|
||||
renewedByCertificateId?: string;
|
||||
};
|
||||
|
||||
const { data: profileData } = useGetCertificateProfileById({
|
||||
profileId: certificateData?.profileId || ""
|
||||
});
|
||||
|
||||
const defaultRenewalDays = useMemo(() => {
|
||||
if (certificateData?.renewBeforeDays) {
|
||||
return certificateData.renewBeforeDays;
|
||||
}
|
||||
if (profileData?.apiConfig?.renewBeforeDays) {
|
||||
return profileData.apiConfig.renewBeforeDays;
|
||||
}
|
||||
return DEFAULT_RENEWAL_BEFORE_DAYS;
|
||||
}, [certificateData?.renewBeforeDays, profileData?.apiConfig?.renewBeforeDays]);
|
||||
|
||||
const isAutoRenewalEnabled = Boolean(
|
||||
certificateData?.renewBeforeDays && certificateData.renewBeforeDays > 0
|
||||
);
|
||||
@@ -134,17 +150,17 @@ export const CertificateManageRenewalModal = ({ popUp, handlePopUpToggle }: Prop
|
||||
} = useForm<FormData>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
renewBeforeDays: DEFAULT_RENEWAL_BEFORE_DAYS
|
||||
renewBeforeDays: defaultRenewalDays
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (popUp.manageRenewal.isOpen) {
|
||||
reset({
|
||||
renewBeforeDays: certificateData?.renewBeforeDays || DEFAULT_RENEWAL_BEFORE_DAYS
|
||||
renewBeforeDays: defaultRenewalDays
|
||||
});
|
||||
}
|
||||
}, [popUp.manageRenewal.isOpen, certificateData?.renewBeforeDays, reset]);
|
||||
}, [popUp.manageRenewal.isOpen, defaultRenewalDays, reset]);
|
||||
|
||||
const onUpdateRenewal = async (data: FormData) => {
|
||||
try {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export const CertificateRenewalDisableModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
await updateRenewalConfig({
|
||||
certificateId: certificateData.certificateId,
|
||||
projectSlug: currentProject.slug,
|
||||
disableAutoRenewal: true
|
||||
enableAutoRenewal: false
|
||||
});
|
||||
|
||||
createNotification({
|
||||
|
||||
@@ -36,7 +36,8 @@ import {
|
||||
import {
|
||||
ProjectPermissionCertificateActions,
|
||||
ProjectPermissionSub,
|
||||
useProject
|
||||
useProject,
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { useListWorkspaceCertificates, useUpdateRenewalConfig } from "@app/hooks/api";
|
||||
import { caSupportsCapability } from "@app/hooks/api/ca/constants";
|
||||
@@ -56,8 +57,8 @@ const isExpiringWithinOneDay = (notAfter: string): boolean => {
|
||||
};
|
||||
|
||||
const getAutoRenewalInfo = (certificate: TCertificate) => {
|
||||
if (certificate.renewedById) {
|
||||
return { text: "Renewed", variant: "success" as const };
|
||||
if (certificate.renewedByCertificateId) {
|
||||
return { text: "Renewed", variant: "instance" as const };
|
||||
}
|
||||
|
||||
const isRevoked = certificate.status === CertStatus.REVOKED;
|
||||
@@ -65,8 +66,36 @@ const getAutoRenewalInfo = (certificate: TCertificate) => {
|
||||
const hasNoProfile = !certificate.profileId;
|
||||
const isExpiringWithinDay = isExpiringWithinOneDay(certificate.notAfter);
|
||||
|
||||
if (isRevoked || isExpired || hasNoProfile || isExpiringWithinDay) {
|
||||
return null;
|
||||
if (isRevoked) {
|
||||
return {
|
||||
text: "Not Available",
|
||||
variant: "instance" as const,
|
||||
tooltip: "Auto-renewal is not available for revoked certificates"
|
||||
};
|
||||
}
|
||||
|
||||
if (isExpired) {
|
||||
return {
|
||||
text: "Not Available",
|
||||
variant: "instance" as const,
|
||||
tooltip: "Auto-renewal is not available for expired certificates"
|
||||
};
|
||||
}
|
||||
|
||||
if (hasNoProfile) {
|
||||
return {
|
||||
text: "Not Available",
|
||||
variant: "instance" as const,
|
||||
tooltip: "Auto-renewal requires a certificate profile"
|
||||
};
|
||||
}
|
||||
|
||||
if (isExpiringWithinDay) {
|
||||
return {
|
||||
text: "Not Available",
|
||||
variant: "instance" as const,
|
||||
tooltip: "Auto-renewal is not available for certificates expiring within 24 hours"
|
||||
};
|
||||
}
|
||||
|
||||
if (certificate.renewalError) {
|
||||
@@ -127,8 +156,8 @@ type Props = {
|
||||
ttlDays?: number;
|
||||
notAfter?: string;
|
||||
renewalError?: string;
|
||||
renewedFromId?: string;
|
||||
renewedById?: string;
|
||||
renewedFromCertificateId?: string;
|
||||
renewedByCertificateId?: string;
|
||||
}
|
||||
) => void;
|
||||
};
|
||||
@@ -138,6 +167,7 @@ const PER_PAGE_INIT = 25;
|
||||
export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(PER_PAGE_INIT);
|
||||
const { subscription } = useSubscription();
|
||||
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListWorkspaceCertificates({
|
||||
@@ -147,6 +177,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
});
|
||||
|
||||
const { mutateAsync: updateRenewalConfig } = useUpdateRenewalConfig();
|
||||
const isLegacyTemplatesEnabled = subscription.pkiLegacyTemplates;
|
||||
|
||||
const { data: caData } = useListCasByProjectId(currentProject?.id ?? "");
|
||||
|
||||
@@ -173,7 +204,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
await updateRenewalConfig({
|
||||
certificateId,
|
||||
projectSlug: currentProject.slug,
|
||||
disableAutoRenewal: true
|
||||
enableAutoRenewal: false
|
||||
});
|
||||
|
||||
createNotification({
|
||||
@@ -198,7 +229,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
<Th>Status</Th>
|
||||
<Th>Not Before</Th>
|
||||
<Th>Not After</Th>
|
||||
<Th>Auto Renewal</Th>
|
||||
<Th>Renewal Status</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
</THead>
|
||||
@@ -286,32 +317,34 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionCertificateActions.Read}
|
||||
a={ProjectPermissionSub.Certificates}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<DropdownMenuItem
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("certificate", {
|
||||
serialNumber: certificate.serialNumber
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faEye} />}
|
||||
>
|
||||
View Details
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
{isLegacyTemplatesEnabled && (
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionCertificateActions.Read}
|
||||
a={ProjectPermissionSub.Certificates}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<DropdownMenuItem
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("certificate", {
|
||||
serialNumber: certificate.serialNumber
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faEye} />}
|
||||
>
|
||||
View Details
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
)}
|
||||
{/* Manage auto renewal option - not shown for failed renewals */}
|
||||
{(() => {
|
||||
const canManageRenewal =
|
||||
certificate.profileId &&
|
||||
!certificate.renewedById &&
|
||||
!certificate.renewedByCertificateId &&
|
||||
!isRevoked &&
|
||||
!isExpired &&
|
||||
!hasFailed &&
|
||||
@@ -353,8 +386,9 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
ttlDays,
|
||||
notAfter: certificate.notAfter,
|
||||
renewalError: certificate.renewalError,
|
||||
renewedFromId: certificate.renewedFromId,
|
||||
renewedById: certificate.renewedById
|
||||
renewedFromCertificateId:
|
||||
certificate.renewedFromCertificateId,
|
||||
renewedByCertificateId: certificate.renewedByCertificateId
|
||||
});
|
||||
}}
|
||||
disabled={!isAllowed}
|
||||
@@ -373,7 +407,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
{(() => {
|
||||
const canDisableRenewal =
|
||||
certificate.profileId &&
|
||||
!certificate.renewedById &&
|
||||
!certificate.renewedByCertificateId &&
|
||||
!isRevoked &&
|
||||
!isExpired &&
|
||||
!isExpiringWithinDay &&
|
||||
@@ -411,7 +445,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
{(() => {
|
||||
const canRenew =
|
||||
certificate.profileId &&
|
||||
!certificate.renewedById &&
|
||||
!certificate.renewedByCertificateId &&
|
||||
!isRevoked &&
|
||||
!isExpired;
|
||||
|
||||
|
||||
+21
-1
@@ -11,6 +11,26 @@ import {
|
||||
mapTemplateSignatureAlgorithmToApi
|
||||
} from "@app/pages/cert-manager/PoliciesPage/components/CertificateTemplatesV2Tab/shared/certificate-constants";
|
||||
|
||||
const convertTemplateTtlToCertificateTtl = (templateTtl: string): string => {
|
||||
const match = templateTtl.match(/^(\d+)([dmyh])$/);
|
||||
if (!match) return templateTtl;
|
||||
|
||||
const [, value, unit] = match;
|
||||
const numValue = parseInt(value, 10);
|
||||
|
||||
switch (unit) {
|
||||
case "m":
|
||||
return `${numValue * 30}d`;
|
||||
case "y":
|
||||
return `${numValue * 365}d`;
|
||||
case "d":
|
||||
case "h":
|
||||
return templateTtl;
|
||||
default:
|
||||
return templateTtl;
|
||||
}
|
||||
};
|
||||
|
||||
export type TemplateConstraints = {
|
||||
allowedKeyUsages: string[];
|
||||
allowedExtendedKeyUsages: string[];
|
||||
@@ -118,7 +138,7 @@ export const useCertificateTemplate = (
|
||||
|
||||
// Set TTL if available
|
||||
if (templateData.validity?.max) {
|
||||
setValue("ttl", templateData.validity.max);
|
||||
setValue("ttl", convertTemplateTtlToCertificateTtl(templateData.validity.max));
|
||||
}
|
||||
|
||||
// Handle SAN types
|
||||
|
||||
Reference in New Issue
Block a user