From 444e42351e888efcb4afc2aec6887edbf0386f90 Mon Sep 17 00:00:00 2001 From: minhtrannhat Date: Wed, 8 May 2024 17:53:41 -0400 Subject: [PATCH] feat(api): wrap database password with Secret --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/configuration.rs | 27 ++++++++++++++++++--------- src/main.rs | 3 ++- tests/test_utils.rs | 10 ++++++---- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28c93bf..2aaa4d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -615,6 +615,7 @@ dependencies = [ "config", "once_cell", "reqwest", + "secrecy", "serde", "sqlx", "tokio", @@ -1930,6 +1931,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + [[package]] name = "security-framework" version = "2.9.2" diff --git a/Cargo.toml b/Cargo.toml index c14bfc7..6328356 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ tracing-subscriber = { version = "0.3.18", features = ["registry", "env-filter"] tracing-bunyan-formatter = "0.3.9" tracing-log = "0.2.0" once_cell = "1.19.0" +secrecy = { version = "0.8.0", features = ["serde"] } [dependencies.sqlx] version = "0.7" diff --git a/src/configuration.rs b/src/configuration.rs index ff20e95..1d76ee8 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -1,3 +1,5 @@ +use secrecy::{ExposeSecret, Secret}; + #[derive(serde::Deserialize)] pub struct Settings { pub database: DatabaseSettings, @@ -7,7 +9,7 @@ pub struct Settings { #[derive(serde::Deserialize)] pub struct DatabaseSettings { pub username: String, - pub password: String, + pub password: Secret, pub port: u16, pub host: String, pub database_name: String, @@ -25,17 +27,24 @@ pub fn get_configuration() -> Result { } impl DatabaseSettings { - pub fn connection_string(&self) -> String { - format!( + pub fn connection_string(&self) -> Secret { + Secret::new(format!( "postgres://{}:{}@{}:{}/{}", - self.username, self.password, self.host, self.port, self.database_name - ) + self.username, + self.password.expose_secret(), + self.host, + self.port, + self.database_name + )) } - pub fn connection_string_without_db(&self) -> String { - format!( + pub fn connection_string_without_db(&self) -> Secret { + Secret::new(format!( "postgres://{}:{}@{}:{}", - self.username, self.password, self.host, self.port - ) + self.username, + self.password.expose_secret(), + self.host, + self.port + )) } } diff --git a/src/main.rs b/src/main.rs index 746e638..90c4bd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::net::TcpListener; use email_newsletter_api::telemetry::{get_subscriber, init_subscriber}; use email_newsletter_api::{configuration::get_configuration, startup}; +use secrecy::ExposeSecret; use sqlx::PgPool; #[tokio::main] @@ -15,7 +16,7 @@ async fn main() -> Result<(), std::io::Error> { ); init_subscriber(subscriber); - let db_conn = PgPool::connect(&configuration.database.connection_string()) + let db_conn = PgPool::connect(configuration.database.connection_string().expose_secret()) .await .expect("Failed to connect to PostgreSQL"); diff --git a/tests/test_utils.rs b/tests/test_utils.rs index d18aed7..4b1a157 100644 --- a/tests/test_utils.rs +++ b/tests/test_utils.rs @@ -3,6 +3,7 @@ use email_newsletter_api::{ telemetry::{get_subscriber, init_subscriber}, }; use once_cell::sync::Lazy; +use secrecy::ExposeSecret; use sqlx::{Connection, Executor, PgConnection, PgPool}; use std::net::TcpListener; use uuid::Uuid; @@ -57,16 +58,17 @@ pub async fn spawn_app() -> TestApp { } pub async fn configure_test_database(db_config: &DatabaseSettings) -> PgPool { - let mut connection = PgConnection::connect(&db_config.connection_string_without_db()) - .await - .expect("Failed to connect to Postgres"); + let mut connection = + PgConnection::connect(db_config.connection_string_without_db().expose_secret()) + .await + .expect("Failed to connect to Postgres"); connection .execute(format!(r#"CREATE DATABASE "{}";"#, db_config.database_name).as_str()) .await .expect("Failed to create database"); - let conn_pool = PgPool::connect(&db_config.connection_string()) + let conn_pool = PgPool::connect(db_config.connection_string().expose_secret()) .await .expect("Failed to connect to PostgreSQL pool");