fix: review changes

This commit is contained in:
Piyush Gupta
2025-12-05 19:39:21 +05:30
parent 58fbbe0d91
commit fd1a3d5d12
6 changed files with 309 additions and 306 deletions
@@ -26,7 +26,7 @@ const AwsConnectionAssumeRoleCredentialsSchema = z.object({
.trim() .trim()
.min(1) .min(1)
.optional() .optional()
.describe("AWS assume role external id for furthur security in authentication") .describe("AWS assume role external id for further security in authentication")
}); });
const AwsConnectionAccessTokenCredentialsSchema = z.object({ const AwsConnectionAccessTokenCredentialsSchema = z.object({
@@ -64,7 +64,10 @@ export const SanitizedExternalKmsAwsSchema = ExternalKmsAwsSchema.extend({
}), }),
z.object({ z.object({
type: z.literal(KmsAwsCredentialType.AssumeRole), type: z.literal(KmsAwsCredentialType.AssumeRole),
data: AwsConnectionAssumeRoleCredentialsSchema.pick({}) data: AwsConnectionAssumeRoleCredentialsSchema.pick({
assumeRoleArn: true,
externalId: true
})
}) })
]) ])
}); });
+1 -1
View File
@@ -131,7 +131,7 @@ export type AddExternalKmsType = z.infer<typeof AddExternalKmsSchema>;
// we need separate schema for update because the credential field is not required on GCP // we need separate schema for update because the credential field is not required on GCP
export const ExternalKmsUpdateInputSchema = z.discriminatedUnion("type", [ export const ExternalKmsUpdateInputSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal(ExternalKmsProvider.Aws), inputs: ExternalKmsAwsSchema }), z.object({ type: z.literal(ExternalKmsProvider.Aws), inputs: ExternalKmsAwsSchema.partial() }),
z.object({ z.object({
type: z.literal(ExternalKmsProvider.Gcp), type: z.literal(ExternalKmsProvider.Gcp),
inputs: ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true }) inputs: ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true })
@@ -11,7 +11,8 @@ import {
AddExternalKmsType, AddExternalKmsType,
ExternalKmsProvider, ExternalKmsProvider,
Kms, Kms,
KmsAwsCredentialType KmsAwsCredentialType,
UpdateExternalKmsSchema
} from "@app/hooks/api/kms/types"; } from "@app/hooks/api/kms/types";
const AWS_REGIONS = [ const AWS_REGIONS = [
@@ -50,10 +51,12 @@ type Props = {
onCompleted: () => void; onCompleted: () => void;
onCancel: () => void; onCancel: () => void;
kms?: Kms; kms?: Kms;
mode?: "full" | "credentials"; mode?: "full" | "credentials" | "details";
}; };
export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => { export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => {
const validationSchema = kms ? UpdateExternalKmsSchema : AddExternalKmsSchema;
const { const {
control, control,
handleSubmit, handleSubmit,
@@ -61,24 +64,35 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
setValue, setValue,
formState: { isSubmitting } formState: { isSubmitting }
} = useForm<AddExternalKmsType>({ } = useForm<AddExternalKmsType>({
resolver: zodResolver(AddExternalKmsSchema), resolver: zodResolver(validationSchema),
defaultValues: { defaultValues: {
name: kms?.name, name: kms?.name,
description: kms?.description ?? "", description: kms?.description ?? "",
configuration: { configuration: {
type: ExternalKmsProvider.Aws, type: ExternalKmsProvider.Aws,
inputs: { inputs: {
credential: { ...(mode !== "details" &&
type: kms?.externalKms?.configuration?.credential?.type, kms?.externalKms?.configuration?.credential?.type &&
data: { kms.externalKms.configuration.credential.data
accessKey: kms?.externalKms?.configuration?.credential?.data?.accessKey, ? {
secretKey: kms?.externalKms?.configuration?.credential?.data?.secretKey, credential: {
assumeRoleArn: kms?.externalKms?.configuration?.credential?.data?.assumeRoleArn, type: kms.externalKms.configuration.credential.type,
externalId: kms?.externalKms?.configuration?.credential?.data?.externalId data: {
} accessKey: kms.externalKms.configuration.credential.data?.accessKey ?? "",
}, secretKey: kms.externalKms.configuration.credential.data?.secretKey ?? "",
awsRegion: kms?.externalKms?.configuration?.awsRegion, assumeRoleArn:
kmsKeyId: kms?.externalKms?.configuration?.kmsKeyId kms.externalKms.configuration.credential.data?.assumeRoleArn ?? "",
externalId: kms.externalKms.configuration.credential.data?.externalId ?? ""
}
}
}
: {}),
...(mode !== "credentials"
? {
awsRegion: kms?.externalKms?.configuration?.awsRegion ?? "",
kmsKeyId: kms?.externalKms?.configuration?.kmsKeyId ?? ""
}
: {})
} }
} }
} }
@@ -97,16 +111,33 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
const { name, description, configuration } = data; const { name, description, configuration } = data;
try { try {
if (kms) { if (kms) {
if (configuration.type !== ExternalKmsProvider.Aws) {
throw new Error("Invalid configuration type");
}
const awsInputs = configuration.inputs;
if (mode === "credentials") { if (mode === "credentials") {
await updateAwsExternalKms({ await updateAwsExternalKms({
kmsId: kms.id, kmsId: kms.id,
configuration configuration: {
type: ExternalKmsProvider.Aws,
inputs: {
credential: { ...awsInputs.credential }
}
}
}); });
} else { } else {
await updateAwsExternalKms({ await updateAwsExternalKms({
kmsId: kms.id, kmsId: kms.id,
name, name,
description description,
configuration: {
type: ExternalKmsProvider.Aws,
inputs: {
awsRegion: awsInputs.awsRegion,
kmsKeyId: awsInputs.kmsKeyId
}
}
}); });
} }
@@ -114,7 +145,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
text: text:
mode === "credentials" mode === "credentials"
? "Successfully updated AWS External KMS credentials" ? "Successfully updated AWS External KMS credentials"
: "Successfully updated AWS External KMS", : "Successfully updated AWS External KMS Details",
type: "success" type: "success"
}); });
} else { } else {
@@ -138,7 +169,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
return ( return (
<form onSubmit={handleSubmit(handleAwsKmsFormSubmit)} autoComplete="off"> <form onSubmit={handleSubmit(handleAwsKmsFormSubmit)} autoComplete="off">
{mode === "full" && ( {(mode === "full" || mode === "details") && (
<> <>
<Controller <Controller
control={control} control={control}
@@ -160,86 +191,127 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
/> />
</> </>
)} )}
<Controller {(mode === "full" || mode === "credentials") && (
control={control}
name="configuration.inputs.credential.type"
defaultValue={KmsAwsCredentialType.AssumeRole}
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl
label="Authentication Mode"
errorText={error?.message}
isError={Boolean(error)}
>
<Select
defaultValue={field.value}
{...field}
onValueChange={(e) => {
setValue("configuration.inputs.credential.data.accessKey", "");
setValue("configuration.inputs.credential.data.secretKey", "");
setValue("configuration.inputs.credential.data.assumeRoleArn", "");
setValue("configuration.inputs.credential.data.externalId", "");
onChange(e);
}}
className="w-full"
>
<SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
<SelectItem value={KmsAwsCredentialType.AccessKey}>Access Key</SelectItem>
</Select>
</FormControl>
)}
/>
{selectedAwsAuthType === KmsAwsCredentialType.AccessKey ? (
<> <>
<Controller <Controller
control={control} control={control}
name="configuration.inputs.credential.data.accessKey" name="configuration.inputs.credential.type"
render={({ field, fieldState: { error } }) => ( defaultValue={KmsAwsCredentialType.AssumeRole}
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl <FormControl
label="Access Key ID" label="Authentication Mode"
errorText={error?.message} errorText={error?.message}
isError={Boolean(error)} isError={Boolean(error)}
> >
<Input placeholder="" {...field} /> <Select
</FormControl> defaultValue={field.value}
)} {...field}
/> onValueChange={(e) => {
<Controller setValue("configuration.inputs.credential.data.accessKey", "");
control={control} setValue("configuration.inputs.credential.data.secretKey", "");
name="configuration.inputs.credential.data.secretKey" setValue("configuration.inputs.credential.data.assumeRoleArn", "");
render={({ field, fieldState: { error } }) => ( setValue("configuration.inputs.credential.data.externalId", "");
<FormControl
label="Secret Access Key" onChange(e);
errorText={error?.message} }}
isError={Boolean(error)} className="w-full"
> >
<Input type="password" autoComplete="new-password" placeholder="" {...field} /> <SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
<SelectItem value={KmsAwsCredentialType.AccessKey}>Access Key</SelectItem>
</Select>
</FormControl> </FormControl>
)} )}
/> />
{selectedAwsAuthType === KmsAwsCredentialType.AccessKey ? (
<>
<Controller
control={control}
name="configuration.inputs.credential.data.accessKey"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Key ID"
errorText={error?.message}
isError={Boolean(error)}
>
<Input placeholder="" {...field} />
</FormControl>
)}
/>
<Controller
control={control}
name="configuration.inputs.credential.data.secretKey"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Access Key"
errorText={error?.message}
isError={Boolean(error)}
>
<Input type="password" autoComplete="new-password" placeholder="" {...field} />
</FormControl>
)}
/>
</>
) : (
<>
<Controller
control={control}
name="configuration.inputs.credential.data.assumeRoleArn"
render={({ field, fieldState: { error } }) => (
<FormControl
label="IAM Role ARN For Role Assumption"
errorText={error?.message}
isError={Boolean(error)}
>
<Input placeholder="" {...field} />
</FormControl>
)}
/>
<Controller
control={control}
name="configuration.inputs.credential.data.externalId"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Assume Role External ID"
errorText={error?.message}
isError={Boolean(error)}
>
<Input placeholder="" {...field} />
</FormControl>
)}
/>
</>
)}
</> </>
) : ( )}
{(mode === "full" || mode === "details") && (
<> <>
<Controller <Controller
control={control} control={control}
name="configuration.inputs.credential.data.assumeRoleArn" name="configuration.inputs.awsRegion"
render={({ field, fieldState: { error } }) => ( render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl <FormControl label="AWS Region" errorText={error?.message} isError={Boolean(error)}>
label="IAM Role ARN For Role Assumption" <Select
errorText={error?.message} defaultValue={field.value}
isError={Boolean(error)} {...field}
> onValueChange={(e) => onChange(e)}
<Input placeholder="" {...field} /> className="w-full border border-mineshaft-500"
>
{AWS_REGIONS.map((awsRegion) => (
<SelectItem value={awsRegion.slug} key={`kms-aws-region-${awsRegion.slug}`}>
{awsRegion.name} <Badge variant="neutral">{awsRegion.slug}</Badge>
</SelectItem>
))}
</Select>
</FormControl> </FormControl>
)} )}
/> />
<Controller <Controller
control={control} control={control}
name="configuration.inputs.credential.data.externalId" name="configuration.inputs.kmsKeyId"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl
label="Assume Role External ID" label="AWS KMS Key ID"
errorText={error?.message} errorText={error?.message}
isError={Boolean(error)} isError={Boolean(error)}
> >
@@ -249,35 +321,6 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
/> />
</> </>
)} )}
<Controller
control={control}
name="configuration.inputs.awsRegion"
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl label="AWS Region" errorText={error?.message} isError={Boolean(error)}>
<Select
defaultValue={field.value}
{...field}
onValueChange={(e) => onChange(e)}
className="w-full border border-mineshaft-500"
>
{AWS_REGIONS.map((awsRegion) => (
<SelectItem value={awsRegion.slug} key={`kms-aws-region-${awsRegion.slug}`}>
{awsRegion.name} <Badge variant="neutral">{awsRegion.slug}</Badge>
</SelectItem>
))}
</Select>
</FormControl>
)}
/>
<Controller
control={control}
name="configuration.inputs.kmsKeyId"
render={({ field, fieldState: { error } }) => (
<FormControl label="AWS KMS Key ID" errorText={error?.message} isError={Boolean(error)}>
<Input placeholder="" {...field} />
</FormControl>
)}
/>
<div className="mt-6 flex items-center space-x-4"> <div className="mt-6 flex items-center space-x-4">
<Button type="submit" isLoading={isSubmitting}> <Button type="submit" isLoading={isSubmitting}>
{mode === "credentials" ? "Update Credentials" : "Save"} {mode === "credentials" ? "Update Credentials" : "Save"}
@@ -1,4 +1,4 @@
import { ContentLoader, Modal, ModalContent } from "@app/components/v2"; import { Modal, ModalContent } from "@app/components/v2";
import { useGetExternalKmsById } from "@app/hooks/api"; import { useGetExternalKmsById } from "@app/hooks/api";
import { ExternalKmsProvider } from "@app/hooks/api/kms/types"; import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
@@ -18,7 +18,7 @@ export const EditExternalKmsCredentialsModal = ({
provider, provider,
onOpenChange onOpenChange
}: Props) => { }: Props) => {
const { data: externalKms, isPending } = useGetExternalKmsById({ kmsId, provider }); const { data: kms } = useGetExternalKmsById({ kmsId, provider });
return ( return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}> <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent <ModalContent
@@ -26,18 +26,17 @@ export const EditExternalKmsCredentialsModal = ({
subTitle="Update the credentials for this KMS." subTitle="Update the credentials for this KMS."
bodyClassName="overflow-visible" bodyClassName="overflow-visible"
> >
{isPending && <ContentLoader />} {kms?.externalKms?.provider === ExternalKmsProvider.Aws && (
{externalKms?.externalKms?.provider === ExternalKmsProvider.Aws && (
<AwsKmsForm <AwsKmsForm
kms={externalKms} kms={kms}
mode="credentials" mode="credentials"
onCancel={() => onOpenChange(false)} onCancel={() => onOpenChange(false)}
onCompleted={() => onOpenChange(false)} onCompleted={() => onOpenChange(false)}
/> />
)} )}
{externalKms?.externalKms?.provider === ExternalKmsProvider.Gcp && ( {kms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
<GcpKmsForm <GcpKmsForm
kms={externalKms} kms={kms}
mode="credentials" mode="credentials"
onCancel={() => onOpenChange(false)} onCancel={() => onOpenChange(false)}
onCompleted={() => onOpenChange(false)} onCompleted={() => onOpenChange(false)}
@@ -1,20 +1,9 @@
import { FormProvider, useForm } from "react-hook-form"; import { Modal, ModalContent } from "@app/components/v2";
import { zodResolver } from "@hookform/resolvers/zod"; import { useGetExternalKmsById } from "@app/hooks/api";
import { z } from "zod"; import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
import { createNotification } from "@app/components/notifications"; import { AwsKmsForm } from "./AwsKmsForm";
import { import { GcpKmsForm } from "./GcpKmsForm";
Button,
ContentLoader,
FormControl,
Input,
Modal,
ModalClose,
ModalContent
} from "@app/components/v2";
import { useOrganization } from "@app/context";
import { useGetExternalKmsById, useUpdateExternalKms } from "@app/hooks/api";
import { ExternalKmsProvider, Kms } from "@app/hooks/api/kms/types";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
@@ -23,85 +12,32 @@ type Props = {
provider: ExternalKmsProvider; provider: ExternalKmsProvider;
}; };
const formSchema = z.object({
name: z.string().min(1).trim(),
description: z.string().trim().optional()
});
type FormData = z.infer<typeof formSchema>;
type ContentProps = { kms: Kms; provider: ExternalKmsProvider; onComplete: () => void };
const Content = ({ kms, onComplete, provider }: ContentProps) => {
const { currentOrg } = useOrganization();
const { mutateAsync: updateExternalKms, isPending } = useUpdateExternalKms(
currentOrg.id,
provider
);
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: {
name: kms.name,
description: kms.description ?? ""
}
});
const {
handleSubmit,
formState: { isDirty }
} = form;
const onSubmit = async (formData: FormData) => {
if (!kms) return;
await updateExternalKms({
kmsId: kms.id,
name: formData.name,
description: formData.description
});
createNotification({
text: "Successfully updated KMS details",
type: "success"
});
onComplete();
};
return (
<FormProvider {...form}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl label="Alias">
<Input {...form.register("name")} />
</FormControl>
<FormControl label="Description">
<Input {...form.register("description")} />
</FormControl>
<div className="mt-6 flex items-center space-x-4">
<Button type="submit" isLoading={isPending} isDisabled={!isDirty}>
Update Details
</Button>
<ModalClose asChild>
<Button variant="outline_bg">Cancel</Button>
</ModalClose>
</div>
</form>
</FormProvider>
);
};
export const EditExternalKmsDetailsModal = ({ isOpen, onOpenChange, kmsId, provider }: Props) => { export const EditExternalKmsDetailsModal = ({ isOpen, onOpenChange, kmsId, provider }: Props) => {
const { data: kms, isPending } = useGetExternalKmsById({ kmsId, provider }); const { data: kms } = useGetExternalKmsById({ kmsId, provider });
return ( return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}> <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent <ModalContent
className="max-w-2xl"
title="Edit KMS Details" title="Edit KMS Details"
subTitle="Update the name and description for this KMS." subTitle="Update the name and description for this KMS."
bodyClassName="overflow-visible"
> >
{isPending && <ContentLoader />} {kms?.externalKms?.provider === ExternalKmsProvider.Aws && (
{kms && <Content kms={kms} provider={provider} onComplete={() => onOpenChange(false)} />} <AwsKmsForm
kms={kms}
mode="details"
onCancel={() => onOpenChange(false)}
onCompleted={() => onOpenChange(false)}
/>
)}
{kms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
<GcpKmsForm
kms={kms}
mode="details"
onCancel={() => onOpenChange(false)}
onCompleted={() => onOpenChange(false)}
/>
)}
</ModalContent> </ModalContent>
</Modal> </Modal>
); );
@@ -24,7 +24,7 @@ type Props = {
onCompleted: () => void; onCompleted: () => void;
onCancel: () => void; onCancel: () => void;
kms?: Kms; kms?: Kms;
mode?: "full" | "credentials"; mode?: "full" | "credentials" | "details";
}; };
const GCP_REGIONS = [ const GCP_REGIONS = [
@@ -145,53 +145,70 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
// handles the form submission // handles the form submission
const handleGcpKmsFormSubmit = async (data: AddExternalKmsGcpFormSchemaType) => { const handleGcpKmsFormSubmit = async (data: AddExternalKmsGcpFormSchemaType) => {
const { name, description, gcpRegion: gcpRegionObject, keyObject } = data; const { name, description, gcpRegion: gcpRegionObject, keyObject } = data;
const gcpRegion = gcpRegionObject.value;
if (!keys.find((k) => k.value === keyObject?.value)) {
setError("keyObject", {
message: "Please select a valid key."
});
resetField("keyObject");
return;
}
try { try {
if (kms) { if (kms) {
if (mode === "credentials") { if (mode === "details") {
await updateGcpExternalKms({
kmsId: kms.id,
name: kms.name,
description: kms.description,
configuration: {
type: ExternalKmsProvider.Gcp,
inputs: {
gcpRegion,
keyName: keyObject?.value
}
}
});
} else {
await updateGcpExternalKms({ await updateGcpExternalKms({
kmsId: kms.id, kmsId: kms.id,
name, name,
description, description
});
createNotification({
text: "Successfully updated GCP External KMS Details",
type: "success"
});
} else if (mode === "credentials") {
const gcpRegion = gcpRegionObject?.value;
if (!gcpRegion) {
setError("gcpRegion", {
message: "Please select a GCP region."
});
return;
}
if (keyObject && !keys.find((k) => k.value === keyObject.value)) {
setError("keyObject", {
message: "Please select a valid key."
});
resetField("keyObject");
return;
}
await updateGcpExternalKms({
kmsId: kms.id,
configuration: { configuration: {
type: ExternalKmsProvider.Gcp, type: ExternalKmsProvider.Gcp,
inputs: { inputs: {
gcpRegion, gcpRegion,
keyName: keyObject?.value keyName: keyObject?.value ?? kms.externalKms.configuration.keyName
} }
} }
}); });
createNotification({
text: "Successfully updated GCP External KMS configuration",
type: "success"
});
}
} else {
const gcpRegion = gcpRegionObject?.value;
if (!gcpRegion) {
setError("gcpRegion", {
message: "Please select a GCP region."
});
return;
}
if (!keys.find((k) => k.value === keyObject?.value)) {
setError("keyObject", {
message: "Please select a valid key."
});
resetField("keyObject");
return;
} }
createNotification({
text:
mode === "credentials"
? "Successfully updated GCP External KMS configuration"
: "Successfully updated GCP External KMS",
type: "success"
});
} else {
const credentialJson = await getCredentialFileJson(); const credentialJson = await getCredentialFileJson();
if (!credentialJson) { if (!credentialJson) {
return; return;
@@ -230,8 +247,9 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
if (!kms && !credentialJson) { if (!kms && !credentialJson) {
return; return;
} }
const gcpRegion = getValues("gcpRegion").value; const gcpRegionObject = getValues("gcpRegion");
if (!gcpRegion.length) { const gcpRegion = gcpRegionObject?.value;
if (!gcpRegion) {
setError("gcpRegion", { setError("gcpRegion", {
message: "Please select a GCP region to fetch GCP Keys." message: "Please select a GCP region to fetch GCP Keys."
}); });
@@ -284,7 +302,7 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
return ( return (
<form onSubmit={handleSubmit(handleGcpKmsFormSubmit)} autoComplete="off"> <form onSubmit={handleSubmit(handleGcpKmsFormSubmit)} autoComplete="off">
{mode === "full" && ( {(mode === "full" || mode === "details") && (
<> <>
<Controller <Controller
control={control} control={control}
@@ -306,75 +324,79 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
/> />
</> </>
)} )}
<Controller {(mode === "full" || mode === "credentials") && (
control={control} <>
name="gcpRegion" <Controller
render={({ field, fieldState: { error } }) => ( control={control}
<FormControl label="GCP Region" errorText={error?.message} isError={Boolean(error)}> name="gcpRegion"
<FilterableSelect render={({ field, fieldState: { error } }) => (
className="w-full" <FormControl label="GCP Region" errorText={error?.message} isError={Boolean(error)}>
placeholder="Select a GCP region" <FilterableSelect
name="gcpRegion" className="w-full"
options={GCP_REGIONS} placeholder="Select a GCP region"
value={field.value} name="gcpRegion"
onChange={(e) => { options={GCP_REGIONS}
resetField("keyObject"); value={field.value}
field.onChange(e); onChange={(e) => {
fetchGCPKeys(); resetField("keyObject");
}} field.onChange(e);
formatOptionLabel={formatOptionLabel} fetchGCPKeys();
}}
formatOptionLabel={formatOptionLabel}
/>
</FormControl>
)}
/>
{!kms && (
<Controller
control={control}
name="credentialFile"
render={({ field: { value, onChange, ref, ...rest }, fieldState: { error } }) => (
<FormControl
label="Service Account Credential JSON"
errorText={error?.message}
isError={Boolean(error)}
>
<Input
{...rest}
ref={ref}
type="file"
accept=".json"
placeholder=""
value={value?.filename}
onChange={(e) => {
onChange(e.target.files);
fetchGCPKeys();
}}
/>
</FormControl>
)}
/> />
</FormControl>
)}
/>
{!kms && (
<Controller
control={control}
name="credentialFile"
render={({ field: { value, onChange, ref, ...rest }, fieldState: { error } }) => (
<FormControl
label="Service Account Credential JSON"
errorText={error?.message}
isError={Boolean(error)}
>
<Input
{...rest}
ref={ref}
type="file"
accept=".json"
placeholder=""
value={value?.filename}
onChange={(e) => {
onChange(e.target.files);
fetchGCPKeys();
}}
/>
</FormControl>
)} )}
/> <Controller
)} control={control}
<Controller name="keyObject"
control={control} render={({ field, fieldState: { error } }) => (
name="keyObject" <FormControl label="GCP Key Name" errorText={error?.message} isError={Boolean(error)}>
render={({ field, fieldState: { error } }) => ( <FilterableSelect
<FormControl label="GCP Key Name" errorText={error?.message} isError={Boolean(error)}> className="w-full"
<FilterableSelect placeholder={getPlaceholderText()}
className="w-full" isDisabled={!isCredentialValid || !keys.length}
placeholder={getPlaceholderText()} name="key"
isDisabled={!isCredentialValid || !keys.length} options={keys}
name="key" value={field.value}
options={keys} onChange={field.onChange}
value={field.value} />
onChange={field.onChange} </FormControl>
/> )}
</FormControl> />
)} {kms && (
/> <span className="text-xs text-mineshaft-300">
{kms && ( To change your GCP credentials, create a new external KMS and assign it to project you
<span className="text-xs text-mineshaft-300"> want to use it with.
To change your GCP credentials, create a new external KMS and assign it to project you </span>
want to use it with. )}
</span> </>
)} )}
<div className="mt-6 flex items-center space-x-4"> <div className="mt-6 flex items-center space-x-4">
<Button type="submit" isLoading={isSubmitting}> <Button type="submit" isLoading={isSubmitting}>