keyfork/keyfork-shard/src/prompt_manager.rs

75 lines
2.3 KiB
Rust

use std::path::PathBuf;
use keyfork_pinentry::{
self, default_binary, ConfirmationDialog, MessageDialog, PassphraseInput, SecretString,
};
#[derive(thiserror::Error, Debug)]
pub enum PinentryError {
#[error("No pinentry binary found")]
NoPinentryFound,
#[error("{0}")]
Internal(#[from] keyfork_pinentry::Error),
}
pub type Result<T, E = PinentryError> = std::result::Result<T, E>;
/// Display message dialogues, confirmation prompts, and passphrase inputs with keyfork-pinentry.
pub struct PromptManager {
program_title: String,
pinentry_binary: PathBuf,
}
impl PromptManager {
pub fn new(
program_title: impl Into<String>,
pinentry_binary: impl Into<Option<PathBuf>>,
) -> Result<Self> {
let path = match pinentry_binary.into() {
Some(p) => p,
None => default_binary()?,
};
std::fs::metadata(&path).map_err(|_| PinentryError::NoPinentryFound)?;
Ok(Self {
program_title: program_title.into(),
pinentry_binary: path,
})
}
#[allow(dead_code)]
pub fn prompt_confirmation(&self, prompt: impl AsRef<str>) -> Result<bool> {
ConfirmationDialog::with_binary(self.pinentry_binary.clone())
.with_title(&self.program_title)
.confirm(prompt.as_ref())
.map_err(|e| e.into())
}
pub fn prompt_message(&self, prompt: impl AsRef<str>) -> Result<()> {
MessageDialog::with_binary(self.pinentry_binary.clone())
.with_title(&self.program_title)
.show_message(prompt.as_ref())
.map_err(|e| e.into())
}
pub fn prompt_passphrase(
&self,
prompt: impl AsRef<str>,
description: impl Into<Option<String>>,
) -> Result<SecretString> {
match description.into() {
Some(desc) => PassphraseInput::with_binary(self.pinentry_binary.clone())
.with_title(&self.program_title)
.with_prompt(prompt.as_ref())
.with_description(&desc)
.interact()
.map_err(|e| e.into()),
None => PassphraseInput::with_binary(self.pinentry_binary.clone())
.with_title(&self.program_title)
.with_prompt(prompt.as_ref())
.interact()
.map_err(|e| e.into()),
}
}
}