1use base64;
2use http::header::{AUTHORIZATION, CONTENT_TYPE};
3use http::HeaderMap;
4use reqwest::Client as reqwest_client;
5use reqwest::{Method, Response};
6
7use serde::Serialize;
8use std::collections::HashMap;
9use std::str::FromStr;
10
11const OAUTH_BASE_URL: &str = "https://oauth.openapi.it";
12const TEST_OAUTH_BASE_URL: &str = "https://test.oauth.openapi.it";
13
14pub struct OauthClient {
15 client: reqwest_client,
16 url: &'static str,
17}
18
19impl OauthClient {
20 pub fn new(username: &str, apikey: &str, test: bool) -> Result<OauthClient, reqwest::Error> {
21 let url = if test {
22 TEST_OAUTH_BASE_URL
23 } else {
24 OAUTH_BASE_URL
25 };
26 let encoded = base64::encode(format!("{username}:{apikey}"));
27 let auth_header = format!("Basic {encoded}");
28 let mut headers = HeaderMap::new();
29 headers.insert(AUTHORIZATION, auth_header.parse().unwrap());
30 headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
31
32 let client = reqwest::Client::builder()
33 .default_headers(headers)
34 .build()?;
35 Ok(OauthClient { client, url })
36 }
37
38 pub async fn get_scopes(&self, limit: bool) -> Result<String, reqwest::Error> {
39 let params = [("limit", limit as u8)];
40 let url = format!("{}/scopes", self.url);
41 let response: Response = self.client.get(url).query(¶ms).send().await?;
42 let json_str: String = response.text().await?;
43 Ok(json_str)
44 }
45
46 pub async fn create_token(
47 &self,
48 scopes: Vec<&'static str>,
49 ttl: u64,
50 ) -> Result<String, reqwest::Error> {
51 #[derive(Serialize)]
52 struct Body {
53 scopes: Vec<&'static str>,
54 ttl: u64,
55 }
56
57 let body = Body { scopes, ttl };
58 let url = format!("{}/token", self.url);
59 let response: Response = self.client.post(url).json(&body).send().await?;
60 let json_str: String = response.text().await?;
61 Ok(json_str)
62 }
63
64 pub async fn get_tokens(&self, scope: &'static str) -> Result<String, reqwest::Error> {
65 let params = [("scope", scope)];
66 let url = format!("{}/token", self.url);
67 let response: Response = self.client.get(url).query(¶ms).send().await?;
68 let json_str: String = response.text().await?;
69 Ok(json_str)
70 }
71
72 pub async fn delete_token(&self, id: String) -> Result<String, reqwest::Error> {
73 let url = format!("{}/token/{}", self.url, id);
74 let response: Response = self.client.delete(url).send().await?;
75 let json_str: String = response.text().await?;
76 Ok(json_str)
77 }
78
79 pub async fn get_counters(
80 &self,
81 period: &'static str,
82 date: &'static str,
83 ) -> Result<String, reqwest::Error> {
84 let url = format!("{}/counters/{}/{}", self.url, period, date);
85 let response: Response = self.client.get(url).send().await?;
86 let json_str: String = response.text().await?;
87 Ok(json_str)
88 }
89}
90
91pub struct Client {
92 client: reqwest_client,
93}
94
95impl Client {
96 pub fn new(token: String) -> Result<Client, reqwest::Error> {
97 let auth_header = format!("Bearer {token}");
98 let mut headers = HeaderMap::new();
99 headers.insert(AUTHORIZATION, auth_header.parse().unwrap());
100 headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
101
102 let client = reqwest::Client::builder()
103 .default_headers(headers)
104 .build()?;
105 Ok(Client { client })
106 }
107
108 pub async fn request<T>(
109 &self,
110 method: &str,
111 url: &str,
112 payload: Option<&T>,
113 params: Option<HashMap<&str, &str>>,
114 ) -> Result<String, reqwest::Error>
115 where
116 T: Serialize,
117 {
118 let url = format!("{}", url);
119 let mut request = self.client.request(Method::from_str(method).unwrap(), url);
120
121 if let Some(payload) = payload {
122 request = request.json(payload);
123 }
124
125 if let Some(params) = params {
126 request = request.query(¶ms);
127 }
128
129 let response: Response = request.send().await?;
130 let json_str: String = response.text().await?;
131 Ok(json_str)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_oauth_client_creation() {
141 let client = OauthClient::new("test_user", "test_key", true);
142 assert!(client.is_ok());
143 }
144
145 #[test]
146 fn test_api_client_creation() {
147 let client = Client::new("test_token".to_string());
148 assert!(client.is_ok());
149 }
150}