use crate::Credential;
use crate::provide_credential::{ConfigFileCredentialProvider, EnvCredentialProvider};
use async_trait::async_trait;
use reqsign_core::{Context, ProvideCredential, ProvideCredentialChain, Result};
#[derive(Debug, Default)]
pub struct DefaultCredentialProvider {
chain: ProvideCredentialChain<Credential>,
}
impl DefaultCredentialProvider {
pub fn builder() -> DefaultCredentialProviderBuilder {
DefaultCredentialProviderBuilder::default()
}
pub fn new() -> Self {
Self::builder().build()
}
pub fn with_chain(chain: ProvideCredentialChain<Credential>) -> Self {
Self { chain }
}
pub fn push_front(
mut self,
provider: impl ProvideCredential<Credential = Credential> + 'static,
) -> Self {
self.chain = self.chain.push_front(provider);
self
}
}
#[derive(Default)]
pub struct DefaultCredentialProviderBuilder {
env: Option<EnvCredentialProvider>,
config_file: Option<ConfigFileCredentialProvider>,
}
impl DefaultCredentialProviderBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn configure_env<F>(mut self, f: F) -> Self
where
F: FnOnce(EnvCredentialProvider) -> EnvCredentialProvider,
{
let p = self.env.take().unwrap_or_default();
self.env = Some(f(p));
self
}
pub fn disable_env(mut self, disable: bool) -> Self {
if disable {
self.env = None;
} else if self.env.is_none() {
self.env = Some(EnvCredentialProvider::new());
}
self
}
pub fn configure_config_file<F>(mut self, f: F) -> Self
where
F: FnOnce(ConfigFileCredentialProvider) -> ConfigFileCredentialProvider,
{
let p = self.config_file.take().unwrap_or_default();
self.config_file = Some(f(p));
self
}
pub fn disable_config_file(mut self, disable: bool) -> Self {
if disable {
self.config_file = None;
} else if self.config_file.is_none() {
self.config_file = Some(ConfigFileCredentialProvider::new());
}
self
}
pub fn build(self) -> DefaultCredentialProvider {
let mut chain = ProvideCredentialChain::new();
if let Some(p) = self.env {
chain = chain.push(p);
} else {
chain = chain.push(EnvCredentialProvider::new());
}
if let Some(p) = self.config_file {
chain = chain.push(p);
} else {
chain = chain.push(ConfigFileCredentialProvider::new());
}
DefaultCredentialProvider::with_chain(chain)
}
}
#[async_trait]
impl ProvideCredential for DefaultCredentialProvider {
type Credential = Credential;
async fn provide_credential(&self, ctx: &Context) -> Result<Option<Self::Credential>> {
self.chain.provide_credential(ctx).await
}
}