use crate::{
AccessTokenValidator, ValidatedRequest,
core::platform::{MaybeSendBoxFuture, MaybeSendSync},
validator::{
ValidationResult,
metadata::{ProvideValidatorMetadata, ValidatorMetadata},
},
};
pub struct MapClaims<V, F> {
inner: V,
f: F,
}
impl<V, F> MapClaims<V, F> {
pub fn new(inner: V, f: F) -> Self {
Self { inner, f }
}
pub fn inner(&self) -> &V {
&self.inner
}
}
impl<V, F, C> AccessTokenValidator for MapClaims<V, F>
where
V: AccessTokenValidator,
F: Fn(V::Claims) -> C + MaybeSendSync,
C: MaybeSendSync,
{
type Claims = C;
type Error = V::Error;
fn validate_request<'a>(
&'a self,
headers: &'a http::HeaderMap,
method: &'a http::Method,
uri: &'a http::Uri,
client_cert_der: Option<&'a [u8]>,
) -> MaybeSendBoxFuture<'a, ValidationResult<C, V::Error>> {
Box::pin(async move {
let result = self
.inner
.validate_request(headers, method, uri, client_cert_der)
.await;
ValidationResult {
outcome: result.outcome.map(|opt| opt.map(|v| self.remap(v))),
dpop_nonce: result.dpop_nonce,
}
})
}
}
impl<V, F, C> MapClaims<V, F>
where
V: AccessTokenValidator,
F: Fn(V::Claims) -> C,
{
fn remap(&self, v: ValidatedRequest<V::Claims>) -> ValidatedRequest<C> {
ValidatedRequest {
issuer: v.issuer,
subject: v.subject,
audience: v.audience,
jti: v.jti,
issued_at: v.issued_at,
expiration: v.expiration,
cnf: v.cnf,
claims: (self.f)(v.claims),
introspection_jwt: v.introspection_jwt,
}
}
}
impl<V: ProvideValidatorMetadata, F> ProvideValidatorMetadata for MapClaims<V, F> {
fn validator_metadata(&self, resource: Option<&str>) -> ValidatorMetadata {
self.inner.validator_metadata(resource)
}
}