diff --git a/share/default/config/index.container.mysql.toml b/share/default/config/index.container.mysql.toml index 7bd934a4..3ca737b2 100644 --- a/share/default/config/index.container.mysql.toml +++ b/share/default/config/index.container.mysql.toml @@ -4,48 +4,9 @@ log_level = "info" -[website] -name = "Torrust" - -[tracker] -url = "udp://tracker:6969" -mode = "Public" -api_url = "http://tracker:1212" -token = "MyAccessToken" -token_valid_seconds = 7257600 - -[net] -port = 3001 - -[auth] -email_on_signup = "Optional" -min_password_length = 6 -max_password_length = 64 -secret_key = "MaxVerstappenWC2021" - [database] connect_url = "mysql://root:root_secret_password@mysql:3306/torrust_index" [mail] -email_verification_enabled = false -from = "example@email.com" -reply_to = "noreply@email.com" -username = "" -password = "" -server = "mailcatcher" port = 1025 - -[image_cache] -max_request_timeout_ms = 1000 -capacity = 128000000 -entry_size_limit = 4000000 -user_quota_period_seconds = 3600 -user_quota_bytes = 64000000 - -[api] -default_torrent_page_size = 10 -max_torrent_page_size = 30 - -[tracker_statistics_importer] -torrent_info_update_interval = 3600 -port = 3002 \ No newline at end of file +server = "mailcatcher" diff --git a/share/default/config/index.container.sqlite3.toml b/share/default/config/index.container.sqlite3.toml index 77d06a93..95e0c600 100644 --- a/share/default/config/index.container.sqlite3.toml +++ b/share/default/config/index.container.sqlite3.toml @@ -1,51 +1,12 @@ -log_level = "info" - -[website] -name = "Torrust" - -# Please override the tracker token setting the -# `TORRUST_INDEX_CONFIG_OVERRIDE_TRACKER__TOKEN` -# environmental variable! +# Please override the following settings with environmental variable! +# tracker::token -> `TORRUST_INDEX_CONFIG_OVERRIDE_TRACKER__TOKEN` +# auth::secret_key -> `TORRUST_INDEX_CONFIG_OVERRIDE_AUTH__SECRET_KEY` -[tracker] -url = "udp://tracker:6969" -mode = "Public" -api_url = "http://tracker:1212" -token = "MyAccessToken" -token_valid_seconds = 7257600 - -[net] -port = 3001 - -[auth] -email_on_signup = "Optional" -min_password_length = 6 -max_password_length = 64 -secret_key = "MaxVerstappenWC2021" +log_level = "info" [database] connect_url = "sqlite:///var/lib/torrust/index/database/sqlite3.db?mode=rwc" [mail] -email_verification_enabled = false -from = "example@email.com" -reply_to = "noreply@email.com" -username = "" -password = "" -server = "mailcatcher" port = 1025 - -[image_cache] -max_request_timeout_ms = 1000 -capacity = 128000000 -entry_size_limit = 4000000 -user_quota_period_seconds = 3600 -user_quota_bytes = 64000000 - -[api] -default_torrent_page_size = 10 -max_torrent_page_size = 30 - -[tracker_statistics_importer] -torrent_info_update_interval = 3600 -port = 3002 \ No newline at end of file +server = "mailcatcher" diff --git a/share/default/config/index.development.sqlite3.toml b/share/default/config/index.development.sqlite3.toml index c0b04253..8cafd3ea 100644 --- a/share/default/config/index.development.sqlite3.toml +++ b/share/default/config/index.development.sqlite3.toml @@ -1,52 +1,10 @@ -log_level = "info" - -[website] -name = "Torrust" - -[tracker] -api_url = "http://localhost:1212/" -mode = "Public" -token = "MyAccessToken" -token_valid_seconds = 7257600 -url = "udp://localhost:6969" +# Please override the following settings with environmental variable! +# tracker::token -> `TORRUST_INDEX_CONFIG_OVERRIDE_TRACKER__TOKEN` +# auth::secret_key -> `TORRUST_INDEX_CONFIG_OVERRIDE_AUTH__SECRET_KEY` -[net] -port = 3001 +log_level = "info" # Uncomment if you want to enable TSL for development #[net.tsl] #ssl_cert_path = "./storage/index/lib/tls/localhost.crt" #ssl_key_path = "./storage/index/lib/tls/localhost.key" - -[auth] -email_on_signup = "Optional" -max_password_length = 64 -min_password_length = 6 -secret_key = "MaxVerstappenWC2021" - -[database] -connect_url = "sqlite://data.db?mode=rwc" - -[mail] -email_verification_enabled = false -from = "example@email.com" -password = "" -port = 25 -reply_to = "noreply@email.com" -server = "" -username = "" - -[image_cache] -capacity = 128000000 -entry_size_limit = 4000000 -max_request_timeout_ms = 1000 -user_quota_bytes = 64000000 -user_quota_period_seconds = 3600 - -[api] -default_torrent_page_size = 10 -max_torrent_page_size = 30 - -[tracker_statistics_importer] -port = 3002 -torrent_info_update_interval = 3600 diff --git a/share/default/config/index.e2e.container.mysql.toml b/share/default/config/index.e2e.container.mysql.toml index beabe832..037bdcff 100644 --- a/share/default/config/index.e2e.container.mysql.toml +++ b/share/default/config/index.e2e.container.mysql.toml @@ -4,48 +4,13 @@ log_level = "info" -[website] -name = "Torrust" - [tracker] -url = "udp://tracker:6969" -mode = "Public" api_url = "http://tracker:1212" -token = "MyAccessToken" -token_valid_seconds = 7257600 - -[net] -port = 3001 - -[auth] -email_on_signup = "Optional" -min_password_length = 6 -max_password_length = 64 -secret_key = "MaxVerstappenWC2021" +url = "udp://tracker:6969" [database] connect_url = "mysql://root:root_secret_password@mysql:3306/torrust_index_e2e_testing" [mail] -email_verification_enabled = false -from = "example@email.com" -reply_to = "noreply@email.com" -username = "" -password = "" -server = "mailcatcher" port = 1025 - -[image_cache] -max_request_timeout_ms = 1000 -capacity = 128000000 -entry_size_limit = 4000000 -user_quota_period_seconds = 3600 -user_quota_bytes = 64000000 - -[api] -default_torrent_page_size = 10 -max_torrent_page_size = 30 - -[tracker_statistics_importer] -torrent_info_update_interval = 3600 -port = 3002 \ No newline at end of file +server = "mailcatcher" diff --git a/share/default/config/index.e2e.container.sqlite3.toml b/share/default/config/index.e2e.container.sqlite3.toml index e3409ac4..ca6d1944 100644 --- a/share/default/config/index.e2e.container.sqlite3.toml +++ b/share/default/config/index.e2e.container.sqlite3.toml @@ -4,48 +4,13 @@ log_level = "info" -[website] -name = "Torrust" - [tracker] -url = "udp://tracker:6969" -mode = "Public" api_url = "http://tracker:1212" -token = "MyAccessToken" -token_valid_seconds = 7257600 - -[net] -port = 3001 - -[auth] -email_on_signup = "Optional" -min_password_length = 6 -max_password_length = 64 -secret_key = "MaxVerstappenWC2021" +url = "udp://tracker:6969" [database] connect_url = "sqlite:///var/lib/torrust/index/database/e2e_testing_sqlite3.db?mode=rwc" [mail] -email_verification_enabled = false -from = "example@email.com" -reply_to = "noreply@email.com" -username = "" -password = "" -server = "mailcatcher" port = 1025 - -[image_cache] -max_request_timeout_ms = 1000 -capacity = 128000000 -entry_size_limit = 4000000 -user_quota_period_seconds = 3600 -user_quota_bytes = 64000000 - -[api] -default_torrent_page_size = 10 -max_torrent_page_size = 30 - -[tracker_statistics_importer] -torrent_info_update_interval = 3600 -port = 3002 \ No newline at end of file +server = "mailcatcher" diff --git a/src/config/v1/api.rs b/src/config/v1/api.rs index 70f3ddab..4b4db9fd 100644 --- a/src/config/v1/api.rs +++ b/src/config/v1/api.rs @@ -4,16 +4,28 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Api { /// The default page size for torrent lists. + #[serde(default = "Api::default_default_torrent_page_size")] pub default_torrent_page_size: u8, /// The maximum page size for torrent lists. + #[serde(default = "Api::default_max_torrent_page_size")] pub max_torrent_page_size: u8, } impl Default for Api { fn default() -> Self { Self { - default_torrent_page_size: 10, - max_torrent_page_size: 30, + default_torrent_page_size: Api::default_default_torrent_page_size(), + max_torrent_page_size: Api::default_max_torrent_page_size(), } } } + +impl Api { + fn default_default_torrent_page_size() -> u8 { + 10 + } + + fn default_max_torrent_page_size() -> u8 { + 30 + } +} diff --git a/src/config/v1/auth.rs b/src/config/v1/auth.rs index b23c536d..6b7f0786 100644 --- a/src/config/v1/auth.rs +++ b/src/config/v1/auth.rs @@ -6,12 +6,16 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Auth { /// Whether or not to require an email on signup. + #[serde(default = "EmailOnSignup::default")] pub email_on_signup: EmailOnSignup, /// The minimum password length. + #[serde(default = "Auth::default_min_password_length")] pub min_password_length: usize, /// The maximum password length. + #[serde(default = "Auth::default_max_password_length")] pub max_password_length: usize, /// The secret key used to sign JWT tokens. + #[serde(default = "Auth::default_secret_key")] pub secret_key: SecretKey, } @@ -19,9 +23,9 @@ impl Default for Auth { fn default() -> Self { Self { email_on_signup: EmailOnSignup::default(), - min_password_length: 6, - max_password_length: 64, - secret_key: SecretKey::new("MaxVerstappenWC2021"), + min_password_length: Self::default_min_password_length(), + max_password_length: Self::default_max_password_length(), + secret_key: Self::default_secret_key(), } } } @@ -30,6 +34,18 @@ impl Auth { pub fn override_secret_key(&mut self, secret_key: &str) { self.secret_key = SecretKey::new(secret_key); } + + fn default_min_password_length() -> usize { + 6 + } + + fn default_max_password_length() -> usize { + 64 + } + + fn default_secret_key() -> SecretKey { + SecretKey::new("MaxVerstappenWC2021") + } } /// Whether the email is required on signup or not. diff --git a/src/config/v1/database.rs b/src/config/v1/database.rs index 5efa824a..7dfd5a31 100644 --- a/src/config/v1/database.rs +++ b/src/config/v1/database.rs @@ -8,13 +8,20 @@ pub struct Database { /// /// Sqlite: `sqlite://data.db?mode=rwc`. /// Mysql: `mysql://root:root_secret_password@mysql:3306/torrust_index_e2e_testing`. + #[serde(default = "Database::default_connect_url")] pub connect_url: Url, } impl Default for Database { fn default() -> Self { Self { - connect_url: Url::parse("sqlite://data.db?mode=rwc").unwrap(), + connect_url: Self::default_connect_url(), } } } + +impl Database { + fn default_connect_url() -> Url { + Url::parse("sqlite://data.db?mode=rwc").unwrap() + } +} diff --git a/src/config/v1/image_cache.rs b/src/config/v1/image_cache.rs index 4f2990b0..88c5ebec 100644 --- a/src/config/v1/image_cache.rs +++ b/src/config/v1/image_cache.rs @@ -11,27 +11,54 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct ImageCache { /// Maximum time in seconds to wait for downloading the image form the original source. + #[serde(default = "ImageCache::default_max_request_timeout_ms")] pub max_request_timeout_ms: u64, /// Cache size in bytes. + #[serde(default = "ImageCache::default_capacity")] pub capacity: usize, /// Maximum size in bytes for a single image. + #[serde(default = "ImageCache::default_entry_size_limit")] pub entry_size_limit: usize, /// Users have a cache quota per period. For example: 100MB per day. /// This is the period in seconds (1 day in seconds). + #[serde(default = "ImageCache::default_user_quota_period_seconds")] pub user_quota_period_seconds: u64, /// Users have a cache quota per period. For example: 100MB per day. /// This is the maximum size in bytes (100MB in bytes). + #[serde(default = "ImageCache::default_user_quota_bytes")] pub user_quota_bytes: usize, } impl Default for ImageCache { fn default() -> Self { Self { - max_request_timeout_ms: 1000, - capacity: 128_000_000, - entry_size_limit: 4_000_000, - user_quota_period_seconds: 3600, - user_quota_bytes: 64_000_000, + max_request_timeout_ms: Self::default_max_request_timeout_ms(), + capacity: Self::default_capacity(), + entry_size_limit: Self::default_entry_size_limit(), + user_quota_period_seconds: Self::default_user_quota_period_seconds(), + user_quota_bytes: Self::default_user_quota_bytes(), } } } + +impl ImageCache { + fn default_max_request_timeout_ms() -> u64 { + 1000 + } + + fn default_capacity() -> usize { + 128_000_000 + } + + fn default_entry_size_limit() -> usize { + 4_000_000 + } + + fn default_user_quota_period_seconds() -> u64 { + 3600 + } + + fn default_user_quota_bytes() -> usize { + 64_000_000 + } +} diff --git a/src/config/v1/mail.rs b/src/config/v1/mail.rs index 45ed6145..885a4383 100644 --- a/src/config/v1/mail.rs +++ b/src/config/v1/mail.rs @@ -5,31 +5,68 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Mail { /// Whether or not to enable email verification on signup. + #[serde(default = "Mail::default_email_verification_enabled")] pub email_verification_enabled: bool, /// The email address to send emails from. + #[serde(default = "Mail::default_from")] pub from: Mailbox, /// The email address to reply to. + #[serde(default = "Mail::default_reply_to")] pub reply_to: Mailbox, /// The username to use for SMTP authentication. + #[serde(default = "Mail::default_username")] pub username: String, /// The password to use for SMTP authentication. + #[serde(default = "Mail::default_password")] pub password: String, /// The SMTP server to use. + #[serde(default = "Mail::default_server")] pub server: String, /// The SMTP port to use. + #[serde(default = "Mail::default_port")] pub port: u16, } impl Default for Mail { fn default() -> Self { Self { - email_verification_enabled: false, - from: "example@email.com".parse().expect("valid mailbox"), - reply_to: "noreply@email.com".parse().expect("valid mailbox"), - username: String::default(), - password: String::default(), - server: String::default(), - port: 25, + email_verification_enabled: Self::default_email_verification_enabled(), + from: Self::default_from(), + reply_to: Self::default_reply_to(), + username: Self::default_username(), + password: Self::default_password(), + server: Self::default_server(), + port: Self::default_port(), } } } + +impl Mail { + fn default_email_verification_enabled() -> bool { + false + } + + fn default_from() -> Mailbox { + "example@email.com".parse().expect("valid mailbox") + } + + fn default_reply_to() -> Mailbox { + "noreply@email.com".parse().expect("valid mailbox") + } + + fn default_username() -> String { + String::default() + } + + fn default_password() -> String { + String::default() + } + + fn default_server() -> String { + String::default() + } + + fn default_port() -> u16 { + 25 + } +} diff --git a/src/config/v1/mod.rs b/src/config/v1/mod.rs index f5e95bc1..fa51a8f5 100644 --- a/src/config/v1/mod.rs +++ b/src/config/v1/mod.rs @@ -26,24 +26,34 @@ use super::validator::{ValidationError, Validator}; pub struct Settings { /// Logging level. Possible values are: `Off`, `Error`, `Warn`, `Info`, /// `Debug` and `Trace`. Default is `Info`. + #[serde(default)] pub log_level: Option, /// The website customizable values. + #[serde(default)] pub website: Website, /// The tracker configuration. + #[serde(default)] pub tracker: Tracker, /// The network configuration. + #[serde(default)] pub net: Network, /// The authentication configuration. + #[serde(default)] pub auth: Auth, /// The database configuration. + #[serde(default)] pub database: Database, /// The SMTP configuration. + #[serde(default)] pub mail: Mail, /// The image proxy cache configuration. + #[serde(default)] pub image_cache: ImageCache, /// The API configuration. + #[serde(default)] pub api: Api, /// The tracker statistics importer job configuration. + #[serde(default)] pub tracker_statistics_importer: TrackerStatisticsImporter, } diff --git a/src/config/v1/net.rs b/src/config/v1/net.rs index 28b101fc..4c1552a2 100644 --- a/src/config/v1/net.rs +++ b/src/config/v1/net.rs @@ -12,20 +12,37 @@ use crate::config::Tsl; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Network { /// The port to listen on. Default to `3001`. + #[serde(default = "Network::default_port")] pub port: u16, /// The base URL for the API. For example: `http://localhost`. /// If not set, the base URL will be inferred from the request. + #[serde(default = "Network::default_base_url")] pub base_url: Option, /// TSL configuration. + #[serde(default = "Network::default_tsl")] pub tsl: Option, } impl Default for Network { fn default() -> Self { Self { - port: 3001, - base_url: None, - tsl: None, + port: Self::default_port(), + base_url: Self::default_base_url(), + tsl: Self::default_tsl(), } } } + +impl Network { + fn default_port() -> u16 { + 3001 + } + + fn default_base_url() -> Option { + None + } + + fn default_tsl() -> Option { + None + } +} diff --git a/src/config/v1/tracker.rs b/src/config/v1/tracker.rs index bc8a2eb0..67c31bfe 100644 --- a/src/config/v1/tracker.rs +++ b/src/config/v1/tracker.rs @@ -10,25 +10,24 @@ use crate::config::TrackerMode; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Tracker { /// Connection string for the tracker. For example: `udp://TRACKER_IP:6969`. + #[serde(default = "Tracker::default_url")] pub url: Url, /// The mode of the tracker. For example: `Public`. /// See `TrackerMode` in [`torrust-tracker-primitives`](https://docs.rs/torrust-tracker-primitives) /// crate for more information. + #[serde(default = "Tracker::default_mode")] pub mode: TrackerMode, /// The url of the tracker API. For example: `http://localhost:1212/`. + #[serde(default = "Tracker::default_api_url")] pub api_url: Url, /// The token used to authenticate with the tracker API. + #[serde(default = "Tracker::default_token")] pub token: ApiToken, /// The amount of seconds the tracker API token is valid. + #[serde(default = "Tracker::default_token_valid_seconds")] pub token_valid_seconds: u64, } -impl Tracker { - pub fn override_tracker_api_token(&mut self, tracker_api_token: &ApiToken) { - self.token = tracker_api_token.clone(); - } -} - impl Validator for Tracker { fn validate(&self) -> Result<(), ValidationError> { let tracker_mode = self.mode.clone(); @@ -45,15 +44,41 @@ impl Validator for Tracker { impl Default for Tracker { fn default() -> Self { Self { - url: Url::parse("udp://localhost:6969").unwrap(), - mode: TrackerMode::default(), - api_url: Url::parse("http://localhost:1212/").unwrap(), - token: ApiToken::new("MyAccessToken"), - token_valid_seconds: 7_257_600, + url: Self::default_url(), + mode: Self::default_mode(), + api_url: Self::default_api_url(), + token: Self::default_token(), + token_valid_seconds: Self::default_token_valid_seconds(), } } } +impl Tracker { + pub fn override_tracker_api_token(&mut self, tracker_api_token: &ApiToken) { + self.token = tracker_api_token.clone(); + } + + fn default_url() -> Url { + Url::parse("udp://localhost:6969").unwrap() + } + + fn default_mode() -> TrackerMode { + TrackerMode::default() + } + + fn default_api_url() -> Url { + Url::parse("http://localhost:1212/").unwrap() + } + + fn default_token() -> ApiToken { + ApiToken::new("MyAccessToken") + } + + fn default_token_valid_seconds() -> u64 { + 7_257_600 + } +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct ApiToken(String); diff --git a/src/config/v1/tracker_statistics_importer.rs b/src/config/v1/tracker_statistics_importer.rs index 9c43a4a4..531629b1 100644 --- a/src/config/v1/tracker_statistics_importer.rs +++ b/src/config/v1/tracker_statistics_importer.rs @@ -4,16 +4,28 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TrackerStatisticsImporter { /// The interval in seconds to get statistics from the tracker. + #[serde(default = "TrackerStatisticsImporter::default_torrent_info_update_interval")] pub torrent_info_update_interval: u64, /// The port the Importer API is listening on. Default to `3002`. + #[serde(default = "TrackerStatisticsImporter::default_port")] pub port: u16, } impl Default for TrackerStatisticsImporter { fn default() -> Self { Self { - torrent_info_update_interval: 3600, - port: 3002, + torrent_info_update_interval: Self::default_torrent_info_update_interval(), + port: Self::default_port(), } } } + +impl TrackerStatisticsImporter { + fn default_torrent_info_update_interval() -> u64 { + 3600 + } + + fn default_port() -> u16 { + 3002 + } +} diff --git a/src/config/v1/website.rs b/src/config/v1/website.rs index a7a6fbef..489ce265 100644 --- a/src/config/v1/website.rs +++ b/src/config/v1/website.rs @@ -4,13 +4,20 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Website { /// The name of the website. + #[serde(default = "Website::default_name")] pub name: String, } impl Default for Website { fn default() -> Self { Self { - name: "Torrust".to_string(), + name: Self::default_name(), } } } + +impl Website { + fn default_name() -> String { + "Torrust".to_string() + } +}