115 lines
3.1 KiB
Rust
115 lines
3.1 KiB
Rust
use crate::Result;
|
|
use anyhow::Context;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::{
|
|
collections::HashMap,
|
|
fs::{self, OpenOptions},
|
|
io::Write,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
const DEFAULT_PROFILE_NAME: &str = "default";
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ConfigProfile {
|
|
#[serde(default)]
|
|
pub username: Option<String>,
|
|
#[serde(default = "ConfigProfile::default_base_url")]
|
|
pub base_url: String,
|
|
#[serde(default = "ConfigProfile::default_jsonapi_path")]
|
|
pub jsonapi_path: String,
|
|
#[serde(default)]
|
|
pub basic_auth_b64: Option<String>,
|
|
#[serde(default)]
|
|
pub download_root: Option<PathBuf>,
|
|
#[serde(default = "ConfigProfile::default_max_concurrent_downloads")]
|
|
pub max_concurrent_downloads: usize,
|
|
}
|
|
|
|
impl Default for ConfigProfile {
|
|
fn default() -> Self {
|
|
Self {
|
|
username: None,
|
|
base_url: Self::default_base_url(),
|
|
jsonapi_path: Self::default_jsonapi_path(),
|
|
basic_auth_b64: None,
|
|
download_root: None,
|
|
max_concurrent_downloads: Self::default_max_concurrent_downloads(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ConfigProfile {
|
|
fn default_base_url() -> String {
|
|
"https://studip.uni-trier.de".to_string()
|
|
}
|
|
|
|
fn default_jsonapi_path() -> String {
|
|
"/jsonapi.php/v1".to_string()
|
|
}
|
|
|
|
fn default_max_concurrent_downloads() -> usize {
|
|
3
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ConfigFile {
|
|
#[serde(default = "default_profile_name")]
|
|
pub default_profile: String,
|
|
#[serde(default)]
|
|
pub profiles: HashMap<String, ConfigProfile>,
|
|
}
|
|
|
|
impl Default for ConfigFile {
|
|
fn default() -> Self {
|
|
let mut profiles = HashMap::new();
|
|
profiles.insert(DEFAULT_PROFILE_NAME.to_string(), ConfigProfile::default());
|
|
Self {
|
|
default_profile: DEFAULT_PROFILE_NAME.to_string(),
|
|
profiles,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn default_profile_name() -> String {
|
|
DEFAULT_PROFILE_NAME.to_string()
|
|
}
|
|
|
|
impl ConfigFile {
|
|
pub fn load_or_default(path: &Path) -> Result<Self> {
|
|
match fs::read_to_string(path) {
|
|
Ok(contents) => {
|
|
let file: Self =
|
|
toml::from_str(&contents).context("Failed to parse config.toml")?;
|
|
Ok(file)
|
|
}
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(Self::default()),
|
|
Err(err) => Err(err.into()),
|
|
}
|
|
}
|
|
|
|
pub fn save(&self, path: &Path) -> Result<()> {
|
|
if let Some(parent) = path.parent() {
|
|
fs::create_dir_all(parent)?;
|
|
}
|
|
|
|
let contents = toml::to_string_pretty(self)?;
|
|
|
|
let mut file = OpenOptions::new()
|
|
.create(true)
|
|
.write(true)
|
|
.truncate(true)
|
|
.open(path)?;
|
|
#[cfg(unix)]
|
|
{
|
|
use std::os::unix::fs::PermissionsExt;
|
|
let mut perms = file.metadata()?.permissions();
|
|
perms.set_mode(0o600);
|
|
file.set_permissions(perms)?;
|
|
}
|
|
file.write_all(contents.as_bytes())?;
|
|
Ok(())
|
|
}
|
|
}
|