diff --git a/build.rs b/build.rs index 7609593..d506869 100644 --- a/build.rs +++ b/build.rs @@ -2,4 +2,4 @@ fn main() { // trigger recompilation when a new migration is added println!("cargo:rerun-if-changed=migrations"); -} \ No newline at end of file +} diff --git a/justfile b/justfile index be8a788..066ce79 100644 --- a/justfile +++ b/justfile @@ -47,6 +47,10 @@ test: testv: RUST_BACKTRACE=1 cargo test -- --nocapture +## Format the code +format: + cargo fmt + ## Run the linter lint: cargo check diff --git a/src/configuration.rs b/src/configuration.rs index 6df5fdb..ac39d91 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -1,10 +1,9 @@ use secrecy::{ExposeSecret, Secret}; -use sqlx::postgres::{PgConnectOptions, PgSslMode}; use serde_aux::field_attributes::deserialize_number_from_string; +use sqlx::postgres::{PgConnectOptions, PgSslMode}; use crate::domain::SubscriberEmail; - #[derive(Clone, serde::Deserialize)] pub struct Settings { pub database: DatabaseSettings, @@ -49,13 +48,17 @@ pub fn get_configuration() -> Result { .expect("Failed to parse APP_ENVIRONMENT"); let environment_filename = format!("{}.yaml", environment.as_str()); let settings = config::Config::builder() + .add_source(config::File::from( + configuration_directory.join("base.yaml"), + )) + .add_source(config::File::from( + configuration_directory.join(environment_filename), + )) .add_source( - config::File::from(configuration_directory.join("base.yaml")) - ) - .add_source( - config::File::from(configuration_directory.join(environment_filename)) + config::Environment::with_prefix("APP") + .separator("__") + .prefix_separator("_"), ) - .add_source(config::Environment::with_prefix("APP").separator("__").prefix_separator("_")) .build()?; // Try to convert the configuration reader into our Settings type settings.try_deserialize::() diff --git a/src/domain/mod.rs b/src/domain/mod.rs index 49b35d6..e771a2e 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -1,7 +1,7 @@ +mod new_subscriber; mod subscriber_email; mod subscriber_name; -mod new_subscriber; +pub use new_subscriber::NewSubscriber; pub use subscriber_email::SubscriberEmail; pub use subscriber_name::SubscriberName; -pub use new_subscriber::NewSubscriber; diff --git a/src/domain/new_subscriber.rs b/src/domain/new_subscriber.rs index 1b78516..dad8a71 100644 --- a/src/domain/new_subscriber.rs +++ b/src/domain/new_subscriber.rs @@ -1,6 +1,5 @@ - -use crate::domain::subscriber_name::SubscriberName; use crate::domain::subscriber_email::SubscriberEmail; +use crate::domain::subscriber_name::SubscriberName; pub struct NewSubscriber { pub email: SubscriberEmail, diff --git a/src/domain/subscriber_email.rs b/src/domain/subscriber_email.rs index edaf7c0..f66f18e 100644 --- a/src/domain/subscriber_email.rs +++ b/src/domain/subscriber_email.rs @@ -7,8 +7,7 @@ impl SubscriberEmail { pub fn parse(s: String) -> Result { if validate_email(&s) { Ok(Self(s)) - } - else { + } else { Err(format!("{} is not a valid email address.", s)) } } @@ -22,11 +21,11 @@ impl AsRef for SubscriberEmail { #[cfg(test)] mod tests { + use crate::domain::SubscriberEmail; + use claims::assert_err; use fake::faker::internet::en::SafeEmail; use fake::Fake; use rand::{rngs::StdRng, SeedableRng}; - use claims::assert_err; - use crate::domain::SubscriberEmail; #[test] fn empty_string_is_rejected() { diff --git a/src/domain/subscriber_name.rs b/src/domain/subscriber_name.rs index 40ef7d0..70893b3 100644 --- a/src/domain/subscriber_name.rs +++ b/src/domain/subscriber_name.rs @@ -11,8 +11,7 @@ impl SubscriberName { let contains_forbidden_characters = s.chars().any(|c| forbidden_characters.contains(&c)); if is_empty_or_whitespace || is_too_long || contains_forbidden_characters { Err(format!("{} is not a valid subscriber name.", s)) - } - else { + } else { Ok(Self(s)) } } @@ -24,7 +23,6 @@ impl AsRef for SubscriberName { } } - #[cfg(test)] mod tests { use crate::domain::SubscriberName; diff --git a/src/email_client.rs b/src/email_client.rs index 4f3ff21..f0dc301 100644 --- a/src/email_client.rs +++ b/src/email_client.rs @@ -27,10 +27,7 @@ impl EmailClient { timeout: std::time::Duration, ) -> Self { let base_url = Url::parse(&base_url).expect("Invalid base URL for email client."); - let http_client = Client::builder() - .timeout(timeout) - .build() - .unwrap(); + let http_client = Client::builder().timeout(timeout).build().unwrap(); Self { http_client, base_url, diff --git a/src/main.rs b/src/main.rs index b55a0a8..948e2a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,7 @@ -use zero2prod::startup::Application; use zero2prod::configuration::get_configuration; +use zero2prod::startup::Application; use zero2prod::telemetry::{get_subscriber, init_subscriber}; - #[tokio::main] async fn main() -> Result<(), std::io::Error> { // setup tracing @@ -15,4 +14,3 @@ async fn main() -> Result<(), std::io::Error> { server.run_until_stopped().await?; Ok(()) } - diff --git a/src/routes/health_check.rs b/src/routes/health_check.rs index f4472dc..8b7da39 100644 --- a/src/routes/health_check.rs +++ b/src/routes/health_check.rs @@ -1,4 +1,4 @@ -use actix_web::{Responder, HttpResponse}; +use actix_web::{HttpResponse, Responder}; pub async fn health_check() -> impl Responder { HttpResponse::Ok() diff --git a/src/routes/subscriptions_confirm.rs b/src/routes/subscriptions_confirm.rs index e76b66c..6bbbe11 100644 --- a/src/routes/subscriptions_confirm.rs +++ b/src/routes/subscriptions_confirm.rs @@ -19,15 +19,12 @@ pub async fn confirm(parameters: web::Query, pool: web::Data return HttpResponse::InternalServerError().finish(); } HttpResponse::Ok().finish() - }, + } None => return HttpResponse::Unauthorized().finish(), } } -pub async fn confirm_subscriber( - pool: &PgPool, - subscriber_id: Uuid, -) -> Result<(), sqlx::Error> { +pub async fn confirm_subscriber(pool: &PgPool, subscriber_id: Uuid) -> Result<(), sqlx::Error> { sqlx::query!( r#" UPDATE subscriptions diff --git a/src/startup.rs b/src/startup.rs index 0c9c0cf..2322616 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -1,6 +1,6 @@ use crate::configuration::{DatabaseSettings, Settings}; use crate::email_client::EmailClient; -use crate::routes::{health_check, subscribe, confirm}; +use crate::routes::{confirm, health_check, subscribe}; use actix_web::dev::Server; use actix_web::{web, App, HttpServer}; use sqlx::postgres::PgPoolOptions; diff --git a/tests/api/helpers.rs b/tests/api/helpers.rs index 8fce0f6..94b58d2 100644 --- a/tests/api/helpers.rs +++ b/tests/api/helpers.rs @@ -1,10 +1,10 @@ use once_cell::sync::Lazy; -use sqlx::{Connection, Executor, PgConnection, PgPool}; use sqlx::postgres::PgPoolOptions; +use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; use wiremock::MockServer; -use zero2prod::configuration::{DatabaseSettings, get_configuration}; -use zero2prod::startup::{Application, get_connection_pool}; +use zero2prod::configuration::{get_configuration, DatabaseSettings}; +use zero2prod::startup::{get_connection_pool, Application}; use zero2prod::telemetry::{get_subscriber, init_subscriber}; pub struct TestApp { @@ -91,7 +91,9 @@ pub async fn spawn_app() -> TestApp { configure_database(&configuration.database).await; // Launch the application as a background task - let application = Application::build(configuration.clone()).await.expect("Failed to build application."); + let application = Application::build(configuration.clone()) + .await + .expect("Failed to build application."); let application_port = application.port(); let address = format!("http://localhost:{}", application_port); let _ = tokio::spawn(application.run_until_stopped()); @@ -105,10 +107,9 @@ pub async fn spawn_app() -> TestApp { async fn configure_database(config: &DatabaseSettings) -> PgPool { // Create database - let mut connection = - PgConnection::connect_with(&config.without_db()) - .await - .expect("Failed to connect to Postgres"); + let mut connection = PgConnection::connect_with(&config.without_db()) + .await + .expect("Failed to connect to Postgres"); connection .execute(&*format!(r#"CREATE DATABASE "{}";"#, config.name)) .await diff --git a/tests/api/main.rs b/tests/api/main.rs index ce62707..177847a 100644 --- a/tests/api/main.rs +++ b/tests/api/main.rs @@ -1,4 +1,4 @@ -mod helpers; mod health_check; +mod helpers; mod subscriptions; mod subscriptions_confirm; diff --git a/tests/api/subscriptions_confirm.rs b/tests/api/subscriptions_confirm.rs index dc8d96e..1d2760f 100644 --- a/tests/api/subscriptions_confirm.rs +++ b/tests/api/subscriptions_confirm.rs @@ -35,7 +35,10 @@ async fn the_link_returned_by_subscribe_returns_a_200_if_called() { assert_eq!(confirmation_links.html, confirmation_links.plain_text); assert_eq!(confirmation_links.html.host_str().unwrap(), "127.0.0.1"); - assert_eq!(confirmation_links.plain_text.host_str().unwrap(), "127.0.0.1"); + assert_eq!( + confirmation_links.plain_text.host_str().unwrap(), + "127.0.0.1" + ); let mut confirmation_link = confirmation_links.html.clone(); confirmation_link.set_port(Some(app.port)).unwrap(); @@ -67,7 +70,11 @@ async fn clicking_on_the_confirmation_link_confirms_a_subscriber() { confirmation_link.set_port(Some(app.port)).unwrap(); // Act - reqwest::get(confirmation_link).await.unwrap().error_for_status().unwrap(); + reqwest::get(confirmation_link) + .await + .unwrap() + .error_for_status() + .unwrap(); // Assert let saved = sqlx::query!("SELECT email, name, status FROM subscriptions",)