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
|
// Only let admins read this
|
||||||
is_admin(context.pool(), user.id).await?;
|
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 })
|
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_username: env_var("SETUP__ADMIN_USERNAME"),
|
||||||
admin_password: env_var("SETUP__ADMIN_PASSWORD"),
|
admin_password: env_var("SETUP__ADMIN_PASSWORD"),
|
||||||
admin_email: Some(env_var("SETUP__ADMIN_EMAIL")),
|
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 {
|
database: Some(DatabaseConfigOpt {
|
||||||
user: env_var("DATABASE__USER"),
|
user: env_var("DATABASE__USER"),
|
||||||
|
|
|
@ -1,107 +1,141 @@
|
||||||
use crate::settings::{structs::*, structs_opt::*};
|
use crate::settings::{structs::*, structs_opt::*};
|
||||||
|
|
||||||
pub(in crate::settings) trait Merge<T> {
|
pub(in crate::settings) trait Merge<T> {
|
||||||
fn merge(&mut self, opt: T);
|
fn merge(self, opt: T) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Merge<SettingsOpt> for Settings {
|
impl Merge<SettingsOpt> for Settings {
|
||||||
fn merge(&mut self, opt: SettingsOpt) {
|
fn merge(self, opt: SettingsOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.hostname, opt.hostname);
|
Settings {
|
||||||
overwrite_if_some(&mut self.bind, opt.bind);
|
setup: merge_structs(self.setup, opt.setup),
|
||||||
overwrite_if_some(&mut self.port, opt.port);
|
database: merge_structs(self.database, opt.database),
|
||||||
overwrite_if_some(&mut self.tls_enabled, opt.tls_enabled);
|
hostname: opt.hostname.unwrap_or(self.hostname),
|
||||||
overwrite_if_some(&mut self.jwt_secret, opt.jwt_secret);
|
bind: opt.bind.unwrap_or(self.bind),
|
||||||
overwrite_if_some(&mut self.pictrs_url, opt.pictrs_url);
|
port: opt.port.unwrap_or(self.port),
|
||||||
overwrite_if_some(&mut self.iframely_url, opt.iframely_url);
|
tls_enabled: opt.tls_enabled.unwrap_or(self.tls_enabled),
|
||||||
merge_if_some(&mut self.captcha, opt.captcha);
|
jwt_secret: opt.jwt_secret.unwrap_or(self.jwt_secret),
|
||||||
merge_if_some(&mut self.rate_limit, opt.rate_limit);
|
pictrs_url: opt.pictrs_url.unwrap_or(self.pictrs_url),
|
||||||
merge_if_some_opt(&mut self.email, opt.email);
|
iframely_url: opt.iframely_url.unwrap_or(self.iframely_url),
|
||||||
merge_if_some_opt(&mut self.setup, opt.setup);
|
rate_limit: merge_structs(self.rate_limit, opt.rate_limit),
|
||||||
merge_if_some(&mut self.federation, opt.federation);
|
email: merge_structs(self.email, opt.email),
|
||||||
merge_if_some(&mut self.database, opt.database);
|
federation: merge_structs(self.federation, opt.federation),
|
||||||
|
captcha: merge_structs(self.captcha, opt.captcha),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Merge<RateLimitConfigOpt> for RateLimitConfig {
|
impl Merge<RateLimitConfigOpt> for RateLimitConfig {
|
||||||
fn merge(&mut self, opt: RateLimitConfigOpt) {
|
fn merge(self, opt: RateLimitConfigOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.message, opt.message);
|
RateLimitConfig {
|
||||||
overwrite_if_some(&mut self.message_per_second, opt.message_per_second);
|
message: opt.message.unwrap_or(self.message),
|
||||||
overwrite_if_some(&mut self.post, opt.post);
|
message_per_second: opt.message_per_second.unwrap_or(self.message_per_second),
|
||||||
overwrite_if_some(&mut self.post_per_second, opt.post_per_second);
|
post: opt.post.unwrap_or(self.post),
|
||||||
overwrite_if_some(&mut self.register, opt.register);
|
post_per_second: opt.post_per_second.unwrap_or(self.post_per_second),
|
||||||
overwrite_if_some(&mut self.register_per_second, opt.register_per_second);
|
register: opt.register.unwrap_or(self.register),
|
||||||
overwrite_if_some(&mut self.image, opt.image);
|
register_per_second: opt.register_per_second.unwrap_or(self.register_per_second),
|
||||||
overwrite_if_some(&mut self.image_per_second, opt.image_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 {
|
impl Merge<SetupOpt> for Option<Setup> {
|
||||||
fn merge(&mut self, opt: SetupOpt) {
|
fn merge(self, opt: SetupOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.admin_username, opt.admin_username);
|
if let Some(setup) = self {
|
||||||
overwrite_if_some(&mut self.admin_password, opt.admin_password);
|
Some(Setup {
|
||||||
overwrite_if_some(&mut self.admin_email, opt.admin_email);
|
admin_username: opt.admin_username.unwrap_or(setup.admin_username),
|
||||||
overwrite_if_some(&mut self.site_name, opt.site_name);
|
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 {
|
impl Merge<EmailConfigOpt> for Option<EmailConfig> {
|
||||||
fn merge(&mut self, opt: EmailConfigOpt) {
|
fn merge(self, opt: EmailConfigOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.smtp_server, opt.smtp_server);
|
if let Some(email_config) = self {
|
||||||
overwrite_if_some(&mut self.smtp_login, opt.smtp_login);
|
Some(EmailConfig {
|
||||||
overwrite_if_some(&mut self.smtp_password, opt.smtp_password);
|
smtp_server: opt.smtp_server.unwrap_or(email_config.smtp_server),
|
||||||
overwrite_if_some(&mut self.smtp_from_address, opt.smtp_from_address);
|
smtp_login: opt.smtp_login.unwrap_or(email_config.smtp_login),
|
||||||
overwrite_if_some(&mut self.use_tls, opt.use_tls);
|
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 {
|
impl Merge<DatabaseConfigOpt> for DatabaseConfig {
|
||||||
fn merge(&mut self, opt: DatabaseConfigOpt) {
|
fn merge(self, opt: DatabaseConfigOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.user, opt.user);
|
DatabaseConfig {
|
||||||
overwrite_if_some(&mut self.password, opt.password);
|
user: opt.user.unwrap_or(self.user),
|
||||||
overwrite_if_some(&mut self.host, opt.host);
|
password: opt.password.unwrap_or(self.password),
|
||||||
overwrite_if_some(&mut self.port, opt.port);
|
host: opt.host.unwrap_or(self.host),
|
||||||
overwrite_if_some(&mut self.database, opt.database);
|
port: opt.port.unwrap_or(self.port),
|
||||||
overwrite_if_some(&mut self.pool_size, opt.pool_size);
|
database: opt.database.unwrap_or(self.database),
|
||||||
|
pool_size: opt.pool_size.unwrap_or(self.pool_size),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Merge<FederationConfigOpt> for FederationConfig {
|
impl Merge<FederationConfigOpt> for FederationConfig {
|
||||||
fn merge(&mut self, opt: FederationConfigOpt) {
|
fn merge(self, opt: FederationConfigOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.enabled, opt.enabled);
|
FederationConfig {
|
||||||
overwrite_if_some(&mut self.allowed_instances, opt.allowed_instances);
|
enabled: opt.enabled.unwrap_or(self.enabled),
|
||||||
overwrite_if_some(&mut self.blocked_instances, opt.blocked_instances);
|
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 {
|
impl Merge<CaptchaConfigOpt> for CaptchaConfig {
|
||||||
fn merge(&mut self, opt: CaptchaConfigOpt) {
|
fn merge(self, opt: CaptchaConfigOpt) -> Self {
|
||||||
overwrite_if_some(&mut self.enabled, opt.enabled);
|
CaptchaConfig {
|
||||||
overwrite_if_some(&mut self.difficulty, opt.difficulty);
|
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>)
|
|
||||||
where
|
|
||||||
T: Merge<U>,
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn merge_structs<T, U>(lhs: T, rhs: Option<U>) -> T
|
||||||
|
where
|
||||||
|
T: Merge<U> + std::clone::Clone,
|
||||||
|
{
|
||||||
|
if let Some(x) = rhs {
|
||||||
|
lhs.merge(x)
|
||||||
|
} else {
|
||||||
|
lhs.to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use deser_hjson::from_str;
|
use deser_hjson::from_str;
|
||||||
use std::{env, fs, io::Error, sync::RwLock};
|
use std::{env, fs, sync::RwLock};
|
||||||
|
|
||||||
pub mod defaults;
|
pub mod defaults;
|
||||||
mod environment;
|
mod environment;
|
||||||
|
@ -39,10 +39,12 @@ impl Settings {
|
||||||
let mut config = Settings::default();
|
let mut config = Settings::default();
|
||||||
|
|
||||||
// Read the config file
|
// 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
|
// Read env vars
|
||||||
config.merge(parse_from_env());
|
config = config.merge(parse_from_env());
|
||||||
|
|
||||||
if config.hostname == Settings::default().hostname {
|
if config.hostname == Settings::default().hostname {
|
||||||
return Err(anyhow!("Hostname variable is not set!").into());
|
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())
|
env::var("LEMMY_CONFIG_LOCATION").unwrap_or_else(|_| CONFIG_FILE.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_config_file() -> Result<String, Error> {
|
pub fn read_config_file() -> Option<String> {
|
||||||
fs::read_to_string(Self::get_config_location())
|
fs::read_to_string(Self::get_config_location()).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_allowed_instances(&self) -> Vec<String> {
|
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)?;
|
fs::write(CONFIG_FILE, data)?;
|
||||||
|
|
||||||
// Reload the new settings
|
// Reload the new settings
|
||||||
|
@ -144,6 +146,6 @@ impl Settings {
|
||||||
Err(e) => panic!("{}", e),
|
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:
|
lemmy-alpha:
|
||||||
image: lemmy-federation:latest
|
image: lemmy-federation:latest
|
||||||
environment:
|
environment:
|
||||||
|
- RUST_BACKTRACE=full
|
||||||
- LEMMY_HOSTNAME=lemmy-alpha:8541
|
- LEMMY_HOSTNAME=lemmy-alpha:8541
|
||||||
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
|
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
|
||||||
- LEMMY_JWT_SECRET=changeme
|
- 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
|
sudo chown -R 991:991 volumes/pictrs_$Item
|
||||||
done
|
done
|
||||||
|
|
||||||
sudo docker-compose up
|
sudo docker-compose up -d
|
||||||
|
sudo docker-compose logs -f lemmy-alpha
|
||||||
|
|
Loading…
Reference in a new issue