@@ -6,7 +6,7 @@ use reqwest::RequestBuilder;
66use reqwest:: { Client , Method } ;
77use serde_json:: Value ;
88use std:: cell:: RefCell ;
9-
9+ use std :: time :: { SystemTime , UNIX_EPOCH } ;
1010pub struct ApiClient {
1111 url : String ,
1212 client : Client ,
@@ -33,30 +33,57 @@ impl ApiClient {
3333 self
3434 }
3535
36+ /// Validate the OAuth2 token and refresh it if it is expired
37+ async fn validate_and_refresh_oauth2_token (
38+ & self ,
39+ auth : & RefCell < Auth > ,
40+ token : Token ,
41+ username : Option < & str > ,
42+ ) -> Result < String , Error > {
43+ match token {
44+ Token :: OAuth2 ( token) => {
45+ let current_time = SystemTime :: now ( )
46+ . duration_since ( UNIX_EPOCH )
47+ . unwrap ( )
48+ . as_secs ( ) ;
49+
50+ if current_time > token. expiration_time {
51+ let new_token = auth. borrow_mut ( ) . oauth2_refresh_token ( username) . await ?;
52+ Ok ( format ! ( "Bearer {}" , new_token) )
53+ } else {
54+ Ok ( format ! ( "Bearer {}" , token. access_token) )
55+ }
56+ }
57+ _ => Err ( Error :: AuthError ( AuthError :: WrongTokenFoundInStore ) ) ,
58+ }
59+ }
60+
61+ /// Get the OAuth2 token from the token store, validate it and refresh it if it is expired
3662 async fn get_oauth2_token (
3763 & self ,
3864 auth : & RefCell < Auth > ,
3965 username : Option < & str > ,
4066 ) -> Result < String , Error > {
41- match username {
42- Some ( username) => {
43- let token = auth. borrow_mut ( ) . oauth2 ( Some ( username) ) . await ?;
44- Ok ( format ! ( "Bearer {}" , token) )
67+ let token = {
68+ let mut auth_ref = auth. borrow_mut ( ) ;
69+ match username {
70+ Some ( username) => auth_ref. get_token_store ( ) . get_oauth2_token ( username) ,
71+ None => auth_ref. get_token_store ( ) . get_first_oauth2_token ( ) ,
72+ }
73+ } ;
74+ match token {
75+ Some ( token) => {
76+ self . validate_and_refresh_oauth2_token ( auth, token, username)
77+ . await
4578 }
4679 None => {
47- if let Some ( token) = auth. borrow_mut ( ) . get_token_store ( ) . get_first_oauth2_token ( ) {
48- match token {
49- Token :: OAuth2 ( token) => Ok ( format ! ( "Bearer {}" , token) ) ,
50- _ => Err ( Error :: AuthError ( AuthError :: WrongTokenFoundInStore ) ) ,
51- }
52- } else {
53- let token = auth. borrow_mut ( ) . oauth2 ( None ) . await ?;
54- Ok ( format ! ( "Bearer {}" , token) )
55- }
80+ let token = auth. borrow_mut ( ) . oauth2 ( username) . await ?;
81+ Ok ( format ! ( "Bearer {}" , token) )
5682 }
5783 }
5884 }
5985
86+ /// Get the auth header for the request
6087 async fn get_auth_header (
6188 & self ,
6289 method : & str ,
@@ -69,7 +96,7 @@ impl ApiClient {
6996 None => return Ok ( "" . to_string ( ) ) ,
7097 } ;
7198
72- match auth_type. as_deref ( ) {
99+ match auth_type {
73100 Some ( "app" ) => {
74101 if let Some ( token) = auth. borrow ( ) . bearer_token ( ) {
75102 Ok ( format ! ( "Bearer {}" , token) )
@@ -90,16 +117,16 @@ impl ApiClient {
90117 let token = {
91118 let mut auth_ref = auth. borrow_mut ( ) ;
92119 if let Some ( username) = username {
120+ // Username passed, we need to get the token for the specific username
93121 auth_ref. get_token_store ( ) . get_oauth2_token ( username)
94122 } else {
123+ // No username passed, we need to get the first oauth2 token
95124 auth_ref. get_token_store ( ) . get_first_oauth2_token ( )
96125 }
97126 } ;
98127 if let Some ( token) = token {
99- match token {
100- Token :: OAuth2 ( token) => Ok ( format ! ( "Bearer {}" , token) ) ,
101- _ => Err ( Error :: AuthError ( AuthError :: WrongTokenFoundInStore ) ) ,
102- }
128+ self . validate_and_refresh_oauth2_token ( auth, token, username)
129+ . await
103130 } else {
104131 let oauth1_result = {
105132 let auth_ref = auth. borrow ( ) ;
@@ -121,7 +148,7 @@ impl ApiClient {
121148 }
122149 }
123150
124- pub async fn build_request (
151+ pub async fn build_request (
125152 & self ,
126153 method : & str ,
127154 endpoint : & str ,
@@ -188,8 +215,8 @@ pub async fn build_request(
188215 let response = request_builder. send ( ) . await ?;
189216
190217 if verbose {
191- println ! ( "Request: {:#?}" , req) ;
192- println ! ( "Response: {:#?}" , response)
218+ println ! ( "{:#?}" , req) ;
219+ println ! ( "{:#?}" , response)
193220 }
194221
195222 let status = response. status ( ) ;
@@ -201,7 +228,7 @@ pub async fn build_request(
201228 } else {
202229 Ok ( res)
203230 }
204- } ,
231+ }
205232 Err ( _) => {
206233 let status = status. to_string ( ) ;
207234 Err ( Error :: ApiError ( serde_json:: json!( {
@@ -226,15 +253,22 @@ mod tests {
226253
227254 fn mock_auth ( ) -> Auth {
228255 let config = Config :: from_env ( ) ;
229- let auth = Auth :: new ( config )
230- . with_token_store ( TokenStore :: from_file_path ( ".xurl_test" . into ( ) ) ) ;
256+ let auth =
257+ Auth :: new ( config ) . with_token_store ( TokenStore :: from_file_path ( ".xurl_test" . into ( ) ) ) ;
231258 auth
232259 }
233260
234261 fn setup_tests_with_mock_oauth2_token ( ) -> Auth {
235262 let mut auth = mock_auth ( ) ;
236263 let token_store = auth. get_token_store ( ) ;
237- token_store. save_oauth2_token ( "test" , "fake_token" ) . unwrap ( ) ;
264+ let current_time = SystemTime :: now ( )
265+ . duration_since ( UNIX_EPOCH )
266+ . unwrap ( )
267+ . as_secs ( )
268+ + 7200 ;
269+ token_store
270+ . save_oauth2_token ( "test" , "fake_token" , "fake_refresh_token" , current_time)
271+ . unwrap ( ) ;
238272
239273 auth
240274 }
0 commit comments