Skip to main content

fotos_lib/
credentials.rs

1/// OS keychain abstraction for API key storage.
2///
3/// Uses the keyring crate to store/retrieve API keys from:
4/// - GNOME Keyring (Linux GNOME)
5/// - KWallet (Linux KDE)
6/// - Windows Credential Manager
7use anyhow::Result;
8
9const SERVICE_NAME: &str = "fotos";
10
11/// Map a provider string to a keychain account name.
12///
13/// Named providers (e.g. `"anthropic"`) use `{provider}-api-key`.
14/// Custom endpoints (`"endpoint:{id}"`) use `"endpoint-{id}"` (hyphens only,
15/// since colons are unsafe in some keychain backends).
16fn make_account(provider: &str) -> String {
17    if let Some(id) = provider.strip_prefix("endpoint:") {
18        format!("endpoint-{id}")
19    } else {
20        format!("{provider}-api-key")
21    }
22}
23
24pub fn store_api_key(provider: &str, key: &str) -> Result<()> {
25    let account = make_account(provider);
26    let entry = keyring::Entry::new(SERVICE_NAME, &account)?;
27    entry.set_password(key)?;
28    Ok(())
29}
30
31pub fn get_api_key(provider: &str) -> Result<String> {
32    let account = make_account(provider);
33    let entry = keyring::Entry::new(SERVICE_NAME, &account)?;
34    Ok(entry.get_password()?)
35}
36
37pub fn delete_api_key(provider: &str) -> Result<()> {
38    let account = make_account(provider);
39    let entry = keyring::Entry::new(SERVICE_NAME, &account)?;
40    entry.delete_credential()?;
41    Ok(())
42}