use super::RegistryInfo;
use crate::error::Error;
use crate::platform;
use crate::platform::ffi;
use std::fmt;
use std::time::SystemTime;
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct KeychainQueryResult {
pub username: String,
pub password: String,
pub modified_date: SystemTime,
pub created_date: SystemTime,
}
impl fmt::Debug for KeychainQueryResult {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("KeychainQueryResult")
.field("username", &self.username)
.field("modified_date", &self.modified_date)
.field("created_date", &self.created_date)
.finish_non_exhaustive()
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct KeychainQuery;
impl KeychainQuery {
pub fn new() -> Self {
Self
}
pub fn save(
&self,
security_domain: &str,
access_group: Option<&str>,
hostname: &str,
username: &str,
password: &str,
) -> Result<(), Error> {
platform::outcome(
ffi::cz_keychain_query_save(
security_domain,
access_group.map(str::to_string),
hostname,
username,
password,
),
format!("save {hostname} to the keychain"),
)
.map(drop)
}
pub fn delete(&self, security_domain: &str, access_group: Option<&str>, hostname: &str) -> Result<(), Error> {
platform::outcome(
ffi::cz_keychain_query_delete(security_domain, access_group.map(str::to_string), hostname),
format!("delete {hostname} from the keychain"),
)
.map(drop)
}
pub fn get(
&self,
security_domain: &str,
access_group: Option<&str>,
hostname: &str,
) -> Result<Option<KeychainQueryResult>, Error> {
platform::outcome(
ffi::cz_keychain_query_get(security_domain, access_group.map(str::to_string), hostname),
format!("read {hostname} from the keychain"),
)
.map(|outcome| outcome.is_some().then(|| outcome.keychain_query_result()))
}
pub fn list(&self, security_domain: &str, access_group: Option<&str>) -> Result<Vec<RegistryInfo>, Error> {
platform::outcome(
ffi::cz_keychain_query_list(security_domain, access_group.map(str::to_string)),
format!("list the keychain's entries for {security_domain}"),
)
.map(|outcome| outcome.registry_infos())
}
pub fn exists(&self, security_domain: &str, access_group: Option<&str>, hostname: &str) -> Result<bool, Error> {
platform::outcome(
ffi::cz_keychain_query_exists(security_domain, access_group.map(str::to_string), hostname),
format!("look for {hostname} in the keychain"),
)
.map(|outcome| outcome.boolean())
}
}