use std::pin::Pin;
use crate::{
BoxedError,
crypto::{
KeyMatchStrength,
refreshable::ScheduledRefreshable,
verifier::{JwsVerifier, KeyMatch, VerifyError},
},
platform::{Duration, MaybeSendFuture, MaybeSendSync},
};
pub struct ScheduledRefreshVerifier<V> {
inner: ScheduledRefreshable<V>,
}
impl<V: std::fmt::Debug> std::fmt::Debug for ScheduledRefreshVerifier<V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ScheduledRefreshVerifier")
.field("inner", &self.inner)
.finish_non_exhaustive()
}
}
#[bon::bon]
impl<V: JwsVerifier + std::fmt::Debug + MaybeSendSync + 'static> ScheduledRefreshVerifier<V> {
#[builder]
pub async fn new(
factory: impl Fn() -> Pin<Box<dyn MaybeSendFuture<Output = Result<V, BoxedError>>>>
+ MaybeSendSync
+ 'static,
#[builder(default = Duration::from_hours(1))]
ttl: Duration,
#[builder(default = Duration::from_secs(30))]
failure_backoff: Duration,
#[builder(default = Duration::from_mins(1))]
min_refresh_interval: Duration,
) -> Result<Self, BoxedError> {
let inner = ScheduledRefreshable::builder()
.factory(factory)
.ttl(ttl)
.failure_backoff(failure_backoff)
.min_refresh_interval(min_refresh_interval)
.build()
.await?;
Ok(Self { inner })
}
}
impl<V: JwsVerifier + std::fmt::Debug + MaybeSendSync + 'static> JwsVerifier
for ScheduledRefreshVerifier<V>
{
type Error = V::Error;
fn key_match(&self, key_match: &KeyMatch<'_>) -> Option<KeyMatchStrength> {
self.inner.load().key_match(key_match)
}
async fn verify(
&self,
input: &[u8],
signature: &[u8],
key_match: &KeyMatch<'_>,
) -> Result<(), VerifyError<Self::Error>> {
self.inner
.load_full()
.verify(input, signature, key_match)
.await
}
async fn try_refresh(&self) -> bool {
self.inner.try_refresh().await
}
}