aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoris2023-08-19 15:07:10 +0200
committerJoris2023-08-19 15:08:27 +0200
commit4854531d60ad2c68ccdbf19eed6fe9a6ce1b6797 (patch)
tree9b0951fbfe13e382c545f942ad1fac0558f07227 /src
parent4e675127922e455b347246e81178d8c076720aea (diff)
downloadbudget-4854531d60ad2c68ccdbf19eed6fe9a6ce1b6797.tar.gz
budget-4854531d60ad2c68ccdbf19eed6fe9a6ce1b6797.tar.bz2
budget-4854531d60ad2c68ccdbf19eed6fe9a6ce1b6797.zip
Use environment variables instead of config file
Diffstat (limited to 'src')
-rw-r--r--src/main.rs30
-rw-r--r--src/model/config.rs42
2 files changed, 44 insertions, 28 deletions
diff --git a/src/main.rs b/src/main.rs
index 74917a9..65d52df 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,7 @@
-use clap::Parser;
use hyper::service::{make_service_fn, service_fn};
use hyper::Server;
use sqlx::sqlite::SqlitePool;
use std::convert::Infallible;
-use std::net::SocketAddr;
#[macro_use]
extern crate log;
@@ -22,20 +20,7 @@ mod templates;
mod utils;
mod validation;
-use model::config::Config;
-
-#[derive(Parser)]
-#[clap()]
-struct Args {
- #[clap(short, long, default_value = "0.0.0.0:3000")]
- address: SocketAddr,
-
- #[clap(short, long, default_value = "config.json")]
- config: String,
-
- #[clap(short, long, default_value = "database.db")]
- database: String,
-}
+use model::config;
#[tokio::main]
async fn main() {
@@ -44,13 +29,10 @@ async fn main() {
)
.init();
- let args = Args::parse();
-
- let config_str = std::fs::read_to_string(&args.config)
- .unwrap_or_else(|_| panic!("{}", format!("Missing {}", args.config)));
- let config: Config = serde_json::from_str(&config_str).unwrap();
+ let config = config::from_env()
+ .unwrap_or_else(|err| panic!("Error reading config: {err}"));
- let pool = SqlitePool::connect(&format!("sqlite:{}", args.database))
+ let pool = SqlitePool::connect(&format!("sqlite:{}", config.db_path))
.await
.unwrap();
@@ -78,8 +60,8 @@ async fn main() {
}
});
- info!("Starting server at {}", args.address);
- if let Err(e) = Server::bind(&args.address).serve(make_svc).await {
+ info!("Starting server at {}", config.socket_address);
+ if let Err(e) = Server::bind(&config.socket_address).serve(make_svc).await {
error!("server error: {}", e);
}
}
diff --git a/src/model/config.rs b/src/model/config.rs
index e69b4c4..1fa5bb4 100644
--- a/src/model/config.rs
+++ b/src/model/config.rs
@@ -1,8 +1,42 @@
-use serde::Deserialize;
+use std::env;
+use std::net::SocketAddr;
+use std::str::FromStr;
-#[derive(Clone, Deserialize)]
+#[derive(Clone)]
pub struct Config {
- pub secure_cookies: bool,
- pub mock_mails: bool,
pub auth_secret: String,
+ pub db_path: String,
+ pub mock_mails: bool,
+ pub secure_cookies: bool,
+ pub socket_address: SocketAddr,
+}
+
+pub fn from_env() -> Result<Config, String> {
+ Ok(Config {
+ auth_secret: read_string("AUTH_SECRET")?,
+ db_path: read_string("DB_PATH")?,
+ mock_mails: read_bool("MOCK_MAILS")?,
+ secure_cookies: read_bool("SECURE_COOKIES")?,
+ socket_address: read_socket_address("SOCKET_ADDRESS")?,
+ })
+}
+
+fn read_socket_address(key: &str) -> Result<SocketAddr, String> {
+ SocketAddr::from_str(&read_string(key)?).map_err(|err| {
+ format!("environment variable '{key}' is not a socket address: {err}")
+ })
+}
+
+fn read_bool(key: &str) -> Result<bool, String> {
+ read_string(key).and_then(|v| match v.as_str() {
+ "true" => Ok(true),
+ "false" => Ok(false),
+ _ => Err(format!(
+ "environment variable '{key}' is not a boolean: '{v}'"
+ )),
+ })
+}
+
+fn read_string(key: &str) -> Result<String, String> {
+ env::var(key).map_err(|_| format!("missing environment variable '{key}'"))
}