use std::{num::NonZeroUsize, time::Duration};
use reqwest::header::{CONTENT_TYPE, HeaderValue};
use crate::{PrivyCreateError, generated::Client, get_auth_header, jwt_exchange::JwtExchange};
const DEFAULT_BASE_URL: &str = "https://api.privy.io";
const APP_ID_ENV_VAR: &str = "PRIVY_TEST_APP_ID";
const APP_SECRET_ENV_VAR: &str = "PRIVY_TEST_APP_SECRET";
const BASE_URL_ENV_VAR: &str = "PRIVY_TEST_URL";
#[derive(Clone, Debug)]
pub struct PrivyClient {
pub(crate) app_id: String,
#[allow(dead_code)]
pub(crate) app_secret: String,
pub(crate) base_url: String,
pub(crate) client: Client,
pub jwt_exchange: JwtExchange,
}
pub struct PrivyClientOptions {
pub cache_size: NonZeroUsize,
pub base_url: String,
}
impl Default for PrivyClientOptions {
fn default() -> Self {
Self {
cache_size: NonZeroUsize::new(1000).expect("non-zero"),
base_url: String::from(DEFAULT_BASE_URL),
}
}
}
impl PrivyClient {
pub fn new(app_id: String, app_secret: String) -> Result<Self, PrivyCreateError> {
Self::new_with_options(app_id, app_secret, PrivyClientOptions::default())
}
pub fn new_from_env() -> Result<Self, PrivyCreateError> {
let app_id = std::env::var(APP_ID_ENV_VAR).map_err(|_| PrivyCreateError::InvalidAppId)?;
let app_secret =
std::env::var(APP_SECRET_ENV_VAR).map_err(|_| PrivyCreateError::InvalidAppSecret)?;
Self::new_with_options(
app_id,
app_secret,
PrivyClientOptions {
base_url: std::env::var(BASE_URL_ENV_VAR)
.unwrap_or_else(|_| DEFAULT_BASE_URL.to_string()),
..PrivyClientOptions::default()
},
)
}
pub fn new_with_options(
app_id: String,
app_secret: String,
options: PrivyClientOptions,
) -> Result<Self, PrivyCreateError> {
let client_version = concat!("rust:", env!("CARGO_PKG_VERSION"));
tracing::debug!("Privy client version: {}", client_version);
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
reqwest::header::AUTHORIZATION,
HeaderValue::from_str(&get_auth_header(&app_id, &app_secret))?,
);
headers.insert("privy-app-id", HeaderValue::from_str(&app_id)?);
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert("privy-client", HeaderValue::from_static(client_version));
let client_with_custom_defaults = reqwest::ClientBuilder::new()
.connect_timeout(Duration::from_secs(15))
.timeout(Duration::from_secs(15))
.default_headers(headers)
.build()?;
Ok(Self {
app_id,
app_secret,
client: Client::new_with_client(&options.base_url, client_with_custom_defaults),
base_url: options.base_url,
jwt_exchange: JwtExchange::new(options.cache_size),
})
}
#[must_use]
pub fn utils(&self) -> crate::utils::Utils {
crate::utils::Utils {
app_id: self.app_id.clone(),
}
}
pub fn app_id(&self) -> &str {
&self.app_id
}
pub fn base_url(&self) -> &str {
&self.base_url
}
}