use std::fmt;
#[derive(Debug, Clone)]
pub struct PermissionRequest {
pub title: String,
pub options: Vec<PermissionOption>,
}
#[derive(Debug, Clone)]
pub struct PermissionOption {
pub id: String,
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PermissionDecision {
Allow(String),
Deny,
}
impl PermissionDecision {
pub fn allow_once() -> Self {
Self::Allow("allow_once".to_string())
}
pub fn deny() -> Self {
Self::Deny
}
}
impl fmt::Display for PermissionDecision {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Allow(id) => write!(f, "allow({id})"),
Self::Deny => write!(f, "deny"),
}
}
}
#[derive(Default)]
pub enum PermissionPolicy {
#[default]
AutoApprove,
DenyAll,
Custom(Box<dyn Fn(&PermissionRequest) -> PermissionDecision + Send + Sync>),
}
impl PermissionPolicy {
pub fn decide(&self, request: &PermissionRequest) -> PermissionDecision {
match self {
Self::AutoApprove => {
request
.options
.first()
.map(|opt| PermissionDecision::Allow(opt.id.clone()))
.unwrap_or_else(PermissionDecision::deny)
}
Self::DenyAll => PermissionDecision::Deny,
Self::Custom(f) => f(request),
}
}
}
impl fmt::Debug for PermissionPolicy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AutoApprove => write!(f, "PermissionPolicy::AutoApprove"),
Self::DenyAll => write!(f, "PermissionPolicy::DenyAll"),
Self::Custom(_) => write!(f, "PermissionPolicy::Custom(...)"),
}
}
}