1use std::fmt::Debug;
2use std::sync::Arc;
3use std::time::Duration;
4
5use async_trait::async_trait;
6use futures::future::BoxFuture;
7use reqwest::Client;
8
9use crate::service::HttpService;
10use crate::{Result, RetryConfig, TemporaryToken, TokenCache};
11
12#[async_trait]
20pub trait CredentialProvider: std::fmt::Debug + Send + Sync {
21 type Credential;
23
24 async fn get_credential(&self) -> Result<Arc<Self::Credential>>;
26}
27
28#[derive(Debug)]
30pub struct StaticCredentialProvider<T> {
31 credential: Arc<T>,
32}
33
34impl<T> StaticCredentialProvider<T> {
35 pub fn new(credential: T) -> Self {
37 Self {
38 credential: Arc::new(credential),
39 }
40 }
41}
42
43#[async_trait]
44impl<T> CredentialProvider for StaticCredentialProvider<T>
45where
46 T: std::fmt::Debug + Send + Sync,
47{
48 type Credential = T;
49
50 async fn get_credential(&self) -> Result<Arc<T>> {
51 Ok(Arc::clone(&self.credential))
52 }
53}
54
55#[derive(Debug)]
57pub(crate) struct TokenCredentialProvider<T: TokenProvider> {
58 inner: T,
59 client: Client,
60 service: Arc<dyn HttpService>,
61 retry: RetryConfig,
62 cache: TokenCache<Arc<T::Credential>>,
63}
64
65impl<T: TokenProvider> TokenCredentialProvider<T> {
66 pub(crate) fn new(
67 inner: T,
68 client: Client,
69 service: Arc<dyn HttpService>,
70 retry: RetryConfig,
71 ) -> Self {
72 Self {
73 inner,
74 client,
75 service,
76 retry,
77 cache: Default::default(),
78 }
79 }
80
81 pub(crate) fn with_min_ttl(mut self, min_ttl: Duration) -> Self {
83 self.cache = self.cache.with_min_ttl(min_ttl);
84 self
85 }
86}
87
88#[async_trait]
89impl<T: TokenProvider> CredentialProvider for TokenCredentialProvider<T> {
90 type Credential = T::Credential;
91
92 async fn get_credential(&self) -> Result<Arc<Self::Credential>> {
93 self.cache
94 .get_or_insert_with(|| {
95 self.inner
96 .fetch_token(&self.client, &self.service, &self.retry)
97 })
98 .await
99 }
100}
101
102pub trait RequestSigner: Debug + Send + Sync {
110 fn sign<'a>(
112 &'a self,
113 req: reqwest::RequestBuilder,
114 ) -> BoxFuture<'a, Result<reqwest::RequestBuilder>>;
115}
116
117#[derive(Debug)]
121pub struct SignerChain {
122 signers: Vec<Arc<dyn RequestSigner>>,
123}
124
125impl SignerChain {
126 pub fn new(signers: Vec<Arc<dyn RequestSigner>>) -> Self {
127 Self { signers }
128 }
129}
130
131impl RequestSigner for SignerChain {
132 fn sign<'a>(
133 &'a self,
134 req: reqwest::RequestBuilder,
135 ) -> BoxFuture<'a, Result<reqwest::RequestBuilder>> {
136 Box::pin(async move {
137 let mut current = req;
138 for signer in &self.signers {
139 current = signer.sign(current).await?;
140 }
141 Ok(current)
142 })
143 }
144}
145
146#[async_trait]
147pub(crate) trait TokenProvider: std::fmt::Debug + Send + Sync {
148 type Credential: std::fmt::Debug + Send + Sync;
149
150 async fn fetch_token(
151 &self,
152 client: &Client,
153 service: &Arc<dyn HttpService>,
154 retry: &RetryConfig,
155 ) -> Result<TemporaryToken<Arc<Self::Credential>>>;
156}