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_org_admin_token: String,
31 jwt_secret: String,
33 pub gh_client_secret: String,
35 pub gh_org_name: String,
37 pub gh_org_team_slug: String,
39 pub gh_admin_usernames: String,
41 pub slack_webhook_url: String,
43
44 pub max_upload_limit: usize,
47 pub log_location: PathBuf,
49
50 static_files_url: String,
53 static_file_storage_location: PathBuf,
55 uploaded_qps_path: PathBuf,
57 library_qps_path: PathBuf,
59
60 pub server_port: i32,
63
64 pub cors_allowed_origins: String,
67
68 pub paths: Paths,
70}
71
72impl EnvVars {
73 pub fn parse() -> Result<Self, Box<dyn std::error::Error>> {
75 let db_name = std::env::var("DB_NAME")?;
76 let db_host = std::env::var("DB_HOST")?;
77 let db_port = std::env::var("DB_PORT")?;
78 let db_user = std::env::var("DB_USER")?;
79 let db_password = std::env::var("DB_PASSWORD")?;
80 let gh_client_id = std::env::var("GH_CLIENT_ID")?;
81 let gh_org_admin_token = std::env::var("GH_ORG_ADMIN_TOKEN")?;
82 let jwt_secret = std::env::var("JWT_SECRET")?;
83 let gh_client_secret = std::env::var("GH_CLIENT_SECRET")?;
84 let gh_org_name = std::env::var("GH_ORG_NAME").unwrap_or_default();
85 let gh_org_team_slug = std::env::var("GH_ORG_TEAM_SLUG").unwrap_or_default();
86 let gh_admin_usernames = std::env::var("GH_ADMIN_USERNAMES").unwrap_or_default();
87 let slack_webhook_url = std::env::var("SLACK_WEBHOOK_URL").unwrap_or_default();
88 let max_upload_limit = std::env::var("MAX_UPLOAD_LIMIT")
89 .unwrap_or_else(|_| "10".to_string())
90 .parse::<usize>()?;
91 let log_location = std::env::var("LOG_LOCATION")
92 .unwrap_or_else(|_| "./log/application.log".to_string())
93 .into();
94 let static_files_url = std::env::var("STATIC_FILES_URL")
95 .unwrap_or_else(|_| "https://static.metakgp.org".to_string());
96 let static_file_storage_location = std::env::var("STATIC_FILE_STORAGE_LOCATION")
97 .unwrap_or_else(|_| "/srv/static".to_string())
98 .into();
99 let uploaded_qps_path = std::env::var("UPLOADED_QPS_PATH")
100 .unwrap_or_else(|_| "/iqps/uploaded".to_string())
101 .into();
102 let library_qps_path = std::env::var("LIBRARY_QPS_PATH")
103 .unwrap_or_else(|_| "/peqp/qp".to_string())
104 .into();
105 let server_port = std::env::var("SERVER_PORT")
106 .unwrap_or_else(|_| "8080".to_string())
107 .parse::<i32>()?;
108 let cors_allowed_origins = std::env::var("CORS_ALLOWED_ORIGINS")
109 .unwrap_or_else(|_| "https://qp.metakgp.org,http://localhost:5173".to_string());
110 Ok(Self {
111 db_name,
112 db_host,
113 db_port,
114 db_user,
115 db_password,
116 gh_client_id,
117 gh_org_admin_token,
118 jwt_secret,
119 gh_client_secret,
120 gh_org_name,
121 gh_org_team_slug,
122 gh_admin_usernames,
123 slack_webhook_url,
124 max_upload_limit,
125 log_location,
126 static_files_url,
127 static_file_storage_location,
128 uploaded_qps_path,
129 library_qps_path,
130 server_port,
131 cors_allowed_origins,
132 paths: Paths::default(),
133 })
134 }
135
136 pub fn process(mut self) -> Result<Self, Box<dyn std::error::Error>> {
138 self.paths = Paths::new(
139 &self.static_files_url,
140 &self.static_file_storage_location,
141 &self.uploaded_qps_path,
142 &self.library_qps_path,
143 )?;
144 self.log_location = std::path::absolute(self.log_location)?;
145
146 Ok(self)
147 }
148
149 pub fn get_jwt_key(&self) -> Result<Hmac<Sha256>, InvalidLength> {
151 Hmac::new_from_slice(self.jwt_secret.as_bytes())
152 }
153}