use std::cell::RefCell;
use zeroize::Zeroizing;
use crate::error::Error;
use crate::gui::{Approval, PreexecChoice};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockApprovalResponse {
AllowOnce,
AllowAlways,
Deny,
Timeout,
}
impl MockApprovalResponse {
fn into_result(self) -> Result<Approval, Error> {
match self {
Self::AllowOnce => Ok(Approval::AllowOnce),
Self::AllowAlways => Ok(Approval::AllowAlways),
Self::Deny | Self::Timeout => Err(Error::UserDenied),
}
}
}
#[derive(Clone, Debug)]
enum MockState {
Approval(MockApprovalResponse),
Passphrase(Zeroizing<String>),
SecretValue(Zeroizing<String>),
Totp(String),
Preexec(PreexecChoice),
}
thread_local! {
static MOCK_STATE: RefCell<Option<MockState>> = const { RefCell::new(None) };
}
pub fn set_mock_approval(response: MockApprovalResponse) {
MOCK_STATE.with(|s| *s.borrow_mut() = Some(MockState::Approval(response)));
}
pub fn set_mock_passphrase(passphrase: &str) {
MOCK_STATE.with(|s| {
*s.borrow_mut() = Some(MockState::Passphrase(Zeroizing::new(
passphrase.to_string(),
)));
});
}
pub fn set_mock_secret_value(value: &str) {
MOCK_STATE.with(|s| {
*s.borrow_mut() = Some(MockState::SecretValue(Zeroizing::new(value.to_string())));
});
}
pub fn set_mock_totp(code: &str) {
MOCK_STATE.with(|s| *s.borrow_mut() = Some(MockState::Totp(code.to_string())));
}
pub fn set_mock_preexec_choice(choice: PreexecChoice) {
MOCK_STATE.with(|s| *s.borrow_mut() = Some(MockState::Preexec(choice)));
}
pub fn clear_mock() {
MOCK_STATE.with(|s| *s.borrow_mut() = None);
}
pub(crate) fn get_mock_approval() -> Option<Result<Approval, Error>> {
MOCK_STATE.with(|s| match s.borrow().as_ref() {
Some(MockState::Approval(r)) => Some(r.into_result()),
_ => None,
})
}
pub(crate) fn get_mock_passphrase() -> Option<Zeroizing<String>> {
MOCK_STATE.with(|s| match s.borrow().as_ref() {
Some(MockState::Passphrase(r)) => Some(r.clone()),
_ => None,
})
}
pub(crate) fn get_mock_secret_value() -> Option<Zeroizing<String>> {
MOCK_STATE.with(|s| match s.borrow().as_ref() {
Some(MockState::SecretValue(r)) => Some(r.clone()),
_ => None,
})
}
pub(crate) fn get_mock_totp() -> Option<String> {
MOCK_STATE.with(|s| match s.borrow().as_ref() {
Some(MockState::Totp(r)) => Some(r.clone()),
_ => None,
})
}
pub(crate) fn get_mock_preexec() -> Option<PreexecChoice> {
MOCK_STATE.with(|s| match s.borrow().as_ref() {
Some(MockState::Preexec(r)) => Some(*r),
_ => None,
})
}