diff --git a/Cargo.lock b/Cargo.lock index ea7fdca3..f6421fad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "activitystreams" version = "0.7.0-alpha.10" @@ -1101,6 +1103,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + [[package]] name = "event-listener" version = "2.5.1" @@ -1953,6 +1964,7 @@ dependencies = [ "comrak", "deser-hjson", "diesel", + "envy", "futures", "http", "itertools", @@ -1960,7 +1972,6 @@ dependencies = [ "lazy_static", "lettre", "log", - "merge", "openssl", "percent-encoding", "rand 0.8.3", @@ -2113,28 +2124,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "merge" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9" -dependencies = [ - "merge_derive", - "num-traits", -] - -[[package]] -name = "merge_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "migrations_internals" version = "1.4.1" @@ -2568,30 +2557,6 @@ dependencies = [ "vcpkg", ] -[[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", - "quote", - "syn", - "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", - "quote", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.19" diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index 32eb7513..de9b7b84 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -1,6 +1,13 @@ #!/bin/bash set -e +export LEMMY_JWT_SECRET=changeme +export LEMMY_FEDERATION__ENABLED=true +export LEMMY_TLS_ENABLED=false +export LEMMY_SETUP__ADMIN_PASSWORD=lemmy +export LEMMY_RATE_LIMIT__POST=99999 +export LEMMY_RATE_LIMIT__REGISTER=99999 +export LEMMY_CAPTCHA__ENABLED=false export LEMMY_TEST_SEND_SYNC=1 export RUST_BACKTRACE=1 @@ -28,39 +35,52 @@ fi killall lemmy_server || true -echo "$PWD" - echo "start alpha" LEMMY_HOSTNAME=lemmy-alpha:8541 \ - LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_alpha.hjson \ + LEMMY_PORT=8541 \ LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_alpha" \ - target/lemmy_server >/tmp/lemmy_alpha.out 2>&1 & + LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon \ + LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha \ + LEMMY_SETUP__SITE_NAME=lemmy-alpha \ + target/lemmy_server >/dev/null 2>&1 & echo "start beta" LEMMY_HOSTNAME=lemmy-beta:8551 \ - LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_beta.hjson \ + LEMMY_PORT=8551 \ LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_beta" \ - target/lemmy_server >/tmp/lemmy_beta.out 2>&1 & + LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon \ + LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta \ + LEMMY_SETUP__SITE_NAME=lemmy-beta \ + target/lemmy_server >/dev/null 2>&1 & echo "start gamma" LEMMY_HOSTNAME=lemmy-gamma:8561 \ - LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_gamma.hjson \ + LEMMY_PORT=8561 \ LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_gamma" \ - target/lemmy_server >/tmp/lemmy_gamma.out 2>&1 & + LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon \ + LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma \ + LEMMY_SETUP__SITE_NAME=lemmy-gamma \ + target/lemmy_server >/dev/null 2>&1 & echo "start delta" # An instance with only an allowlist for beta LEMMY_HOSTNAME=lemmy-delta:8571 \ - LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_delta.hjson \ + LEMMY_PORT=8571 \ LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_delta" \ - target/lemmy_server >/tmp/lemmy_delta.out 2>&1 & + LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta \ + LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta \ + LEMMY_SETUP__SITE_NAME=lemmy-delta \ + target/lemmy_server >/dev/null 2>&1 & echo "start epsilon" # An instance who has a blocklist, with lemmy-alpha blocked LEMMY_HOSTNAME=lemmy-epsilon:8581 \ - LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_epsilon.hjson \ + LEMMY_PORT=8581 \ LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_epsilon" \ - target/lemmy_server >/tmp/lemmy_epsilon.out 2>&1 & + LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha \ + LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon \ + LEMMY_SETUP__SITE_NAME=lemmy-epsilon \ + target/lemmy_server >/dev/null 2>&1 & echo "wait for all instances to start" while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8541/api/v2/site')" != "200" ]]; do sleep 1; done diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index d934d1ac..7caaba3b 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -190,7 +190,7 @@ pub(crate) fn check_optional_url(item: &Option>) -> Result<(), Le pub(crate) async fn build_federated_instances( pool: &DbPool, ) -> Result, LemmyError> { - if Settings::get().federation.unwrap_or_default().enabled { + if Settings::get().federation.enabled { let distinct_communities = blocking(pool, move |conn| { Community::distinct_federated_communities(conn) }) @@ -205,9 +205,7 @@ pub(crate) async fn build_federated_instances( .collect::, LemmyError>>()?; linked.extend_from_slice(&allowed); - linked.retain(|a| { - !blocked.contains(a) && !a.eq("") && !a.eq(&Settings::get().hostname.unwrap_or_default()) - }); + linked.retain(|a| !blocked.contains(a) && !a.eq("") && !a.eq(&Settings::get().hostname)); // Sort and remove dupes linked.sort_unstable(); diff --git a/crates/api/src/user.rs b/crates/api/src/user.rs index 5994c241..df8d1263 100644 --- a/crates/api/src/user.rs +++ b/crates/api/src/user.rs @@ -121,7 +121,7 @@ impl Perform for Login { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt(user.id, Settings::get().hostname.unwrap_or_default())?, + jwt: Claims::jwt(user.id, Settings::get().hostname)?, }) } } @@ -161,7 +161,7 @@ impl Perform for Register { .await??; // If its not the admin, check the captcha - if !no_admins && Settings::get().captcha.unwrap_or_default().enabled { + if !no_admins && Settings::get().captcha.enabled { let check = context .chat_server() .send(CheckCaptcha { @@ -303,10 +303,7 @@ impl Perform for Register { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt( - inserted_user.id, - Settings::get().hostname.unwrap_or_default(), - )?, + jwt: Claims::jwt(inserted_user.id, Settings::get().hostname)?, }) } } @@ -320,7 +317,7 @@ impl Perform for GetCaptcha { context: &Data, _websocket_id: Option, ) -> Result { - let captcha_settings = Settings::get().captcha.unwrap_or_default(); + let captcha_settings = Settings::get().captcha; if !captcha_settings.enabled { return Ok(GetCaptchaResponse { ok: None }); @@ -479,10 +476,7 @@ impl Perform for SaveUserSettings { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt( - updated_user.id, - Settings::get().hostname.unwrap_or_default(), - )?, + jwt: Claims::jwt(updated_user.id, Settings::get().hostname)?, }) } } @@ -1018,10 +1012,7 @@ impl Perform for PasswordChange { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt( - updated_user.id, - Settings::get().hostname.unwrap_or_default(), - )?, + jwt: Claims::jwt(updated_user.id, Settings::get().hostname)?, }) } } diff --git a/crates/apub/src/activity_queue.rs b/crates/apub/src/activity_queue.rs index 19f43308..285c8c47 100644 --- a/crates/apub/src/activity_queue.rs +++ b/crates/apub/src/activity_queue.rs @@ -88,7 +88,7 @@ where .await? .iter() .unique() - .filter(|inbox| inbox.host_str() != Some(&Settings::get().hostname.unwrap_or_default())) + .filter(|inbox| inbox.host_str() != Some(&Settings::get().hostname)) .filter(|inbox| check_is_apub_id_valid(inbox).is_ok()) .map(|inbox| inbox.to_owned()) .collect(); @@ -215,7 +215,7 @@ where Kind: Serialize, >::Error: From + Send + Sync + 'static, { - if !Settings::get().federation.unwrap_or_default().enabled || inboxes.is_empty() { + if !Settings::get().federation.enabled || inboxes.is_empty() { return Ok(()); } diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 2a6a9ef5..b7eb70cd 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -41,8 +41,8 @@ use log::debug; use url::Url; /// The types of ActivityPub objects that can be fetched directly by searching for their ID. -#[serde(untagged)] #[derive(serde::Deserialize, Debug)] +#[serde(untagged)] enum SearchAcceptedObjects { Person(Box), Group(Box), diff --git a/crates/apub/src/inbox/mod.rs b/crates/apub/src/inbox/mod.rs index db7225a8..6e90a2bc 100644 --- a/crates/apub/src/inbox/mod.rs +++ b/crates/apub/src/inbox/mod.rs @@ -167,7 +167,7 @@ where let id = activity.id_unchecked().context(location_info!())?; let activity_domain = id.domain().context(location_info!())?; - if activity_domain == Settings::get().hostname.unwrap_or_default() { + if activity_domain == Settings::get().hostname { return Err( anyhow!( "Error: received activity which was sent by local instance: {:?}", diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index 36ee9a7b..159e20cf 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -64,7 +64,7 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> { let domain = apub_id.domain().context(location_info!())?.to_string(); let local_instance = settings.get_hostname_without_port()?; - if !settings.federation.unwrap_or_default().enabled { + if !settings.federation.enabled { return if domain == local_instance { Ok(()) } else { diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs index 3000db51..014144de 100644 --- a/crates/apub/src/objects/mod.rs +++ b/crates/apub/src/objects/mod.rs @@ -194,7 +194,7 @@ where let domain = object_id.domain().context(location_info!())?; // if its a local object, return it directly from the database - if Settings::get().hostname.unwrap_or_default() == domain { + if Settings::get().hostname == domain { let object = blocking(context.pool(), move |conn| { To::read_from_apub_id(conn, &object_id.into()) }) diff --git a/crates/apub/src/objects/user.rs b/crates/apub/src/objects/user.rs index c979170f..de05398f 100644 --- a/crates/apub/src/objects/user.rs +++ b/crates/apub/src/objects/user.rs @@ -99,7 +99,7 @@ impl FromApub for User_ { ) -> Result { let user_id = person.id_unchecked().context(location_info!())?.to_owned(); let domain = user_id.domain().context(location_info!())?; - if domain == Settings::get().hostname.unwrap_or_default() { + if domain == Settings::get().hostname { let user = blocking(context.pool(), move |conn| { User_::read_from_apub_id(conn, &user_id.into()) }) diff --git a/crates/apub/src/routes.rs b/crates/apub/src/routes.rs index b040bb75..68700b9c 100644 --- a/crates/apub/src/routes.rs +++ b/crates/apub/src/routes.rs @@ -23,11 +23,8 @@ static APUB_JSON_CONTENT_TYPE_LONG: &str = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""; pub fn config(cfg: &mut web::ServiceConfig) { - if Settings::get().federation.unwrap_or_default().enabled { - println!( - "federation enabled, host is {}", - Settings::get().hostname.unwrap_or_default() - ); + if Settings::get().federation.enabled { + println!("federation enabled, host is {}", Settings::get().hostname); let digest_verifier = VerifyDigest::new(Sha256::new()); let header_guard_accept = guard::Any(guard::Header("Accept", APUB_JSON_CONTENT_TYPE)) diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 57a12264..0f723fde 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -168,7 +168,7 @@ fn get_feed_user( ) -> Result { let site_view = SiteView::read(&conn)?; let user = User_::find_by_username(&conn, &user_name)?; - let user_url = user.get_profile_url(&Settings::get().hostname.unwrap_or_default()); + let user_url = user.get_profile_url(&Settings::get().hostname); let posts = PostQueryBuilder::create(&conn) .listing_type(&ListingType::All) diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs index 67220aec..0177c7e9 100644 --- a/crates/routes/src/images.rs +++ b/crates/routes/src/images.rs @@ -54,10 +54,8 @@ async fn upload( return Ok(HttpResponse::Unauthorized().finish()); }; - let mut client_req = client.request_from( - format!("{}/image", Settings::get().pictrs_url.unwrap_or_default()), - req.head(), - ); + let mut client_req = + client.request_from(format!("{}/image", Settings::get().pictrs_url), req.head()); if let Some(addr) = req.head().peer_addr { client_req = client_req.header("X-Forwarded-For", addr.to_string()) @@ -80,18 +78,14 @@ async fn full_res( // If there are no query params, the URL is original let url = if params.format.is_none() && params.thumbnail.is_none() { - format!( - "{}/image/original/{}", - Settings::get().pictrs_url.unwrap_or_default(), - name, - ) + format!("{}/image/original/{}", Settings::get().pictrs_url, name,) } else { // Use jpg as a default when none is given let format = params.format.unwrap_or_else(|| "jpg".to_string()); let mut url = format!( "{}/image/process.{}?src={}", - Settings::get().pictrs_url.unwrap_or_default(), + Settings::get().pictrs_url, format, name, ); @@ -140,7 +134,7 @@ async fn delete( let url = format!( "{}/image/delete/{}/{}", - Settings::get().pictrs_url.unwrap_or_default(), + Settings::get().pictrs_url, &token, &file ); diff --git a/crates/routes/src/nodeinfo.rs b/crates/routes/src/nodeinfo.rs index e302b296..a3c2af5a 100644 --- a/crates/routes/src/nodeinfo.rs +++ b/crates/routes/src/nodeinfo.rs @@ -31,7 +31,7 @@ async fn node_info(context: web::Data) -> Result( &jwt, - &DecodingKey::from_secret(Settings::get().jwt_secret.unwrap_or_default().as_ref()), + &DecodingKey::from_secret(Settings::get().jwt_secret.as_ref()), &v, ) } @@ -31,7 +31,7 @@ impl Claims { encode( &Header::default(), &my_claims, - &EncodingKey::from_secret(Settings::get().jwt_secret.unwrap_or_default().as_ref()), + &EncodingKey::from_secret(Settings::get().jwt_secret.as_ref()), ) } } diff --git a/crates/utils/src/email.rs b/crates/utils/src/email.rs index 208d69f6..280ec41c 100644 --- a/crates/utils/src/email.rs +++ b/crates/utils/src/email.rs @@ -20,7 +20,7 @@ pub fn send_email( html: &str, ) -> Result<(), String> { let email_config = Settings::get().email.ok_or("no_email_setup")?; - let domain = Settings::get().hostname.unwrap_or_default(); + let domain = Settings::get().hostname; let (smtp_server, smtp_port) = { let email_and_port = email_config.smtp_server.split(':').collect::>(); diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 8ec2b26c..051c776d 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -83,12 +83,12 @@ impl actix_web::error::ResponseError for LemmyError { lazy_static! { pub static ref WEBFINGER_COMMUNITY_REGEX: Regex = Regex::new(&format!( "^group:([a-z0-9_]{{3, 20}})@{}$", - Settings::get().hostname.unwrap_or_default() + Settings::get().hostname )) .unwrap(); pub static ref WEBFINGER_USER_REGEX: Regex = Regex::new(&format!( "^acct:([a-z0-9_]{{3, 20}})@{}$", - Settings::get().hostname.unwrap_or_default() + Settings::get().hostname )) .unwrap(); } diff --git a/crates/utils/src/rate_limit/mod.rs b/crates/utils/src/rate_limit/mod.rs index fa45c3a4..3c095be1 100644 --- a/crates/utils/src/rate_limit/mod.rs +++ b/crates/utils/src/rate_limit/mod.rs @@ -70,7 +70,7 @@ impl RateLimited { { // Does not need to be blocking because the RwLock in settings never held across await points, // and the operation here locks only long enough to clone - let rate_limit: RateLimitConfig = Settings::get().rate_limit.unwrap_or_default(); + let rate_limit: RateLimitConfig = Settings::get().rate_limit; // before { diff --git a/crates/utils/src/request.rs b/crates/utils/src/request.rs index 522b9cd9..7899dad7 100644 --- a/crates/utils/src/request.rs +++ b/crates/utils/src/request.rs @@ -58,11 +58,7 @@ pub(crate) async fn fetch_iframely( client: &Client, url: &str, ) -> Result { - let fetch_url = format!( - "{}/oembed?url={}", - Settings::get().iframely_url.unwrap_or_default(), - url - ); + let fetch_url = format!("{}/oembed?url={}", Settings::get().iframely_url, url); let response = retry(|| client.get(&fetch_url).send()).await?; @@ -93,7 +89,7 @@ pub(crate) async fn fetch_pictrs( let fetch_url = format!( "{}/image/download?url={}", - Settings::get().pictrs_url.unwrap_or_default(), + Settings::get().pictrs_url, utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed ); diff --git a/crates/utils/src/settings/defaults.rs b/crates/utils/src/settings/defaults.rs index e46b5235..5b733028 100644 --- a/crates/utils/src/settings/defaults.rs +++ b/crates/utils/src/settings/defaults.rs @@ -4,19 +4,20 @@ use std::net::{IpAddr, Ipv4Addr}; impl Default for Settings { fn default() -> Self { Self { - database: Some(DatabaseConfig::default()), - rate_limit: Some(RateLimitConfig::default()), - federation: Some(FederationConfig::default()), - captcha: Some(CaptchaConfig::default()), + database: DatabaseConfig::default(), + rate_limit: RateLimitConfig::default(), + federation: FederationConfig::default(), + captcha: CaptchaConfig::default(), email: None, setup: None, - hostname: None, - bind: Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))), - port: Some(8536), - tls_enabled: Some(true), - jwt_secret: Some("changeme".into()), - pictrs_url: Some("http://pictrs:8080".into()), - iframely_url: Some("http://iframely".into()), + // TODO: not sure how to handle this, its mandatory but not provided by defaults + hostname: "hostname_not_set".into(), + bind: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), + port: 8536, + tls_enabled: true, + jwt_secret: "changeme".into(), + pictrs_url: "http://pictrs:8080".into(), + iframely_url: "http://iframely".into(), } } } @@ -62,8 +63,8 @@ impl Default for FederationConfig { fn default() -> Self { Self { enabled: false, - allowed_instances: Some("".into()), - blocked_instances: Some("".into()), + allowed_instances: "".into(), + blocked_instances: "".into(), } } } diff --git a/crates/utils/src/settings/merge.rs b/crates/utils/src/settings/merge.rs new file mode 100644 index 00000000..7cd1762f --- /dev/null +++ b/crates/utils/src/settings/merge.rs @@ -0,0 +1,107 @@ +use crate::settings::{structs::*, structs_opt::*}; + +pub(in crate::settings) trait Merge { + fn merge(&mut self, opt: T); +} + +impl Merge for Settings { + fn merge(&mut self, opt: SettingsOpt) { + overwrite_if_some(&mut self.hostname, opt.hostname); + overwrite_if_some(&mut self.bind, opt.bind); + overwrite_if_some(&mut self.port, opt.port); + overwrite_if_some(&mut self.tls_enabled, opt.tls_enabled); + overwrite_if_some(&mut self.jwt_secret, opt.jwt_secret); + overwrite_if_some(&mut self.pictrs_url, opt.pictrs_url); + overwrite_if_some(&mut self.iframely_url, opt.iframely_url); + merge_if_some(&mut self.captcha, opt.captcha); + merge_if_some(&mut self.rate_limit, opt.rate_limit); + merge_if_some_opt(&mut self.email, opt.email); + merge_if_some_opt(&mut self.setup, opt.setup); + merge_if_some(&mut self.federation, opt.federation); + merge_if_some(&mut self.database, opt.database); + } +} + +impl Merge for RateLimitConfig { + fn merge(&mut self, opt: RateLimitConfigOpt) { + overwrite_if_some(&mut self.message, opt.message); + overwrite_if_some(&mut self.message_per_second, opt.message_per_second); + overwrite_if_some(&mut self.post, opt.post); + overwrite_if_some(&mut self.post_per_second, opt.post_per_second); + overwrite_if_some(&mut self.register, opt.register); + overwrite_if_some(&mut self.register_per_second, opt.register_per_second); + overwrite_if_some(&mut self.image, opt.image); + overwrite_if_some(&mut self.image_per_second, opt.image_per_second); + } +} + +impl Merge for Setup { + fn merge(&mut self, opt: SetupOpt) { + overwrite_if_some(&mut self.admin_username, opt.admin_username); + overwrite_if_some(&mut self.admin_password, opt.admin_password); + overwrite_if_some(&mut self.admin_email, opt.admin_email); + overwrite_if_some(&mut self.site_name, opt.site_name); + } +} + +impl Merge for EmailConfig { + fn merge(&mut self, opt: EmailConfigOpt) { + overwrite_if_some(&mut self.smtp_server, opt.smtp_server); + overwrite_if_some(&mut self.smtp_login, opt.smtp_login); + overwrite_if_some(&mut self.smtp_password, opt.smtp_password); + overwrite_if_some(&mut self.smtp_from_address, opt.smtp_from_address); + overwrite_if_some(&mut self.use_tls, opt.use_tls); + } +} + +impl Merge for DatabaseConfig { + fn merge(&mut self, opt: DatabaseConfigOpt) { + overwrite_if_some(&mut self.user, opt.user); + overwrite_if_some(&mut self.password, opt.password); + overwrite_if_some(&mut self.host, opt.host); + overwrite_if_some(&mut self.port, opt.port); + overwrite_if_some(&mut self.database, opt.database); + overwrite_if_some(&mut self.pool_size, opt.pool_size); + } +} + +impl Merge for FederationConfig { + fn merge(&mut self, opt: FederationConfigOpt) { + overwrite_if_some(&mut self.enabled, opt.enabled); + overwrite_if_some(&mut self.allowed_instances, opt.allowed_instances); + overwrite_if_some(&mut self.blocked_instances, opt.blocked_instances); + } +} + +impl Merge for CaptchaConfig { + fn merge(&mut self, opt: CaptchaConfigOpt) { + overwrite_if_some(&mut self.enabled, opt.enabled); + overwrite_if_some(&mut self.difficulty, opt.difficulty); + } +} + +fn overwrite_if_some(lhs: &mut T, rhs: Option) { + if let Some(x) = rhs { + *lhs = x; + } +} + +fn merge_if_some(lhs: &mut T, rhs: Option) +where + T: Merge, +{ + if let Some(x) = rhs { + lhs.merge(x); + } +} + +fn merge_if_some_opt(lhs: &mut Option, rhs: Option) +where + T: Merge, +{ + if let Some(x) = rhs { + if let Some(y) = lhs { + y.merge(x) + } + } +} diff --git a/crates/utils/src/settings/mod.rs b/crates/utils/src/settings/mod.rs index 0af0ecd6..4345d4f1 100644 --- a/crates/utils/src/settings/mod.rs +++ b/crates/utils/src/settings/mod.rs @@ -1,11 +1,16 @@ -use crate::{location_info, settings::structs::Settings, LemmyError}; -use anyhow::Context; +use crate::{ + location_info, + settings::{merge::Merge, structs::Settings, structs_opt::SettingsOpt}, + LemmyError, +}; +use anyhow::{anyhow, Context}; use deser_hjson::from_str; -use merge::Merge; use std::{env, fs, io::Error, sync::RwLock}; pub mod defaults; +mod merge; pub mod structs; +mod structs_opt; static CONFIG_FILE: &str = "config/config.hjson"; @@ -25,13 +30,19 @@ impl Settings { /// Note: The env var `LEMMY_DATABASE_URL` is parsed in /// `lemmy_db_queries/src/lib.rs::get_database_url_from_env()` fn init() -> Result { + let mut config = Settings::default(); + // Read the config file - let mut custom_config = from_str::(&Self::read_config_file()?)?; + config.merge(from_str::(&Self::read_config_file()?)?); - // Merge with default - custom_config.merge(Settings::default()); + // Read env vars + config.merge(envy::prefixed("LEMMY_").from_env::()?); - Ok(custom_config) + if config.hostname == Settings::default().hostname { + return Err(anyhow!("Hostname variable is not set!").into()); + } + + Ok(config) } /// Returns the config as a struct. @@ -40,7 +51,7 @@ impl Settings { } pub fn get_database_url(&self) -> String { - let conf = self.database.to_owned().unwrap_or_default(); + let conf = self.database.to_owned(); format!( "postgres://{}:{}@{}:{}/{}", conf.user, conf.password, conf.host, conf.port, conf.database, @@ -59,9 +70,7 @@ impl Settings { let mut allowed_instances: Vec = self .federation .to_owned() - .unwrap_or_default() .allowed_instances - .unwrap_or_default() .split(',') .map(|d| d.trim().to_string()) .collect(); @@ -74,9 +83,7 @@ impl Settings { let mut blocked_instances: Vec = self .federation .to_owned() - .unwrap_or_default() .blocked_instances - .unwrap_or_default() .split(',') .map(|d| d.trim().to_string()) .collect(); @@ -87,12 +94,8 @@ impl Settings { /// Returns either "http" or "https", depending on tls_enabled setting pub fn get_protocol_string(&self) -> &'static str { - if let Some(tls_enabled) = self.tls_enabled { - if tls_enabled { - "https" - } else { - "http" - } + if self.tls_enabled { + "https" } else { "http" } @@ -104,7 +107,7 @@ impl Settings { format!( "{}://{}", self.get_protocol_string(), - self.hostname.to_owned().unwrap_or_default() + self.hostname.to_owned() ) } @@ -116,7 +119,6 @@ impl Settings { self .hostname .to_owned() - .unwrap_or_default() .split(':') .collect::>() .first() diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index f0a6d679..1e92e93d 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -1,22 +1,21 @@ -use merge::Merge; use serde::Deserialize; use std::net::IpAddr; -#[derive(Debug, Deserialize, Clone, Merge)] +#[derive(Debug, Deserialize, Clone)] pub struct Settings { pub setup: Option, - pub database: Option, - pub hostname: Option, - pub bind: Option, - pub port: Option, - pub tls_enabled: Option, - pub jwt_secret: Option, - pub pictrs_url: Option, - pub iframely_url: Option, - pub rate_limit: Option, + pub database: DatabaseConfig, + pub hostname: String, + pub bind: IpAddr, + pub port: u16, + pub tls_enabled: bool, + pub jwt_secret: String, + pub pictrs_url: String, + pub iframely_url: String, + pub rate_limit: RateLimitConfig, pub email: Option, - pub federation: Option, - pub captcha: Option, + pub federation: FederationConfig, + pub captcha: CaptchaConfig, } #[derive(Debug, Deserialize, Clone)] @@ -51,6 +50,7 @@ pub struct EmailConfig { #[derive(Debug, Deserialize, Clone)] pub struct CaptchaConfig { pub enabled: bool, + // TODO: use enum for this pub difficulty: String, } @@ -67,6 +67,6 @@ pub struct DatabaseConfig { #[derive(Debug, Deserialize, Clone)] pub struct FederationConfig { pub enabled: bool, - pub allowed_instances: Option, - pub blocked_instances: Option, + pub allowed_instances: String, + pub blocked_instances: String, } diff --git a/crates/utils/src/settings/structs_opt.rs b/crates/utils/src/settings/structs_opt.rs new file mode 100644 index 00000000..1635c090 --- /dev/null +++ b/crates/utils/src/settings/structs_opt.rs @@ -0,0 +1,71 @@ +use serde::Deserialize; +use std::net::IpAddr; + +#[derive(Debug, Deserialize, Clone)] +pub struct SettingsOpt { + pub setup: Option, + pub database: Option, + pub hostname: Option, + pub bind: Option, + pub port: Option, + pub tls_enabled: Option, + pub jwt_secret: Option, + pub pictrs_url: Option, + pub iframely_url: Option, + pub rate_limit: Option, + pub email: Option, + pub federation: Option, + pub captcha: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct SetupOpt { + pub admin_username: Option, + pub admin_password: Option, + pub admin_email: Option>, + pub site_name: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct RateLimitConfigOpt { + pub message: Option, + pub message_per_second: Option, + pub post: Option, + pub post_per_second: Option, + pub register: Option, + pub register_per_second: Option, + pub image: Option, + pub image_per_second: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct EmailConfigOpt { + pub smtp_server: Option, + pub smtp_login: Option>, + pub smtp_password: Option>, + pub smtp_from_address: Option, + pub use_tls: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct CaptchaConfigOpt { + pub enabled: Option, + pub difficulty: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct DatabaseConfigOpt { + pub user: Option, + pub password: Option, + pub host: Option, + pub port: Option, + pub database: Option, + pub pool_size: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct FederationConfigOpt { + pub enabled: Option, + pub allowed_instances: Option, + pub blocked_instances: Option, +} diff --git a/crates/utils/src/utils.rs b/crates/utils/src/utils.rs index 5cb66831..9ce4c3d9 100644 --- a/crates/utils/src/utils.rs +++ b/crates/utils/src/utils.rs @@ -85,10 +85,7 @@ pub struct MentionData { impl MentionData { pub fn is_local(&self) -> bool { - Settings::get() - .hostname - .unwrap_or_default() - .eq(&self.domain) + Settings::get().hostname.eq(&self.domain) } pub fn full_name(&self) -> String { format!("@{}@{}", &self.name, &self.domain) diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index d56a1fdc..a2712f9f 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -56,6 +56,7 @@ RUN addgroup -g 1000 lemmy RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy # Copy resources +COPY --chown=lemmy:lemmy config/defaults.hjson /config/defaults.hjson COPY --chown=lemmy:lemmy --from=builder /app/lemmy_server /app/lemmy RUN chown lemmy:lemmy /app/lemmy diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index ed662e44..72e6c5ce 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -38,9 +38,20 @@ services: - lemmy-alpha lemmy-alpha: image: lemmy-federation:latest - volumes: - - ./lemmy_alpha.hjson:/config/config.hjson environment: + - LEMMY_HOSTNAME=lemmy-alpha:8541 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_TLS_ENABLED=false + - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon + - LEMMY_PORT=8541 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy-alpha + - LEMMY_RATE_LIMIT__POST=99999 + - LEMMY_RATE_LIMIT__REGISTER=99999 + - LEMMY_CAPTCHA__ENABLED=false - LEMMY_TEST_SEND_SYNC=1 - RUST_BACKTRACE=1 - RUST_LOG=debug @@ -67,9 +78,20 @@ services: - lemmy-beta lemmy-beta: image: lemmy-federation:latest - volumes: - - ./lemmy_beta.hjson:/config/config.hjson environment: + - LEMMY_HOSTNAME=lemmy-beta:8551 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_TLS_ENABLED=false + - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon + - LEMMY_PORT=8551 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy-beta + - LEMMY_RATE_LIMIT__POST=99999 + - LEMMY_RATE_LIMIT__REGISTER=99999 + - LEMMY_CAPTCHA__ENABLED=false - LEMMY_TEST_SEND_SYNC=1 - RUST_BACKTRACE=1 - RUST_LOG=debug @@ -96,9 +118,20 @@ services: - lemmy-gamma lemmy-gamma: image: lemmy-federation:latest - volumes: - - ./lemmy_gamma.hjson:/config/config.hjson environment: + - LEMMY_HOSTNAME=lemmy-gamma:8561 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_TLS_ENABLED=false + - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon + - LEMMY_PORT=8561 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy-gamma + - LEMMY_RATE_LIMIT__POST=99999 + - LEMMY_RATE_LIMIT__REGISTER=99999 + - LEMMY_CAPTCHA__ENABLED=false - LEMMY_TEST_SEND_SYNC=1 - RUST_BACKTRACE=1 - RUST_LOG=debug @@ -126,9 +159,20 @@ services: - lemmy-delta lemmy-delta: image: lemmy-federation:latest - volumes: - - ./lemmy_delta.hjson:/config/config.hjson environment: + - LEMMY_HOSTNAME=lemmy-delta:8571 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_TLS_ENABLED=false + - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta + - LEMMY_PORT=8571 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy-delta + - LEMMY_RATE_LIMIT__POST=99999 + - LEMMY_RATE_LIMIT__REGISTER=99999 + - LEMMY_CAPTCHA__ENABLED=false - LEMMY_TEST_SEND_SYNC=1 - RUST_BACKTRACE=1 - RUST_LOG=debug @@ -156,9 +200,20 @@ services: - lemmy-epsilon lemmy-epsilon: image: lemmy-federation:latest - volumes: - - ./lemmy_epsilon.hjson:/config/config.hjson environment: + - LEMMY_HOSTNAME=lemmy-epsilon:8581 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_TLS_ENABLED=false + - LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha + - LEMMY_PORT=8581 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy-epsilon + - LEMMY_RATE_LIMIT__POST=99999 + - LEMMY_RATE_LIMIT__REGISTER=99999 + - LEMMY_CAPTCHA__ENABLED=false - LEMMY_TEST_SEND_SYNC=1 - RUST_BACKTRACE=1 - RUST_LOG=debug diff --git a/docker/federation/lemmy_alpha.hjson b/docker/federation/lemmy_alpha.hjson deleted file mode 100644 index 3f8fc03d..00000000 --- a/docker/federation/lemmy_alpha.hjson +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostname: lemmy-alpha:8541 - port: 8541 - tls_enabled: false - jwt_secret: changeme - setup: { - admin_username: lemmy_alpha - admin_password: lemmy - site_name: lemmy-alpha - } - database: { - database: lemmy - user: lemmy - password: password - host: postgres_alpha - port: 5432 - pool_size: 5 - } - federation: { - enabled: true - allowed_instances: lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon - } - captcha: { - enabled: false - difficulty: medium - } - rate_limit: { - message: 180 - message_per_second: 60 - post: 99999 - post_per_second: 600 - register: 99999 - register_per_second: 3600 - image: 6 - image_per_second: 3600 - } -} diff --git a/docker/federation/lemmy_beta.hjson b/docker/federation/lemmy_beta.hjson deleted file mode 100644 index f23d8f1c..00000000 --- a/docker/federation/lemmy_beta.hjson +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostname: lemmy-beta:8551 - port: 8551 - tls_enabled: false - jwt_secret: changeme - setup: { - admin_username: lemmy_beta - admin_password: lemmy - site_name: lemmy-beta - } - database: { - database: lemmy - user: lemmy - password: password - host: postgres_beta - port: 5432 - pool_size: 5 - } - federation: { - enabled: true - allowed_instances: lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon - } - captcha: { - enabled: false - difficulty: medium - } - rate_limit: { - message: 180 - message_per_second: 60 - post: 99999 - post_per_second: 600 - register: 99999 - register_per_second: 3600 - image: 6 - image_per_second: 3600 - } -} diff --git a/docker/federation/lemmy_delta.hjson b/docker/federation/lemmy_delta.hjson deleted file mode 100644 index f4fb0ecc..00000000 --- a/docker/federation/lemmy_delta.hjson +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostname: lemmy-delta:8571 - port: 8571 - tls_enabled: false - jwt_secret: changeme - setup: { - admin_username: lemmy_delta - admin_password: lemmy - site_name: lemmy-delta - } - database: { - database: lemmy - user: lemmy - password: password - host: postgres_delta - port: 5432 - pool_size: 5 - } - federation: { - enabled: true - allowed_instances: lemmy-beta - } - captcha: { - enabled: false - difficulty: medium - } - rate_limit: { - message: 180 - message_per_second: 60 - post: 99999 - post_per_second: 600 - register: 99999 - register_per_second: 3600 - image: 6 - image_per_second: 3600 - } -} diff --git a/docker/federation/lemmy_epsilon.hjson b/docker/federation/lemmy_epsilon.hjson deleted file mode 100644 index c04c3127..00000000 --- a/docker/federation/lemmy_epsilon.hjson +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostname: lemmy-epsilon:8581 - port: 8581 - tls_enabled: false - jwt_secret: changeme - setup: { - admin_username: lemmy_epsilon - admin_password: lemmy - site_name: lemmy-epsilon - } - database: { - database: lemmy - user: lemmy - password: password - host: postgres_epsilon - port: 5432 - pool_size: 5 - } - federation: { - enabled: true - blocked_instances: lemmy-alpha - } - captcha: { - enabled: false - difficulty: medium - } - rate_limit: { - message: 180 - message_per_second: 60 - post: 99999 - post_per_second: 600 - register: 99999 - register_per_second: 3600 - image: 6 - image_per_second: 3600 - } -} diff --git a/docker/federation/lemmy_gamma.hjson b/docker/federation/lemmy_gamma.hjson deleted file mode 100644 index f08e2e63..00000000 --- a/docker/federation/lemmy_gamma.hjson +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostname: lemmy-gamma:8561 - port: 8561 - tls_enabled: false - jwt_secret: changeme - setup: { - admin_username: lemmy_gamma - admin_password: lemmy - site_name: lemmy-gamma - } - database: { - database: lemmy - user: lemmy - password: password - host: postgres_gamma - port: 5432 - pool_size: 5 - } - federation: { - enabled: true - allowed_instances: lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon - } - captcha: { - enabled: false - difficulty: medium - } - rate_limit: { - message: 180 - message_per_second: 60 - post: 99999 - post_per_second: 600 - register: 99999 - register_per_second: 3600 - image: 6 - image_per_second: 3600 - } -} diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson index bceb5f6c..bea65d8f 100644 --- a/docker/lemmy.hjson +++ b/docker/lemmy.hjson @@ -29,10 +29,6 @@ password: "password" # host where postgres is running host: "postgres" - # port where postgres can be accessed - port: 5432 - # maximum number of active sql connections - pool_size: 5 } # # optional: email sending configuration # email: { diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile index c4f0358d..8f307bf6 100644 --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -56,6 +56,7 @@ RUN addgroup -g 1000 lemmy RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy # Copy resources +COPY --chown=lemmy:lemmy config/defaults.hjson /config/defaults.hjson COPY --chown=lemmy:lemmy --from=builder /app/lemmy_server /app/lemmy RUN chown lemmy:lemmy /app/lemmy diff --git a/docker/prod/Dockerfile.arm b/docker/prod/Dockerfile.arm index a6e698f0..bcf59003 100644 --- a/docker/prod/Dockerfile.arm +++ b/docker/prod/Dockerfile.arm @@ -31,6 +31,7 @@ RUN addgroup --gid 1000 lemmy RUN adduser --no-create-home --shell /bin/sh --uid 1000 --gid 1000 lemmy # Copy resources +COPY --chown=lemmy:lemmy config/defaults.hjson /config/defaults.hjson COPY --chown=lemmy:lemmy --from=builder /app/lemmy_server /app/lemmy RUN chown lemmy:lemmy /app/lemmy diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index 78a8484e..6b0519d0 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -28,7 +28,7 @@ services: lemmy-ui: image: dessalines/lemmy-ui:0.9.7 ports: - - "1235:1234" + - "127.0.0.1:1235:1234" restart: always environment: - LEMMY_INTERNAL_HOST=lemmy:8536 diff --git a/src/main.rs b/src/main.rs index 58a1a06b..21c4e457 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ async fn main() -> Result<(), LemmyError> { }; let manager = ConnectionManager::::new(&db_url); let pool = Pool::builder() - .max_size(settings.database.unwrap_or_default().pool_size) + .max_size(settings.database.pool_size) .build(manager) .unwrap_or_else(|_| panic!("Error connecting to {}", db_url)); @@ -61,8 +61,7 @@ async fn main() -> Result<(), LemmyError> { println!( "Starting http server at {}:{}", - settings.bind.unwrap(), - settings.port.unwrap_or_default() + settings.bind, settings.port ); let activity_queue = create_activity_queue(); @@ -95,7 +94,7 @@ async fn main() -> Result<(), LemmyError> { .configure(nodeinfo::config) .configure(webfinger::config) }) - .bind((settings.bind.unwrap(), settings.port.unwrap_or_default()))? + .bind((settings.bind, settings.port))? .run() .await?; diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 6658cc72..e82ac9e2 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -39,7 +39,7 @@ use lemmy_server::code_migrations::run_advanced_migrations; use lemmy_utils::{ apub::generate_actor_keypair, rate_limit::{rate_limiter::RateLimiter, RateLimit}, - settings::Settings, + settings::structs::Settings, }; use lemmy_websocket::{chat_server::ChatServer, LemmyContext}; use reqwest::Client; @@ -58,7 +58,7 @@ fn create_context() -> LemmyContext { }; let manager = ConnectionManager::::new(&db_url); let pool = Pool::builder() - .max_size(settings.database.unwrap_or_default().pool_size) + .max_size(settings.database.pool_size) .build(manager) .unwrap(); embedded_migrations::run(&pool.get().unwrap()).unwrap();