mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 12:26:38 +00:00
misc: addressed comments
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
+132
-3
@@ -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>
|
||||
);
|
||||
};
|
||||
-26
@@ -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
|
||||
]);
|
||||
+6
-2
@@ -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
|
||||
|
||||
-31
@@ -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
|
||||
]);
|
||||
Reference in New Issue
Block a user