use anyhow::{Context, Result};
use keyring::Entry;
const SERVICE: &str = "tranc-cli";
const ACCOUNT: &str = "auth-token";
pub fn get_token() -> Result<Option<String>> {
let entry = Entry::new(SERVICE, ACCOUNT).context("failed to open keyring entry")?;
match entry.get_password() {
Ok(token) => Ok(Some(token)),
Err(keyring::Error::NoEntry) => Ok(None),
Err(e) => Err(anyhow::anyhow!("keyring read error: {e}")),
}
}
pub fn set_token(token: &str) -> Result<()> {
let entry = Entry::new(SERVICE, ACCOUNT).context("failed to open keyring entry")?;
entry
.set_password(token)
.context("failed to save token to keyring")?;
Ok(())
}
pub fn delete_token() -> Result<()> {
let entry = Entry::new(SERVICE, ACCOUNT).context("failed to open keyring entry")?;
match entry.delete_credential() {
Ok(()) => Ok(()),
Err(keyring::Error::NoEntry) => Ok(()),
Err(e) => Err(anyhow::anyhow!("keyring delete error: {e}")),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn keyring_roundtrip() {
let token = "tranc_test_token_12345";
set_token(token).expect("set_token failed");
let retrieved = get_token().expect("get_token failed");
assert_eq!(retrieved.as_deref(), Some(token));
delete_token().expect("delete_token failed");
let after_delete = get_token().expect("get_token after delete failed");
assert!(after_delete.is_none());
}
}