From 891b03b95daabecbe836352b8c9d20afeba0911d Mon Sep 17 00:00:00 2001 From: Moleus Date: Wed, 4 Mar 2026 13:41:20 +0300 Subject: [PATCH 1/2] fix(postgres): Support TLS and query params in pg_url --- Cargo.toml | 2 +- src/store/postgres_activation_store.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67119a08..cd0c07b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ sentry_protos = "0.4.11" serde = "1.0.214" serde_yaml = "0.9.34" sha2 = "0.10.8" -sqlx = { version = "0.8.3", features = ["sqlite", "runtime-tokio", "chrono", "postgres"] } +sqlx = { version = "0.8.3", features = ["sqlite", "runtime-tokio", "chrono", "postgres", "tls-native-tls"] } tokio = { version = "1.43.1", features = ["full"] } tokio-stream = { version = "0.1.16", features = ["full"] } tokio-util = "0.7.12" diff --git a/src/store/postgres_activation_store.rs b/src/store/postgres_activation_store.rs index fdfc493b..ea45a532 100644 --- a/src/store/postgres_activation_store.rs +++ b/src/store/postgres_activation_store.rs @@ -20,24 +20,24 @@ pub async fn create_postgres_pool( url: &str, database_name: &str, ) -> Result<(Pool, Pool), Error> { - let conn_str = url.to_owned() + "/" + database_name; + let conn_opts = PgConnectOptions::from_str(url)?.database(database_name); let read_pool = PgPoolOptions::new() .max_connections(64) - .connect_with(PgConnectOptions::from_str(&conn_str)?) + .connect_with(conn_opts.clone()) .await?; let write_pool = PgPoolOptions::new() .max_connections(64) - .connect_with(PgConnectOptions::from_str(&conn_str)?) + .connect_with(conn_opts) .await?; Ok((read_pool, write_pool)) } pub async fn create_default_postgres_pool(url: &str) -> Result, Error> { - let conn_str = url.to_owned() + "/postgres"; + let conn_opts = PgConnectOptions::from_str(url)?.database("postgres"); let default_pool = PgPoolOptions::new() .max_connections(64) - .connect_with(PgConnectOptions::from_str(&conn_str)?) + .connect_with(conn_opts) .await?; Ok(default_pool) } From 9832384c03800cae38d24c45aefd23e6ef07920c Mon Sep 17 00:00:00 2001 From: Moleus Date: Thu, 5 Mar 2026 12:39:14 +0300 Subject: [PATCH 2/2] chore: add tests and commit cargo lock with native-tls dep --- Cargo.lock | 1 + src/store/postgres_activation_store.rs | 50 ++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec1f3551..5b602a4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2762,6 +2762,7 @@ dependencies = [ "indexmap", "log", "memchr", + "native-tls", "once_cell", "percent-encoding", "serde", diff --git a/src/store/postgres_activation_store.rs b/src/store/postgres_activation_store.rs index ea45a532..4d148e2a 100644 --- a/src/store/postgres_activation_store.rs +++ b/src/store/postgres_activation_store.rs @@ -20,7 +20,7 @@ pub async fn create_postgres_pool( url: &str, database_name: &str, ) -> Result<(Pool, Pool), Error> { - let conn_opts = PgConnectOptions::from_str(url)?.database(database_name); + let conn_opts = build_pg_connect_options(url, database_name)?; let read_pool = PgPoolOptions::new() .max_connections(64) .connect_with(conn_opts.clone()) @@ -34,7 +34,7 @@ pub async fn create_postgres_pool( } pub async fn create_default_postgres_pool(url: &str) -> Result, Error> { - let conn_opts = PgConnectOptions::from_str(url)?.database("postgres"); + let conn_opts = build_pg_connect_options(url, "postgres")?; let default_pool = PgPoolOptions::new() .max_connections(64) .connect_with(conn_opts) @@ -42,6 +42,52 @@ pub async fn create_default_postgres_pool(url: &str) -> Result, E Ok(default_pool) } +fn build_pg_connect_options(url: &str, database_name: &str) -> Result { + Ok(PgConnectOptions::from_str(url)?.database(database_name)) +} + +#[cfg(test)] +mod tests { + use super::build_pg_connect_options; + use sqlx::postgres::PgSslMode; + + #[test] + fn test_connect_opts_plain_url() { + let pg_url = "postgresql://user:pass@localhost:5432"; + let custom_db_name = "my-custom-db"; + let opts = build_pg_connect_options(pg_url, custom_db_name).unwrap(); + assert_eq!(opts.get_database(), Some(custom_db_name)); + assert_eq!(opts.get_host(), "localhost"); + assert_eq!(opts.get_port(), 5432); + } + + #[test] + fn test_connect_opts_preserves_sslmode_query_param() { + let pg_url_with_query = "postgresql://user:pass@localhost:5432?sslmode=require"; + let custom_db_name = "my-custom-db"; + let opts = build_pg_connect_options(pg_url_with_query, custom_db_name).unwrap(); + assert_eq!(opts.get_database(), Some(custom_db_name)); + assert!(matches!(opts.get_ssl_mode(), PgSslMode::Require)); + } + + #[test] + fn test_connect_opts_overrides_existing_db_in_url() { + let pg_url_with_existing_db = "postgresql://user:pass@localhost:5432/olddb-in-path"; + let new_db_name = "newdb"; + let opts = build_pg_connect_options(pg_url_with_existing_db, new_db_name).unwrap(); + assert_eq!(opts.get_database(), Some(new_db_name)); + } + + #[test] + fn test_connect_opts_overrides_db_and_preserves_tls() { + let pg_url_with_existing_db_and_tls = "postgresql://user:pass@localhost:5432/olddb?sslmode=verify-ca"; + let new_db_name = "newdb"; + let opts = build_pg_connect_options(pg_url_with_existing_db_and_tls, new_db_name).unwrap(); + assert_eq!(opts.get_database(), Some("newdb")); + assert!(matches!(opts.get_ssl_mode(), PgSslMode::VerifyCa)); + } +} + pub struct PostgresActivationStoreConfig { pub pg_url: String, pub pg_database_name: String,