diff --git a/crates/rattler_networking/src/authentication_storage/fallback_storage.rs b/crates/rattler_networking/src/authentication_storage/fallback_storage.rs index c5b297607..c6f6e1f44 100644 --- a/crates/rattler_networking/src/authentication_storage/fallback_storage.rs +++ b/crates/rattler_networking/src/authentication_storage/fallback_storage.rs @@ -63,6 +63,10 @@ impl FallbackStorage { /// does not exist fn read_json(&self) -> Result, FallbackStorageError> { if !self.path.exists() { + tracing::warn!( + "Can't find path for fallback storage on {}", + self.path.to_string_lossy() + ); return Ok(std::collections::HashMap::new()); } let file = std::fs::File::open(&self.path)?; diff --git a/crates/rattler_networking/src/authentication_storage/storage.rs b/crates/rattler_networking/src/authentication_storage/storage.rs index b7fab6cb5..a1adbd3fd 100644 --- a/crates/rattler_networking/src/authentication_storage/storage.rs +++ b/crates/rattler_networking/src/authentication_storage/storage.rs @@ -19,8 +19,8 @@ pub struct AuthenticationStorage { /// in a global dictionary in the operating system pub store_key: String, - /// Fallback Storage - fallback_storage: fallback_storage::FallbackStorage, + /// Fallback Storage that will be used if the is no key store application available. + pub fallback_storage: fallback_storage::FallbackStorage, /// A cache so that we don't have to access the keyring all the time cache: Arc>>>, diff --git a/crates/rattler_networking/src/lib.rs b/crates/rattler_networking/src/lib.rs index db63bf945..152e557f1 100644 --- a/crates/rattler_networking/src/lib.rs +++ b/crates/rattler_networking/src/lib.rs @@ -2,7 +2,8 @@ //! Networking utilities for Rattler, specifically authenticating requests -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use std::sync::OnceLock; pub use authentication_storage::{authentication::Authentication, storage::AuthenticationStorage}; use reqwest::{Client, IntoUrl, Method, Url}; @@ -10,8 +11,9 @@ use reqwest::{Client, IntoUrl, Method, Url}; pub mod authentication_storage; pub mod retry_policies; -/// A client that can be used to make authenticated requests, based on the [`reqwest::Client`] -#[derive(Clone)] +/// A client that can be used to make authenticated requests, based on the [`reqwest::Client`]. +/// By default it uses the fallback storage in the default [`default_auth_store_fallback_directory`]. +#[derive(Clone, Default)] pub struct AuthenticatedClient { /// The underlying client client: Client, @@ -20,12 +22,24 @@ pub struct AuthenticatedClient { auth_storage: AuthenticationStorage, } -impl Default for AuthenticatedClient { +/// Returns the default auth storage directory used by rattler. +/// Would be placed in $HOME/.rattler, except when there is no home then it will be put in '/rattler/' +pub fn default_auth_store_fallback_directory() -> &'static Path { + static FALLBACK_AUTH_DIR: OnceLock = OnceLock::new(); + FALLBACK_AUTH_DIR.get_or_init(|| { + dirs::home_dir() + .map(|home| home.join(".rattler/")) + .unwrap_or_else(|| { + tracing::warn!("using '/rattler' to store fallback authentication credentials because the home directory could not be found"); + // This can only happen if the dirs lib can't find a home directory this is very unlikely. + PathBuf::from("/rattler/") + }) + }) +} + +impl Default for AuthenticationStorage { fn default() -> Self { - AuthenticatedClient { - client: Client::default(), - auth_storage: AuthenticationStorage::new("rattler", &PathBuf::from("~/.rattler")), - } + AuthenticationStorage::new("rattler", default_auth_store_fallback_directory()) } } @@ -113,6 +127,8 @@ impl AuthenticatedClient { #[cfg(feature = "blocking")] /// A blocking client that can be used to make authenticated requests, based on the [`reqwest::blocking::Client`] +/// By default it uses the fallback storage in the default [`default_auth_store_fallback_directory`]. +#[derive(Default)] pub struct AuthenticatedClientBlocking { /// The underlying client client: reqwest::blocking::Client, @@ -135,16 +151,6 @@ impl AuthenticatedClientBlocking { } } -#[cfg(feature = "blocking")] -impl Default for AuthenticatedClientBlocking { - fn default() -> Self { - AuthenticatedClientBlocking { - client: Default::default(), - auth_storage: AuthenticationStorage::new("rattler", &PathBuf::from("~/.rattler")), - } - } -} - #[cfg(feature = "blocking")] impl AuthenticatedClientBlocking { /// Create a GET request builder for the given URL (see also [`reqwest::blocking::Client::get`])