use async_trait::async_trait;
use origin_domain::Result;
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConfirmationRequest {
pub title: String,
pub body: String,
}
impl ConfirmationRequest {
pub fn new(title: impl Into<String>, body: impl Into<String>) -> Self {
Self {
title: title.into(),
body: body.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfirmationDecision {
Approved,
Denied,
}
#[async_trait]
pub trait ConfirmationService: Debug + Send + Sync + 'static {
async fn confirm(&self, request: ConfirmationRequest) -> Result<ConfirmationDecision>;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct DenyingConfirmationService;
#[async_trait]
impl ConfirmationService for DenyingConfirmationService {
async fn confirm(&self, request: ConfirmationRequest) -> Result<ConfirmationDecision> {
tracing::info!(
title = %request.title,
"confirmation denied — no confirmation service configured"
);
Ok(ConfirmationDecision::Denied)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn the_denying_confirmation_service_always_returns_denied() {
let service = DenyingConfirmationService;
let decision = service
.confirm(ConfirmationRequest::new("Allow?", "Run?"))
.await
.unwrap();
assert_eq!(decision, ConfirmationDecision::Denied);
}
}