diff --git a/src/constants/inner_constants.rs b/src/constants/inner_constants.rs index 7d313644..cac7aa47 100644 --- a/src/constants/inner_constants.rs +++ b/src/constants/inner_constants.rs @@ -142,6 +142,7 @@ pub static ITUNES: &str = "itunes"; pub const REVERSE_PROXY: &str = "REVERSE_PROXY"; pub const REVERSE_PROXY_HEADER: &str = "REVERSE_PROXY_HEADER"; pub const REVERSE_PROXY_AUTO_SIGN_UP: &str = "REVERSE_PROXY_AUTO_SIGN_UP"; +pub const PODFETCH_PROXY_FOR_REQUESTS: &str = "PODFETCH_PROXY"; - -pub const MAIN_ROOM: &str = "main"; \ No newline at end of file +pub const MAIN_ROOM: &str = "main"; +pub const CONNECTION_NUMBERS: &str = "DB_CONNECTIONS"; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 151b51dc..430528c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use actix_web::web::{redirect, Data}; use actix_web::{web, App, HttpResponse, HttpServer, Responder, Scope}; use clokwerk::{Scheduler, TimeUnits}; use std::collections::HashSet; -use std::env::{args, var}; +use std::env::args; use std::io::Read; use std::sync::Mutex; use std::time::Duration; @@ -125,7 +125,8 @@ pub fn run_poll(mut podcast_service: PodcastService) -> Result<(), CustomError> } fn fix_links(content: &str) -> String { - let dir = var("SUB_DIRECTORY").unwrap() + "/ui/"; + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let dir = env_service.sub_directory.clone().unwrap() + "/ui/"; content.replace("/ui/", &dir) } @@ -139,14 +140,14 @@ async fn index() -> impl Responder { #[actix_web::main] async fn main() -> std::io::Result<()> { - + let env_service = EnvironmentService::new(); println!( "Debug file located at {}", concat!(env!("OUT_DIR"), "/built.rs") ); init_logging(); - ENVIRONMENT_SERVICE.get_or_init(EnvironmentService::new); + ENVIRONMENT_SERVICE.get_or_init(|| env_service); if args().len() > 1 { spawn_blocking(move || start_command_line(args())) @@ -339,6 +340,8 @@ async fn main() -> std::io::Result<()> { hash.insert(oidc_config.client_id); } + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let sub_dir = env_service.sub_directory.clone().unwrap_or("/".to_string()); let http_server = HttpServer::new(move || { App::new() @@ -346,7 +349,7 @@ async fn main() -> std::io::Result<()> { .app_data(Data::new(key_param.clone())) .app_data(Data::new(jwk.clone())) .app_data(Data::new(hash.clone())) - .service(redirect("/", var("SUB_DIRECTORY").unwrap() + "/ui/")) + .service(redirect("/", sub_dir.clone() + "/ui/")) .service(get_gpodder_api()) .service(get_global_scope()) .app_data(Data::new(Mutex::new(podcast_service.clone()))) @@ -356,13 +359,14 @@ async fn main() -> std::io::Result<()> { .app_data(data_pool.clone()) .wrap(Condition::new(cfg!(debug_assertions), Logger::default())) }) - .workers(4) - .bind(("0.0.0.0", 8000))? - .run(); + .workers(4) + .bind(("0.0.0.0", 8000))? + .run(); try_join!(http_server, async move { chat_server.await.unwrap() })?; Ok(()) } + pub fn get_api_config() -> Scope { web::scope("/api/v1").configure(config) } @@ -376,7 +380,8 @@ fn config(cfg: &mut web::ServiceConfig) { } pub fn get_global_scope() -> Scope { - let base_path = var("SUB_DIRECTORY").unwrap_or("/".to_string()); + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let base_path = env_service.sub_directory.clone().unwrap_or("/".to_string()); let openapi = ApiDoc::openapi(); let service = get_api_config(); @@ -576,13 +581,11 @@ fn check_if_multiple_auth_is_configured(env: &EnvironmentService) -> bool { async fn init_postgres_db_pool( database_url: &str, ) -> Result>, String> { - let db_connections = var("DB_CONNECTIONS") - .unwrap_or("10".to_string()) - .parse() - .unwrap_or(10); + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let db_connections = env_service.conn_number; let manager = ConnectionManager::::new(database_url); let pool = Pool::builder() - .max_size(db_connections) + .max_size(db_connections as u32) .build(manager) .expect("Failed to create pool."); Ok(pool) diff --git a/src/models/user.rs b/src/models/user.rs index cb23e27a..63858e98 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,6 +1,4 @@ -use crate::constants::inner_constants::{ - Role, API_KEY, BASIC_AUTH, OIDC_AUTH, STANDARD_USER, USERNAME, -}; +use crate::constants::inner_constants::{Role, BASIC_AUTH, ENVIRONMENT_SERVICE, OIDC_AUTH, STANDARD_USER, USERNAME}; use crate::dbconfig::schema::users; use crate::dbconfig::DBType; use crate::utils::environment_variables::is_env_var_present_and_true; @@ -13,7 +11,6 @@ use diesel::prelude::{Insertable, Queryable}; use diesel::ExpressionMethods; use diesel::QueryDsl; use diesel::{AsChangeset, OptionalExtension, RunQueryDsl}; -use dotenv::var; use std::io::Error; use utoipa::ToSchema; @@ -77,7 +74,8 @@ impl User { conn: &mut DbConnection, ) -> Result { use crate::dbconfig::schema::users::dsl::*; - if let Ok(res) = var(USERNAME) { + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + if let Some(res) = env_service.username.clone() { if res == username_to_find { return Ok(User::create_admin_user()); } @@ -97,8 +95,8 @@ impl User { pub fn insert_user(&mut self, conn: &mut DbConnection) -> Result { use crate::dbconfig::schema::users::dsl::*; - - if let Ok(res) = var(USERNAME) { + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + if let Some(res) = env_service.username.clone() { if res == self.username { return Err(Error::new( std::io::ErrorKind::Other, @@ -144,24 +142,21 @@ impl User { .set(users::explicit_consent.eq(self.explicit_consent)) .get_result::(conn); - Ok(User::map_to_dto(user.unwrap())) + Ok(User::map_to_dto(user?)) } pub(crate) fn create_admin_user() -> User { - use crate::constants::inner_constants::PASSWORD; - - let password: Option = std::env::var(PASSWORD) - .map(Some) - .map_err(|_| None::) - .unwrap(); + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let password: Option = env_service.password.clone(); + let username = env_service.username.clone(); User { id: 9999, - username: var(USERNAME).unwrap().to_string(), + username: username.unwrap_or(STANDARD_USER.to_string()), role: Role::Admin.to_string(), password, explicit_consent: true, created_at: Default::default(), - api_key: var(API_KEY).map(Some).unwrap_or(None), + api_key: env_service.api_key_admin.clone(), } } @@ -187,6 +182,8 @@ impl User { } pub fn create_standard_admin_user() -> User { + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + let api_admin: Option = env_service.api_key_admin.clone(); User { id: 9999, username: STANDARD_USER.to_string(), @@ -194,7 +191,7 @@ impl User { password: None, explicit_consent: true, created_at: Default::default(), - api_key: var(API_KEY).map(Some).unwrap_or(None), + api_key: api_admin, } } @@ -335,7 +332,10 @@ impl User { return false; } - if let Ok(res) = var(API_KEY) { + let env_service = ENVIRONMENT_SERVICE.get().unwrap(); + + + if let Some(res) = env_service.api_key_admin.clone() { if !res.is_empty() && res == api_key_to_find { return true; } diff --git a/src/service/environment_service.rs b/src/service/environment_service.rs index fc0739b4..999b845c 100644 --- a/src/service/environment_service.rs +++ b/src/service/environment_service.rs @@ -1,10 +1,4 @@ -use crate::constants::inner_constants::{ - BASIC_AUTH, DATABASE_URL, DATABASE_URL_DEFAULT_SQLITE, GPODDER_INTEGRATION_ENABLED, OIDC_AUTH, - OIDC_AUTHORITY, OIDC_CLIENT_ID, OIDC_JWKS, OIDC_REDIRECT_URI, OIDC_SCOPE, PASSWORD, - PODINDEX_API_KEY, PODINDEX_API_SECRET, POLLING_INTERVAL, POLLING_INTERVAL_DEFAULT, - REVERSE_PROXY, REVERSE_PROXY_AUTO_SIGN_UP, REVERSE_PROXY_HEADER, SERVER_URL, SUB_DIRECTORY, - TELEGRAM_API_ENABLED, TELEGRAM_BOT_CHAT_ID, TELEGRAM_BOT_TOKEN, USERNAME, -}; +use crate::constants::inner_constants::{API_KEY, BASIC_AUTH, CONNECTION_NUMBERS, DATABASE_URL, DATABASE_URL_DEFAULT_SQLITE, GPODDER_INTEGRATION_ENABLED, OIDC_AUTH, OIDC_AUTHORITY, OIDC_CLIENT_ID, OIDC_JWKS, OIDC_REDIRECT_URI, OIDC_SCOPE, PASSWORD, PODFETCH_PROXY_FOR_REQUESTS, PODINDEX_API_KEY, PODINDEX_API_SECRET, POLLING_INTERVAL, POLLING_INTERVAL_DEFAULT, REVERSE_PROXY, REVERSE_PROXY_AUTO_SIGN_UP, REVERSE_PROXY_HEADER, SERVER_URL, SUB_DIRECTORY, TELEGRAM_API_ENABLED, TELEGRAM_BOT_CHAT_ID, TELEGRAM_BOT_TOKEN, USERNAME}; use crate::models::settings::ConfigModel; use crate::utils::environment_variables::is_env_var_present_and_true; use regex::Regex; @@ -38,6 +32,10 @@ pub struct EnvironmentService { pub database_url: String, pub telegram_api: Option, pub any_auth_enabled: bool, + pub sub_directory: Option, + pub proxy_url: Option, + pub conn_number: i16, + pub api_key_admin: Option, } #[derive(Clone)] @@ -76,14 +74,14 @@ impl EnvironmentService { if !server_url.ends_with('/') { server_url += "/" } - - if var(SUB_DIRECTORY).is_err() { + let mut opt_sub_dir = var(SUB_DIRECTORY).map_err(|_|None::).map(Some).unwrap_or(None); + if opt_sub_dir.is_none() { let re = Regex::new(r"^http[s]?://[^/]+(/.*)?$").unwrap(); let directory = re.captures(&server_url).unwrap().get(1).unwrap().as_str(); if directory.ends_with('/') { - env::set_var(SUB_DIRECTORY, &directory[0..directory.len() - 1]); + opt_sub_dir = Some(directory[0..directory.len() - 1].to_string()); } else { - env::set_var(SUB_DIRECTORY, directory); + opt_sub_dir = Some(directory.to_string()); } } @@ -132,10 +130,14 @@ impl EnvironmentService { gpodder_integration_enabled: is_env_var_present_and_true(GPODDER_INTEGRATION_ENABLED), database_url: var(DATABASE_URL).unwrap_or(DATABASE_URL_DEFAULT_SQLITE.to_string()), telegram_api, + sub_directory: opt_sub_dir, + proxy_url: var(PODFETCH_PROXY_FOR_REQUESTS).map(Some).unwrap_or(None), reverse_proxy: is_env_var_present_and_true(REVERSE_PROXY), any_auth_enabled: is_env_var_present_and_true(BASIC_AUTH) || is_env_var_present_and_true(OIDC_AUTH) || is_env_var_present_and_true(REVERSE_PROXY), + conn_number: var(CONNECTION_NUMBERS).unwrap_or("10".to_string()).parse::().unwrap_or(10), + api_key_admin: dotenv::var(API_KEY).map(Some).unwrap_or(None) } } diff --git a/src/utils/reqwest_client.rs b/src/utils/reqwest_client.rs index ec89c743..74a3bc05 100644 --- a/src/utils/reqwest_client.rs +++ b/src/utils/reqwest_client.rs @@ -1,15 +1,11 @@ -use std::env; use reqwest::blocking::ClientBuilder; use reqwest::Proxy; +use crate::constants::inner_constants::ENVIRONMENT_SERVICE; pub fn get_sync_client() -> ClientBuilder { - let proxy_val = env::var("PODFETCH_PROXY"); - - - let mut res = ClientBuilder::new(); - if let Ok(unwrapped_proxy) = proxy_val { + if let Some(unwrapped_proxy) = ENVIRONMENT_SERVICE.get().unwrap().proxy_url.clone() { let proxy = Proxy::all(unwrapped_proxy); match proxy { Ok(e)=>{ @@ -24,12 +20,11 @@ pub fn get_sync_client() -> ClientBuilder { res } -pub fn get_async_sync_client() -> reqwest::ClientBuilder { - let proxy_val = env::var("PODFETCH_PROXY"); +pub fn get_async_sync_client() -> reqwest::ClientBuilder { let mut res = reqwest::ClientBuilder::new(); - if let Ok(unwrapped_proxy) = proxy_val { + if let Some(unwrapped_proxy) = ENVIRONMENT_SERVICE.get().unwrap().proxy_url.clone() { let proxy = Proxy::all(unwrapped_proxy); match proxy { Ok(e)=>{