From 545baa1c367e763a1c26232e94fbc08756e401fd Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Sun, 9 Mar 2025 07:07:55 -0500 Subject: [PATCH] Use Rocket's Figment for configuration Instead of reading our own TOML file for configuration, we can hook into Rocket's [built-in configuration system][0]. Although it doesn't matter much right now, it may if we end up using Rocket's SQL [database integration][1], because it uses the same mechanism. Without making this change, we would end up with two configuration files in that case. [0]: https://rocket.rs/guide/v0.5/configuration/#extracting-values [1]: https://rocket.rs/guide/v0.5/state/#databases --- .gitignore | 2 +- Cargo.lock | 1 - Cargo.toml | 1 - Containerfile | 2 +- src/config.rs | 17 +---------------- src/main.rs | 24 ++++++++++-------------- 6 files changed, 13 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index fc2da41..43665b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/config.toml +/Rocket.toml /firefly.token /target diff --git a/Cargo.lock b/Cargo.lock index 22d4066..1040768 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1645,7 +1645,6 @@ dependencies = [ "rocket_dyn_templates", "serde", "thiserror", - "toml", "tracing", "tracing-subscriber", ] diff --git a/Cargo.toml b/Cargo.toml index 84a734b..3ae29fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,5 @@ rocket = { version = "0.5.1", default-features = false, features = ["json"] } rocket_dyn_templates = { version = "0.2.0", features = ["tera"] } serde = { version = "1.0.218", default-features = false, features = ["derive"] } thiserror = "2.0.12" -toml = "0.8.20" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } diff --git a/Containerfile b/Containerfile index ed5efd1..eda3ad3 100644 --- a/Containerfile +++ b/Containerfile @@ -46,4 +46,4 @@ WORKDIR /usr/local/share/receipts ENTRYPOINT ["/usr/local/bin/receipts"] -CMD ["/etc/receipts/config.toml"] +ENV ROCKET_CONFIG=/etc/receipts/config.toml diff --git a/src/config.rs b/src/config.rs index 37a58c1..4ade9a8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,15 +1,7 @@ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use serde::Deserialize; -#[derive(Debug, thiserror::Error)] -pub enum ConfigError { - #[error("Unable to load file: {0}")] - Io(#[from] std::io::Error), - #[error("Error parsing file: {0}")] - Toml(#[from] toml::de::Error), -} - #[derive(Debug, Deserialize)] pub struct FireflyConfig { pub url: String, @@ -21,10 +13,3 @@ pub struct FireflyConfig { pub struct Config { pub firefly: FireflyConfig, } - -impl Config { - pub fn from_file(path: impl AsRef) -> Result { - let data = std::fs::read_to_string(path)?; - Ok(toml::from_str(&data)?) - } -} diff --git a/src/main.rs b/src/main.rs index 9ca96b4..4883d97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,6 @@ mod config; mod firefly; -use std::path::{Path, PathBuf}; - use rocket::form::Form; use rocket::fs::{FileServer, TempFile}; use rocket::http::Status; @@ -13,7 +11,7 @@ use rocket_dyn_templates::{context, Template}; use serde::Serialize; use tracing::{debug, error}; -use config::{Config, ConfigError}; +use config::Config; use firefly::{ Firefly, TransactionRead, TransactionSplitUpdate, TransactionUpdate, }; @@ -27,14 +25,13 @@ struct Context { #[derive(Debug, thiserror::Error)] enum InitError { #[error("Invalid config: {0}")] - Config(#[from] ConfigError), + Config(std::io::Error), } impl Context { - pub fn init(config: impl AsRef) -> Result { - let config = Config::from_file(config)?; + pub fn init(config: Config) -> Result { let token = std::fs::read_to_string(&config.firefly.token) - .map_err(ConfigError::from)?; + .map_err(InitError::Config)?; let firefly = Firefly::new(&config.firefly.url, &token); Ok(Self { config, firefly }) } @@ -233,13 +230,12 @@ async fn rocket() -> _ { .with_writer(std::io::stderr) .init(); - let cfg_path = match std::env::args_os().nth(1) { - Some(f) => PathBuf::from(f), - None => PathBuf::from("config.toml"), - }; - debug!("Using configuration file {}", cfg_path.display()); + let rocket = rocket::build(); + let figment = rocket.figment(); - let ctx = match Context::init(cfg_path) { + let config: Config = figment.extract().unwrap(); + + let ctx = match Context::init(config) { Ok(c) => c, Err(e) => { error!("Failed to initialize application context: {}", e); @@ -248,7 +244,7 @@ async fn rocket() -> _ { }; debug!("Using Firefly III URL {}", &ctx.firefly.url()); - rocket::build() + rocket .manage(ctx) .mount( "/",