sysmonk/squire/
startup.rs1use std;
2use std::io::Write;
3
4use crate::squire::settings;
5use crate::{constant, squire};
6use chrono::{DateTime, Local};
7use regex::Regex;
8
9pub fn init_logger(debug: bool, utc: bool, crate_name: &String) {
16 if debug {
17 std::env::set_var("RUST_LOG", format!(
18 "actix_web=debug,actix_server=info,{}=debug", crate_name
19 ));
20 std::env::set_var("RUST_BACKTRACE", "1");
21 } else {
22 std::env::set_var("RUST_LOG", format!(
24 "actix_web=warn,actix_server=warn,{}=info", crate_name
25 ));
26 std::env::set_var("RUST_BACKTRACE", "0");
27 }
28 let timestamp = if utc {
29 DateTime::<chrono::Utc>::from(Local::now())
30 .format("%Y-%m-%dT%H:%M:%SZ")
31 .to_string()
32 } else {
33 Local::now()
34 .format("%Y-%m-%dT%H:%M:%SZ")
35 .to_string()
36 };
37 env_logger::Builder::from_default_env()
38 .format(move |buf, record| {
39 writeln!(
40 buf,
41 "[{} {} {}:{}] - {}",
42 timestamp,
43 record.level(),
44 record.target(),
45 record.line().unwrap_or(0),
46 record.args()
47 )
48 })
49 .init();
50}
51
52fn mandatory_vars() -> (String, String) {
62 let mut errors = "".to_owned();
63 let username = match std::env::var("username") {
64 Ok(val) => val,
65 Err(_) => {
66 errors.push_str(
67 "\nusername\n\texpected a string, received null [value=missing]\n",
68 );
69 "".to_string()
70 }
71 };
72 let password = match std::env::var("password") {
73 Ok(val) => val,
74 Err(_) => {
75 errors.push_str(
76 "\npassword\n\texpected a string, received null [value=missing]\n",
77 );
78 "".to_string()
79 }
80 };
81 if !errors.is_empty() {
82 panic!("{}", errors);
83 }
84 (username, password)
85}
86
87fn parse_bool(key: &str) -> Option<bool> {
101 match std::env::var(key) {
102 Ok(val) => match val.parse() {
103 Ok(parsed) => Some(parsed),
104 Err(_) => {
105 panic!("\n{}\n\texpected bool, received '{}' [value=invalid]\n", key, val);
106 }
107 },
108 Err(_) => None,
109 }
110}
111
112fn parse_i64(key: &str) -> Option<i64> {
126 match std::env::var(key) {
127 Ok(val) => match val.parse() {
128 Ok(parsed) => Some(parsed),
129 Err(_) => {
130 panic!("\n{}\n\texpected i64, received '{}' [value=invalid]\n", key, val);
131 }
132 },
133 Err(_) => None,
134 }
135}
136
137fn parse_u16(key: &str) -> Option<u16> {
151 match std::env::var(key) {
152 Ok(val) => match val.parse() {
153 Ok(parsed) => Some(parsed),
154 Err(_) => {
155 panic!("\n{}\n\texpected u16, received '{}' [value=invalid]\n", key, val);
156 }
157 },
158 Err(_) => None,
159 }
160}
161
162fn parse_usize(key: &str) -> Option<usize> {
176 match std::env::var(key) {
177 Ok(val) => match val.parse() {
178 Ok(parsed) => Some(parsed),
179 Err(_) => {
180 panic!("\n{}\n\texpected usize, received '{}' [value=invalid]\n", key, val);
181 }
182 },
183 Err(_) => None,
184 }
185}
186
187fn parse_vec(key: &str) -> Option<Vec<String>> {
201 match std::env::var(key) {
202 Ok(val) => match serde_json::from_str::<Vec<String>>(&val) {
203 Ok(parsed) => Some(parsed),
204 Err(_) => {
205 panic!("\n{}\n\texpected vec, received '{}' [value=invalid]\n", key, val);
206 }
207 },
208 Err(_) => None,
209 }
210}
211
212fn load_env_vars() -> settings::Config {
218 let (username, password) = mandatory_vars();
219 let debug = parse_bool("debug").unwrap_or(settings::default_debug());
220 let utc_logging = parse_bool("utc_logging").unwrap_or(settings::default_utc_logging());
221 let host = std::env::var("host").unwrap_or(settings::default_host());
222 let port = parse_u16("port").unwrap_or(settings::default_port());
223 let session_duration = parse_i64("session_duration").unwrap_or(settings::default_session_duration());
224 let workers = parse_usize("workers").unwrap_or(settings::default_workers());
225 let max_connections = parse_usize("max_connections").unwrap_or(settings::default_max_connections());
226 let websites = parse_vec("websites").unwrap_or(settings::default_websites());
227 settings::Config {
228 username,
229 password,
230 debug,
231 utc_logging,
232 host,
233 port,
234 session_duration,
235 workers,
236 max_connections,
237 websites,
238 }
239}
240
241pub fn complexity_checker(password: &str) -> Result<(), String> {
260 let mock_password = "*".repeat(password.len());
261
262 if password.len() < 8 {
264 return Err(
265 format!(
266 "\npassword\n\t[{}] password must be at least 8 or more characters [value=invalid]\n", mock_password
267 )
268 );
269 }
270
271 let has_digit = Regex::new(r"\d").unwrap();
273 if !has_digit.is_match(password) {
274 return Err(
275 format!(
276 "\npassword\n\t[{}] password must include at least one digit [value=invalid]\n", mock_password
277 )
278 );
279 }
280
281 let has_uppercase = Regex::new(r"[A-Z]").unwrap();
283 if !has_uppercase.is_match(password) {
284 return Err(
285 format!(
286 "\npassword\n\t[{}] password must include at least one uppercase letter [value=invalid]\n", mock_password
287 )
288 );
289 }
290
291 let has_lowercase = Regex::new(r"[a-z]").unwrap();
293 if !has_lowercase.is_match(password) {
294 return Err(
295 format!(
296 "\npassword\n\t[{}] password must include at least one lowercase letter [value=invalid]\n", mock_password
297 )
298 );
299 }
300
301 let has_special_char = Regex::new(r###"[ !#$%&'()*+,./:;<=>?@\\^_`{|}~"-]"###).unwrap();
303 if !has_special_char.is_match(password) {
304 return Err(
305 format!(
306 "\npassword\n\t[{}] password must contain at least one special character [value=invalid]\n", mock_password
307 )
308 );
309 }
310 Ok(())
311}
312
313fn validate_vars() -> settings::Config {
319 let config = load_env_vars();
320 let mut errors = "".to_owned();
321 if config.username.len() < 4 {
322 let err1 = format!(
323 "\nusername\n\t[{}] username should be at least 4 or more characters [value=invalid]\n",
324 config.username
325 );
326 errors.push_str(&err1);
327 }
328 match complexity_checker(&config.password) {
329 Ok(_) => (),
330 Err(err) => {
331 errors.push_str(&err);
332 }
333 }
334 if !errors.is_empty() {
335 panic!("{}", errors);
336 }
337 config
338}
339
340pub fn get_config(metadata: &constant::MetaData) -> std::sync::Arc<settings::Config> {
350 let mut env_file = squire::parser::arguments(metadata);
351 if env_file.is_empty() {
352 env_file = std::env::var("env_file")
353 .unwrap_or(std::env::var("ENV_FILE")
354 .unwrap_or(".env".to_string()));
355 }
356 let env_file_path = std::env::current_dir()
357 .unwrap_or_default()
358 .join(env_file);
359 let _ = dotenv::from_path(env_file_path.as_path());
360 std::sync::Arc::new(validate_vars())
361}