#![deny(clippy::all)]
use log::*;
use std::path::Path;
mod error;
mod insecure;
pub use error::{KeyringError, Result};
use insecure::InsecureKeyringManager;
use cfg_if::*;
cfg_if! {
if #[cfg(target_os = "linux")] {
mod linux;
use linux::LinuxKeyringManager as PlatformKeyringManager;
} else if #[cfg(target_os = "windows")] {
mod windows;
use windows::WindowsKeyringManager as PlatformKeyringManager;
} else if #[cfg(target_os = "macos")] {
mod macos;
use macos::MacosKeyringManager as PlatformKeyringManager;
} else if #[cfg(target_os = "ios")] {
mod ios;
use ios::IosKeyringManager as PlatformKeyringManager;
} else if #[cfg(target_os = "android")] {
pub(crate) mod android;
use android::AndroidKeyringManager as PlatformKeyringManager;
pub use android::AndroidKeyringContext;
} else {
struct PlatformKeyringManager {}
impl PlatformKeyringManager {
pub fn with_keyring<F, T>(&self, _service: &str, _key: &str, _func: F) -> Result<T>
where
F: FnOnce(&mut dyn Keyring) -> Result<T>,
{
Err(KeyringError::NoBackendFound)
}
}
}
}
pub trait Keyring {
fn set_value(&mut self, value: &str) -> Result<()>;
fn get_value(&self) -> Result<String>;
fn delete_value(&mut self) -> Result<()>;
}
enum KeyringManagerKind {
#[allow(dead_code)]
Secure(PlatformKeyringManager),
Insecure(InsecureKeyringManager),
}
pub struct KeyringManager {
kind: KeyringManagerKind,
}
impl KeyringManager {
cfg_if! {
if #[cfg(all(target_os = "macos", feature = "macos-specify-keychain"))] {
pub fn new_secure_with_path(application: &str, path: &Path) -> Result<Self> {
Ok(KeyringManager {
kind: KeyringManagerKind::Secure(PlatformKeyringManager::with_path(application, path)?),
})
}
}
}
cfg_if! {
if #[cfg(target_os = "android")] {
pub fn new_secure(application: &str, context: AndroidKeyringContext) -> Result<Self> {
Ok(KeyringManager {
kind: KeyringManagerKind::Secure(PlatformKeyringManager::new(application, context)?),
})
}
} else if #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos", target_os = "ios"))] {
pub fn new_secure(application: &str) -> Result<Self> {
Ok(KeyringManager {
kind: KeyringManagerKind::Secure(PlatformKeyringManager::new(application)?),
})
}
} else {
pub fn new_secure(_application: &str) -> Result<Self> {
Err(KeyringError::NoBackendFound)
}
}
}
pub fn new_insecure(application: &str, insecure_keyring_file: &Path) -> Result<Self> {
Ok(KeyringManager {
kind: KeyringManagerKind::Insecure(InsecureKeyringManager::new(
application,
insecure_keyring_file,
)?),
})
}
pub fn with_keyring<F, T>(&self, service: &str, key: &str, f: F) -> Result<T>
where
F: FnOnce(&mut dyn Keyring) -> Result<T>,
{
match &self.kind {
KeyringManagerKind::Secure(pkm) => pkm.with_keyring(service, key, f),
KeyringManagerKind::Insecure(ikm) => ikm.with_keyring(service, key, f),
}
}
}
pub(crate) fn map_to_generic<E: std::fmt::Display>(e: E) -> KeyringError {
KeyringError::Generic(format!("{}", e))
}
pub(crate) fn map_log_err<T: std::error::Error>(e: T) -> T {
error!("{}", e);
e
}
cfg_if! {
if #[cfg(test)] {
mod tests;
} else if #[cfg(feature="keyring_manager_android_tests")] {
pub mod tests;
} else if #[cfg(feature="keyring_manager_ios_tests")] {
pub mod tests;
}
}