use std::collections::HashMap;
use std::marker::PhantomData;
use async_trait::async_trait;
use ppoppo_token::id_token::Nonce;
use super::port::{IdAssertion, IdTokenVerifier, IdVerifyError, ScopePiiReader};
use crate::token::Expectations;
pub struct MemoryIdTokenVerifier<S: ScopePiiReader> {
assertions: HashMap<String, IdAssertion<S>>,
default_failure: Option<IdVerifyError>,
#[allow(dead_code)]
expectations: Option<Expectations>,
_scope: PhantomData<S>,
}
impl<S: ScopePiiReader> Default for MemoryIdTokenVerifier<S> {
fn default() -> Self {
Self {
assertions: HashMap::new(),
default_failure: None,
expectations: None,
_scope: PhantomData,
}
}
}
impl<S: ScopePiiReader> MemoryIdTokenVerifier<S> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_expectations(mut self, expectations: Expectations) -> Self {
self.expectations = Some(expectations);
self
}
pub fn insert(
&mut self,
id_token: impl Into<String>,
assertion: IdAssertion<S>,
) -> &mut Self {
self.assertions.insert(id_token.into(), assertion);
self
}
pub fn fail_with(&mut self, err: IdVerifyError) -> &mut Self {
self.default_failure = Some(err);
self
}
}
#[async_trait]
impl<S: ScopePiiReader> IdTokenVerifier<S> for MemoryIdTokenVerifier<S> {
async fn verify(
&self,
id_token: &str,
_expected_nonce: &Nonce,
) -> Result<IdAssertion<S>, IdVerifyError> {
if let Some(err) = self.default_failure.clone() {
return Err(err);
}
self.assertions
.get(id_token)
.cloned()
.ok_or(IdVerifyError::SignatureInvalid)
}
}