From 4d8684f14658e404e25bac8235340129920e5017 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 20 Oct 2019 13:31:31 -0400 Subject: fall back to /etc and /var if ~/.config files don't exist --- src/config.rs | 25 +++++++++++--------- src/dirs.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++--------------- src/oauth.rs | 33 ++++++++++++++++---------- src/server.rs | 6 +++-- 4 files changed, 95 insertions(+), 45 deletions(-) diff --git a/src/config.rs b/src/config.rs index dcc44d7..10b358b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -41,17 +41,20 @@ pub fn config() -> config::Config { crate::dirs::Dirs::new().config_file(CONFIG_FILENAME); let mut config = config::Config::default(); - if let Err(e) = config.merge(config::File::from(config_filename.clone())) - { - log::warn!( - "failed to read config file {}: {}", - config_filename.to_string_lossy(), - e - ); - // if merge returns an error, the config source will still have been - // added to the config object, so the config object will likely never - // work, so we should recreate it from scratch. - config = config::Config::default(); + if let Some(config_filename) = config_filename { + if let Err(e) = + config.merge(config::File::from(config_filename.clone())) + { + log::warn!( + "failed to read config file {}: {}", + config_filename.to_string_lossy(), + e + ); + // if merge returns an error, the config source will still have been + // added to the config object, so the config object will likely never + // work, so we should recreate it from scratch. + config = config::Config::default(); + } } config diff --git a/src/dirs.rs b/src/dirs.rs index 44f828b..feea8e4 100644 --- a/src/dirs.rs +++ b/src/dirs.rs @@ -1,42 +1,80 @@ use crate::prelude::*; pub struct Dirs { - project_dirs: directories::ProjectDirs, + project_dirs: Option, } impl Dirs { pub fn new() -> Self { - // TODO: fall back to /var, /etc, etc if we're running without $HOME - // set Self { - project_dirs: directories::ProjectDirs::from("", "", "teleterm") - .expect("failed to find valid home directory"), + project_dirs: directories::ProjectDirs::from("", "", "teleterm"), } } pub fn create_all(&self) -> Result<()> { - let filename = self.data_dir(); - std::fs::create_dir_all(filename).with_context(|| { - crate::error::CreateDir { - filename: filename.to_string_lossy(), - } - })?; + if let Some(filename) = self.data_dir() { + std::fs::create_dir_all(filename).with_context(|| { + crate::error::CreateDir { + filename: filename.to_string_lossy(), + } + })?; + } Ok(()) } - fn config_dir(&self) -> &std::path::Path { - self.project_dirs.config_dir() + fn global_config_dir(&self) -> &std::path::Path { + std::path::Path::new("/etc/teleterm") + } + + fn config_dir(&self) -> Option<&std::path::Path> { + self.project_dirs + .as_ref() + .map(directories::ProjectDirs::config_dir) + } + + pub fn config_file(&self, name: &str) -> Option { + if let Some(config_dir) = self.config_dir() { + let file = config_dir.join(name); + if file.exists() { + return Some(file); + } + } + + let file = self.global_config_dir().join(name); + if file.exists() { + return Some(file); + } + + None } - pub fn config_file(&self, name: &str) -> std::path::PathBuf { - self.config_dir().join(name) + fn global_data_dir(&self) -> &std::path::Path { + std::path::Path::new("/var/lib/teleterm") } - fn data_dir(&self) -> &std::path::Path { - self.project_dirs.data_dir() + fn data_dir(&self) -> Option<&std::path::Path> { + self.project_dirs + .as_ref() + .map(directories::ProjectDirs::data_dir) } - pub fn data_file(&self, name: &str) -> std::path::PathBuf { - self.data_dir().join(name) + pub fn data_file( + &self, + name: &str, + must_exist: bool, + ) -> Option { + if let Some(data_dir) = self.data_dir() { + let file = data_dir.join(name); + if !must_exist || file.exists() { + return Some(file); + } + } + + let file = self.global_data_dir().join(name); + if !must_exist || file.exists() { + return Some(file); + } + + None } } diff --git a/src/oauth.rs b/src/oauth.rs index 0840585..26aecbc 100644 --- a/src/oauth.rs +++ b/src/oauth.rs @@ -13,9 +13,12 @@ pub trait Oauth { fn user_id(&self) -> &str; fn name(&self) -> &str; - fn server_token_file(&self) -> std::path::PathBuf { + fn server_token_file( + &self, + must_exist: bool, + ) -> Option { let name = format!("server-oauth-{}-{}", self.name(), self.user_id()); - crate::dirs::Dirs::new().data_file(&name) + crate::dirs::Dirs::new().data_file(&name, must_exist) } fn generate_authorize_url(&self) -> String { @@ -31,7 +34,7 @@ pub trait Oauth { code: &str, ) -> Box + Send> { - let token_cache_file = self.server_token_file(); + let token_cache_file = self.server_token_file(false).unwrap(); let fut = self .client() .exchange_code(oauth2::AuthorizationCode::new(code.to_string())) @@ -52,7 +55,7 @@ pub trait Oauth { token: &str, ) -> Box + Send> { - let token_cache_file = self.server_token_file(); + let token_cache_file = self.server_token_file(false).unwrap(); let fut = self .client() .exchange_refresh_token(&oauth2::RefreshToken::new( @@ -80,7 +83,7 @@ pub fn save_client_auth_id( auth: crate::protocol::AuthType, id: &str, ) -> impl futures::future::Future { - let id_file = client_id_file(auth); + let id_file = client_id_file(auth, false).unwrap(); let id = id.to_string(); tokio::fs::File::create(id_file.clone()) .with_context(move || crate::error::CreateFile { @@ -95,18 +98,22 @@ pub fn save_client_auth_id( pub fn load_client_auth_id( auth: crate::protocol::AuthType, ) -> Option { - let id_file = client_id_file(auth); - std::fs::File::open(id_file).ok().and_then(|mut file| { - let mut id = vec![]; - file.read_to_end(&mut id) - .ok() - .map(|_| std::string::String::from_utf8_lossy(&id).to_string()) + client_id_file(auth, true).and_then(|id_file| { + std::fs::File::open(id_file).ok().and_then(|mut file| { + let mut id = vec![]; + file.read_to_end(&mut id).ok().map(|_| { + std::string::String::from_utf8_lossy(&id).to_string() + }) + }) }) } -fn client_id_file(auth: crate::protocol::AuthType) -> std::path::PathBuf { +fn client_id_file( + auth: crate::protocol::AuthType, + must_exist: bool, +) -> Option { let filename = format!("client-oauth-{}", auth.name()); - crate::dirs::Dirs::new().data_file(&filename) + crate::dirs::Dirs::new().data_file(&filename, must_exist) } fn cache_refresh_token( diff --git a/src/server.rs b/src/server.rs index 8c965a9..cbc410f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -433,11 +433,13 @@ impl client.user_id() ); - if refresh { + let token_filename = client.server_token_file(true); + if let (Some(token_filename), true) = + (token_filename, refresh) + { let term_type = term_type.to_string(); let client = conn.oauth_client.take().unwrap(); let mut new_state = conn.state.clone(); - let token_filename = client.server_token_file(); let fut = tokio::fs::File::open(token_filename.clone()) .with_context(move || crate::error::OpenFile { filename: token_filename -- cgit v1.2.3-54-g00ecf