use crate::errors::{Context, SdError};
use nix::dir;
use nix::fcntl::OFlag;
use nix::sys::stat::Mode;
use std::env;
use std::fs::File;
use std::path::PathBuf;
#[derive(Debug)]
pub struct CredentialsLoader {
path: PathBuf,
_dirfd: dir::Dir,
}
impl CredentialsLoader {
pub fn open() -> Result<Self, SdError> {
let path = Self::path_from_env().ok_or_else(|| {
SdError::from("No valid environment variable 'CREDENTIALS_DIRECTORY' found")
})?;
let _dirfd = dir::Dir::open(&path, OFlag::O_RDONLY | OFlag::O_DIRECTORY, Mode::empty())
.with_context(|| format!("Opening credentials directory at '{}'", path.display()))?;
let loader = Self { path, _dirfd };
Ok(loader)
}
pub fn path_from_env() -> Option<PathBuf> {
env::var("CREDENTIALS_DIRECTORY").map(|v| v.into()).ok()
}
pub fn get(&self, id: impl AsRef<str>) -> Result<File, SdError> {
let cred_path = self.cred_absolute_path(id.as_ref())?;
File::open(&cred_path).map_err(|e| {
let msg = format!("Opening credential at {}: {}", cred_path.display(), e);
SdError::from(msg)
})
}
fn cred_absolute_path(&self, id: &str) -> Result<PathBuf, SdError> {
if id.contains('/') {
return Err(SdError::from("Invalid credential ID"));
}
let abs_path = self.path.join(id);
Ok(abs_path)
}
pub fn iter(&self) -> Result<std::fs::ReadDir, SdError> {
std::fs::read_dir(&self.path)
.with_context(|| format!("Opening credential directory at {}", self.path.display()))
}
}