diff --git a/backend/src/ee/services/secret-rotation-v2/mssql-credentials/mssql-credentials-rotation-constants.ts b/backend/src/ee/services/secret-rotation-v2/mssql-credentials/mssql-credentials-rotation-constants.ts index 670c98997..b256bd77f 100644 --- a/backend/src/ee/services/secret-rotation-v2/mssql-credentials/mssql-credentials-rotation-constants.ts +++ b/backend/src/ee/services/secret-rotation-v2/mssql-credentials/mssql-credentials-rotation-constants.ts @@ -7,7 +7,20 @@ export const MSSQL_CREDENTIALS_ROTATION_LIST_OPTION: TSecretRotationV2ListItem = type: SecretRotation.MsSqlCredentials, connection: AppConnection.MsSql, template: { - createUserStatement: `CREATE LOGIN [my_mssql_user] WITH PASSWORD = 'my_temporary_password'; CREATE USER [my_mssql_user] FOR LOGIN [my_mssql_user]; GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO [my_mssql_user];`, + createUserStatement: `-- Create login at the server level +CREATE LOGIN [infisical_user] WITH PASSWORD = 'my-password'; + +-- Grant server-level connect permission +GRANT CONNECT SQL TO [infisical_user]; + +-- Switch to the database where you want to create the user +USE my_database; + +-- Create the database user mapped to the login +CREATE USER [infisical_user] FOR LOGIN [infisical_user]; + +-- Grant permissions to the user on the schema in this database +GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO [infisical_user];`, secretsMapping: { username: "MSSQL_DB_USERNAME", password: "MSSQL_DB_PASSWORD" diff --git a/backend/src/ee/services/secret-rotation-v2/postgres-credentials/postgres-credentials-rotation-constants.ts b/backend/src/ee/services/secret-rotation-v2/postgres-credentials/postgres-credentials-rotation-constants.ts index 68a31e8c9..395ed46d1 100644 --- a/backend/src/ee/services/secret-rotation-v2/postgres-credentials/postgres-credentials-rotation-constants.ts +++ b/backend/src/ee/services/secret-rotation-v2/postgres-credentials/postgres-credentials-rotation-constants.ts @@ -7,7 +7,14 @@ export const POSTGRES_CREDENTIALS_ROTATION_LIST_OPTION: TSecretRotationV2ListIte type: SecretRotation.PostgresCredentials, connection: AppConnection.Postgres, template: { - createUserStatement: `CREATE USER "my_pg_user" WITH ENCRYPTED PASSWORD 'temporary_password'; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "my_pg_user";`, + createUserStatement: `-- create user role +CREATE USER infisical_user WITH ENCRYPTED PASSWORD 'temporary_password'; + +-- grant database connection permissions +GRANT CONNECT ON DATABASE my_database TO infisical_user; + +-- grant relevant table permissions +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO infisical_user;`, secretsMapping: { username: "POSTGRES_DB_USERNAME", password: "POSTGRES_DB_PASSWORD" diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 7fa6e6df7..ea5c07789 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -1691,6 +1691,8 @@ export const AppConnections = { database: "The name of the database to connect to.", username: "The username to connect to the database with.", password: "The password to connect to the database with.", + sslEnabled: "Whether or not to use SSL when connecting to the database.", + sslRejectUnauthorized: "Whether or not to reject unauthorized SSL certificates.", sslCertificate: "The SSL certificate to use for connection." } } diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index f43b0b443..0906e5269 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -59,8 +59,6 @@ const envSchema = z QUEUE_WORKERS_ENABLED: zodStrBool.default("true"), HTTPS_ENABLED: zodStrBool, ROTATION_DEVELOPMENT_MODE: zodStrBool.default("false").optional(), - DB_SSL_REJECT_UNAUTHORIZED: zodStrBool.default("true"), - DB_SSL_REQUIRED: zodStrBool.default("true"), // smtp options SMTP_HOST: zpStr(z.string().optional()), SMTP_IGNORE_TLS: zodStrBool.default("false"), diff --git a/backend/src/services/app-connection/mssql/mssql-connection-schemas.ts b/backend/src/services/app-connection/mssql/mssql-connection-schemas.ts index 1b659b658..38ef0eef6 100644 --- a/backend/src/services/app-connection/mssql/mssql-connection-schemas.ts +++ b/backend/src/services/app-connection/mssql/mssql-connection-schemas.ts @@ -29,7 +29,9 @@ export const SanitizedMsSqlConnectionSchema = z.discriminatedUnion("method", [ host: true, database: true, port: true, - username: true + username: true, + sslEnabled: true, + sslRejectUnauthorized: true }) }) ]); diff --git a/backend/src/services/app-connection/postgres/postgres-connection-schemas.ts b/backend/src/services/app-connection/postgres/postgres-connection-schemas.ts index 3867ea8bf..510f7b7d0 100644 --- a/backend/src/services/app-connection/postgres/postgres-connection-schemas.ts +++ b/backend/src/services/app-connection/postgres/postgres-connection-schemas.ts @@ -27,7 +27,9 @@ export const SanitizedPostgresConnectionSchema = z.discriminatedUnion("method", host: true, database: true, port: true, - username: true + username: true, + sslEnabled: true, + sslRejectUnauthorized: true }) }) ]); diff --git a/backend/src/services/app-connection/shared/sql/sql-connection-fns.ts b/backend/src/services/app-connection/shared/sql/sql-connection-fns.ts index 4a6f2b05f..ed1d99941 100644 --- a/backend/src/services/app-connection/shared/sql/sql-connection-fns.ts +++ b/backend/src/services/app-connection/shared/sql/sql-connection-fns.ts @@ -5,7 +5,6 @@ import { TSqlCredentialsRotationGeneratedCredentials, TSqlCredentialsRotationWithConnection } from "@app/ee/services/secret-rotation-v2/shared/sql-credentials/sql-credentials-rotation-types"; -import { getConfig } from "@app/lib/config/env"; import { BadRequestError, DatabaseError } from "@app/lib/errors"; import { alphaNumericNanoId } from "@app/lib/nanoid"; import { AppConnection } from "@app/services/app-connection/app-connection-enums"; @@ -21,16 +20,14 @@ const SQL_CONNECTION_CLIENT_MAP = { const getConnectionConfig = ({ app, - credentials: { sslCertificate, host } + credentials: { host, sslCertificate, sslEnabled, sslRejectUnauthorized } }: Pick) => { - const appCfg = getConfig(); - switch (app) { case AppConnection.Postgres: { return { - ssl: appCfg.DB_SSL_REQUIRED + ssl: sslEnabled ? { - rejectUnauthorized: appCfg.DB_SSL_REJECT_UNAUTHORIZED, + rejectUnauthorized: sslRejectUnauthorized, ca: sslCertificate, servername: host } @@ -39,13 +36,13 @@ const getConnectionConfig = ({ } case AppConnection.MsSql: { return { - options: appCfg.DB_SSL_REQUIRED + options: sslEnabled ? { - trustServerCertificate: !appCfg.DB_SSL_REJECT_UNAUTHORIZED, + trustServerCertificate: !sslRejectUnauthorized, encrypt: true, cryptoCredentialsDetails: sslCertificate ? { ca: sslCertificate } : {} } - : undefined + : { encrypt: false } }; } default: diff --git a/backend/src/services/app-connection/shared/sql/sql-connection-schemas.ts b/backend/src/services/app-connection/shared/sql/sql-connection-schemas.ts index 9688d8d43..500ed596a 100644 --- a/backend/src/services/app-connection/shared/sql/sql-connection-schemas.ts +++ b/backend/src/services/app-connection/shared/sql/sql-connection-schemas.ts @@ -8,5 +8,12 @@ export const BaseSqlUsernameAndPasswordConnectionSchema = z.object({ database: z.string().trim().min(1, "Database required").describe(AppConnections.CREDENTIALS.SQL_CONNECTION.database), username: z.string().trim().min(1, "Username required").describe(AppConnections.CREDENTIALS.SQL_CONNECTION.username), password: z.string().trim().min(1, "Password required").describe(AppConnections.CREDENTIALS.SQL_CONNECTION.password), - sslCertificate: z.string().trim().optional().describe(AppConnections.CREDENTIALS.SQL_CONNECTION.sslCertificate) + sslEnabled: z.boolean().describe(AppConnections.CREDENTIALS.SQL_CONNECTION.sslEnabled), + sslRejectUnauthorized: z.boolean().describe(AppConnections.CREDENTIALS.SQL_CONNECTION.sslRejectUnauthorized), + sslCertificate: z + .string() + .trim() + .transform((value) => value || undefined) + .optional() + .describe(AppConnections.CREDENTIALS.SQL_CONNECTION.sslCertificate) }); diff --git a/docs/documentation/platform/secret-rotation/mssql.mdx b/docs/documentation/platform/secret-rotation/mssql.mdx index a60e89db7..8789e4152 100644 --- a/docs/documentation/platform/secret-rotation/mssql.mdx +++ b/docs/documentation/platform/secret-rotation/mssql.mdx @@ -11,19 +11,19 @@ description: "Learn how to automatically rotate Microsoft SQL Server credentials An example creation statement might look like: ```SQL -- create server-level logins - CREATE LOGIN infisical_user_1 WITH PASSWORD = 'my-password'; - CREATE LOGIN infisical_user_2 WITH PASSWORD = 'my-password'; + CREATE LOGIN [infisical_user_1] WITH PASSWORD = 'my-password'; + CREATE LOGIN [infisical_user_2] WITH PASSWORD = 'my-password'; + GRANT CONNECT SQL TO [infisical_user_1]; + GRANT CONNECT SQL TO [infisical_user_2]; -- create database-level users with login from above USE my_database; - CREATE USER infisical_user_1 FOR LOGIN infisical_user_1; - CREATE USER infisical_user_2 FOR LOGIN infisical_user_2; - GRANT CONNECT TO infisical_user_1; - GRANT CONNECT TO infisical_user_2; + CREATE USER [infisical_user_1] FOR LOGIN [infisical_user_1]; + CREATE USER [infisical_user_2] FOR LOGIN [infisical_user_2]; -- grant relevant permissions - GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO infisical_user_1; - GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO infisical_user_2; + GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO [infisical_user_1]; + GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO [infisical_user_2]; ``` diff --git a/docs/documentation/platform/secret-rotation/postgres.mdx b/docs/documentation/platform/secret-rotation/postgres.mdx index d39b12f81..e0606e6ab 100644 --- a/docs/documentation/platform/secret-rotation/postgres.mdx +++ b/docs/documentation/platform/secret-rotation/postgres.mdx @@ -10,14 +10,16 @@ description: "Learn how to automatically rotate PostgreSQL credentials." An example creation statement might look like: ```SQL - -- first user + -- create user roles CREATE USER infisical_user_1 WITH ENCRYPTED PASSWORD 'temporary_password'; - GRANT CONNECT ON DATABASE my_database TO infisical_user_1; - GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO infisical_user_1; - - -- second user CREATE USER infisical_user_2 WITH ENCRYPTED PASSWORD 'temporary_password'; + + -- grant database connection permissions + GRANT CONNECT ON DATABASE my_database TO infisical_user_1; GRANT CONNECT ON DATABASE my_database TO infisical_user_2; + + -- grant relevant table permissions + GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO infisical_user_1; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO infisical_user_2; ``` diff --git a/docs/images/app-connections/mssql/create-username-and-password-method.png b/docs/images/app-connections/mssql/create-username-and-password-method.png index cb6380462..c30423857 100644 Binary files a/docs/images/app-connections/mssql/create-username-and-password-method.png and b/docs/images/app-connections/mssql/create-username-and-password-method.png differ diff --git a/docs/images/app-connections/postgres/create-username-and-password-method.png b/docs/images/app-connections/postgres/create-username-and-password-method.png index f09ebc603..deecd87b6 100644 Binary files a/docs/images/app-connections/postgres/create-username-and-password-method.png and b/docs/images/app-connections/postgres/create-username-and-password-method.png differ diff --git a/docs/integrations/app-connections/mssql.mdx b/docs/integrations/app-connections/mssql.mdx index e85c7e8bf..ca91a17db 100644 --- a/docs/integrations/app-connections/mssql.mdx +++ b/docs/integrations/app-connections/mssql.mdx @@ -11,16 +11,20 @@ Infisical supports connecting to Microsoft SQL Server using database principals. Infisical recommends creating a designated server login and database user in your Microsoft SQL Server database for your connection. ```SQL - -- create server-level login - CREATE LOGIN infisical_login WITH PASSWORD = 'my-password'; + -- Create login at the server level + CREATE LOGIN [infisical_app] WITH PASSWORD = 'my-password'; - -- create database-level user with login from above + -- Grant server-level connect permission + GRANT CONNECT SQL TO [infisical_app]; + + -- Switch to the specific database where you want to create the user USE my_database; - CREATE USER infisical_user FOR LOGIN infisical_login; - GRANT CONNECT TO infisical_user; + + -- Create the database user mapped to the login + CREATE USER [infisical_app] FOR LOGIN [infisical_app]; -- If you intend to use Platform Managed Credentials (see below) - GRANT ALTER ANY LOGIN TO infisical_login; + GRANT ALTER ANY LOGIN TO [infisical_app]; ``` @@ -95,6 +99,8 @@ Infisical supports connecting to Microsoft SQL Server using database principals. "database": "default", "username": "infisical_login", "password": "my-password", + "sslEnabled": true, + "sslRejectUnauthorized": true }, }' ``` @@ -117,7 +123,9 @@ Infisical supports connecting to Microsoft SQL Server using database principals. "host": "123.4.5.6", "port": 1433, "database": "default", - "username": "infisical_login" + "username": "infisical_login", + "sslEnabled": true, + "sslRejectUnauthorized": true } } } diff --git a/docs/integrations/app-connections/postgres.mdx b/docs/integrations/app-connections/postgres.mdx index abf968bd9..523fc35a8 100644 --- a/docs/integrations/app-connections/postgres.mdx +++ b/docs/integrations/app-connections/postgres.mdx @@ -12,7 +12,7 @@ Infisical supports connecting to PostgreSQL using a database role. Infisical recommends creating a designated role in your PostgreSQL database for your connection. ```SQL -- create user role - CREATE ROLE infisical_role WITH LOGIN PASSWORD 'my-password' + CREATE ROLE infisical_role WITH LOGIN PASSWORD 'my-password'; -- grant login access to the specified database GRANT CONNECT ON DATABASE my_database TO infisical_role; @@ -27,6 +27,7 @@ Infisical supports connecting to PostgreSQL using a database role. For Secret Rotations, your Infisical user will require the ability to alter other users' passwords: ```SQL + -- enable permissions to alter login credentials ALTER ROLE infisical_role WITH CREATEROLE; ``` @@ -88,6 +89,8 @@ Infisical supports connecting to PostgreSQL using a database role. "database": "default", "username": "infisical_role", "password": "my-password", + "sslEnabled": true, + "sslRejectUnauthorized": true }, }' ``` @@ -110,7 +113,9 @@ Infisical supports connecting to PostgreSQL using a database role. "host": "123.4.5.6", "port": 5432, "database": "default", - "username": "infisical_role" + "username": "infisical_role", + "sslEnabled": true, + "sslRejectUnauthorized": true } } } diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 503b711e3..8eda21edd 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -439,19 +439,6 @@ When set, all visits to the Infisical login page will automatically redirect use information. -## External Database Connections - - - Specify whether external database connections should reject unauthorized SSL certificates. - We highly recommend keeping this value set to `true` for production use-cases. - - - - Specify whether external database connections should require SSL. - We highly recommend keeping this value set to `true` for production use-cases. - - - ## App Connections You can configure third-party app connections for re-use across Infisical Projects. diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/shared/SqlRotationParametersFields.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/shared/SqlRotationParametersFields.tsx index 7aa19aeb9..0b992e0dc 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/shared/SqlRotationParametersFields.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/shared/SqlRotationParametersFields.tsx @@ -57,7 +57,7 @@ export const SqlRotationParametersFields = () => { to suit your needs.

-

+          
             {rotationOption!.template.createUserStatement}
           

diff --git a/frontend/src/hooks/api/appConnections/types/shared/sql-connection.ts b/frontend/src/hooks/api/appConnections/types/shared/sql-connection.ts index 79a14b520..d0e71158e 100644 --- a/frontend/src/hooks/api/appConnections/types/shared/sql-connection.ts +++ b/frontend/src/hooks/api/appConnections/types/shared/sql-connection.ts @@ -4,4 +4,6 @@ export type TBaseSqlConnectionCredentials = { username: string; password: string; database: string; + sslEnabled: boolean; + sslRejectUnauthorized: boolean; }; diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AwsConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AwsConnectionForm.tsx index d1137a887..1731cceef 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AwsConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AwsConnectionForm.tsx @@ -22,7 +22,7 @@ import { type Props = { appConnection?: TAwsConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/DatabricksConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/DatabricksConnectionForm.tsx index 997609d1b..f5f531b4c 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/DatabricksConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/DatabricksConnectionForm.tsx @@ -25,7 +25,7 @@ import { type Props = { appConnection?: TDatabricksConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/GcpConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/GcpConnectionForm.tsx index 26160fe17..8d639111b 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/GcpConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/GcpConnectionForm.tsx @@ -28,7 +28,7 @@ import { type Props = { appConnection?: TGcpConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/HumanitecConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/HumanitecConnectionForm.tsx index b9a41f25c..39785c99b 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/HumanitecConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/HumanitecConnectionForm.tsx @@ -21,7 +21,7 @@ import { type Props = { appConnection?: THumanitecConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/MsSqlConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/MsSqlConnectionForm.tsx index bcea2f3bc..fecac3d3e 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/MsSqlConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/MsSqlConnectionForm.tsx @@ -24,7 +24,7 @@ import { type Props = { appConnection?: TMsSqlConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ @@ -44,6 +44,7 @@ type FormData = z.infer; export const MsSqlConnectionForm = ({ appConnection, onSubmit }: Props) => { const isUpdate = Boolean(appConnection); const [showConfirmation, setShowConfirmation] = useState(false); + const [selectedTabIndex, setSelectedTabIndex] = useState(0); const form = useForm({ resolver: zodResolver(formSchema), @@ -56,7 +57,9 @@ export const MsSqlConnectionForm = ({ appConnection, onSubmit }: Props) => { database: "default", username: "", password: "", - sslCertificate: "" + sslEnabled: true, + sslRejectUnauthorized: true, + sslCertificate: undefined } } }); @@ -69,18 +72,23 @@ export const MsSqlConnectionForm = ({ appConnection, onSubmit }: Props) => { const isPlatformManagedCredentials = appConnection?.isPlatformManagedCredentials ?? false; - const confirmSubmit = (formData: FormData) => { + const confirmSubmit = async (formData: FormData) => { if (formData.isPlatformManagedCredentials) { setShowConfirmation(true); return; } - onSubmit(formData); + await onSubmit(formData); }; return ( -
+ { + setSelectedTabIndex(0); + handleSubmit(confirmSubmit)(e); + }} + > {!isUpdate && } { )} /> - + {isPlatformManagedCredentials ? ( ) : ( diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/PostgresConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/PostgresConnectionForm.tsx index bb4b9be95..52bbaee30 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/PostgresConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/PostgresConnectionForm.tsx @@ -21,7 +21,7 @@ import { type Props = { appConnection?: TPostgresConnection; - onSubmit: (formData: FormData) => void; + onSubmit: (formData: FormData) => Promise; }; const rootSchema = genericAppConnectionFieldsSchema.extend({ @@ -41,6 +41,7 @@ type FormData = z.infer; export const PostgresConnectionForm = ({ appConnection, onSubmit }: Props) => { const isUpdate = Boolean(appConnection); const [showConfirmation, setShowConfirmation] = useState(false); + const [selectedTabIndex, setSelectedTabIndex] = useState(0); const form = useForm({ resolver: zodResolver(formSchema), @@ -53,7 +54,9 @@ export const PostgresConnectionForm = ({ appConnection, onSubmit }: Props) => { database: "default", username: "", password: "", - sslCertificate: "" + sslEnabled: true, + sslRejectUnauthorized: true, + sslCertificate: undefined } } }); @@ -66,18 +69,23 @@ export const PostgresConnectionForm = ({ appConnection, onSubmit }: Props) => { const isPlatformManagedCredentials = appConnection?.isPlatformManagedCredentials ?? false; - const confirmSubmit = (formData: FormData) => { + const confirmSubmit = async (formData: FormData) => { if (formData.isPlatformManagedCredentials) { setShowConfirmation(true); return; } - onSubmit(formData); + await onSubmit(formData); }; return ( - + { + setSelectedTabIndex(0); + handleSubmit(confirmSubmit)(e); + }} + > {!isUpdate && } { )} /> - + {isPlatformManagedCredentials ? ( ) : ( diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/shared/SqlConnectionFields.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/shared/SqlConnectionFields.tsx index 7b8b7c532..66ea546ec 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/shared/SqlConnectionFields.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/shared/SqlConnectionFields.tsx @@ -1,122 +1,207 @@ +import { Dispatch, SetStateAction } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tab } from "@headlessui/react"; import { FormControl, Input, SecretInput, Switch, TextArea, Tooltip } from "@app/components/v2"; type Props = { isPlatformManagedCredentials: boolean; + selectedTabIndex: number; + setSelectedTabIndex: Dispatch>; }; -export const SqlConnectionFields = ({ isPlatformManagedCredentials }: Props) => { - const { control } = useFormContext(); +export const SqlConnectionFields = ({ + isPlatformManagedCredentials, + setSelectedTabIndex, + selectedTabIndex +}: Props) => { + const { control, watch } = useFormContext(); + const sslEnabled = watch("credentials.sslEnabled"); return ( <> -
- ( - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> -
-
- ( - - - - )} - /> - ( - - onChange(e.target.value)} - isDisabled={isPlatformManagedCredentials} - /> - - )} - /> -
- ( - + + + `w-30 -mb-[0.14rem] px-4 py-2 text-sm font-medium outline-none disabled:opacity-60 ${ + selected ? "border-b-2 border-mineshaft-300 text-mineshaft-200" : "text-bunker-300" + }` + } > -