diff --git a/services/reports/src/config.rs b/services/reports/src/config.rs --- a/services/reports/src/config.rs +++ b/services/reports/src/config.rs @@ -2,9 +2,11 @@ use clap::Parser; use comm_services_lib::blob::client::Url; use once_cell::sync::Lazy; -use tracing::info; +use tracing::{info, warn}; -// environment variabl names +use crate::email::config::{EmailArgs, EmailConfig}; + +// environment variable names const ENV_LOCALSTACK_ENDPOINT: &str = "LOCALSTACK_ENDPOINT"; const ENV_BLOB_SERVICE_URL: &str = "BLOB_SERVICE_URL"; @@ -21,12 +23,23 @@ #[arg(env = ENV_LOCALSTACK_ENDPOINT)] #[arg(long)] localstack_endpoint: Option, + + /// This config shouldn't be used directly. It's used for parsing purposes + /// only. Use [`AppConfig::email_config()`] instead. + #[command(flatten)] + email_args: EmailArgs, } impl AppConfig { pub fn is_dev(&self) -> bool { self.localstack_endpoint.is_some() } + + pub fn email_config(&self) -> Option { + // we return None in case of error because this should've already been + // checked by parse_cmdline_args() + self.email_args.parse().ok().flatten() + } } /// Stores configuration parsed from command-line arguments @@ -37,7 +50,19 @@ /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> { // force evaluation of the lazy initialized config - Ok(Lazy::force(&CONFIG)) + let cfg = Lazy::force(&CONFIG); + + // initialize e-mail config to check for errors + match cfg.email_args.parse()? { + Some(_) => { + info!("E-mail config found. E-mail notifications are enabled."); + } + None => { + warn!("E-mail config is disabled or missing! E-mails will not be sent."); + } + } + + Ok(cfg) } /// Provides region/credentials configuration for AWS SDKs diff --git a/services/reports/src/main.rs b/services/reports/src/main.rs --- a/services/reports/src/main.rs +++ b/services/reports/src/main.rs @@ -31,10 +31,11 @@ configure_logging()?; let cfg = config::parse_cmdline_args()?; let aws_config = config::load_aws_config().await; + let email_config = cfg.email_config(); let db = database::client::DatabaseClient::new(&aws_config); let blob_client = BlobServiceClient::new(cfg.blob_service_url.clone()); - let service = ReportsService::new(db, blob_client); + let service = ReportsService::new(db, blob_client, email_config); crate::http::run_http_server(service).await } diff --git a/services/reports/src/service.rs b/services/reports/src/service.rs --- a/services/reports/src/service.rs +++ b/services/reports/src/service.rs @@ -8,6 +8,7 @@ use std::{ collections::HashMap, future::{ready, Ready}, + sync::Arc, }; use tracing::error; @@ -16,6 +17,7 @@ client::{DatabaseClient, ReportsPage}, item::ReportItem, }, + email::config::EmailConfig, report_types::{ReportID, ReportInput, ReportOutput, ReportType}, }; @@ -46,14 +48,20 @@ db: DatabaseClient, blob_client: BlobServiceClient, requesting_user_id: Option, + email_config: Option>, } impl ReportsService { - pub fn new(db: DatabaseClient, blob_client: BlobServiceClient) -> Self { + pub fn new( + db: DatabaseClient, + blob_client: BlobServiceClient, + email_config: Option, + ) -> Self { Self { db, blob_client, requesting_user_id: None, + email_config: email_config.map(Arc::new), } } @@ -61,6 +69,7 @@ let user_id = user.user_id.to_string(); Self { db: self.db.clone(), + email_config: self.email_config.clone(), blob_client: self.blob_client.with_user_identity(user), requesting_user_id: Some(user_id), }