diff options
Diffstat (limited to 'src/config.rs')
-rw-r--r-- | src/config.rs | 119 |
1 files changed, 97 insertions, 22 deletions
diff --git a/src/config.rs b/src/config.rs index bbc39f7..efb1b5f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,51 +1,59 @@ use crate::prelude::*; use std::io::{Read as _, Write as _}; -use tokio::io::AsyncReadExt as _; +use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; #[derive(serde::Serialize, serde::Deserialize, Debug)] pub struct Config { pub email: Option<String>, pub base_url: Option<String>, pub identity_url: Option<String>, + pub notifications_url: Option<String>, #[serde(default = "default_lock_timeout")] pub lock_timeout: u64, + #[serde(default = "default_sync_interval")] + pub sync_interval: u64, #[serde(default = "default_pinentry")] pub pinentry: String, - #[serde(default = "stub_device_id")] - pub device_id: String, + pub client_cert_path: Option<std::path::PathBuf>, + // backcompat, no longer generated in new configs + #[serde(skip_serializing)] + pub device_id: Option<String>, } impl Default for Config { fn default() -> Self { Self { - email: Default::default(), - base_url: Default::default(), - identity_url: Default::default(), + email: None, + base_url: None, + identity_url: None, + notifications_url: None, lock_timeout: default_lock_timeout(), + sync_interval: default_sync_interval(), pinentry: default_pinentry(), - device_id: default_device_id(), + client_cert_path: None, + device_id: None, } } } +#[must_use] pub fn default_lock_timeout() -> u64 { 3600 } -pub fn default_pinentry() -> String { - "pinentry".to_string() -} - -fn default_device_id() -> String { - uuid::Uuid::new_v4().to_hyphenated().to_string() +#[must_use] +pub fn default_sync_interval() -> u64 { + 3600 } -fn stub_device_id() -> String { - String::from("fix") +#[must_use] +pub fn default_pinentry() -> String { + "pinentry".to_string() } impl Config { + #[must_use] pub fn new() -> Self { Self::default() } @@ -127,36 +135,103 @@ impl Config { } pub fn validate() -> Result<()> { - let mut config = Self::load()?; + let config = Self::load()?; if config.email.is_none() { return Err(Error::ConfigMissingEmail); } - if config.device_id == stub_device_id() { - config.device_id = default_device_id(); - config.save()?; - } Ok(()) } + #[must_use] pub fn base_url(&self) -> String { self.base_url.clone().map_or_else( || "https://api.bitwarden.com".to_string(), - |url| format!("{}/api", url.trim_end_matches('/')), + |url| { + let clean_url = url.trim_end_matches('/').to_string(); + if clean_url == "https://api.bitwarden.eu" { + clean_url + } else { + format!("{clean_url}/api") + } + }, ) } + #[must_use] pub fn identity_url(&self) -> String { self.identity_url.clone().unwrap_or_else(|| { self.base_url.clone().map_or_else( || "https://identity.bitwarden.com".to_string(), - |url| format!("{}/identity", url.trim_end_matches('/')), + |url| { + let clean_url = url.trim_end_matches('/').to_string(); + if clean_url == "https://identity.bitwarden.eu" { + clean_url + } else { + format!("{clean_url}/identity") + } + }, + ) + }) + } + + #[must_use] + pub fn notifications_url(&self) -> String { + self.notifications_url.clone().unwrap_or_else(|| { + self.base_url.clone().map_or_else( + || "https://notifications.bitwarden.com".to_string(), + |url| { + let clean_url = url.trim_end_matches('/').to_string(); + if clean_url == "https://notifications.bitwarden.eu" { + clean_url + } else { + format!("{clean_url}/notifications") + } + }, ) }) } + #[must_use] + pub fn client_cert_path(&self) -> Option<&std::path::Path> { + self.client_cert_path.as_deref() + } + + #[must_use] pub fn server_name(&self) -> String { self.base_url .clone() .unwrap_or_else(|| "default".to_string()) } } + +pub async fn device_id(config: &Config) -> Result<String> { + let file = crate::dirs::device_id_file(); + if let Ok(mut fh) = tokio::fs::File::open(&file).await { + let mut s = String::new(); + fh.read_to_string(&mut s) + .await + .map_err(|e| Error::LoadDeviceId { + source: e, + file: file.clone(), + })?; + Ok(s.trim().to_string()) + } else { + let id = config.device_id.as_ref().map_or_else( + || uuid::Uuid::new_v4().hyphenated().to_string(), + String::to_string, + ); + let mut fh = tokio::fs::File::create(&file).await.map_err(|e| { + Error::LoadDeviceId { + source: e, + file: file.clone(), + } + })?; + fh.write_all(id.as_bytes()).await.map_err(|e| { + Error::LoadDeviceId { + source: e, + file: file.clone(), + } + })?; + Ok(id) + } +} |