use cts_common::{CtsServiceDiscovery, Region, ServiceDiscovery};
use crate::access_key::AccessKey;
use crate::access_key_refresher::AccessKeyRefresher;
use crate::auto_refresh::AutoRefresh;
use crate::token_store::{NoStore, TokenStore};
use crate::{ensure_trailing_slash, AuthError, AuthStrategy, SecretToken, ServiceToken};
pub struct AccessKeyStrategy<S = NoStore> {
inner: AutoRefresh<AccessKeyRefresher, S>,
}
impl AccessKeyStrategy {
pub fn new(region: Region, access_key: AccessKey) -> Result<Self, AuthError> {
Self::builder(region, access_key).build()
}
pub fn builder(region: Region, access_key: AccessKey) -> AccessKeyStrategyBuilder {
AccessKeyStrategyBuilder {
region,
access_key: access_key.into_secret_token(),
audience: None,
base_url_override: None,
token_store: NoStore,
}
}
}
impl<S: TokenStore> AuthStrategy for &AccessKeyStrategy<S> {
async fn get_token(self) -> Result<ServiceToken, AuthError> {
Ok(self.inner.get_token().await?)
}
}
pub struct AccessKeyStrategyBuilder<S = NoStore> {
region: Region,
access_key: SecretToken,
audience: Option<String>,
base_url_override: Option<url::Url>,
token_store: S,
}
impl<S> AccessKeyStrategyBuilder<S> {
pub fn audience(mut self, audience: impl Into<String>) -> Self {
self.audience = Some(audience.into());
self
}
#[cfg(any(test, feature = "test-utils"))]
pub fn base_url(mut self, url: url::Url) -> Self {
self.base_url_override = Some(url);
self
}
pub fn with_token_store<T: TokenStore>(self, store: T) -> AccessKeyStrategyBuilder<T> {
AccessKeyStrategyBuilder {
region: self.region,
access_key: self.access_key,
audience: self.audience,
base_url_override: self.base_url_override,
token_store: store,
}
}
}
impl<S: TokenStore> AccessKeyStrategyBuilder<S> {
pub fn build(self) -> Result<AccessKeyStrategy<S>, AuthError> {
let base_url = match self.base_url_override {
Some(url) => url,
None => crate::cts_base_url_from_env()?
.unwrap_or(CtsServiceDiscovery::endpoint(self.region)?),
};
let refresher = AccessKeyRefresher::new(
self.access_key,
ensure_trailing_slash(base_url),
self.audience,
);
Ok(AccessKeyStrategy {
inner: AutoRefresh::with_store(refresher, self.token_store),
})
}
}