diff --git a/.gitignore b/.gitignore index a727c0a..8a0f2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /data +/wkd.toml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e95f9c8..a37bf5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1902,6 +1902,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1956,6 +1965,7 @@ version = "0.1.0" dependencies = [ "actix-web", "chrono", + "once_cell", "rand 0.8.5", "sequoia-net", "sequoia-openpgp", @@ -1963,6 +1973,7 @@ dependencies = [ "serde_json", "thiserror", "tokio", + "toml", ] [[package]] @@ -2200,6 +2211,40 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -2648,6 +2693,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 7725023..44b28e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] actix-web = "4.3.1" chrono = "0.4.24" +once_cell = "1.17.1" rand = "0.8.5" sequoia-net = "0.27.0" sequoia-openpgp = "1.14.0" @@ -15,3 +16,4 @@ serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0.96" thiserror = "1.0.40" tokio = { version = "1.27.0", features = ["time"] } +toml = "0.7.3" diff --git a/src/confirmation.rs b/src/confirmation.rs index 2563cd0..a2a58fc 100644 --- a/src/confirmation.rs +++ b/src/confirmation.rs @@ -1,8 +1,8 @@ use crate::errors::Error; use crate::management::{delete_key, Action, Pending}; +use crate::pending_path; +use crate::settings::SETTINGS; use crate::utils::{get_email_from_cert, parse_pem}; -use crate::PENDING; -use crate::{pending_path, PATH, VARIANT}; use std::fs; use std::path::Path; @@ -28,7 +28,12 @@ pub fn confirm_action(token: &str) -> Result<(), Error> { Some(domain) => domain.to_string(), None => return Err(Error::ParseEmail), }; - match sequoia_net::wkd::insert(PATH, domain, VARIANT, &cert) { + match sequoia_net::wkd::insert( + &SETTINGS.folder_structure.root_folder, + domain, + SETTINGS.variant, + &cert, + ) { Ok(_) => (), Err(_) => return Err(Error::AddingKey), } diff --git a/src/main.rs b/src/main.rs index e621786..f018c10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ mod confirmation; mod errors; mod management; +mod settings; mod utils; +use crate::settings::SETTINGS; use crate::utils::key_exists; use self::confirmation::{confirm_action, send_confirmation_email}; @@ -10,18 +12,11 @@ use self::management::{clean_stale, store_pending_addition, store_pending_deleti use self::utils::{gen_random_token, get_email_from_cert, parse_pem}; use actix_web::{get, post, web, App, HttpServer, Result}; -use sequoia_net::wkd::Variant; use serde::Deserialize; use std::fs; use std::path::Path; use tokio::{task, time}; -const PATH: &str = "data"; -const PENDING: &str = "pending"; -const MAX_AGE: i64 = 0; -const VARIANT: Variant = Variant::Advanced; -const PORT: u16 = 8080; - #[derive(Deserialize, Debug)] struct Pem { key: String, @@ -44,11 +39,11 @@ async fn main() -> std::io::Result<()> { let mut metronome = time::interval(time::Duration::from_secs(60 * 60 * 3)); loop { metronome.tick().await; - clean_stale(MAX_AGE).unwrap(); + clean_stale(SETTINGS.max_age).unwrap(); } }); HttpServer::new(|| App::new().service(submit).service(confirm).service(delete)) - .bind(("127.0.0.1", PORT))? + .bind(("127.0.0.1", SETTINGS.port))? .run() .await } diff --git a/src/management.rs b/src/management.rs index 4fdc292..676dcd9 100644 --- a/src/management.rs +++ b/src/management.rs @@ -1,7 +1,7 @@ use crate::errors::Error; +use crate::pending_path; +use crate::settings::SETTINGS; use crate::utils::get_user_file_path; -use crate::PENDING; -use crate::{pending_path, PATH}; use chrono::Utc; use serde::{Deserialize, Serialize}; @@ -95,7 +95,7 @@ pub fn clean_stale(max_age: i64) -> Result<(), Error> { } pub fn delete_key(email: &str) -> Result<(), Error> { - let path = Path::new(PATH).join(get_user_file_path(email)?); + let path = Path::new(&SETTINGS.folder_structure.root_folder).join(get_user_file_path(email)?); match fs::remove_file(path) { Ok(_) => Ok(()), Err(_) => Err(Error::Inaccessible), diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..dde4194 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,45 @@ +use std::fs; + +use once_cell::sync::Lazy; +use sequoia_net::wkd::Variant; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Settings { + #[serde(with = "VariantDef")] + pub variant: Variant, + pub max_age: i64, + pub port: u16, + pub folder_structure: FolderStructure, + pub smtp_settings: MailSettings, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct FolderStructure { + pub root_folder: String, + pub pending_folder: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct MailSettings { + pub smtp_host: String, + pub smtp_username: String, + pub smtp_password: String, + pub smtp_port: u16, + pub mail_from: String, + pub mail_subject: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(remote = "Variant")] +pub enum VariantDef { + Advanced, + Direct, +} + +fn get_settings() -> Settings { + let content = fs::read_to_string("wkd.toml").unwrap(); + toml::from_str(&content).unwrap() +} + +pub static SETTINGS: Lazy = Lazy::new(get_settings); diff --git a/src/utils.rs b/src/utils.rs index 7059d0f..f71a9ea 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,5 @@ use crate::errors::Error; -use crate::{PATH, PENDING, VARIANT}; +use crate::settings::SETTINGS; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use sequoia_net::wkd::Url; @@ -9,7 +9,8 @@ use std::path::{Path, PathBuf}; #[macro_export] macro_rules! pending_path { () => { - Path::new(PATH).join(PENDING) + Path::new(&SETTINGS.folder_structure.root_folder) + .join(&SETTINGS.folder_structure.pending_folder) }; } @@ -45,7 +46,7 @@ pub fn get_user_file_path(email: &str) -> Result { Ok(wkd_url) => wkd_url, Err(_) => return Err(Error::PathGeneration), }; - match wkd_url.to_file_path(VARIANT) { + match wkd_url.to_file_path(SETTINGS.variant) { Ok(path) => Ok(path), Err(_) => Err(Error::PathGeneration), }