use reqsign_core::Result;
use reqsign_core::{Context, ProvideCredential, ProvideCredentialChain};
use crate::credential::Credential;
use crate::provide_credential::EnvCredentialProvider;
#[derive(Debug)]
pub struct DefaultCredentialProvider {
chain: ProvideCredentialChain<Credential>,
}
impl Default for DefaultCredentialProvider {
fn default() -> Self {
Self::new()
}
}
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
}
}
pub struct DefaultCredentialProviderBuilder {
env: Option<EnvCredentialProvider>,
}
impl Default for DefaultCredentialProviderBuilder {
fn default() -> Self {
Self {
env: Some(EnvCredentialProvider),
}
}
}
impl DefaultCredentialProviderBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn env(mut self, provider: EnvCredentialProvider) -> Self {
self.env = Some(provider);
self
}
pub fn no_env(mut self) -> Self {
self.env = None;
self
}
pub fn build(self) -> DefaultCredentialProvider {
let mut chain = ProvideCredentialChain::new();
if let Some(p) = self.env {
chain = chain.push(p);
}
DefaultCredentialProvider::with_chain(chain)
}
}
impl ProvideCredential for DefaultCredentialProvider {
type Credential = Credential;
async fn provide_credential(&self, ctx: &Context) -> Result<Option<Self::Credential>> {
self.chain.provide_credential(ctx).await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants::*;
use reqsign_core::StaticEnv;
use std::collections::HashMap;
#[tokio::test]
async fn test_default_loader_without_env() {
let ctx = Context::new().with_env(StaticEnv {
home_dir: None,
envs: HashMap::new(),
});
let loader = DefaultCredentialProvider::new();
let credential = loader.provide_credential(&ctx).await.unwrap();
assert!(credential.is_none());
}
#[tokio::test]
async fn test_default_loader_with_env() {
let ctx = Context::new().with_env(StaticEnv {
home_dir: None,
envs: HashMap::from_iter([
(ENV_ACCESS_KEY_ID.to_string(), "access_key_id".to_string()),
(
ENV_SECRET_ACCESS_KEY.to_string(),
"secret_access_key".to_string(),
),
]),
});
let loader = DefaultCredentialProvider::new();
let credential = loader.provide_credential(&ctx).await.unwrap().unwrap();
assert_eq!("access_key_id", credential.access_key_id);
assert_eq!("secret_access_key", credential.secret_access_key);
}
#[tokio::test]
async fn test_default_loader_with_security_token() {
let ctx = Context::new().with_env(StaticEnv {
home_dir: None,
envs: HashMap::from_iter([
(ENV_ACCESS_KEY_ID.to_string(), "access_key_id".to_string()),
(
ENV_SECRET_ACCESS_KEY.to_string(),
"secret_access_key".to_string(),
),
(ENV_SESSION_TOKEN.to_string(), "security_token".to_string()),
]),
});
let loader = DefaultCredentialProvider::new();
let credential = loader.provide_credential(&ctx).await.unwrap().unwrap();
assert_eq!("access_key_id", credential.access_key_id);
assert_eq!("secret_access_key", credential.secret_access_key);
assert_eq!("security_token", credential.session_token.unwrap());
}
#[tokio::test]
async fn test_default_loader_with_no_env() {
let ctx = Context::new().with_env(StaticEnv {
home_dir: None,
envs: HashMap::from_iter([
(ENV_ACCESS_KEY_ID.to_string(), "access_key_id".to_string()),
(
ENV_SECRET_ACCESS_KEY.to_string(),
"secret_access_key".to_string(),
),
]),
});
let loader = DefaultCredentialProvider::builder().no_env().build();
let credential = loader.provide_credential(&ctx).await.unwrap();
assert!(credential.is_none());
}
}