use super::access_token::AccessTokenBuilder;
use super::{AccessToken, AppConfig, HttpClient};
use crate::{Result, constants};
use async_trait::async_trait;
use http::{Method, Request};
use std::collections::HashMap;
use std::sync::Arc;
#[async_trait]
pub trait TokenType: Send + Sync {
async fn token(&self) -> Result<AccessToken>;
fn app_config(&self) -> AppConfig;
}
#[derive(Clone)]
pub struct StableToken {
pub app_id: String,
pub secret: String,
pub end_point: String,
pub force_refresh: bool,
client: Arc<dyn HttpClient>,
}
impl StableToken {
pub fn new(
app_id: &str,
secret: &str,
force_refresh: bool,
client: Arc<dyn HttpClient>,
) -> Self {
StableToken {
app_id: app_id.to_string(),
secret: secret.to_string(),
end_point: constants::STABLE_ACCESS_TOKEN_END_POINT.to_string(),
force_refresh,
client,
}
}
}
#[async_trait]
impl TokenType for StableToken {
async fn token(&self) -> Result<AccessToken> {
let mut body: HashMap<&str, String> = HashMap::new();
body.insert("grant_type", "client_credential".into());
body.insert("appid", self.app_id.to_string());
body.insert("secret", self.secret.to_string());
if self.force_refresh {
body.insert("force_refresh", self.force_refresh.to_string());
}
let req_body = serde_json::to_vec(&body)?;
let request = Request::builder()
.uri(self.end_point.clone())
.method(Method::POST)
.header("User-Agent", constants::HTTP_CLIENT_USER_AGENT)
.body(req_body)?;
let response = self.client.execute(request).await?;
let response_body = response.into_body();
let token_builder = serde_json::from_slice::<AccessTokenBuilder>(&response_body)?;
Ok(token_builder.build())
}
fn app_config(&self) -> AppConfig {
AppConfig {
app_id: self.app_id.clone(),
secret: self.secret.clone(),
}
}
}
pub struct NonStableToken {
pub app_id: String,
pub secret: String,
pub end_point: String,
client: Arc<dyn HttpClient>,
}
impl NonStableToken {
pub fn new(app_id: &str, secret: &str, client: Arc<dyn HttpClient>) -> Self {
NonStableToken {
app_id: app_id.to_string(),
secret: secret.to_string(),
end_point: constants::ACCESS_TOKEN_END_POINT.to_string(),
client,
}
}
}
#[async_trait]
impl TokenType for NonStableToken {
async fn token(&self) -> Result<AccessToken> {
let mut body: HashMap<&str, String> = HashMap::new();
body.insert("grant_type", "client_credential".into());
body.insert("appid", self.app_id.to_string());
body.insert("secret", self.secret.to_string());
let req_body = serde_json::to_vec(&body)?;
let request = Request::builder()
.uri(self.end_point.clone())
.method(Method::POST)
.header("User-Agent", constants::HTTP_CLIENT_USER_AGENT)
.body(req_body)?;
let response = self.client.execute(request).await?;
let response_body = response.into_body();
let token_builder = serde_json::from_slice::<AccessTokenBuilder>(&response_body)?;
Ok(token_builder.build())
}
fn app_config(&self) -> AppConfig {
AppConfig {
app_id: self.app_id.clone(),
secret: self.secret.clone(),
}
}
}