1mod device_code;
9mod three_leg;
10mod token_ops;
11mod two_leg;
12pub mod types;
13
14#[cfg(test)]
15mod tests;
16
17pub use types::*;
18
19use std::sync::Arc;
20use tokio::sync::RwLock;
21
22use crate::config::Config;
23use crate::http::HttpClientConfig;
24use types::{CachedToken, TokenCache};
25
26#[derive(Clone)]
30pub struct AuthClient {
31 pub(crate) config: Config,
32 pub(crate) http_client: reqwest::Client,
33 pub(crate) cached_2leg_token: Arc<RwLock<Option<CachedToken>>>,
34 pub(crate) cached_3leg_token: Arc<tokio::sync::Mutex<TokenCache>>,
35}
36
37impl AuthClient {
38 pub fn new(config: Config) -> Self {
40 Self::new_with_http_config(config, HttpClientConfig::default())
41 }
42
43 pub fn new_with_http_config(config: Config, http_config: HttpClientConfig) -> Self {
45 let stored_token = Self::load_stored_token_static(&config);
47
48 let http_client = http_config
50 .create_client()
51 .unwrap_or_else(|_| reqwest::Client::new()); Self {
54 config,
55 http_client,
56 cached_2leg_token: Arc::new(RwLock::new(None)),
57 cached_3leg_token: Arc::new(tokio::sync::Mutex::new(TokenCache {
58 token: stored_token,
59 refreshing: false,
60 })),
61 }
62 }
63
64 pub fn config(&self) -> &Config {
66 &self.config
67 }
68
69 #[cfg(any(test, feature = "test-utils"))]
72 pub async fn set_3leg_token_for_testing(&self, token: crate::types::StoredToken) {
73 let mut cache = self.cached_3leg_token.lock().await;
74 cache.token = Some(token);
75 }
76
77 #[cfg(any(test, feature = "test-utils"))]
80 pub async fn set_2leg_token_for_testing(&self, access_token: String, expires_in_secs: u64) {
81 use std::time::{Duration, Instant};
82 let mut cache = self.cached_2leg_token.write().await;
83 *cache = Some(CachedToken {
84 access_token,
85 expires_at: Instant::now() + Duration::from_secs(expires_in_secs),
86 });
87 }
88}