mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Improve Gitlab sync destination check and show projectId on duplicate destination
This commit is contained in:
@@ -5,13 +5,15 @@ type Props = {
|
||||
onOpenChange: (isOpen: boolean) => void;
|
||||
onConfirm: () => void;
|
||||
isLoading?: boolean;
|
||||
duplicateProjectId?: string;
|
||||
};
|
||||
|
||||
export const DuplicateDestinationConfirmationModal = ({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
onConfirm,
|
||||
isLoading
|
||||
isLoading,
|
||||
duplicateProjectId
|
||||
}: Props) => {
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
@@ -21,6 +23,14 @@ export const DuplicateDestinationConfirmationModal = ({
|
||||
Another secret sync in your organization is already configured with the same
|
||||
destination. Proceeding may cause conflicts or overwrite existing data.
|
||||
</p>
|
||||
{duplicateProjectId && (
|
||||
<p className="mt-2 text-xs text-mineshaft-400">
|
||||
Duplicate found in project ID:{" "}
|
||||
<code className="rounded bg-mineshaft-600 px-1 py-0.5 text-mineshaft-200">
|
||||
{duplicateProjectId}
|
||||
</code>
|
||||
</p>
|
||||
)}
|
||||
<p className="mt-2">Are you sure you want to continue?</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
|
||||
|
||||
const [destinationConfigToCheck, setDestinationConfigToCheck] = useState<unknown>(null);
|
||||
const [checkDuplicateEnabled, setCheckDuplicateEnabled] = useState(false);
|
||||
const [storedDuplicateProjectId, setStoredDuplicateProjectId] = useState<string | undefined>();
|
||||
|
||||
const { data: hasDuplicate, isLoading: isCheckingDuplicate } = useCheckDuplicateDestination(
|
||||
const { data: duplicateData, isLoading: isCheckingDuplicate } = useCheckDuplicateDestination(
|
||||
secretSync.destination,
|
||||
destinationConfigToCheck,
|
||||
secretSync.projectId,
|
||||
@@ -84,7 +85,8 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
|
||||
|
||||
useEffect(() => {
|
||||
if (checkDuplicateEnabled && !isCheckingDuplicate && destinationConfigToCheck) {
|
||||
if (hasDuplicate) {
|
||||
if (duplicateData?.hasDuplicate) {
|
||||
setStoredDuplicateProjectId(duplicateData.duplicateProjectId);
|
||||
setShowDuplicateConfirmation(true);
|
||||
} else if (pendingFormData) {
|
||||
performUpdate(pendingFormData);
|
||||
@@ -96,7 +98,8 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
|
||||
}, [
|
||||
checkDuplicateEnabled,
|
||||
isCheckingDuplicate,
|
||||
hasDuplicate,
|
||||
duplicateData?.hasDuplicate,
|
||||
duplicateData?.duplicateProjectId,
|
||||
destinationConfigToCheck,
|
||||
pendingFormData,
|
||||
performUpdate
|
||||
@@ -197,9 +200,15 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
|
||||
|
||||
<DuplicateDestinationConfirmationModal
|
||||
isOpen={showDuplicateConfirmation}
|
||||
onOpenChange={setShowDuplicateConfirmation}
|
||||
onOpenChange={(open) => {
|
||||
setShowDuplicateConfirmation(open);
|
||||
if (!open) {
|
||||
setStoredDuplicateProjectId(undefined);
|
||||
}
|
||||
}}
|
||||
onConfirm={handleConfirmDuplicate}
|
||||
isLoading={updateSecretSync.isPending}
|
||||
duplicateProjectId={storedDuplicateProjectId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -67,7 +67,7 @@ export const SecretSyncReviewFields = () => {
|
||||
|
||||
const destinationName = SECRET_SYNC_MAP[destination].name;
|
||||
|
||||
const { hasDuplicate, isChecking } = useDuplicateDestinationCheck({
|
||||
const { hasDuplicate, duplicateProjectId, isChecking } = useDuplicateDestinationCheck({
|
||||
destination,
|
||||
projectId: currentProject?.id || "",
|
||||
enabled: true,
|
||||
@@ -192,10 +192,17 @@ export const SecretSyncReviewFields = () => {
|
||||
<div className="mb-2 flex items-start rounded-md border border-yellow-600 bg-yellow-900/20 px-3 py-2">
|
||||
<div className="flex text-sm text-yellow-100">
|
||||
<FontAwesomeIcon icon={faWarning} className="mr-2 mt-1 text-yellow-600" />
|
||||
<p>
|
||||
Another secret sync in your organization is already configured with the same
|
||||
destination. This may lead to conflicts or unexpected behavior.
|
||||
</p>
|
||||
<div>
|
||||
<p>
|
||||
Another secret sync in your organization is already configured with the same
|
||||
destination. This may lead to conflicts or unexpected behavior.
|
||||
</p>
|
||||
{duplicateProjectId && (
|
||||
<p className="mt-1 text-xs text-yellow-200">
|
||||
Duplicate found in project ID: <code className="rounded bg-yellow-800/50 px-1 py-0.5">{duplicateProjectId}</code>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -103,23 +103,28 @@ export const useCheckDuplicateDestination = (
|
||||
projectId: string,
|
||||
excludeSyncId?: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<boolean, unknown, boolean, ReturnType<typeof secretSyncKeys.duplicateCheck>>,
|
||||
UseQueryOptions<
|
||||
{ hasDuplicate: boolean; duplicateProjectId?: string },
|
||||
unknown,
|
||||
{ hasDuplicate: boolean; duplicateProjectId?: string },
|
||||
ReturnType<typeof secretSyncKeys.duplicateCheck>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: secretSyncKeys.duplicateCheck(destination, destinationConfig, excludeSyncId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.post<{ hasDuplicate: boolean }>(
|
||||
`/api/v1/secret-syncs/${destination}/check-destination`,
|
||||
{
|
||||
destinationConfig,
|
||||
excludeSyncId,
|
||||
projectId
|
||||
}
|
||||
);
|
||||
const { data } = await apiRequest.post<{
|
||||
hasDuplicate: boolean;
|
||||
duplicateProjectId?: string;
|
||||
}>(`/api/v1/secret-syncs/${destination}/check-destination`, {
|
||||
destinationConfig,
|
||||
excludeSyncId,
|
||||
projectId
|
||||
});
|
||||
|
||||
return data.hasDuplicate;
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(destinationConfig) && Object.keys(destinationConfig || {}).length > 0,
|
||||
...options
|
||||
|
||||
@@ -30,7 +30,7 @@ export const useDuplicateDestinationCheck = ({
|
||||
const shouldCheck = enabled && hasValidConfig;
|
||||
|
||||
const {
|
||||
data: hasDuplicate,
|
||||
data: duplicateData,
|
||||
isLoading,
|
||||
error,
|
||||
refetch
|
||||
@@ -41,7 +41,8 @@ export const useDuplicateDestinationCheck = ({
|
||||
});
|
||||
|
||||
return {
|
||||
hasDuplicate: shouldCheck ? Boolean(hasDuplicate) : false,
|
||||
hasDuplicate: shouldCheck ? Boolean(duplicateData?.hasDuplicate) : false,
|
||||
duplicateProjectId: duplicateData?.duplicateProjectId,
|
||||
isChecking: shouldCheck && isLoading,
|
||||
hasError: Boolean(error),
|
||||
hasValidConfig,
|
||||
|
||||
Reference in New Issue
Block a user