feat: gcp secret sync management

This commit is contained in:
Sheen Capadngan
2025-01-25 03:01:10 +08:00
parent 58f51411c0
commit 753c28a2d3
34 changed files with 467 additions and 22 deletions
@@ -0,0 +1,51 @@
import { Controller, useFormContext, useWatch } from "react-hook-form";
import { SingleValue } from "react-select";
import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
import { FilterableSelect, FormControl } from "@app/components/v2";
import { useGcpConnectionListProjects } from "@app/hooks/api/appConnections/gcp/queries";
import { TGitHubConnectionEnvironment } from "@app/hooks/api/appConnections/github";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TSecretSyncForm } from "../schemas";
export const GcpSyncFields = () => {
const { control, setValue } = useFormContext<TSecretSyncForm & { destination: SecretSync.GCP }>();
const connectionId = useWatch({ name: "connection.id", control });
const { data: projects, isPending } = useGcpConnectionListProjects(connectionId, {
enabled: Boolean(connectionId)
});
return (
<>
<SecretSyncConnectionField
onChange={() => {
setValue("destinationConfig.projectId", "");
}}
/>
<Controller
name="destinationConfig.projectId"
control={control}
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl isError={Boolean(error)} errorText={error?.message} label="Project">
<FilterableSelect
menuPlacement="top"
isLoading={isPending && Boolean(connectionId)}
isDisabled={!connectionId}
value={projects?.find((project) => project.id === value) ?? null}
onChange={(option) =>
onChange((option as SingleValue<TGitHubConnectionEnvironment>)?.id ?? null)
}
options={projects}
placeholder="Select a GCP project..."
getOptionLabel={(option) => option.name}
getOptionValue={(option) => option.id.toString()}
/>
</FormControl>
)}
/>
</>
);
};
@@ -4,6 +4,7 @@ import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TSecretSyncForm } from "../schemas";
import { AwsParameterStoreSyncFields } from "./AwsParameterStoreSyncFields";
import { GcpSyncFields } from "./GcpSyncFields";
import { GitHubSyncFields } from "./GitHubSyncFields";
export const SecretSyncDestinationFields = () => {
@@ -16,6 +17,8 @@ export const SecretSyncDestinationFields = () => {
return <AwsParameterStoreSyncFields />;
case SecretSync.GitHub:
return <GitHubSyncFields />;
case SecretSync.GCP:
return <GcpSyncFields />;
default:
throw new Error(`Unhandled Destination Config Field: ${destination}`);
}
@@ -0,0 +1,12 @@
import { useFormContext } from "react-hook-form";
import { SecretSyncLabel } from "@app/components/secret-syncs";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const GcpSyncReviewFields = () => {
const { watch } = useFormContext<TSecretSyncForm & { destination: SecretSync.GCP }>();
const projectId = watch("destinationConfig.projectId");
return <SecretSyncLabel label="Project ID">{projectId}</SecretSyncLabel>;
};
@@ -8,6 +8,7 @@ import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/hel
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { AwsParameterStoreSyncReviewFields } from "./AwsParameterStoreSyncReviewFields";
import { GcpSyncReviewFields } from "./GcpSyncReviewFIelds";
import { GitHubSyncReviewFields } from "./GitHubSyncReviewFields";
export const SecretSyncReviewFields = () => {
@@ -38,6 +39,9 @@ export const SecretSyncReviewFields = () => {
case SecretSync.GitHub:
DestinationFieldsComponent = <GitHubSyncReviewFields />;
break;
case SecretSync.GCP:
DestinationFieldsComponent = <GcpSyncReviewFields />;
break;
default:
throw new Error(`Unhandled Destination Review Fields: ${destination}`);
}
@@ -0,0 +1,10 @@
import { z } from "zod";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const GcpSyncDestinationSchema = z.object({
destination: z.literal(SecretSync.GCP),
destinationConfig: z.object({
projectId: z.string().min(1, "Project ID required")
})
});
@@ -5,6 +5,7 @@ import { SecretSyncInitialSyncBehavior } from "@app/hooks/api/secretSyncs";
import { slugSchema } from "@app/lib/schemas";
import { AwsParameterStoreSyncDestinationSchema } from "./aws-parameter-store-sync-destination-schema";
import { GcpSyncDestinationSchema } from "./gcp-sync-destination-schema";
const BaseSecretSyncSchema = z.object({
name: slugSchema({ field: "Name" }),
@@ -31,7 +32,8 @@ const BaseSecretSyncSchema = z.object({
const SecretSyncUnionSchema = z.discriminatedUnion("destination", [
AwsParameterStoreSyncDestinationSchema,
GitHubSyncDestinationSchema
GitHubSyncDestinationSchema,
GcpSyncDestinationSchema
]);
export const SecretSyncFormSchema = SecretSyncUnionSchema.and(BaseSecretSyncSchema);