lib_client_google_auth/
token.rs1use async_trait::async_trait;
2use chrono::{DateTime, Duration, Utc};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Token {
8 pub access_token: String,
10
11 pub token_type: String,
13
14 pub expires_at: DateTime<Utc>,
16
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub refresh_token: Option<String>,
20
21 #[serde(default)]
23 pub scopes: Vec<String>,
24}
25
26impl Token {
27 pub fn new(access_token: String, expires_in_secs: i64) -> Self {
29 Self {
30 access_token,
31 token_type: "Bearer".to_string(),
32 expires_at: Utc::now() + Duration::seconds(expires_in_secs),
33 refresh_token: None,
34 scopes: Vec::new(),
35 }
36 }
37
38 pub fn is_expired(&self) -> bool {
40 Utc::now() + Duration::seconds(60) >= self.expires_at
41 }
42
43 pub fn with_refresh_token(mut self, token: String) -> Self {
45 self.refresh_token = Some(token);
46 self
47 }
48
49 pub fn with_scopes(mut self, scopes: Vec<String>) -> Self {
51 self.scopes = scopes;
52 self
53 }
54}
55
56#[derive(Debug, Deserialize)]
58pub struct TokenResponse {
59 pub access_token: String,
60 pub token_type: String,
61 pub expires_in: i64,
62 pub refresh_token: Option<String>,
63 pub scope: Option<String>,
64}
65
66impl From<TokenResponse> for Token {
67 fn from(resp: TokenResponse) -> Self {
68 let scopes = resp
69 .scope
70 .map(|s| s.split_whitespace().map(String::from).collect())
71 .unwrap_or_default();
72
73 Token::new(resp.access_token, resp.expires_in)
74 .with_scopes(scopes)
75 .with_refresh_token(resp.refresh_token.unwrap_or_default())
76 }
77}
78
79#[async_trait]
81pub trait TokenStore: Send + Sync {
82 async fn load(&self, key: &str) -> crate::Result<Option<Token>>;
84
85 async fn store(&self, key: &str, token: &Token) -> crate::Result<()>;
87
88 async fn delete(&self, key: &str) -> crate::Result<()>;
90}
91
92#[derive(Debug, Default)]
94pub struct MemoryTokenStore {
95 tokens: std::sync::RwLock<std::collections::HashMap<String, Token>>,
96}
97
98impl MemoryTokenStore {
99 pub fn new() -> Self {
100 Self::default()
101 }
102}
103
104#[async_trait]
105impl TokenStore for MemoryTokenStore {
106 async fn load(&self, key: &str) -> crate::Result<Option<Token>> {
107 Ok(self.tokens.read().unwrap().get(key).cloned())
108 }
109
110 async fn store(&self, key: &str, token: &Token) -> crate::Result<()> {
111 self.tokens
112 .write()
113 .unwrap()
114 .insert(key.to_string(), token.clone());
115 Ok(())
116 }
117
118 async fn delete(&self, key: &str) -> crate::Result<()> {
119 self.tokens.write().unwrap().remove(key);
120 Ok(())
121 }
122}