use std::collections::HashSet;
use std::sync::{Mutex, MutexGuard};
use crate::{budget_store::RevocationCommitMetadata, RevocationStoreError};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RevocationObservation {
pub revoked: bool,
pub commit: Option<RevocationCommitMetadata>,
}
pub trait RevocationStore: Send + Sync {
fn is_revoked(&self, capability_id: &str) -> Result<bool, RevocationStoreError>;
fn revoke(&self, capability_id: &str) -> Result<bool, RevocationStoreError>;
fn observe_revocation(
&self,
capability_id: &str,
) -> Result<RevocationObservation, RevocationStoreError> {
Ok(RevocationObservation {
revoked: self.is_revoked(capability_id)?,
commit: None,
})
}
fn is_ephemeral(&self) -> bool {
true
}
}
#[derive(Debug, Default)]
pub struct InMemoryRevocationStore {
revoked: Mutex<HashSet<String>>,
}
impl InMemoryRevocationStore {
pub fn new() -> Self {
Self::default()
}
fn revoked(&self) -> Result<MutexGuard<'_, HashSet<String>>, RevocationStoreError> {
self.revoked.lock().map_err(|_| {
RevocationStoreError::Sync("in-memory revocation store lock poisoned".to_string())
})
}
}
impl RevocationStore for InMemoryRevocationStore {
fn is_revoked(&self, capability_id: &str) -> Result<bool, RevocationStoreError> {
Ok(self.revoked()?.contains(capability_id))
}
fn revoke(&self, capability_id: &str) -> Result<bool, RevocationStoreError> {
Ok(self.revoked()?.insert(capability_id.to_owned()))
}
}