diff --git a/Cargo.lock b/Cargo.lock index 6c5adba31..ae76e133f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,6 +1000,26 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31ad93652f40969dead8d4bf897a41e9462095152eb21c56e5830537e41179dd" +[[package]] +name = "doku" +version = "0.9.0" +source = "git+https://github.com/anixe/doku?branch=issue/1#97e58175aa2972c003a8155d6f58aca91a9bfe88" +dependencies = [ + "doku-derive", +] + +[[package]] +name = "doku-derive" +version = "0.9.0" +source = "git+https://github.com/anixe/doku?branch=issue/1#97e58175aa2972c003a8155d6f58aca91a9bfe88" +dependencies = [ + "darling 0.13.0", + "proc-macro-error", + "proc-macro2 1.0.29", + "quote 1.0.9", + "syn 1.0.77", +] + [[package]] name = "either" version = "1.6.1" @@ -1924,6 +1944,7 @@ dependencies = [ "clokwerk", "diesel", "diesel_migrations", + "doku", "env_logger", "http-signature-normalization-actix", "lemmy_api", @@ -1960,6 +1981,7 @@ dependencies = [ "comrak", "deser-hjson", "diesel", + "doku", "futures", "http", "itertools", @@ -2643,6 +2665,30 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.29", + "quote 1.0.9", + "syn 1.0.77", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.29", + "quote 1.0.9", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" diff --git a/Cargo.toml b/Cargo.toml index 199c732ee..4be87c970 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ activitystreams = "0.7.0-alpha.11" actix-rt = { version = "2.2.0", default-features = false } serde_json = { version = "1.0.68", features = ["preserve_order"] } clokwerk = "0.3.5" +doku = { git = "https://github.com/anixe/doku", branch = "issue/1" } [dev-dependencies.cargo-husky] version = "1.5.0" diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index f8e7804ac..7bd99601c 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -39,3 +39,4 @@ deser-hjson = "1.0.2" smart-default = "0.6.0" webpage = { version = "1.3.0", default-features = false, features = ["serde"] } jsonwebtoken = "7.2.0" +doku = { git = "https://github.com/anixe/doku", branch = "issue/1" } diff --git a/crates/utils/src/settings/mod.rs b/crates/utils/src/settings/mod.rs index 7e320701d..6678b91f5 100644 --- a/crates/utils/src/settings/mod.rs +++ b/crates/utils/src/settings/mod.rs @@ -11,6 +11,16 @@ static DEFAULT_CONFIG_FILE: &str = "config/config.hjson"; lazy_static! { static ref SETTINGS: RwLock = RwLock::new(Settings::init().expect("Failed to load settings file")); + static ref WEBFINGER_COMMUNITY_REGEX: Regex = Regex::new(&format!( + "^group:([a-z0-9_]{{3,}})@{}$", + Settings::get().hostname + )) + .expect("compile webfinger regex"); + static ref WEBFINGER_USER_REGEX: Regex = Regex::new(&format!( + "^acct:([a-z0-9_]{{3,}})@{}$", + Settings::get().hostname + )) + .expect("compile webfinger regex"); } impl Settings { @@ -21,22 +31,12 @@ impl Settings { /// Warning: Only call this once. pub fn init() -> Result { // Read the config file - let mut config = from_str::(&Self::read_config_file()?)?; + let config = from_str::(&Self::read_config_file()?)?; if config.hostname == "unset" { return Err(anyhow!("Hostname variable is not set!").into()); } - // Initialize the regexes - config.webfinger_community_regex = Some( - Regex::new(&format!("^group:([a-z0-9_]{{3,}})@{}$", config.hostname)) - .expect("compile webfinger regex"), - ); - config.webfinger_username_regex = Some( - Regex::new(&format!("^acct:([a-z0-9_]{{3,}})@{}$", config.hostname)) - .expect("compile webfinger regex"), - ); - Ok(config) } @@ -106,17 +106,11 @@ impl Settings { } pub fn webfinger_community_regex(&self) -> Regex { - self - .webfinger_community_regex - .to_owned() - .expect("compile webfinger regex") + WEBFINGER_COMMUNITY_REGEX.to_owned() } pub fn webfinger_username_regex(&self) -> Regex { - self - .webfinger_username_regex - .to_owned() - .expect("compile webfinger regex") + WEBFINGER_USER_REGEX.to_owned() } pub fn slur_regex(&self) -> Regex { diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index 293349348..823c40dee 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -1,8 +1,8 @@ -use regex::Regex; +use doku::prelude::*; use serde::Deserialize; use std::net::{IpAddr, Ipv4Addr}; -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] #[serde(default)] pub struct Settings { #[serde(default)] @@ -18,28 +18,25 @@ pub struct Settings { #[default(None)] pub setup: Option, #[default("unset")] + #[doku(example = "example.com")] pub hostname: String, #[default(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))] + #[doku(as = "String")] pub bind: IpAddr, #[default(8536)] pub port: u16, #[default(true)] pub tls_enabled: bool, #[default(None)] + #[doku(example = "http://localhost:8080")] pub pictrs_url: Option, #[default(None)] pub additional_slurs: Option, #[default(20)] pub actor_name_max_length: usize, - #[default(None)] - #[serde(skip)] - pub webfinger_community_regex: Option, - #[default(None)] - #[serde(skip)] - pub webfinger_username_regex: Option, } -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] #[serde(default)] pub struct CaptchaConfig { #[default(false)] @@ -48,7 +45,7 @@ pub struct CaptchaConfig { pub difficulty: String, } -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] #[serde(default)] pub struct DatabaseConfig { #[default("lemmy")] @@ -65,16 +62,18 @@ pub struct DatabaseConfig { pub pool_size: u32, } -#[derive(Debug, Deserialize, Clone)] +#[derive(Debug, Deserialize, Clone, Doku)] pub struct EmailConfig { + #[doku(example = "localhost:25")] pub smtp_server: String, pub smtp_login: Option, pub smtp_password: Option, + #[doku(example = "noreply@example.com")] pub smtp_from_address: String, pub use_tls: bool, } -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] #[serde(default)] pub struct FederationConfig { #[default(false)] @@ -87,7 +86,7 @@ pub struct FederationConfig { pub strict_allowlist: bool, } -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] #[serde(default)] pub struct RateLimitConfig { #[default(180)] @@ -108,10 +107,13 @@ pub struct RateLimitConfig { pub image_per_second: i32, } -#[derive(Debug, Deserialize, Clone, SmartDefault)] +#[derive(Debug, Deserialize, Clone, SmartDefault, Doku)] pub struct SetupConfig { + #[doku(example = "admin")] pub admin_username: String, + #[doku(example = "my_passwd")] pub admin_password: String, + #[doku(example = "My Lemmy Instance")] pub site_name: String, #[default(None)] pub admin_email: Option, diff --git a/src/main.rs b/src/main.rs index 7d49e32ba..91225b70f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,13 +23,19 @@ use lemmy_utils::{ }; use lemmy_websocket::{chat_server::ChatServer, LemmyContext}; use reqwest::Client; -use std::{sync::Arc, thread}; +use std::{env, sync::Arc, thread}; use tokio::sync::Mutex; embed_migrations!(); #[actix_web::main] async fn main() -> Result<(), LemmyError> { + let args: Vec = env::args().collect(); + if args.len() == 2 && args[1] == "--print-config-docs" { + println!("{}", doku::to_json_val(&Settings::default())); + return Ok(()); + } + env_logger::init(); let settings = Settings::init().expect("Couldn't initialize settings.");