mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 01:28:13 +00:00
Add MongoDB connection form and related updates
- Implemented MongoDB connection form with validation and credential handling. - Updated enums and maps to include MongoDB support across backend and frontend. - Enhanced app connection schemas to accommodate MongoDB connection options. - Integrated MongoDB connection handling in relevant components and hooks.
This commit is contained in:
@@ -8,7 +8,8 @@ export enum SecretRotation {
|
|||||||
AwsIamUserSecret = "aws-iam-user-secret",
|
AwsIamUserSecret = "aws-iam-user-secret",
|
||||||
LdapPassword = "ldap-password",
|
LdapPassword = "ldap-password",
|
||||||
OktaClientSecret = "okta-client-secret",
|
OktaClientSecret = "okta-client-secret",
|
||||||
RedisCredentials = "redis-credentials"
|
RedisCredentials = "redis-credentials",
|
||||||
|
MongoDBCredentials = "mongodb-credentials"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SecretRotationStatus {
|
export enum SecretRotationStatus {
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ export const SECRET_ROTATION_NAME_MAP: Record<SecretRotation, string> = {
|
|||||||
[SecretRotation.AwsIamUserSecret]: "AWS IAM User Secret",
|
[SecretRotation.AwsIamUserSecret]: "AWS IAM User Secret",
|
||||||
[SecretRotation.LdapPassword]: "LDAP Password",
|
[SecretRotation.LdapPassword]: "LDAP Password",
|
||||||
[SecretRotation.OktaClientSecret]: "Okta Client Secret",
|
[SecretRotation.OktaClientSecret]: "Okta Client Secret",
|
||||||
[SecretRotation.RedisCredentials]: "Redis Credentials"
|
[SecretRotation.RedisCredentials]: "Redis Credentials",
|
||||||
|
[SecretRotation.MongoDBCredentials]: "MongoDB Credentials"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SECRET_ROTATION_CONNECTION_MAP: Record<SecretRotation, AppConnection> = {
|
export const SECRET_ROTATION_CONNECTION_MAP: Record<SecretRotation, AppConnection> = {
|
||||||
@@ -24,5 +25,6 @@ export const SECRET_ROTATION_CONNECTION_MAP: Record<SecretRotation, AppConnectio
|
|||||||
[SecretRotation.AwsIamUserSecret]: AppConnection.AWS,
|
[SecretRotation.AwsIamUserSecret]: AppConnection.AWS,
|
||||||
[SecretRotation.LdapPassword]: AppConnection.LDAP,
|
[SecretRotation.LdapPassword]: AppConnection.LDAP,
|
||||||
[SecretRotation.OktaClientSecret]: AppConnection.Okta,
|
[SecretRotation.OktaClientSecret]: AppConnection.Okta,
|
||||||
[SecretRotation.RedisCredentials]: AppConnection.Redis
|
[SecretRotation.RedisCredentials]: AppConnection.Redis,
|
||||||
|
[SecretRotation.MongoDBCredentials]: AppConnection.MongoDB
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ import {
|
|||||||
SanitizedLaravelForgeConnectionSchema
|
SanitizedLaravelForgeConnectionSchema
|
||||||
} from "@app/services/app-connection/laravel-forge";
|
} from "@app/services/app-connection/laravel-forge";
|
||||||
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
||||||
|
import {
|
||||||
|
MongoDBConnectionListItemSchema,
|
||||||
|
SanitizedMongoDBConnectionSchema
|
||||||
|
} from "@app/services/app-connection/mongodb";
|
||||||
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
||||||
import { MySqlConnectionListItemSchema, SanitizedMySqlConnectionSchema } from "@app/services/app-connection/mysql";
|
import { MySqlConnectionListItemSchema, SanitizedMySqlConnectionSchema } from "@app/services/app-connection/mysql";
|
||||||
import {
|
import {
|
||||||
@@ -169,6 +173,7 @@ const SanitizedAppConnectionSchema = z.union([
|
|||||||
...SanitizedOktaConnectionSchema.options,
|
...SanitizedOktaConnectionSchema.options,
|
||||||
...SanitizedAzureADCSConnectionSchema.options,
|
...SanitizedAzureADCSConnectionSchema.options,
|
||||||
...SanitizedRedisConnectionSchema.options,
|
...SanitizedRedisConnectionSchema.options,
|
||||||
|
...SanitizedMongoDBConnectionSchema.options,
|
||||||
...SanitizedLaravelForgeConnectionSchema.options,
|
...SanitizedLaravelForgeConnectionSchema.options,
|
||||||
...SanitizedChefConnectionSchema.options
|
...SanitizedChefConnectionSchema.options
|
||||||
]);
|
]);
|
||||||
@@ -214,6 +219,7 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
|||||||
OktaConnectionListItemSchema,
|
OktaConnectionListItemSchema,
|
||||||
AzureADCSConnectionListItemSchema,
|
AzureADCSConnectionListItemSchema,
|
||||||
RedisConnectionListItemSchema,
|
RedisConnectionListItemSchema,
|
||||||
|
MongoDBConnectionListItemSchema,
|
||||||
LaravelForgeConnectionListItemSchema,
|
LaravelForgeConnectionListItemSchema,
|
||||||
ChefConnectionListItemSchema
|
ChefConnectionListItemSchema
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
HCVaultConnectionMethod,
|
HCVaultConnectionMethod,
|
||||||
HumanitecConnectionMethod,
|
HumanitecConnectionMethod,
|
||||||
LdapConnectionMethod,
|
LdapConnectionMethod,
|
||||||
|
MongoDBConnectionMethod,
|
||||||
MsSqlConnectionMethod,
|
MsSqlConnectionMethod,
|
||||||
MySqlConnectionMethod,
|
MySqlConnectionMethod,
|
||||||
OktaConnectionMethod,
|
OktaConnectionMethod,
|
||||||
@@ -127,6 +128,7 @@ export const APP_CONNECTION_MAP: Record<
|
|||||||
[AppConnection.Northflank]: { name: "Northflank", image: "Northflank.png" },
|
[AppConnection.Northflank]: { name: "Northflank", image: "Northflank.png" },
|
||||||
[AppConnection.Okta]: { name: "Okta", image: "Okta.png" },
|
[AppConnection.Okta]: { name: "Okta", image: "Okta.png" },
|
||||||
[AppConnection.Redis]: { name: "Redis", image: "Redis.png" },
|
[AppConnection.Redis]: { name: "Redis", image: "Redis.png" },
|
||||||
|
[AppConnection.MongoDB]: { name: "MongoDB", image: "MongoDB.png" },
|
||||||
[AppConnection.LaravelForge]: {
|
[AppConnection.LaravelForge]: {
|
||||||
name: "Laravel Forge",
|
name: "Laravel Forge",
|
||||||
image: "Laravel Forge.png",
|
image: "Laravel Forge.png",
|
||||||
@@ -179,6 +181,7 @@ export const getAppConnectionMethodDetails = (method: TAppConnection["method"])
|
|||||||
case OracleDBConnectionMethod.UsernameAndPassword:
|
case OracleDBConnectionMethod.UsernameAndPassword:
|
||||||
case AzureADCSConnectionMethod.UsernamePassword:
|
case AzureADCSConnectionMethod.UsernamePassword:
|
||||||
case RedisConnectionMethod.UsernameAndPassword:
|
case RedisConnectionMethod.UsernameAndPassword:
|
||||||
|
case MongoDBConnectionMethod.UsernameAndPassword:
|
||||||
return { name: "Username & Password", icon: faLock };
|
return { name: "Username & Password", icon: faLock };
|
||||||
case HCVaultConnectionMethod.AccessToken:
|
case HCVaultConnectionMethod.AccessToken:
|
||||||
case TeamCityConnectionMethod.AccessToken:
|
case TeamCityConnectionMethod.AccessToken:
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ export type TRedisConnectionOption = TAppConnectionOptionBase & {
|
|||||||
app: AppConnection.Redis;
|
app: AppConnection.Redis;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TMongoDBConnectionOption = TAppConnectionOptionBase & {
|
||||||
|
app: AppConnection.MongoDB;
|
||||||
|
};
|
||||||
|
|
||||||
export type TAppConnectionOption =
|
export type TAppConnectionOption =
|
||||||
| TAwsConnectionOption
|
| TAwsConnectionOption
|
||||||
| TGitHubConnectionOption
|
| TGitHubConnectionOption
|
||||||
@@ -225,6 +229,8 @@ export type TAppConnectionOption =
|
|||||||
| TOktaConnectionOption
|
| TOktaConnectionOption
|
||||||
| TAzureAdCsConnectionOption
|
| TAzureAdCsConnectionOption
|
||||||
| TLaravelForgeConnectionOption
|
| TLaravelForgeConnectionOption
|
||||||
|
| TRedisConnectionOption
|
||||||
|
| TMongoDBConnectionOption
|
||||||
| TChefConnectionOption;
|
| TChefConnectionOption;
|
||||||
|
|
||||||
export type TAppConnectionOptionMap = {
|
export type TAppConnectionOptionMap = {
|
||||||
@@ -268,6 +274,7 @@ export type TAppConnectionOptionMap = {
|
|||||||
[AppConnection.Okta]: TOktaConnectionOption;
|
[AppConnection.Okta]: TOktaConnectionOption;
|
||||||
[AppConnection.AzureADCS]: TAzureAdCsConnectionOption;
|
[AppConnection.AzureADCS]: TAzureAdCsConnectionOption;
|
||||||
[AppConnection.Redis]: TRedisConnectionOption;
|
[AppConnection.Redis]: TRedisConnectionOption;
|
||||||
|
[AppConnection.MongoDB]: TMongoDBConnectionOption;
|
||||||
[AppConnection.LaravelForge]: TLaravelForgeConnectionOption;
|
[AppConnection.LaravelForge]: TLaravelForgeConnectionOption;
|
||||||
[AppConnection.Chef]: TChefConnectionOption;
|
[AppConnection.Chef]: TChefConnectionOption;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { THerokuConnection } from "./heroku-connection";
|
|||||||
import { THumanitecConnection } from "./humanitec-connection";
|
import { THumanitecConnection } from "./humanitec-connection";
|
||||||
import { TLaravelForgeConnection } from "./laravel-forge-connection";
|
import { TLaravelForgeConnection } from "./laravel-forge-connection";
|
||||||
import { TLdapConnection } from "./ldap-connection";
|
import { TLdapConnection } from "./ldap-connection";
|
||||||
|
import { TMongoDBConnection } from "./mongodb-connection";
|
||||||
import { TMsSqlConnection } from "./mssql-connection";
|
import { TMsSqlConnection } from "./mssql-connection";
|
||||||
import { TMySqlConnection } from "./mysql-connection";
|
import { TMySqlConnection } from "./mysql-connection";
|
||||||
import { TNetlifyConnection } from "./netlify-connection";
|
import { TNetlifyConnection } from "./netlify-connection";
|
||||||
@@ -67,6 +68,7 @@ export * from "./heroku-connection";
|
|||||||
export * from "./humanitec-connection";
|
export * from "./humanitec-connection";
|
||||||
export * from "./laravel-forge-connection";
|
export * from "./laravel-forge-connection";
|
||||||
export * from "./ldap-connection";
|
export * from "./ldap-connection";
|
||||||
|
export * from "./mongodb-connection";
|
||||||
export * from "./mssql-connection";
|
export * from "./mssql-connection";
|
||||||
export * from "./mysql-connection";
|
export * from "./mysql-connection";
|
||||||
export * from "./netlify-connection";
|
export * from "./netlify-connection";
|
||||||
@@ -127,6 +129,7 @@ export type TAppConnection =
|
|||||||
| TNorthflankConnection
|
| TNorthflankConnection
|
||||||
| TOktaConnection
|
| TOktaConnection
|
||||||
| TRedisConnection
|
| TRedisConnection
|
||||||
|
| TMongoDBConnection
|
||||||
| TChefConnection;
|
| TChefConnection;
|
||||||
|
|
||||||
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id" | "projectId">;
|
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id" | "projectId">;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||||
|
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
|
||||||
|
|
||||||
|
export enum MongoDBConnectionMethod {
|
||||||
|
UsernameAndPassword = "username-and-password"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TMongoDBConnectionCredentials = {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
database: string;
|
||||||
|
sslEnabled: boolean;
|
||||||
|
sslRejectUnauthorized: boolean;
|
||||||
|
sslCertificate?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TMongoDBConnection = TRootAppConnection & { app: AppConnection.MongoDB } & {
|
||||||
|
method: MongoDBConnectionMethod.UsernameAndPassword;
|
||||||
|
credentials: TMongoDBConnectionCredentials;
|
||||||
|
};
|
||||||
+5
@@ -34,6 +34,7 @@ import { HerokuConnectionForm } from "./HerokuAppConnectionForm";
|
|||||||
import { HumanitecConnectionForm } from "./HumanitecConnectionForm";
|
import { HumanitecConnectionForm } from "./HumanitecConnectionForm";
|
||||||
import { LaravelForgeConnectionForm } from "./LaravelForgeConnectionForm";
|
import { LaravelForgeConnectionForm } from "./LaravelForgeConnectionForm";
|
||||||
import { LdapConnectionForm } from "./LdapConnectionForm";
|
import { LdapConnectionForm } from "./LdapConnectionForm";
|
||||||
|
import { MongoDBConnectionForm } from "./MongoDBConnectionForm";
|
||||||
import { MsSqlConnectionForm } from "./MsSqlConnectionForm";
|
import { MsSqlConnectionForm } from "./MsSqlConnectionForm";
|
||||||
import { MySqlConnectionForm } from "./MySqlConnectionForm";
|
import { MySqlConnectionForm } from "./MySqlConnectionForm";
|
||||||
import { NetlifyConnectionForm } from "./NetlifyConnectionForm";
|
import { NetlifyConnectionForm } from "./NetlifyConnectionForm";
|
||||||
@@ -170,6 +171,8 @@ const CreateForm = ({ app, onComplete, projectId }: CreateFormProps) => {
|
|||||||
return <OktaConnectionForm onSubmit={onSubmit} />;
|
return <OktaConnectionForm onSubmit={onSubmit} />;
|
||||||
case AppConnection.Redis:
|
case AppConnection.Redis:
|
||||||
return <RedisConnectionForm onSubmit={onSubmit} />;
|
return <RedisConnectionForm onSubmit={onSubmit} />;
|
||||||
|
case AppConnection.MongoDB:
|
||||||
|
return <MongoDBConnectionForm onSubmit={onSubmit} />;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled App ${app}`);
|
throw new Error(`Unhandled App ${app}`);
|
||||||
}
|
}
|
||||||
@@ -326,6 +329,8 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
|||||||
return <OktaConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
return <OktaConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
case AppConnection.Redis:
|
case AppConnection.Redis:
|
||||||
return <RedisConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
return <RedisConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
|
case AppConnection.MongoDB:
|
||||||
|
return <MongoDBConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`);
|
throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`);
|
||||||
}
|
}
|
||||||
|
|||||||
+334
@@ -0,0 +1,334 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||||
|
import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { Tab } from "@headlessui/react";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
Input,
|
||||||
|
ModalClose,
|
||||||
|
SecretInput,
|
||||||
|
Select,
|
||||||
|
SelectItem,
|
||||||
|
Switch,
|
||||||
|
TextArea,
|
||||||
|
Tooltip
|
||||||
|
} from "@app/components/v2";
|
||||||
|
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||||
|
import { MongoDBConnectionMethod, TMongoDBConnection } from "@app/hooks/api/appConnections";
|
||||||
|
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||||
|
|
||||||
|
import {
|
||||||
|
genericAppConnectionFieldsSchema,
|
||||||
|
GenericAppConnectionsFields
|
||||||
|
} from "./GenericAppConnectionFields";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
appConnection?: TMongoDBConnection;
|
||||||
|
onSubmit: (formData: FormData) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rootSchema = genericAppConnectionFieldsSchema.extend({
|
||||||
|
app: z.literal(AppConnection.MongoDB)
|
||||||
|
});
|
||||||
|
|
||||||
|
const formSchema = z.discriminatedUnion("method", [
|
||||||
|
rootSchema.extend({
|
||||||
|
method: z.literal(MongoDBConnectionMethod.UsernameAndPassword),
|
||||||
|
credentials: z.object({
|
||||||
|
host: z.string().trim().min(1, "Host required"),
|
||||||
|
port: z.coerce.number().default(27017),
|
||||||
|
username: z.string().trim().min(1, "Username required"),
|
||||||
|
password: z.string().trim().min(1, "Password required"),
|
||||||
|
database: z.string().trim().min(1, "Database required"),
|
||||||
|
sslEnabled: z.boolean().default(false),
|
||||||
|
sslRejectUnauthorized: z.boolean().default(true),
|
||||||
|
sslCertificate: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.transform((value) => value || undefined)
|
||||||
|
.optional()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
type FormData = z.infer<typeof formSchema>;
|
||||||
|
|
||||||
|
export const MongoDBConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||||
|
const isUpdate = Boolean(appConnection);
|
||||||
|
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
|
||||||
|
|
||||||
|
const form = useForm<FormData>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: appConnection ?? {
|
||||||
|
app: AppConnection.MongoDB,
|
||||||
|
method: MongoDBConnectionMethod.UsernameAndPassword,
|
||||||
|
credentials: {
|
||||||
|
host: "",
|
||||||
|
port: 27017,
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
database: "",
|
||||||
|
sslEnabled: false,
|
||||||
|
sslRejectUnauthorized: true,
|
||||||
|
sslCertificate: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
watch,
|
||||||
|
control,
|
||||||
|
setValue,
|
||||||
|
formState: { isSubmitting, isDirty }
|
||||||
|
} = form;
|
||||||
|
|
||||||
|
const host = watch("credentials.host");
|
||||||
|
const sslEnabled = watch("credentials.sslEnabled");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (host && host.includes("+srv") && !sslEnabled) {
|
||||||
|
setValue("credentials.sslEnabled", true, { shouldDirty: true });
|
||||||
|
}
|
||||||
|
}, [host, sslEnabled, setValue]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormProvider {...form}>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
{!isUpdate && <GenericAppConnectionsFields />}
|
||||||
|
<Controller
|
||||||
|
name="method"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
tooltipText={`The method you would like to use to connect with ${
|
||||||
|
APP_CONNECTION_MAP[AppConnection.MongoDB].name
|
||||||
|
}. This field cannot be changed after creation.`}
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Method"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
isDisabled={isUpdate}
|
||||||
|
value={value}
|
||||||
|
onValueChange={(val) => onChange(val)}
|
||||||
|
className="w-full border border-mineshaft-500"
|
||||||
|
position="popper"
|
||||||
|
dropdownContainerClassName="max-w-none"
|
||||||
|
>
|
||||||
|
{Object.values(MongoDBConnectionMethod).map((method) => {
|
||||||
|
return (
|
||||||
|
<SelectItem value={method} key={method}>
|
||||||
|
{getAppConnectionMethodDetails(method).name}{" "}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tab.Group selectedIndex={selectedTabIndex} onChange={setSelectedTabIndex}>
|
||||||
|
<Tab.List className="-pb-1 mb-6 w-full border-b-2 border-mineshaft-600">
|
||||||
|
<Tab
|
||||||
|
className={({ selected }) =>
|
||||||
|
`-mb-[0.14rem] px-4 py-2 text-sm font-medium whitespace-nowrap outline-hidden disabled:opacity-60 ${
|
||||||
|
selected
|
||||||
|
? "border-b-2 border-mineshaft-300 text-mineshaft-200"
|
||||||
|
: "text-bunker-300"
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Configuration
|
||||||
|
</Tab>
|
||||||
|
<Tab
|
||||||
|
className={({ selected }) =>
|
||||||
|
`-mb-[0.14rem] px-4 py-2 text-sm font-medium whitespace-nowrap outline-hidden disabled:opacity-60 ${
|
||||||
|
selected
|
||||||
|
? "border-b-2 border-mineshaft-300 text-mineshaft-200"
|
||||||
|
: "text-bunker-300"
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
SSL ({sslEnabled ? "Enabled" : "Disabled"})
|
||||||
|
</Tab>
|
||||||
|
</Tab.List>
|
||||||
|
<Tab.Panels className="mb-4 rounded-sm border border-mineshaft-600 bg-mineshaft-700/70 p-3 pb-0">
|
||||||
|
<Tab.Panel>
|
||||||
|
<div className="mt-[0.675rem] flex items-start gap-2">
|
||||||
|
<Controller
|
||||||
|
name="credentials.host"
|
||||||
|
control={control}
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
className="flex-1"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Host"
|
||||||
|
>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="credentials.database"
|
||||||
|
control={control}
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
className="flex-1"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Database"
|
||||||
|
>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="credentials.port"
|
||||||
|
control={control}
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
className="w-28"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Port"
|
||||||
|
>
|
||||||
|
<Input type="number" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-[0.675rem] flex items-start gap-2">
|
||||||
|
<Controller
|
||||||
|
name="credentials.username"
|
||||||
|
control={control}
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Username"
|
||||||
|
className="flex-1"
|
||||||
|
>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="credentials.password"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
label="Password"
|
||||||
|
className="flex-1"
|
||||||
|
>
|
||||||
|
<SecretInput
|
||||||
|
containerClassName="text-gray-400 w-full group-focus-within:border-primary-400/50! border border-mineshaft-500 bg-mineshaft-900 px-2.5 py-1.5"
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tab.Panel>
|
||||||
|
<Tab.Panel>
|
||||||
|
<Controller
|
||||||
|
name="credentials.sslEnabled"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
|
<FormControl isError={Boolean(error?.message)} errorText={error?.message}>
|
||||||
|
<Switch
|
||||||
|
className="bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-green/80"
|
||||||
|
id="ssl-enabled"
|
||||||
|
thumbClassName="bg-mineshaft-800"
|
||||||
|
isChecked={value}
|
||||||
|
onCheckedChange={onChange}
|
||||||
|
>
|
||||||
|
Enable SSL
|
||||||
|
</Switch>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="credentials.sslCertificate"
|
||||||
|
control={control}
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
className={sslEnabled ? "" : "opacity-50"}
|
||||||
|
label="SSL Certificate"
|
||||||
|
isOptional
|
||||||
|
>
|
||||||
|
<TextArea className="h-14 resize-none!" {...field} isDisabled={!sslEnabled} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="credentials.sslRejectUnauthorized"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
className={sslEnabled ? "" : "opacity-50"}
|
||||||
|
isError={Boolean(error?.message)}
|
||||||
|
errorText={error?.message}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
className="bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-green/80"
|
||||||
|
id="ssl-reject-unauthorized"
|
||||||
|
thumbClassName="bg-mineshaft-800"
|
||||||
|
isChecked={sslEnabled ? value : false}
|
||||||
|
onCheckedChange={onChange}
|
||||||
|
isDisabled={!sslEnabled}
|
||||||
|
>
|
||||||
|
<p className="w-38">
|
||||||
|
Reject Unauthorized
|
||||||
|
<Tooltip
|
||||||
|
className="max-w-md"
|
||||||
|
content={
|
||||||
|
<p>
|
||||||
|
If enabled, Infisical will only connect to the server if it has a
|
||||||
|
valid, trusted SSL certificate.
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faQuestionCircle} size="sm" className="ml-1" />
|
||||||
|
</Tooltip>
|
||||||
|
</p>
|
||||||
|
</Switch>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Tab.Panel>
|
||||||
|
</Tab.Panels>
|
||||||
|
</Tab.Group>
|
||||||
|
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<Button
|
||||||
|
className="mr-4"
|
||||||
|
size="sm"
|
||||||
|
type="submit"
|
||||||
|
colorSchema="secondary"
|
||||||
|
isLoading={isSubmitting}
|
||||||
|
isDisabled={isSubmitting || !isDirty}
|
||||||
|
>
|
||||||
|
{isUpdate ? "Update Credentials" : "Connect to Database"}
|
||||||
|
</Button>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button colorSchema="secondary" variant="plain">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user