diff --git a/Cargo.lock b/Cargo.lock index 698c6fe..ee0e003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,16 +285,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -406,6 +396,27 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -586,8 +597,8 @@ dependencies = [ "clap", "color-eyre", "crossterm", + "dirs", "futures", - "keyring", "nucleo", "octocrab", "ratatui", @@ -947,18 +958,6 @@ dependencies = [ "simple_asn1", ] -[[package]] -name = "keyring" -version = "3.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" -dependencies = [ - "log", - "security-framework 2.11.1", - "security-framework 3.5.1", - "zeroize", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -971,6 +970,16 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1156,6 +1165,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "owo-colors" version = "4.2.3" @@ -1322,6 +1337,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "ring" version = "0.17.14" @@ -1400,7 +1426,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -1459,19 +1485,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.5.1" @@ -1479,7 +1492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ "bitflags", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", diff --git a/Cargo.toml b/Cargo.toml index 222edfd..fd52dcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ crossterm = { version = "0.28", features = ["event-stream"] } nucleo = "0.5" tokio = { version = "1.42", features = ["full"] } futures = "0.3" -keyring = { version = "3.6", features = ["apple-native"] } +dirs = "6.0" clap = { version = "4.5", features = ["derive"] } color-eyre = "0.6" serde = { version = "1.0", features = ["derive"] } diff --git a/src/auth.rs b/src/auth.rs index aa2e29d..3149f79 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,26 +1,34 @@ use color_eyre::eyre::{eyre, Result}; -use keyring::Entry; +use std::fs; use std::io::{self, Write}; +use std::path::PathBuf; -const SERVICE_NAME: &str = "ghune-github-cli"; -const USERNAME: &str = "github-token"; +#[cfg(unix)] +use std::os::unix::fs::PermissionsExt; -pub struct TokenManager { - entry: Entry, +fn token_file_path() -> Result { + let config_dir = dirs::config_dir() + .ok_or_else(|| eyre!("Could not find config directory"))? + .join("ghune"); + Ok(config_dir.join("token")) } +pub struct TokenManager; + impl TokenManager { pub fn new() -> Result { - let entry = Entry::new(SERVICE_NAME, USERNAME)?; - Ok(Self { entry }) + Ok(Self) } pub fn get_token(&self) -> Result> { - match self.entry.get_password() { - Ok(token) => Ok(Some(token)), - Err(keyring::Error::NoEntry) => Ok(None), - Err(e) => Err(e.into()), + let path = token_file_path()?; + if path.exists() { + let token = fs::read_to_string(&path)?.trim().to_string(); + if !token.is_empty() { + return Ok(Some(token)); + } } + Ok(None) } pub fn get_or_prompt_token(&self) -> Result { @@ -52,15 +60,27 @@ impl TokenManager { } pub fn store_token(&self, token: &str) -> Result<()> { - self.entry.set_password(token)?; + let path = token_file_path()?; + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + fs::write(&path, format!("{}\n", token))?; + + #[cfg(unix)] + { + let mut perms = fs::metadata(&path)?.permissions(); + perms.set_mode(0o600); + fs::set_permissions(&path, perms)?; + } + Ok(()) } pub fn clear_token(&self) -> Result<()> { - match self.entry.delete_credential() { - Ok(()) => Ok(()), - Err(keyring::Error::NoEntry) => Ok(()), - Err(e) => Err(e.into()), + let path = token_file_path()?; + if path.exists() { + fs::remove_file(&path)?; } + Ok(()) } }