misc: addressed comments

This commit is contained in:
Sheen Capadngan
2025-11-19 03:01:12 +08:00
parent a4f3b5d037
commit 6afb6a4a50
13 changed files with 161 additions and 196 deletions
@@ -61,18 +61,15 @@ export const PamAccessAccountModal = ({ isOpen, onOpenChange, account }: Props)
const command = useMemo(() => {
if (!account) return "";
if (
account.resource.resourceType === PamResourceType.Postgres ||
account.resource.resourceType === PamResourceType.MySQL
) {
return `infisical pam db access-account ${account.id} --duration ${cliDuration}`;
switch (account.resource.resourceType) {
case PamResourceType.Postgres:
case PamResourceType.MySQL:
return `infisical pam db access-account ${account.id} --duration ${cliDuration}`;
case PamResourceType.SSH:
return `infisical pam ssh access-account ${account.id} --duration ${cliDuration}`;
default:
return "";
}
if (account.resource.resourceType === PamResourceType.SSH) {
return `infisical pam ssh ${account.id} --duration ${cliDuration}`;
}
return "";
}, [account, cliDuration]);
if (!account) return null;
@@ -10,7 +10,7 @@ import { DiscriminativePick } from "@app/types";
import { PamAccountHeader } from "../PamAccountHeader";
import { MySQLAccountForm } from "./MySQLAccountForm";
import { PostgresAccountForm } from "./PostgresAccountForm";
import { SSHAccountForm } from "./SSHAccountForm";
import { SshAccountForm } from "./SshAccountForm";
type FormProps = {
onComplete: (account: TPamAccount) => void;
@@ -68,7 +68,7 @@ const CreateForm = ({
);
case PamResourceType.SSH:
return (
<SSHAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
<SshAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
);
default:
throw new Error(`Unhandled resource: ${resourceType}`);
@@ -99,7 +99,7 @@ const UpdateForm = ({ account, onComplete }: UpdateFormProps) => {
case PamResourceType.MySQL:
return <MySQLAccountForm account={account as any} onSubmit={onSubmit} />;
case PamResourceType.SSH:
return <SSHAccountForm account={account as any} onSubmit={onSubmit} />;
return <SshAccountForm account={account as any} onSubmit={onSubmit} />;
default:
throw new Error(`Unhandled resource: ${account.resource.resourceType}`);
}
@@ -1,105 +0,0 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { FormProvider, useForm } from "react-hook-form";
import { z } from "zod";
import { Button, ModalClose } from "@app/components/v2";
import { PamResourceType, TSSHAccount } from "@app/hooks/api/pam";
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
import { GenericAccountFields, genericAccountFieldsSchema } from "./GenericAccountFields";
import { BaseSshAccountSchema } from "./shared/ssh-account-schemas";
import { SshAccountFields } from "./shared/SshAccountFields";
type Props = {
account?: TSSHAccount;
resourceId?: string;
resourceType?: PamResourceType;
onSubmit: (formData: FormData) => Promise<void>;
};
const formSchema = genericAccountFieldsSchema.extend({
credentials: BaseSshAccountSchema,
// We don't support rotation for now, just feed a false value to
// make the schema happy
rotationEnabled: z.boolean().default(false)
});
type FormData = z.infer<typeof formSchema>;
export const SSHAccountForm = ({ account, onSubmit }: Props) => {
const isUpdate = Boolean(account);
const getDefaultCredentials = () => {
if (!account) return undefined;
if (account.credentials.authMethod === SSHAuthMethod.Password) {
return {
...account.credentials,
password: UNCHANGED_PASSWORD_SENTINEL
};
}
if (account.credentials.authMethod === SSHAuthMethod.PublicKey) {
return {
...account.credentials,
privateKey: UNCHANGED_PASSWORD_SENTINEL
};
}
return account.credentials;
};
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: account
? {
...account,
credentials: getDefaultCredentials()
}
: {
name: "",
description: "",
credentials: {
authMethod: SSHAuthMethod.Password,
username: "",
password: ""
}
}
});
const {
handleSubmit,
formState: { isSubmitting, isDirty }
} = form;
return (
<FormProvider {...form}>
<form
onSubmit={(e) => {
handleSubmit(onSubmit)(e);
}}
>
<GenericAccountFields />
<SshAccountFields isUpdate={isUpdate} />
<div className="mt-6 flex items-center">
<Button
className="mr-4"
size="sm"
type="submit"
colorSchema="secondary"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
{isUpdate ? "Update Account" : "Create Account"}
</Button>
<ModalClose asChild>
<Button colorSchema="secondary" variant="plain">
Cancel
</Button>
</ModalClose>
</div>
</form>
</FormProvider>
);
};
@@ -1,11 +1,63 @@
import { useEffect, useState } from "react";
import { Controller, useFormContext, useWatch } from "react-hook-form";
import { Controller, FormProvider, useForm, useFormContext, useWatch } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { FormControl, Input, Select, SelectItem, TextArea } from "@app/components/v2";
import {
Button,
FormControl,
Input,
ModalClose,
Select,
SelectItem,
TextArea
} from "@app/components/v2";
import { PamResourceType, TSSHAccount } from "@app/hooks/api/pam";
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
export const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
import { GenericAccountFields, genericAccountFieldsSchema } from "./GenericAccountFields";
type Props = {
account?: TSSHAccount;
resourceId?: string;
resourceType?: PamResourceType;
onSubmit: (formData: FormData) => Promise<void>;
};
export const SSHPasswordCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Password),
username: z.string().trim().min(1, "Username is required"),
password: z.string().trim().min(1, "Password is required")
});
export const SSHPublicKeyCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.PublicKey),
username: z.string().trim().min(1, "Username is required"),
privateKey: z.string().trim().min(1, "Private key is required")
});
export const SSHCertificateCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Certificate),
username: z.string().trim().min(1, "Username is required")
});
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
SSHPasswordCredentialsSchema,
SSHPublicKeyCredentialsSchema,
SSHCertificateCredentialsSchema
]);
const formSchema = genericAccountFieldsSchema.extend({
credentials: BaseSshAccountSchema,
// We don't support rotation for now, just feed a false value to
// make the schema happy
rotationEnabled: z.boolean().default(false)
});
type FormData = z.infer<typeof formSchema>;
const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
const { control, setValue } = useFormContext();
const [showPassword, setShowPassword] = useState(false);
@@ -141,3 +193,80 @@ export const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
</div>
);
};
export const SshAccountForm = ({ account, onSubmit }: Props) => {
const isUpdate = Boolean(account);
const getDefaultCredentials = () => {
if (!account) return undefined;
if (account.credentials.authMethod === SSHAuthMethod.Password) {
return {
...account.credentials,
password: UNCHANGED_PASSWORD_SENTINEL
};
}
if (account.credentials.authMethod === SSHAuthMethod.PublicKey) {
return {
...account.credentials,
privateKey: UNCHANGED_PASSWORD_SENTINEL
};
}
return account.credentials;
};
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: account
? {
...account,
credentials: getDefaultCredentials()
}
: {
name: "",
description: "",
credentials: {
authMethod: SSHAuthMethod.Password,
username: "",
password: ""
}
}
});
const {
handleSubmit,
formState: { isSubmitting, isDirty }
} = form;
return (
<FormProvider {...form}>
<form
onSubmit={(e) => {
handleSubmit(onSubmit)(e);
}}
>
<GenericAccountFields />
<SshAccountFields isUpdate={isUpdate} />
<div className="mt-6 flex items-center">
<Button
className="mr-4"
size="sm"
type="submit"
colorSchema="secondary"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
{isUpdate ? "Update Account" : "Create Account"}
</Button>
<ModalClose asChild>
<Button colorSchema="secondary" variant="plain">
Cancel
</Button>
</ModalClose>
</div>
</form>
</FormProvider>
);
};
@@ -1,26 +0,0 @@
import { z } from "zod";
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
export const SSHPasswordCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Password),
username: z.string().trim().min(1, "Username is required"),
password: z.string().trim().min(1, "Password is required")
});
export const SSHPublicKeyCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.PublicKey),
username: z.string().trim().min(1, "Username is required"),
privateKey: z.string().trim().min(1, "Private key is required")
});
export const SSHCertificateCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Certificate),
username: z.string().trim().min(1, "Username is required")
});
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
SSHPasswordCredentialsSchema,
SSHPublicKeyCredentialsSchema,
SSHCertificateCredentialsSchema
]);
@@ -5,15 +5,19 @@ import { z } from "zod";
import { Button, ModalClose } from "@app/components/v2";
import { PamResourceType, TSSHResource } from "@app/hooks/api/pam";
import { GenericResourceFields, genericResourceFieldsSchema } from "./GenericResourceFields";
import { BaseSshConnectionDetailsSchema } from "./shared/ssh-resource-schemas";
import { SshResourceFields } from "./shared/SshResourceFields";
import { GenericResourceFields, genericResourceFieldsSchema } from "./GenericResourceFields";
type Props = {
resource?: TSSHResource;
onSubmit: (formData: FormData) => Promise<void>;
};
const BaseSshConnectionDetailsSchema = z.object({
host: z.string().trim().min(1, "Host is required"),
port: z.number().int().min(1).max(65535)
});
const formSchema = genericResourceFieldsSchema.extend({
resourceType: z.literal(PamResourceType.SSH),
connectionDetails: BaseSshConnectionDetailsSchema
@@ -1,31 +0,0 @@
import { z } from "zod";
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
export const BaseSshConnectionDetailsSchema = z.object({
host: z.string().trim().min(1, "Host is required"),
port: z.number().int().min(1).max(65535)
});
export const SSHPasswordCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Password),
username: z.string().trim().min(1, "Username is required"),
password: z.string().trim().min(1, "Password is required")
});
export const SSHPublicKeyCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.PublicKey),
username: z.string().trim().min(1, "Username is required"),
privateKey: z.string().trim().min(1, "Private key is required")
});
export const SSHCertificateCredentialsSchema = z.object({
authMethod: z.literal(SSHAuthMethod.Certificate),
username: z.string().trim().min(1, "Username is required")
});
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
SSHPasswordCredentialsSchema,
SSHPublicKeyCredentialsSchema,
SSHCertificateCredentialsSchema
]);