Deny unknown config fields (#5370)

This commit is contained in:
Nutomic 2025-01-29 18:51:10 +00:00 committed by GitHub
parent fb825843dd
commit 2847040b3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 17 deletions

View file

@ -2,7 +2,7 @@ use crate::{error::LemmyResult, location_info};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use deser_hjson::from_str; use deser_hjson::from_str;
use regex::Regex; use regex::Regex;
use std::{env, fs, io::Error, sync::LazyLock}; use std::{env, fs, sync::LazyLock};
use structs::{PictrsConfig, Settings}; use structs::{PictrsConfig, Settings};
use url::Url; use url::Url;
@ -39,7 +39,10 @@ impl Settings {
/// `lemmy_db_schema/src/lib.rs::get_database_url_from_env()` /// `lemmy_db_schema/src/lib.rs::get_database_url_from_env()`
/// Warning: Only call this once. /// Warning: Only call this once.
pub(crate) fn init() -> LemmyResult<Self> { pub(crate) fn init() -> LemmyResult<Self> {
let config = from_str::<Settings>(&Self::read_config_file()?)?; let path =
env::var("LEMMY_CONFIG_LOCATION").unwrap_or_else(|_| DEFAULT_CONFIG_FILE.to_string());
let plain = fs::read_to_string(path)?;
let config = from_str::<Settings>(&plain)?;
if config.hostname == "unset" { if config.hostname == "unset" {
Err(anyhow!("Hostname variable is not set!").into()) Err(anyhow!("Hostname variable is not set!").into())
} else { } else {
@ -55,14 +58,6 @@ impl Settings {
} }
} }
fn get_config_location() -> String {
env::var("LEMMY_CONFIG_LOCATION").unwrap_or_else(|_| DEFAULT_CONFIG_FILE.to_string())
}
fn read_config_file() -> Result<String, Error> {
fs::read_to_string(Self::get_config_location())
}
/// Returns either "http" or "https", depending on tls_enabled setting /// Returns either "http" or "https", depending on tls_enabled setting
pub fn get_protocol_string(&self) -> &'static str { pub fn get_protocol_string(&self) -> &'static str {
if self.tls_enabled { if self.tls_enabled {
@ -109,3 +104,15 @@ impl Settings {
fn pictrs_placeholder_url() -> Url { fn pictrs_placeholder_url() -> Url {
Url::parse("http://localhost:8080").expect("parse pictrs url") Url::parse("http://localhost:8080").expect("parse pictrs url")
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_load_config() -> LemmyResult<()> {
Settings::init()?;
Ok(())
}
}

View file

@ -9,7 +9,7 @@ use std::{
use url::Url; use url::Url;
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
#[serde(default)] #[serde(default, deny_unknown_fields)]
pub struct Settings { pub struct Settings {
/// settings related to the postgresql database /// settings related to the postgresql database
pub database: DatabaseConfig, pub database: DatabaseConfig,
@ -109,7 +109,6 @@ pub struct PictrsConfig {
} }
#[derive(Debug, Deserialize, Serialize, Clone, Default, Document, PartialEq)] #[derive(Debug, Deserialize, Serialize, Clone, Default, Document, PartialEq)]
#[serde(deny_unknown_fields)]
pub enum PictrsImageMode { pub enum PictrsImageMode {
/// Leave images unchanged, don't generate any local thumbnails for post urls. Instead the /// Leave images unchanged, don't generate any local thumbnails for post urls. Instead the
/// Opengraph image is directly returned as thumbnail /// Opengraph image is directly returned as thumbnail
@ -132,7 +131,7 @@ pub enum PictrsImageMode {
} }
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
#[serde(default)] #[serde(default, deny_unknown_fields)]
pub struct DatabaseConfig { pub struct DatabaseConfig {
/// Configure the database by specifying URI pointing to a postgres instance /// Configure the database by specifying URI pointing to a postgres instance
/// ///
@ -153,7 +152,7 @@ pub struct DatabaseConfig {
} }
#[derive(Debug, Deserialize, Serialize, Clone, Document, SmartDefault)] #[derive(Debug, Deserialize, Serialize, Clone, Document, SmartDefault)]
#[serde(deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct EmailConfig { pub struct EmailConfig {
/// Hostname and port of the smtp server /// Hostname and port of the smtp server
#[doku(example = "localhost:25")] #[doku(example = "localhost:25")]
@ -180,7 +179,7 @@ impl EmailConfig {
} }
#[derive(Debug, Deserialize, Serialize, Clone, Default, Document)] #[derive(Debug, Deserialize, Serialize, Clone, Default, Document)]
#[serde(deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct SetupConfig { pub struct SetupConfig {
/// Username for the admin user /// Username for the admin user
#[doku(example = "admin")] #[doku(example = "admin")]
@ -197,7 +196,7 @@ pub struct SetupConfig {
} }
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
#[serde(deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct PrometheusConfig { pub struct PrometheusConfig {
// Address that the Prometheus metrics will be served on. // Address that the Prometheus metrics will be served on.
#[default(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))] #[default(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))]
@ -210,7 +209,7 @@ pub struct PrometheusConfig {
} }
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
#[serde(default)] #[serde(default, deny_unknown_fields)]
// named federation"worker"config to disambiguate from the activitypub library configuration // named federation"worker"config to disambiguate from the activitypub library configuration
pub struct FederationWorkerConfig { pub struct FederationWorkerConfig {
/// Limit to the number of concurrent outgoing federation requests per target instance. /// Limit to the number of concurrent outgoing federation requests per target instance.