97 lines
3.3 KiB
Rust
97 lines
3.3 KiB
Rust
use std::{path::Path, sync::OnceLock};
|
|
|
|
use config::Config;
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct ServerConfig {
|
|
pub address: Option<String>,
|
|
pub port: Option<u16>,
|
|
}
|
|
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct PostgresConfig {
|
|
pub host: Option<String>,
|
|
pub port: Option<u16>,
|
|
pub user: String,
|
|
pub password: String,
|
|
pub name: String,
|
|
}
|
|
|
|
/// Rendering of the lecture notes to pdf
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct NotesConfig {
|
|
/// Directory of `template.tex`, `box-filter.lua` and `assets/`
|
|
pub template_dir: String,
|
|
/// Logo shown at the top right, relative to `template_dir`
|
|
pub logo: Option<String>,
|
|
/// Shown in the header of the pdf
|
|
pub student_name: Option<String>,
|
|
pub student_id: Option<String>,
|
|
}
|
|
|
|
/// TimeTagger account the focus sessions are counted in
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct TimetaggerConfig {
|
|
/// Api of the TimeTagger server, `https://timetagger.app/api/v2` by default
|
|
pub url: Option<String>,
|
|
/// Api token, from the account page of TimeTagger
|
|
pub token: String,
|
|
}
|
|
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct AppConfig {
|
|
pub server: ServerConfig,
|
|
pub postgres: PostgresConfig,
|
|
/// Directory containing the built frontend
|
|
pub frontend_dir: String,
|
|
/// Where the files of the courses and associations are stored (lecture notes,
|
|
/// pdf...), one folder each. A local directory standing in for the NAS for now.
|
|
pub storage_dir: String,
|
|
pub notes: NotesConfig,
|
|
/// Optional: without it the pomodoro only counts the time in the app
|
|
pub timetagger: Option<TimetaggerConfig>,
|
|
}
|
|
|
|
impl AppConfig {
|
|
pub fn get_bind_address(&self) -> String {
|
|
let address = self.server.address.clone().unwrap_or("0.0.0.0".to_owned());
|
|
let port = self.server.port.unwrap_or(3000);
|
|
format!("{}:{}", address, port)
|
|
}
|
|
|
|
pub fn get_postgresql_url(&self) -> String {
|
|
let host = self.postgres.host.clone().unwrap_or("localhost".to_owned());
|
|
let port = self.postgres.port.unwrap_or(5432);
|
|
let user = self.postgres.user.clone();
|
|
let password = self.postgres.password.clone();
|
|
let name = self.postgres.name.clone();
|
|
format!("postgres://{user}:{password}@{host}:{port}/{name}")
|
|
}
|
|
}
|
|
|
|
/// Loads the configuration, by decreasing priority:
|
|
/// - `APP__SERVER__PORT=3000` style environment variables
|
|
/// - `./config.yml`
|
|
/// - the file pointed by `$APP_CONFIG` (`/etc/studium/config.yml` by default)
|
|
pub fn get() -> &'static AppConfig {
|
|
static CONFIG: OnceLock<AppConfig> = OnceLock::new();
|
|
CONFIG.get_or_init(|| {
|
|
let config_path =
|
|
std::env::var("APP_CONFIG").unwrap_or("/etc/studium/config.yml".to_owned());
|
|
let config_path = Path::new(&config_path);
|
|
|
|
let raw = Config::builder()
|
|
.add_source(config::File::from(config_path).required(false))
|
|
.add_source(config::File::with_name("config").required(false))
|
|
.add_source(
|
|
config::Environment::with_prefix("APP")
|
|
.separator("__")
|
|
.ignore_empty(true),
|
|
)
|
|
.build()
|
|
.expect("Invalid config source");
|
|
raw.try_deserialize::<AppConfig>()
|
|
.expect("Invalid config format")
|
|
})
|
|
}
|