Merge pull request #4942 from Infisical/agent-docs-2

feat(dynamic-secrets): retry lease revocation when failing
This commit is contained in:
varonix
2025-11-26 12:56:33 -08:00
committed by GitHub
12 changed files with 651 additions and 143 deletions
@@ -121,6 +121,9 @@ const Page = () => {
const tableRef = useRef<HTMLTableElement>(null);
const [isVisible, setIsVisible] = useState(false);
const [selectedDynamicSecretId, setSelectedDynamicSecretId] = useState<string | null>(
routerQueryParams.dynamicSecretId || ""
);
const { isBatchMode, pendingChanges } = useBatchMode();
const { loadPendingChanges, setExistingKeys } = useBatchModeActions();
@@ -165,6 +168,28 @@ const Page = () => {
if (isVisible) setIsVisible(false);
}, [environment]);
useEffect(() => {
if (routerQueryParams.dynamicSecretId !== null) {
setSelectedDynamicSecretId(routerQueryParams.dynamicSecretId);
navigate({
search: (prev) => ({
...prev,
dynamicSecretId: undefined
})
});
// if any of the router query params are changed, we have to clear the selected dynamic secret id to avoid re-rendering the lease modal when it suddendly becomes available
} else {
setSelectedDynamicSecretId(null);
}
}, [
routerQueryParams.filterBy,
routerQueryParams.search,
routerQueryParams.secretPath,
routerQueryParams.tags
]);
const canReadSecret = hasSecretReadValueOrDescribePermission(
permission,
ProjectPermissionSecretActions.DescribeSecret,
@@ -1039,6 +1064,7 @@ const Page = () => {
)}
{canReadDynamicSecret && Boolean(dynamicSecrets?.length) && (
<DynamicSecretListView
selectedDynamicSecretId={selectedDynamicSecretId}
environment={environment}
projectSlug={projectSlug}
secretPath={secretPath}
@@ -1,3 +1,4 @@
import { useEffect } from "react";
import { subject } from "@casl/ability";
import { faEdit, faFingerprint, faTrash, faWarning } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -13,6 +14,7 @@ import {
Tag,
Tooltip
} from "@app/components/v2";
import { Badge } from "@app/components/v3";
import { ProjectPermissionDynamicSecretActions, ProjectPermissionSub } from "@app/context";
import { usePopUp } from "@app/hooks";
import { useDeleteDynamicSecret } from "@app/hooks/api";
@@ -36,9 +38,11 @@ type Props = {
environment: string;
projectSlug: string;
secretPath?: string;
selectedDynamicSecretId: string | null;
};
export const DynamicSecretListView = ({
selectedDynamicSecretId,
dynamicSecrets = [],
environment,
projectSlug,
@@ -71,6 +75,15 @@ export const DynamicSecretListView = ({
});
};
useEffect(() => {
if (
selectedDynamicSecretId &&
dynamicSecrets.find((secret) => secret.id === selectedDynamicSecretId)
) {
handlePopUpOpen("dynamicSecretLeases", selectedDynamicSecretId);
}
}, [selectedDynamicSecretId]);
return (
<>
{dynamicSecrets.map((secret) => {
@@ -231,7 +244,12 @@ export const DynamicSecretListView = ({
</div>
</div>
<ModalContent
title="Dynamic secret leases"
title={
<div className="flex items-center space-x-2">
<p>Dynamic secret leases</p>
<Badge variant="neutral">{secret.name}</Badge>
</div>
}
subTitle="Revoke or renew your secret leases"
className="max-w-3xl"
>
@@ -12,6 +12,7 @@ const SecretDashboardPageQueryParamsSchema = z.object({
search: z.string().catch(""),
tags: z.string().catch(""),
filterBy: z.string().catch(""),
dynamicSecretId: z.string().catch(""),
connectionId: z.string().optional(),
connectionName: z.string().optional()
});
@@ -26,7 +27,8 @@ export const Route = createFileRoute(
secretPath: "/",
search: "",
tags: "",
filterBy: ""
filterBy: "",
dynamicSecretId: ""
})
]
},