@@ -8,46 +8,72 @@ use serde::Serialize;
88use std:: collections:: HashMap ;
99use std:: str:: FromStr ;
1010
11+ // Base URL for production OAuth endpoint
1112const OAUTH_BASE_URL : & str = "https://oauth.openapi.it" ;
13+ // Base URL for test OAuth endpoint
1214const TEST_OAUTH_BASE_URL : & str = "https://test.oauth.openapi.it" ;
1315
16+ /// OAuth client for OpenAPI authentication and token management
1417pub struct OauthClient {
1518 client : reqwest_client ,
1619 url : & ' static str ,
1720}
1821
1922impl OauthClient {
23+ /// Creates a new OAuth client with Basic authentication
24+ ///
25+ /// # Arguments
26+ /// * `username` - The API username
27+ /// * `apikey` - The API key for authentication
28+ /// * `test` - If true, uses test environment; otherwise production
2029 pub fn new ( username : & str , apikey : & str , test : bool ) -> Result < OauthClient , reqwest:: Error > {
30+ // Select appropriate base URL based on environment
2131 let url = if test {
2232 TEST_OAUTH_BASE_URL
2333 } else {
2434 OAUTH_BASE_URL
2535 } ;
36+
37+ // Encode credentials for Basic auth
2638 let encoded = base64:: encode ( format ! ( "{username}:{apikey}" ) ) ;
2739 let auth_header = format ! ( "Basic {encoded}" ) ;
2840 let mut headers = HeaderMap :: new ( ) ;
41+
42+ // TODO: Replace unwrap() with graceful error message for invalid header values
2943 headers. insert ( AUTHORIZATION , auth_header. parse ( ) . unwrap ( ) ) ;
3044 headers. insert ( CONTENT_TYPE , "application/json" . parse ( ) . unwrap ( ) ) ;
3145
46+ // Build HTTP client with default headers
3247 let client = reqwest:: Client :: builder ( )
3348 . default_headers ( headers)
3449 . build ( ) ?;
3550 Ok ( OauthClient { client, url } )
3651 }
3752
53+ /// Retrieves available OAuth scopes
54+ ///
55+ /// # Arguments
56+ /// * `limit` - If true, returns limited scope information
3857 pub async fn get_scopes ( & self , limit : bool ) -> Result < String , reqwest:: Error > {
3958 let params = [ ( "limit" , limit as u8 ) ] ;
4059 let url = format ! ( "{}/scopes" , self . url) ;
4160 let response: Response = self . client . get ( url) . query ( & params) . send ( ) . await ?;
61+ // TODO: Add error handling for non-2xx status codes with descriptive messages
4262 let json_str: String = response. text ( ) . await ?;
4363 Ok ( json_str)
4464 }
4565
66+ /// Creates a new access token with specified scopes and time-to-live
67+ ///
68+ /// # Arguments
69+ /// * `scopes` - List of permission scopes for the token
70+ /// * `ttl` - Token lifetime in seconds
4671 pub async fn create_token (
4772 & self ,
4873 scopes : Vec < & ' static str > ,
4974 ttl : u64 ,
5075 ) -> Result < String , reqwest:: Error > {
76+ // Request body structure for token creation
5177 #[ derive( Serialize ) ]
5278 struct Body {
5379 scopes : Vec < & ' static str > ,
@@ -57,54 +83,89 @@ impl OauthClient {
5783 let body = Body { scopes, ttl } ;
5884 let url = format ! ( "{}/token" , self . url) ;
5985 let response: Response = self . client . post ( url) . json ( & body) . send ( ) . await ?;
86+ // TODO: Check response status and provide meaningful error for failed token creation
6087 let json_str: String = response. text ( ) . await ?;
6188 Ok ( json_str)
6289 }
6390
91+ /// Retrieves existing tokens filtered by scope
92+ ///
93+ /// # Arguments
94+ /// * `scope` - The scope to filter tokens by
6495 pub async fn get_tokens ( & self , scope : & ' static str ) -> Result < String , reqwest:: Error > {
6596 let params = [ ( "scope" , scope) ] ;
6697 let url = format ! ( "{}/token" , self . url) ;
6798 let response: Response = self . client . get ( url) . query ( & params) . send ( ) . await ?;
99+ // TODO: Add error handling for invalid scope or empty results
68100 let json_str: String = response. text ( ) . await ?;
69101 Ok ( json_str)
70102 }
71103
104+ /// Deletes a token by its ID
105+ ///
106+ /// # Arguments
107+ /// * `id` - The unique identifier of the token to delete
72108 pub async fn delete_token ( & self , id : String ) -> Result < String , reqwest:: Error > {
73109 let url = format ! ( "{}/token/{}" , self . url, id) ;
74110 let response: Response = self . client . delete ( url) . send ( ) . await ?;
111+ // TODO: Provide clear error message when token not found or already deleted
75112 let json_str: String = response. text ( ) . await ?;
76113 Ok ( json_str)
77114 }
78115
116+ /// Retrieves API usage counters for a specific period and date
117+ ///
118+ /// # Arguments
119+ /// * `period` - The time period (e.g., "day", "month")
120+ /// * `date` - The date in appropriate format
79121 pub async fn get_counters (
80122 & self ,
81123 period : & ' static str ,
82124 date : & ' static str ,
83125 ) -> Result < String , reqwest:: Error > {
84126 let url = format ! ( "{}/counters/{}/{}" , self . url, period, date) ;
85127 let response: Response = self . client . get ( url) . send ( ) . await ?;
128+ // TODO: Validate period and date format, provide descriptive error for invalid values
86129 let json_str: String = response. text ( ) . await ?;
87130 Ok ( json_str)
88131 }
89132}
90133
134+ /// Generic API client with Bearer token authentication
91135pub struct Client {
92136 client : reqwest_client ,
93137}
94138
95139impl Client {
140+ /// Creates a new API client with Bearer token authentication
141+ ///
142+ /// # Arguments
143+ /// * `token` - The Bearer token for API authentication
96144 pub fn new ( token : String ) -> Result < Client , reqwest:: Error > {
97145 let auth_header = format ! ( "Bearer {token}" ) ;
98146 let mut headers = HeaderMap :: new ( ) ;
147+
148+ // TODO: Replace unwrap() with graceful error message for invalid token format
99149 headers. insert ( AUTHORIZATION , auth_header. parse ( ) . unwrap ( ) ) ;
100150 headers. insert ( CONTENT_TYPE , "application/json" . parse ( ) . unwrap ( ) ) ;
101151
152+ // Build HTTP client with Bearer auth headers
102153 let client = reqwest:: Client :: builder ( )
103154 . default_headers ( headers)
104155 . build ( ) ?;
105156 Ok ( Client { client } )
106157 }
107158
159+ /// Makes an HTTP request to the specified URL
160+ ///
161+ /// # Arguments
162+ /// * `method` - HTTP method as string (e.g., "GET", "POST")
163+ /// * `url` - The full URL to request
164+ /// * `payload` - Optional JSON payload for the request body
165+ /// * `params` - Optional query parameters
166+ ///
167+ /// # Returns
168+ /// The response body as a JSON string
108169 pub async fn request < T > (
109170 & self ,
110171 method : & str ,
@@ -116,17 +177,25 @@ impl Client {
116177 T : Serialize ,
117178 {
118179 let url = format ! ( "{}" , url) ;
180+
181+ // TODO: Replace unwrap() with proper error handling for invalid HTTP methods
182+ // Consider returning a descriptive error like "Invalid HTTP method: {method}"
119183 let mut request = self . client . request ( Method :: from_str ( method) . unwrap ( ) , url) ;
120184
185+ // Attach JSON payload if provided
121186 if let Some ( payload) = payload {
122187 request = request. json ( payload) ;
123188 }
124189
190+ // Attach query parameters if provided
125191 if let Some ( params) = params {
126192 request = request. query ( & params) ;
127193 }
128194
195+ // Execute the request
129196 let response: Response = request. send ( ) . await ?;
197+ // TODO: Check HTTP status code and provide meaningful error messages for different status codes
198+ // (e.g., 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Server Error)
130199 let json_str: String = response. text ( ) . await ?;
131200 Ok ( json_str)
132201 }
@@ -136,15 +205,21 @@ impl Client {
136205mod tests {
137206 use super :: * ;
138207
208+ /// Tests successful creation of OAuth client with test credentials
139209 #[ test]
140210 fn test_oauth_client_creation ( ) {
141211 let client = OauthClient :: new ( "test_user" , "test_key" , true ) ;
142212 assert ! ( client. is_ok( ) ) ;
143213 }
144214
215+ /// Tests successful creation of API client with Bearer token
145216 #[ test]
146217 fn test_api_client_creation ( ) {
147218 let client = Client :: new ( "test_token" . to_string ( ) ) ;
148219 assert ! ( client. is_ok( ) ) ;
149220 }
221+
222+ // TODO: Add test for invalid credentials and verify error messages are descriptive
223+ // TODO: Add test for invalid HTTP method in request() and verify error handling
224+ // TODO: Add integration tests for API endpoints with mock server
150225}
0 commit comments