use crate::client::identity::{Identity, IdentityResolver, IdentityResolvers};
use crate::client::orchestrator::{BoxError, HttpRequest};
use crate::config_bag::ConfigBag;
use crate::type_erasure::{TypeErasedBox, TypedBox};
use aws_smithy_types::Document;
use std::borrow::Cow;
use std::fmt;
use std::sync::Arc;
#[cfg(feature = "http-auth")]
pub mod http;
pub mod option_resolver;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AuthSchemeId {
scheme_id: &'static str,
}
impl AuthSchemeId {
pub const fn new(scheme_id: &'static str) -> Self {
Self { scheme_id }
}
pub const fn as_str(&self) -> &'static str {
self.scheme_id
}
}
impl From<&'static str> for AuthSchemeId {
fn from(scheme_id: &'static str) -> Self {
Self::new(scheme_id)
}
}
#[derive(Debug)]
pub struct AuthOptionResolverParams(TypeErasedBox);
impl AuthOptionResolverParams {
pub fn new<T: fmt::Debug + Send + Sync + 'static>(params: T) -> Self {
Self(TypedBox::new(params).erase())
}
pub fn get<T: fmt::Debug + Send + Sync + 'static>(&self) -> Option<&T> {
self.0.downcast_ref()
}
}
pub trait AuthOptionResolver: Send + Sync + fmt::Debug {
fn resolve_auth_options(
&self,
params: &AuthOptionResolverParams,
) -> Result<Cow<'_, [AuthSchemeId]>, BoxError>;
}
impl AuthOptionResolver for Box<dyn AuthOptionResolver> {
fn resolve_auth_options(
&self,
params: &AuthOptionResolverParams,
) -> Result<Cow<'_, [AuthSchemeId]>, BoxError> {
(**self).resolve_auth_options(params)
}
}
#[derive(Debug)]
struct HttpAuthSchemesInner {
schemes: Vec<(AuthSchemeId, Box<dyn HttpAuthScheme>)>,
}
#[derive(Clone, Debug)]
pub struct HttpAuthSchemes {
inner: Arc<HttpAuthSchemesInner>,
}
impl HttpAuthSchemes {
pub fn builder() -> builders::HttpAuthSchemesBuilder {
Default::default()
}
pub fn scheme(&self, scheme_id: AuthSchemeId) -> Option<&dyn HttpAuthScheme> {
self.inner
.schemes
.iter()
.find(|scheme| scheme.0 == scheme_id)
.map(|scheme| &*scheme.1)
}
}
pub trait HttpAuthScheme: Send + Sync + fmt::Debug {
fn scheme_id(&self) -> AuthSchemeId;
fn identity_resolver<'a>(
&self,
identity_resolvers: &'a IdentityResolvers,
) -> Option<&'a dyn IdentityResolver>;
fn request_signer(&self) -> &dyn HttpRequestSigner;
}
pub trait HttpRequestSigner: Send + Sync + fmt::Debug {
fn sign_request(
&self,
request: &mut HttpRequest,
identity: &Identity,
auth_scheme_endpoint_config: AuthSchemeEndpointConfig<'_>,
config_bag: &ConfigBag,
) -> Result<(), BoxError>;
}
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct AuthSchemeEndpointConfig<'a>(Option<&'a Document>);
impl<'a> AuthSchemeEndpointConfig<'a> {
pub fn new(config: Option<&'a Document>) -> Self {
Self(config)
}
pub fn empty() -> Self {
Self(None)
}
pub fn config(&self) -> Option<&'a Document> {
self.0
}
}
pub mod builders {
use super::*;
#[derive(Debug, Default)]
pub struct HttpAuthSchemesBuilder {
schemes: Vec<(AuthSchemeId, Box<dyn HttpAuthScheme>)>,
}
impl HttpAuthSchemesBuilder {
pub fn new() -> Self {
Default::default()
}
pub fn auth_scheme(
mut self,
scheme_id: AuthSchemeId,
auth_scheme: impl HttpAuthScheme + 'static,
) -> Self {
self.schemes.push((scheme_id, Box::new(auth_scheme) as _));
self
}
pub fn build(self) -> HttpAuthSchemes {
HttpAuthSchemes {
inner: Arc::new(HttpAuthSchemesInner {
schemes: self.schemes,
}),
}
}
}
}