use std::pin::Pin;
use crate::{
crypto::{
KeyMatchStrength,
refreshable::ScheduledRefreshable,
verifier::{JwsVerifier, KeyMatch, VerifyError},
},
error::Error,
platform::{Duration, MaybeSendBoxFuture, 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 + 'static> ScheduledRefreshVerifier<V> {
#[builder]
pub async fn new(
factory: impl Fn() -> Pin<Box<dyn MaybeSendFuture<Output = Result<V, Error>>>>
+ 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, Error> {
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 + 'static> JwsVerifier for ScheduledRefreshVerifier<V> {
fn key_match(&self, key_match: &KeyMatch<'_>) -> Option<KeyMatchStrength> {
self.inner.load().key_match(key_match)
}
fn verify<'a>(
&'a self,
input: &'a [u8],
signature: &'a [u8],
key_match: &'a KeyMatch<'a>,
) -> MaybeSendBoxFuture<'a, Result<(), VerifyError>> {
Box::pin(async move {
self.inner
.load_full()
.verify(input, signature, key_match)
.await
})
}
fn try_refresh(&self) -> MaybeSendBoxFuture<'_, bool> {
Box::pin(self.inner.try_refresh())
}
}