Rewrite merge code to fix tests
This commit is contained in:
parent
62c9be5b56
commit
59cce4a1f5
6 changed files with 126 additions and 86 deletions
|
@ -583,7 +583,9 @@ impl Perform for GetSiteConfig {
|
|||
// Only let admins read this
|
||||
is_admin(context.pool(), user.id).await?;
|
||||
|
||||
let config_hjson = Settings::read_config_file()?;
|
||||
// TODO: should make the response field optional?
|
||||
// or include env vars, but then we cant really save it
|
||||
let config_hjson = Settings::read_config_file().unwrap_or("".to_string());
|
||||
|
||||
Ok(GetSiteConfigResponse { config_hjson })
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ pub(in crate::settings) fn parse_from_env() -> SettingsOpt {
|
|||
admin_username: env_var("SETUP__ADMIN_USERNAME"),
|
||||
admin_password: env_var("SETUP__ADMIN_PASSWORD"),
|
||||
admin_email: Some(env_var("SETUP__ADMIN_EMAIL")),
|
||||
site_name: env_var("SETUP__ADMIN_SITE_NAME"),
|
||||
site_name: env_var("SETUP__SITE_NAME"),
|
||||
}),
|
||||
database: Some(DatabaseConfigOpt {
|
||||
user: env_var("DATABASE__USER"),
|
||||
|
|
|
@ -1,107 +1,141 @@
|
|||
use crate::settings::{structs::*, structs_opt::*};
|
||||
|
||||
pub(in crate::settings) trait Merge<T> {
|
||||
fn merge(&mut self, opt: T);
|
||||
fn merge(self, opt: T) -> Self;
|
||||
}
|
||||
|
||||
impl Merge<SettingsOpt> 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);
|
||||
fn merge(self, opt: SettingsOpt) -> Self {
|
||||
Settings {
|
||||
setup: merge_structs(self.setup, opt.setup),
|
||||
database: merge_structs(self.database, opt.database),
|
||||
hostname: opt.hostname.unwrap_or(self.hostname),
|
||||
bind: opt.bind.unwrap_or(self.bind),
|
||||
port: opt.port.unwrap_or(self.port),
|
||||
tls_enabled: opt.tls_enabled.unwrap_or(self.tls_enabled),
|
||||
jwt_secret: opt.jwt_secret.unwrap_or(self.jwt_secret),
|
||||
pictrs_url: opt.pictrs_url.unwrap_or(self.pictrs_url),
|
||||
iframely_url: opt.iframely_url.unwrap_or(self.iframely_url),
|
||||
rate_limit: merge_structs(self.rate_limit, opt.rate_limit),
|
||||
email: merge_structs(self.email, opt.email),
|
||||
federation: merge_structs(self.federation, opt.federation),
|
||||
captcha: merge_structs(self.captcha, opt.captcha),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<RateLimitConfigOpt> 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);
|
||||
fn merge(self, opt: RateLimitConfigOpt) -> Self {
|
||||
RateLimitConfig {
|
||||
message: opt.message.unwrap_or(self.message),
|
||||
message_per_second: opt.message_per_second.unwrap_or(self.message_per_second),
|
||||
post: opt.post.unwrap_or(self.post),
|
||||
post_per_second: opt.post_per_second.unwrap_or(self.post_per_second),
|
||||
register: opt.register.unwrap_or(self.register),
|
||||
register_per_second: opt.register_per_second.unwrap_or(self.register_per_second),
|
||||
image: opt.image.unwrap_or(self.image),
|
||||
image_per_second: opt.image_per_second.unwrap_or(self.image_per_second),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<SetupOpt> 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<SetupOpt> for Option<Setup> {
|
||||
fn merge(self, opt: SetupOpt) -> Self {
|
||||
if let Some(setup) = self {
|
||||
Some(Setup {
|
||||
admin_username: opt.admin_username.unwrap_or(setup.admin_username),
|
||||
admin_password: opt.admin_password.unwrap_or(setup.admin_password),
|
||||
admin_email: opt.admin_email.unwrap_or(setup.admin_email),
|
||||
site_name: opt.site_name.unwrap_or(setup.site_name),
|
||||
})
|
||||
} else if let (Some(admin_username), Some(admin_password), Some(site_name)) =
|
||||
(opt.admin_username, opt.admin_password, opt.site_name)
|
||||
{
|
||||
Some(Setup {
|
||||
admin_username,
|
||||
admin_password,
|
||||
admin_email: opt.admin_email.flatten(),
|
||||
site_name,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<EmailConfigOpt> 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<EmailConfigOpt> for Option<EmailConfig> {
|
||||
fn merge(self, opt: EmailConfigOpt) -> Self {
|
||||
if let Some(email_config) = self {
|
||||
Some(EmailConfig {
|
||||
smtp_server: opt.smtp_server.unwrap_or(email_config.smtp_server),
|
||||
smtp_login: opt.smtp_login.unwrap_or(email_config.smtp_login),
|
||||
smtp_password: opt.smtp_password.unwrap_or(email_config.smtp_password),
|
||||
smtp_from_address: opt
|
||||
.smtp_from_address
|
||||
.unwrap_or(email_config.smtp_from_address),
|
||||
use_tls: opt.use_tls.unwrap_or(email_config.use_tls),
|
||||
})
|
||||
} else if let (Some(smtp_server), Some(smtp_from_address), Some(use_tls)) =
|
||||
(opt.smtp_server, opt.smtp_from_address, opt.use_tls)
|
||||
{
|
||||
Some(EmailConfig {
|
||||
smtp_server,
|
||||
smtp_login: opt
|
||||
.smtp_login
|
||||
.or(self.clone().map(|s| s.smtp_login))
|
||||
.flatten(),
|
||||
smtp_password: opt
|
||||
.smtp_password
|
||||
.or(self.map(|s| s.smtp_password))
|
||||
.flatten(),
|
||||
smtp_from_address,
|
||||
use_tls,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<DatabaseConfigOpt> 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);
|
||||
fn merge(self, opt: DatabaseConfigOpt) -> Self {
|
||||
DatabaseConfig {
|
||||
user: opt.user.unwrap_or(self.user),
|
||||
password: opt.password.unwrap_or(self.password),
|
||||
host: opt.host.unwrap_or(self.host),
|
||||
port: opt.port.unwrap_or(self.port),
|
||||
database: opt.database.unwrap_or(self.database),
|
||||
pool_size: opt.pool_size.unwrap_or(self.pool_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<FederationConfigOpt> 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);
|
||||
fn merge(self, opt: FederationConfigOpt) -> Self {
|
||||
FederationConfig {
|
||||
enabled: opt.enabled.unwrap_or(self.enabled),
|
||||
allowed_instances: opt.allowed_instances.unwrap_or(self.allowed_instances),
|
||||
blocked_instances: opt.blocked_instances.unwrap_or(self.blocked_instances),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge<CaptchaConfigOpt> 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 merge(self, opt: CaptchaConfigOpt) -> Self {
|
||||
CaptchaConfig {
|
||||
enabled: opt.enabled.unwrap_or(self.enabled),
|
||||
difficulty: opt.difficulty.unwrap_or(self.difficulty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn overwrite_if_some<T>(lhs: &mut T, rhs: Option<T>) {
|
||||
if let Some(x) = rhs {
|
||||
*lhs = x;
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_if_some<T, U>(lhs: &mut T, rhs: Option<U>)
|
||||
fn merge_structs<T, U>(lhs: T, rhs: Option<U>) -> T
|
||||
where
|
||||
T: Merge<U>,
|
||||
T: Merge<U> + std::clone::Clone,
|
||||
{
|
||||
if let Some(x) = rhs {
|
||||
lhs.merge(x);
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_if_some_opt<T, U>(lhs: &mut Option<T>, rhs: Option<U>)
|
||||
where
|
||||
T: Merge<U>,
|
||||
{
|
||||
if let Some(x) = rhs {
|
||||
if let Some(y) = lhs {
|
||||
y.merge(x)
|
||||
}
|
||||
lhs.merge(x)
|
||||
} else {
|
||||
lhs.to_owned()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
};
|
||||
use anyhow::{anyhow, Context};
|
||||
use deser_hjson::from_str;
|
||||
use std::{env, fs, io::Error, sync::RwLock};
|
||||
use std::{env, fs, sync::RwLock};
|
||||
|
||||
pub mod defaults;
|
||||
mod environment;
|
||||
|
@ -39,10 +39,12 @@ impl Settings {
|
|||
let mut config = Settings::default();
|
||||
|
||||
// Read the config file
|
||||
config.merge(from_str::<SettingsOpt>(&Self::read_config_file()?)?);
|
||||
if let Some(config_file) = &Self::read_config_file() {
|
||||
config = config.merge(from_str::<SettingsOpt>(config_file)?);
|
||||
}
|
||||
|
||||
// Read env vars
|
||||
config.merge(parse_from_env());
|
||||
config = config.merge(parse_from_env());
|
||||
|
||||
if config.hostname == Settings::default().hostname {
|
||||
return Err(anyhow!("Hostname variable is not set!").into());
|
||||
|
@ -68,8 +70,8 @@ impl Settings {
|
|||
env::var("LEMMY_CONFIG_LOCATION").unwrap_or_else(|_| CONFIG_FILE.to_string())
|
||||
}
|
||||
|
||||
pub fn read_config_file() -> Result<String, Error> {
|
||||
fs::read_to_string(Self::get_config_location())
|
||||
pub fn read_config_file() -> Option<String> {
|
||||
fs::read_to_string(Self::get_config_location()).ok()
|
||||
}
|
||||
|
||||
pub fn get_allowed_instances(&self) -> Vec<String> {
|
||||
|
@ -133,7 +135,7 @@ impl Settings {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn save_config_file(data: &str) -> Result<String, Error> {
|
||||
pub fn save_config_file(data: &str) -> Result<String, LemmyError> {
|
||||
fs::write(CONFIG_FILE, data)?;
|
||||
|
||||
// Reload the new settings
|
||||
|
@ -144,6 +146,6 @@ impl Settings {
|
|||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
|
||||
Self::read_config_file()
|
||||
Self::read_config_file().ok_or(anyhow!("Failed to read config").into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ services:
|
|||
lemmy-alpha:
|
||||
image: lemmy-federation:latest
|
||||
environment:
|
||||
- RUST_BACKTRACE=full
|
||||
- LEMMY_HOSTNAME=lemmy-alpha:8541
|
||||
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
|
||||
- LEMMY_JWT_SECRET=changeme
|
||||
|
|
|
@ -8,4 +8,5 @@ for Item in alpha beta gamma delta epsilon ; do
|
|||
sudo chown -R 991:991 volumes/pictrs_$Item
|
||||
done
|
||||
|
||||
sudo docker-compose up
|
||||
sudo docker-compose up -d
|
||||
sudo docker-compose logs -f lemmy-alpha
|
||||
|
|
Loading…
Reference in a new issue