1use std::path::PathBuf;
6
7use hmac::{digest::InvalidLength, Hmac, Mac};
8use sha2::Sha256;
9
10use crate::pathutils::Paths;
11
12pub struct EnvVars {
13 pub db_name: String,
16 pub db_host: String,
18 pub db_port: String,
20 pub db_user: String,
22 pub db_password: String,
24
25 pub gh_client_id: String,
28 pub gh_client_secret: String,
30 jwt_secret: String,
32 pub gh_org_name: String,
34 pub gh_org_team_slug: String,
36 pub gh_admin_usernames: String,
38 pub slack_webhook_url: String,
40
41 pub max_upload_limit: usize,
44 pub log_location: PathBuf,
46
47 static_files_url: String,
50 static_file_storage_location: PathBuf,
52 uploaded_qps_path: PathBuf,
54 library_qps_path: PathBuf,
56
57 pub server_port: i32,
60
61 pub cors_allowed_origins: String,
64
65 pub paths: Paths,
67}
68
69impl EnvVars {
70 pub fn parse() -> Result<Self, Box<dyn std::error::Error>> {
72 let db_name = std::env::var("DB_NAME")?;
73 let db_host = std::env::var("DB_HOST")?;
74 let db_port = std::env::var("DB_PORT")?;
75 let db_user = std::env::var("DB_USER")?;
76 let db_password = std::env::var("DB_PASSWORD")?;
77 let gh_client_id = std::env::var("GH_CLIENT_ID")?;
78 let jwt_secret = std::env::var("JWT_SECRET")?;
79 let gh_client_secret = std::env::var("GH_CLIENT_SECRET")?;
80 let gh_org_name = std::env::var("GH_ORG_NAME").unwrap_or_default();
81 let gh_org_team_slug = std::env::var("GH_ORG_TEAM_SLUG").unwrap_or_default();
82 let gh_admin_usernames = std::env::var("GH_ADMIN_USERNAMES").unwrap_or_default();
83 let slack_webhook_url = std::env::var("SLACK_WEBHOOK_URL").unwrap_or_default();
84 let max_upload_limit: usize = std::env::var("MAX_UPLOAD_LIMIT")
85 .map(|s| s.parse())
86 .unwrap_or(Ok(10))?;
87 let log_location = std::env::var("LOG_LOCATION")
88 .unwrap_or("./log/application.log".to_string())
89 .into();
90 let static_files_url =
91 std::env::var("STATIC_FILES_URL").unwrap_or("https://static.metakgp.org".to_string());
92 let static_file_storage_location = std::env::var("STATIC_FILE_STORAGE_LOCATION")
93 .unwrap_or("/srv/static".to_string())
94 .into();
95 let uploaded_qps_path = std::env::var("UPLOADED_QPS_PATH")
96 .unwrap_or("/iqps/uploaded".to_string())
97 .into();
98 let library_qps_path = std::env::var("LIBRARY_QPS_PATH")
99 .unwrap_or("/peqp/qp".to_string())
100 .into();
101 let server_port: i32 = std::env::var("SERVER_PORT")
102 .map(|s| s.parse())
103 .unwrap_or(Ok(8080))?;
104 let cors_allowed_origins = std::env::var("CORS_ALLOWED_ORIGINS")
105 .unwrap_or("https://qp.metakgp.org,http://localhost:5173".to_string());
106
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}