2021-03-09 10:28:54 +00:00
/*
2022-01-08 16:46:05 +00:00
* Copyright ( C ) 2022 Aravinth Manivannan < realaravinth @ batsense . net >
2021-08-04 13:54:35 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https ://www.gnu.org/licenses/>.
* /
2021-05-12 12:32:16 +00:00
use std ::path ::Path ;
2022-10-17 17:49:42 +00:00
use std ::{ env , fs } ;
2021-03-09 10:28:54 +00:00
use config ::{ Config , ConfigError , Environment , File } ;
2022-07-20 12:12:02 +00:00
use derive_more ::Display ;
2021-07-14 14:39:00 +00:00
use log ::{ debug , warn } ;
2022-07-20 12:12:02 +00:00
use serde ::{ Deserialize , Serialize } ;
2021-03-09 10:28:54 +00:00
use url ::Url ;
#[ derive(Debug, Clone, Deserialize) ]
pub struct Server {
pub port : u32 ,
pub domain : String ,
pub cookie_secret : String ,
pub ip : String ,
2021-04-11 17:53:14 +00:00
pub url_prefix : Option < String > ,
2021-08-05 15:35:27 +00:00
pub proxy_has_tls : bool ,
2021-03-09 10:28:54 +00:00
}
2021-03-10 15:13:25 +00:00
#[ derive(Debug, Clone, Deserialize) ]
pub struct Captcha {
pub salt : String ,
2021-03-24 09:01:11 +00:00
pub gc : u64 ,
2022-08-09 10:58:30 +00:00
pub runners : Option < usize > ,
pub queue_length : usize ,
2022-05-27 09:55:33 +00:00
pub enable_stats : bool ,
2021-12-03 08:51:18 +00:00
pub default_difficulty_strategy : DefaultDifficultyStrategy ,
}
#[ derive(Debug, Clone, Deserialize) ]
pub struct DefaultDifficultyStrategy {
pub avg_traffic_difficulty : u32 ,
pub broke_my_site_traffic_difficulty : u32 ,
pub peak_sustainable_traffic_difficulty : u32 ,
pub duration : u32 ,
2021-03-10 15:13:25 +00:00
}
2021-06-29 15:38:40 +00:00
#[ derive(Debug, Clone, Deserialize) ]
pub struct Smtp {
pub from : String ,
2021-07-09 06:34:48 +00:00
pub reply : String ,
2021-06-29 15:38:40 +00:00
pub url : String ,
pub username : String ,
pub password : String ,
2021-06-30 15:27:26 +00:00
pub port : u16 ,
2021-06-29 15:38:40 +00:00
}
2021-03-09 10:28:54 +00:00
impl Server {
2021-03-10 16:07:20 +00:00
#[ cfg(not(tarpaulin_include)) ]
2021-03-09 10:28:54 +00:00
pub fn get_ip ( & self ) -> String {
format! ( " {} : {} " , self . ip , self . port )
}
}
2022-07-20 12:12:02 +00:00
//#[derive(Debug, Clone, Deserialize)]
//struct DatabaseBuilder {
// pub port: u32,
// pub hostname: String,
// pub username: String,
// pub password: String,
// pub name: String,
//}
//impl DatabaseBuilder {
// #[cfg(not(tarpaulin_include))]
// fn extract_database_url(url: &Url) -> Self {
2022-08-04 15:06:54 +00:00
// debug!("Database name: {}", url.path());
2022-07-20 12:12:02 +00:00
// let mut path = url.path().split('/');
// path.next();
// let name = path.next().expect("no database name").to_string();
// DatabaseBuilder {
// port: url.port().expect("Enter database port").into(),
// hostname: url.host().expect("Enter database host").to_string(),
// username: url.username().into(),
// password: url.password().expect("Enter database password").into(),
// name,
// }
// }
//}
#[ derive(Deserialize, Serialize, Display, PartialEq, Clone, Debug) ]
#[ serde(rename_all = " lowercase " ) ]
pub enum DBType {
#[ display(fmt = " postgres " ) ]
Postgres ,
#[ display(fmt = " maria " ) ]
Maria ,
2021-03-09 10:28:54 +00:00
}
2022-07-20 12:12:02 +00:00
impl DBType {
fn from_url ( url : & Url ) -> Result < Self , ConfigError > {
match url . scheme ( ) {
" mysql " = > Ok ( Self ::Maria ) ,
" postgres " = > Ok ( Self ::Postgres ) ,
_ = > Err ( ConfigError ::Message ( " Unknown database type " . into ( ) ) ) ,
2021-03-09 10:28:54 +00:00
}
}
}
#[ derive(Debug, Clone, Deserialize) ]
pub struct Database {
pub url : String ,
pub pool : u32 ,
2022-07-20 12:12:02 +00:00
pub database_type : DBType ,
2021-03-09 10:28:54 +00:00
}
2021-06-11 14:01:03 +00:00
#[ derive(Debug, Clone, Deserialize) ]
pub struct Redis {
pub url : String ,
pub pool : u32 ,
}
2021-03-09 10:28:54 +00:00
#[ derive(Debug, Clone, Deserialize) ]
pub struct Settings {
pub debug : bool ,
2021-08-04 13:54:35 +00:00
pub commercial : bool ,
2021-03-09 10:28:54 +00:00
pub database : Database ,
2021-06-11 14:01:03 +00:00
pub redis : Option < Redis > ,
2021-03-09 10:28:54 +00:00
pub server : Server ,
2021-12-03 08:51:18 +00:00
pub captcha : Captcha ,
2021-05-02 13:06:39 +00:00
pub source_code : String ,
2021-06-29 15:38:40 +00:00
pub smtp : Option < Smtp > ,
2021-08-09 05:07:19 +00:00
pub allow_registration : bool ,
pub allow_demo : bool ,
2021-03-09 10:28:54 +00:00
}
#[ cfg(not(tarpaulin_include)) ]
impl Settings {
pub fn new ( ) -> Result < Self , ConfigError > {
let mut s = Config ::new ( ) ;
2021-05-12 12:32:16 +00:00
const CURRENT_DIR : & str = " ./config/default.toml " ;
2021-06-01 12:03:47 +00:00
const ETC : & str = " /etc/mcaptcha/config.toml " ;
2021-05-12 12:32:16 +00:00
2022-05-27 09:55:33 +00:00
s . set ( " capatcha.enable_stats " , true . to_string ( ) )
. expect ( " unable to set capatcha.enable_stats default config " ) ;
2021-06-01 12:03:47 +00:00
if let Ok ( path ) = env ::var ( " MCAPTCHA_CONFIG " ) {
2022-10-22 19:28:58 +00:00
let absolute_path = Path ::new ( & path ) . canonicalize ( ) . unwrap ( ) ;
log ::info! (
2022-10-24 14:22:10 +00:00
" Loading config file from {} " ,
absolute_path . to_str ( ) . unwrap ( )
2022-10-22 19:28:58 +00:00
) ;
s . merge ( File ::with_name ( absolute_path . to_str ( ) . unwrap ( ) ) ) ? ;
2021-05-12 12:32:16 +00:00
} else if Path ::new ( CURRENT_DIR ) . exists ( ) {
2022-10-22 19:28:58 +00:00
let absolute_path = fs ::canonicalize ( CURRENT_DIR ) . unwrap ( ) ;
log ::info! (
2022-10-24 14:22:10 +00:00
" Loading config file from {} " ,
absolute_path . to_str ( ) . unwrap ( )
2022-10-22 19:28:58 +00:00
) ;
2021-05-12 12:32:16 +00:00
// merging default config from file
2022-10-22 19:28:58 +00:00
s . merge ( File ::with_name ( absolute_path . to_str ( ) . unwrap ( ) ) ) ? ;
2021-05-12 12:32:16 +00:00
} else if Path ::new ( ETC ) . exists ( ) {
2022-10-17 17:49:42 +00:00
log ::info! ( " {} " , format! ( " Loading config file from {} " , ETC ) ) ;
2021-05-12 12:32:16 +00:00
s . merge ( File ::with_name ( ETC ) ) ? ;
} else {
2022-10-17 17:49:42 +00:00
log ::warn! ( " Configuration file not found " ) ;
2021-05-12 12:32:16 +00:00
}
2021-03-09 10:28:54 +00:00
2021-06-01 12:03:47 +00:00
s . merge ( Environment ::with_prefix ( " MCAPTCHA " ) . separator ( " _ " ) ) ? ;
2021-03-09 10:28:54 +00:00
2021-05-02 13:06:39 +00:00
check_url ( & s ) ;
2022-10-17 17:49:42 +00:00
if let Ok ( val ) = env ::var ( " PORT " ) {
s . set ( " server.port " , val ) . unwrap ( ) ;
log ::info! ( " Overriding [server].port with environment variable " ) ;
2021-03-09 10:28:54 +00:00
}
match env ::var ( " DATABASE_URL " ) {
Ok ( val ) = > {
let url = Url ::parse ( & val ) . expect ( " couldn't parse Database URL " ) ;
2022-07-20 12:12:02 +00:00
s . set ( " database.url " , url . to_string ( ) ) . unwrap ( ) ;
2022-07-23 11:16:49 +00:00
let database_type = DBType ::from_url ( & url ) . unwrap ( ) ;
s . set ( " database.database_type " , database_type . to_string ( ) )
. unwrap ( ) ;
2022-10-17 17:49:42 +00:00
log ::info! ( " Overriding [database].url and [database].database_type with environment variable " ) ;
2022-07-20 12:12:02 +00:00
}
Err ( e ) = > {
set_database_url ( & mut s ) ;
2021-03-09 10:28:54 +00:00
}
}
2022-05-07 10:40:14 +00:00
// setting default values
#[ cfg(test) ]
s . set ( " database.pool " , 2. to_string ( ) )
. expect ( " Couldn't set database pool count " ) ;
2021-05-12 12:32:16 +00:00
match s . try_into ( ) {
Ok ( val ) = > Ok ( val ) ,
2021-06-11 18:09:38 +00:00
Err ( e ) = > Err ( ConfigError ::Message ( format! ( " \n \n Error: {} . If it says missing fields, then please refer to https://github.com/mCaptcha/mcaptcha#configuration to learn more about how mcaptcha reads configuration \n \n " , e ) ) ) ,
2021-05-12 12:32:16 +00:00
}
2021-03-09 10:28:54 +00:00
}
}
2021-05-02 13:06:39 +00:00
#[ cfg(not(tarpaulin_include)) ]
fn check_url ( s : & Config ) {
let url = s
. get ::< String > ( " source_code " )
. expect ( " Couldn't access source_code " ) ;
Url ::parse ( & url ) . expect ( " Please enter a URL for source_code in settings " ) ;
}
2021-03-10 16:07:20 +00:00
#[ cfg(not(tarpaulin_include)) ]
2021-03-09 10:28:54 +00:00
fn set_database_url ( s : & mut Config ) {
s . set (
" database.url " ,
format! (
r "postgres://{}:{}@{}:{}/{}" ,
s . get ::< String > ( " database.username " )
. expect ( " Couldn't access database username " ) ,
2022-10-22 19:28:58 +00:00
urlencoding ::encode (
s . get ::< String > ( " database.password " )
. expect ( " Couldn't access database password " )
. as_str ( )
) ,
2021-03-09 10:28:54 +00:00
s . get ::< String > ( " database.hostname " )
. expect ( " Couldn't access database hostname " ) ,
s . get ::< String > ( " database.port " )
. expect ( " Couldn't access database port " ) ,
s . get ::< String > ( " database.name " )
. expect ( " Couldn't access database name " )
) ,
)
2022-08-04 15:06:54 +00:00
. expect ( " Couldn't set database url " ) ;
2021-03-09 10:28:54 +00:00
}
2021-04-11 17:53:14 +00:00
2021-04-14 04:15:59 +00:00
//#[cfg(test)]
//mod tests {
// use super::*;
//
// #[test]
// fn url_prefix_test() {
// let mut settings = Settings::new().unwrap();
// assert!(settings.server.url_prefix.is_none());
// settings.server.url_prefix = Some("test".into());
// settings.server.check_url_prefix();
// settings.server.url_prefix = Some(" ".into());
// settings.server.check_url_prefix();
// assert!(settings.server.url_prefix.is_none());
// }
2021-06-29 15:38:40 +00:00
//
// #[test]
// fn smtp_config_works() {
// let settings = Settings::new().unwrap();
// assert!(settings.smtp.is_some());
// assert_eq!(settings.smtp.as_ref().unwrap().password, "password");
// assert_eq!(settings.smtp.as_ref().unwrap().username, "admin");
// }
2021-04-14 04:15:59 +00:00
//}