medullah_web/
app_setup.rs1use std::path::Path;
2#[allow(unused_imports)]
3use std::sync::Arc;
4use std::{env, fs};
5
6#[cfg(feature = "mailer")]
7use crate::app_state::AppMailerConfig;
8use crate::app_state::{AppHelpers, AppServices, MedullahState};
9#[cfg(feature = "database")]
10use crate::database::DBPool;
11#[cfg(feature = "jwt")]
12use crate::helpers::jwt::Jwt;
13#[cfg(feature = "crypto")]
14use crate::helpers::password::Password;
15use crate::http::Method;
16#[cfg(feature = "rabbitmq")]
17use crate::prelude::RabbitMQ;
18#[cfg(feature = "redis")]
19use crate::prelude::Redis;
20#[cfg(feature = "rabbitmq")]
21use crate::rabbitmq::conn::establish_rabbit_connection_pool;
22#[cfg(feature = "redis")]
23use crate::redis::conn::establish_redis_connection_pool;
24#[cfg(feature = "redis")]
25use crate::services::cache_service::CacheService;
26use crate::MEDULLAH;
27#[cfg(feature = "database")]
28use diesel::r2d2::ConnectionManager;
29#[cfg(feature = "database")]
30use diesel::PgConnection;
31use log::info;
32#[cfg(feature = "templating")]
33use tera::Tera;
34
35pub struct MedullahSetup {
36 pub env_prefix: String,
37 pub private_key: String,
38 pub public_key: String,
39 pub auth_iss_public_key: String,
40 pub allowed_origins: Vec<String>,
41 pub allowed_methods: Vec<Method>,
42}
43
44pub async fn make_app_state(setup: MedullahSetup) -> MedullahState {
45 let app = create_app_state(setup).await;
46 MEDULLAH
47 .set(app.clone())
48 .expect("failed to set up medullah-web");
49 app
50}
51
52async fn create_app_state(setup: MedullahSetup) -> MedullahState {
53 let helpers = make_helpers(&setup.env_prefix, &setup);
54 let env_prefix = setup.env_prefix;
55
56 #[cfg(feature = "database")]
57 let database_pool = establish_database_connection(&env_prefix);
58
59 #[cfg(feature = "redis")]
60 let redis_pool = establish_redis_connection_pool(&env_prefix);
61 #[cfg(feature = "redis")]
62 let redis = Arc::new(Redis::new(redis_pool.clone()));
63
64 #[cfg(feature = "rabbitmq")]
66 let rabbitmq_pool = establish_rabbit_connection_pool(&env_prefix).await;
67
68 #[cfg(feature = "rabbitmq")]
69 let rabbitmq = Arc::new(tokio::sync::Mutex::new(
70 RabbitMQ::new(rabbitmq_pool.clone()).await.unwrap(),
71 ));
72
73 #[cfg(feature = "templating")]
75 let tera_templating = {
76 let tpl_dir = crate::helpers::fs::get_cwd() + "/resources/templates/**/*.tera.html";
77 Tera::new(tpl_dir.as_str()).unwrap()
78 };
79
80 MedullahState {
81 helpers,
82
83 app_id: env::var(format!("{}_APP_ID", env_prefix)).unwrap(),
84 app_domain: env::var(format!("{}_APP_DOMAIN", env_prefix)).unwrap(),
85 app_name: env::var(format!("{}_APP_NAME", env_prefix)).unwrap(),
86 app_desc: env::var(format!("{}_APP_DESC", env_prefix)).unwrap(),
87 app_help_email: env::var(format!("{}_APP_HELP_EMAIL", env_prefix)).unwrap(),
88 app_frontend_url: env::var(format!("{}_FRONTEND_ADDRESS", env_prefix)).unwrap(),
89
90 app_private_key: setup.private_key,
91 app_public_key: setup.public_key,
92 app_key: env::var(format!("{}_APP_KEY", env_prefix)).unwrap(),
93
94 #[cfg(feature = "redis")]
95 redis_pool,
96 #[cfg(feature = "redis")]
97 redis: redis.clone(),
98 #[cfg(feature = "rabbitmq")]
99 rabbitmq_pool,
100 #[cfg(feature = "rabbitmq")]
101 rabbitmq,
102 #[cfg(feature = "database")]
103 database: database_pool,
104 #[cfg(feature = "templating")]
105 tera: tera_templating,
106
107 #[cfg(feature = "jwt")]
108 auth_iss_public_key: setup.auth_iss_public_key,
109 #[cfg(feature = "jwt")]
110 auth_pat_prefix: env::var(format!("{}_AUTH_PAT_PREFIX", env_prefix)).unwrap(),
111 #[cfg(feature = "jwt")]
112 auth_token_lifetime: env::var(format!("{}_AUTH_TOKEN_LIFETIME", env_prefix))
113 .unwrap()
114 .parse()
115 .unwrap(),
116
117 allowed_origins: setup.allowed_origins,
118 allowed_methods: setup.allowed_methods,
119
120 #[cfg(feature = "mailer")]
121 mailer_config: make_mailer_config(&env_prefix),
122
123 services: AppServices {
124 #[cfg(feature = "redis")]
125 cache: Arc::new(CacheService::new(redis)),
126 },
127
128 app_env_prefix: env_prefix,
129 }
130}
131
132pub fn get_server_host_config(env_prefix: &String) -> (String, u16, usize) {
133 let host: String = env::var(format!("{}_SERVER_HOST", env_prefix)).unwrap();
134 let port: u16 = env::var(format!("{}_SERVER_PORT", env_prefix))
135 .unwrap()
136 .parse()
137 .unwrap();
138 let workers: usize = env::var(format!("{}_SERVER_WORKERS", env_prefix))
139 .unwrap()
140 .parse()
141 .unwrap();
142 (host, port, workers)
143}
144
145#[allow(unused_variables)]
146fn make_helpers(env_prefix: &str, setup: &MedullahSetup) -> AppHelpers {
147 #[cfg(feature = "crypto")]
148 let app_key = env::var(format!("{}_APP_KEY", env_prefix)).unwrap();
149
150 #[cfg(feature = "jwt")]
151 let token_lifetime: i64 = env::var(format!("{}_AUTH_TOKEN_LIFETIME", env_prefix))
152 .unwrap()
153 .parse()
154 .unwrap();
155
156 AppHelpers {
157 #[cfg(feature = "jwt")]
158 jwt: Arc::new(Jwt::new(
159 setup.auth_iss_public_key.clone(),
160 setup.private_key.clone(),
161 token_lifetime,
162 )),
163 #[cfg(feature = "crypto")]
164 password: Arc::new(Password::new(app_key)),
165 }
166}
167
168#[cfg(feature = "mailer")]
169fn make_mailer_config(env_prefix: &str) -> AppMailerConfig {
170 AppMailerConfig {
171 from_name: env::var(format!("{}_MAIL_FROM_NAME", env_prefix)).unwrap(),
172 from_email: env::var(format!("{}_MAIL_FROM_EMAIL", env_prefix)).unwrap(),
173 server_endpoint: env::var(format!("{}_MAILER_SERVER_ENDPOINT", env_prefix)).unwrap(),
174 server_auth_token: env::var(format!("{}_MAILER_SERVER_AUTH_TOKEN", env_prefix)).unwrap(),
175 server_application_id: env::var(format!("{}_MAILER_SERVER_APPLICATION_ID", env_prefix))
176 .unwrap(),
177 }
178}
179
180#[cfg(feature = "database")]
181pub fn establish_database_connection(env_prefix: &String) -> DBPool {
182 let db_url: String = env::var(format!("{}_DATABASE_DSN", env_prefix)).unwrap();
183 let manager = ConnectionManager::<PgConnection>::new(db_url);
184 r2d2::Pool::builder()
185 .build(manager)
186 .expect("Failed to create database pool.")
187}
188
189pub fn load_config_file(file: &str) -> String {
190 fs::read_to_string(format!("resources/config/{}", file)).unwrap()
191}
192
193pub fn load_environment_variables(service: &str) {
194 info!(
195 "log level: {:?}",
196 env::var("RUST_LOG").unwrap_or(String::from("info"))
197 );
198 info!("root directory: {:?}", service);
199
200 let path = format!("apps/{}/.env", service);
202 dotenv::from_filename(path).ok();
203
204 if Path::new(".env").exists() {
206 info!("loading env file: .env");
207 dotenv::from_filename(".env").ok();
208 }
209
210 if Path::new(".env.main").exists() {
212 info!("loading env file: .env.main");
213 dotenv::from_filename(".env.main").ok();
214 }
215
216 let filename = format!(".env.{}", service);
218 if Path::new(filename.as_str()).exists() {
219 info!("loading env file: {}", filename);
220 dotenv::from_filename(filename).ok();
221 }
222}