1use std::path::PathBuf;
6
7use hmac::{digest::InvalidLength, Hmac, Mac};
8use sha2::Sha256;
9
10use crate::pathutils::Paths;
11
12#[derive(Clone)]
13pub struct EnvVars {
14 pub db_name: String,
17 pub db_host: String,
19 pub db_port: String,
21 pub db_user: String,
23 pub db_password: String,
25
26 pub gh_client_id: String,
29 pub gh_client_secret: String,
31 jwt_secret: String,
33 pub gh_org_name: String,
35 pub gh_org_team_slug: String,
37 pub gh_admin_usernames: String,
39 pub slack_webhook_url: String,
41
42 pub max_upload_limit: usize,
45 pub log_location: PathBuf,
47
48 static_files_url: String,
51 static_file_storage_location: PathBuf,
53 uploaded_qps_path: PathBuf,
55 library_qps_path: PathBuf,
57
58 pub server_port: i32,
61
62 pub cors_allowed_origins: String,
65
66 pub paths: Paths,
68}
69
70impl EnvVars {
71 pub fn parse() -> Result<Self, Box<dyn std::error::Error>> {
73 let db_name = std::env::var("DB_NAME")?;
74 let db_host = std::env::var("DB_HOST")?;
75 let db_port = std::env::var("DB_PORT")?;
76 let db_user = std::env::var("DB_USER")?;
77 let db_password = std::env::var("DB_PASSWORD")?;
78 let gh_client_id = std::env::var("GH_CLIENT_ID")?;
79 let jwt_secret = std::env::var("JWT_SECRET")?;
80 let gh_client_secret = std::env::var("GH_CLIENT_SECRET")?;
81 let gh_org_name = std::env::var("GH_ORG_NAME").unwrap_or_default();
82 let gh_org_team_slug = std::env::var("GH_ORG_TEAM_SLUG").unwrap_or_default();
83 let gh_admin_usernames = std::env::var("GH_ADMIN_USERNAMES").unwrap_or_default();
84 let slack_webhook_url = std::env::var("SLACK_WEBHOOK_URL").unwrap_or_default();
85 let max_upload_limit = std::env::var("MAX_UPLOAD_LIMIT")
86 .unwrap_or_else(|_| "10".to_string())
87 .parse::<usize>()?;
88 let log_location = std::env::var("LOG_LOCATION")
89 .unwrap_or_else(|_| "./log/application.log".to_string())
90 .into();
91 let static_files_url = std::env::var("STATIC_FILES_URL")
92 .unwrap_or_else(|_| "https://static.metakgp.org".to_string());
93 let static_file_storage_location = std::env::var("STATIC_FILE_STORAGE_LOCATION")
94 .unwrap_or_else(|_| "/srv/static".to_string())
95 .into();
96 let uploaded_qps_path = std::env::var("UPLOADED_QPS_PATH")
97 .unwrap_or_else(|_| "/iqps/uploaded".to_string())
98 .into();
99 let library_qps_path = std::env::var("LIBRARY_QPS_PATH")
100 .unwrap_or_else(|_| "/peqp/qp".to_string())
101 .into();
102 let server_port = std::env::var("SERVER_PORT")
103 .unwrap_or_else(|_| "8080".to_string())
104 .parse::<i32>()?;
105 let cors_allowed_origins = std::env::var("CORS_ALLOWED_ORIGINS")
106 .unwrap_or_else(|_| "https://qp.metakgp.org,http://localhost:5173".to_string());
107 Ok(Self {
108 db_name,
109 db_host,
110 db_port,
111 db_user,
112 db_password,
113 gh_client_id,
114 jwt_secret,
115 gh_client_secret,
116 gh_org_name,
117 gh_org_team_slug,
118 gh_admin_usernames,
119 slack_webhook_url,
120 max_upload_limit,
121 log_location,
122 static_files_url,
123 static_file_storage_location,
124 uploaded_qps_path,
125 library_qps_path,
126 server_port,
127 cors_allowed_origins,
128 paths: Paths::default(),
129 })
130 }
131
132 pub fn process(mut self) -> Result<Self, Box<dyn std::error::Error>> {
134 self.paths = Paths::new(
135 &self.static_files_url,
136 &self.static_file_storage_location,
137 &self.uploaded_qps_path,
138 &self.library_qps_path,
139 )?;
140 self.log_location = std::path::absolute(self.log_location)?;
141
142 Ok(self)
143 }
144
145 pub fn get_jwt_key(&self) -> Result<Hmac<Sha256>, InvalidLength> {
147 Hmac::new_from_slice(self.jwt_secret.as_bytes())
148 }
149}