From 176bd238a421932855f51321c70ff14f634053de Mon Sep 17 00:00:00 2001 From: Lennart K <18233294+lennart-k@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:28:46 +0100 Subject: [PATCH] Add config using environment variables with figment --- Cargo.lock | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ README.md | 2 +- src/config.rs | 4 +-- src/main.rs | 13 ++++---- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5ae83c..65ffd12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -495,6 +495,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -650,6 +659,12 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + [[package]] name = "byteorder" version = "1.5.0" @@ -1093,6 +1108,20 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "figment" +version = "0.10.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +dependencies = [ + "atomic", + "pear", + "serde", + "toml", + "uncased", + "version_check", +] + [[package]] name = "flate2" version = "1.0.35" @@ -1735,6 +1764,12 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + [[package]] name = "inout" version = "0.1.3" @@ -2214,6 +2249,29 @@ dependencies = [ "sha2", ] +[[package]] +name = "pear" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -2371,6 +2429,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + [[package]] name = "prost" version = "0.13.4" @@ -2766,6 +2837,7 @@ dependencies = [ "async-trait", "clap", "dashmap", + "figment", "opentelemetry", "opentelemetry-otlp", "opentelemetry-semantic-conventions", @@ -3878,6 +3950,15 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + [[package]] name = "unicase" version = "2.8.1" @@ -4405,6 +4486,12 @@ dependencies = [ "syn", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yoke" version = "0.7.5" diff --git a/Cargo.toml b/Cargo.toml index 3865b80..fb4f000 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -149,6 +149,8 @@ tracing-subscriber = { version = "0.3", features = [ "registry", ] } +figment = { version = "0.10", features = ["env", "toml"] } + rand.workspace = true rpassword.workspace = true argon2.workspace = true diff --git a/README.md b/README.md index e362e45..d9d40f2 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ rustical gen-config You'll have to set your database path to something like `/var/lib/rustical/db.sqlite3`. -Next, configure the principals by creating a file specified in `auth.path` (by default `/etc/rustical/principals.toml`) and inserting your principals: +Next, configure the principals by creating a file specified in `auth.toml.path` (by default `/etc/rustical/principals.toml`) and inserting your principals: ```toml [[principals]] diff --git a/src/config.rs b/src/config.rs index f4cb4c8..5ce70ca 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,14 +25,14 @@ pub struct SqliteDataStoreConfig { } #[derive(Debug, Deserialize, Serialize)] -#[serde(tag = "backend", rename_all = "snake_case")] +#[serde(rename_all = "snake_case")] #[serde(deny_unknown_fields)] pub enum DataStoreConfig { Sqlite(SqliteDataStoreConfig), } #[derive(Debug, Deserialize, Serialize)] -#[serde(tag = "backend", rename_all = "snake_case")] +#[serde(rename_all = "snake_case")] #[serde(deny_unknown_fields)] pub enum AuthConfig { Toml(TomlUserStoreConfig), diff --git a/src/main.rs b/src/main.rs index 4b6a541..3c0dea0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ use app::make_app; use clap::{Parser, Subcommand}; use commands::{cmd_gen_config, cmd_pwhash}; use config::{DataStoreConfig, SqliteDataStoreConfig}; +use figment::providers::{Env, Format, Toml}; +use figment::Figment; use rustical_dav::push::push_notifier; use rustical_nextcloud_login::NextcloudFlows; use rustical_store::auth::TomlPrincipalStore; @@ -14,7 +16,6 @@ use rustical_store_sqlite::addressbook_store::SqliteAddressbookStore; use rustical_store_sqlite::calendar_store::SqliteCalendarStore; use rustical_store_sqlite::{create_db_pool, SqliteStore}; use setup_tracing::setup_tracing; -use std::fs; use std::sync::Arc; use tokio::sync::mpsc::Receiver; @@ -72,11 +73,11 @@ async fn main() -> Result<()> { Some(Command::GenConfig(gen_config_args)) => cmd_gen_config(gen_config_args)?, Some(Command::Pwhash(pwhash_args)) => cmd_pwhash(pwhash_args)?, None => { - let config: Config = toml::from_str( - &fs::read_to_string(&args.config_file).unwrap_or_else(|err| { - panic!("Could not open file at {}: {}", &args.config_file, err) - }), - )?; + let config: Config = Figment::new() + // TODO: What to do when config file does not exist? + .merge(Toml::file(&args.config_file)) + .merge(Env::prefixed("RUSTICAL_").split("__")) + .extract()?; setup_tracing(&config.tracing);