#![allow(missing_docs)]
#![allow(clippy::needless_lifetimes)]
#![allow(clippy::too_many_arguments)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "requests")]
pub mod application_management;
#[cfg(feature = "requests")]
pub mod ats;
#[cfg(feature = "requests")]
pub mod companies;
#[cfg(feature = "requests")]
pub mod current_user;
#[cfg(feature = "requests")]
pub mod employees;
#[cfg(feature = "requests")]
pub mod groups;
#[cfg(feature = "requests")]
pub mod leaves;
mod methods;
#[cfg(feature = "requests")]
pub mod saml;
#[cfg(test)]
mod tests;
pub mod types;
pub mod utils;
#[cfg(feature = "requests")]
use std::env;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "requests")]
static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
#[derive(Clone, Debug)]
#[cfg(feature = "requests")]
pub struct Client {
token: String,
base_url: String,
#[cfg(feature = "retry")]
client: reqwest_middleware::ClientWithMiddleware,
#[cfg(feature = "retry")]
#[cfg(not(target_arch = "wasm32"))]
#[allow(dead_code)]
client_http1_only: reqwest_middleware::ClientWithMiddleware,
#[cfg(not(feature = "retry"))]
client: reqwest::Client,
#[cfg(not(feature = "retry"))]
#[cfg(not(target_arch = "wasm32"))]
#[allow(dead_code)]
client_http1_only: reqwest::Client,
}
#[cfg(feature = "retry")]
#[cfg(feature = "requests")]
pub struct RequestBuilder(pub reqwest_middleware::RequestBuilder);
#[cfg(not(feature = "retry"))]
#[cfg(feature = "requests")]
pub struct RequestBuilder(pub reqwest::RequestBuilder);
#[cfg(feature = "requests")]
impl Client {
#[tracing::instrument]
#[cfg(not(target_arch = "wasm32"))]
pub fn new_from_reqwest<T>(
token: T,
builder_http: reqwest::ClientBuilder,
builder_websocket: reqwest::ClientBuilder,
) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(feature = "retry")]
{
let retry_policy =
reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
match (builder_http.build(), builder_websocket.build()) {
(Ok(c), Ok(c1)) => {
let client = reqwest_middleware::ClientBuilder::new(c)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
let client_http1_only = reqwest_middleware::ClientBuilder::new(c1)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
Client {
token: token.to_string(),
base_url: "https://api.rippling.com".to_string(),
client,
client_http1_only,
}
}
(Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
}
}
#[cfg(not(feature = "retry"))]
{
match (builder_http.build(), builder_websocket.build()) {
(Ok(c), Ok(c1)) => Client {
token: token.to_string(),
base_url: "https://api.rippling.com".to_string(),
client: c,
client_http1_only: c1,
},
(Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
}
}
}
#[tracing::instrument]
#[cfg(target_arch = "wasm32")]
pub fn new_from_reqwest<T>(token: T, builder_http: reqwest::ClientBuilder) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(feature = "retry")]
{
let retry_policy =
reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
match builder_http.build() {
Ok(c) => {
let client = reqwest_middleware::ClientBuilder::new(c)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
Client {
token: token.to_string(),
base_url: "https://api.rippling.com".to_string(),
client,
}
}
Err(e) => panic!("creating reqwest client failed: {:?}", e),
}
}
#[cfg(not(feature = "retry"))]
{
match builder_http.build() {
Ok(c) => Client {
token: token.to_string(),
base_url: "https://api.rippling.com".to_string(),
client: c,
},
Err(e) => panic!("creating reqwest client failed: {:?}", e),
}
}
}
#[tracing::instrument]
pub fn new<T>(token: T) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(not(target_arch = "wasm32"))]
let client = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
#[cfg(target_arch = "wasm32")]
let client = reqwest::Client::builder();
#[cfg(not(target_arch = "wasm32"))]
let client_http1 = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.http1_only();
#[cfg(not(target_arch = "wasm32"))]
return Self::new_from_reqwest(token, client, client_http1);
#[cfg(target_arch = "wasm32")]
Self::new_from_reqwest(token, client)
}
#[tracing::instrument]
pub fn set_base_url<H>(&mut self, base_url: H)
where
H: Into<String> + std::fmt::Display + std::fmt::Debug,
{
self.base_url = base_url.to_string().trim_end_matches('/').to_string();
}
#[tracing::instrument]
pub fn new_from_env() -> Self {
let token = env::var("RIPPLING_BASE_API_TOKEN").expect("must set RIPPLING_BASE_API_TOKEN");
Client::new(token)
}
#[tracing::instrument]
pub async fn request_raw(
&self,
method: reqwest::Method,
uri: &str,
body: Option<reqwest::Body>,
) -> anyhow::Result<RequestBuilder> {
let u = if uri.starts_with("https://") || uri.starts_with("http://") {
uri.to_string()
} else {
format!("{}/{}", self.base_url, uri.trim_start_matches('/'))
};
let mut req = self.client.request(method, &u);
req = req.bearer_auth(&self.token);
req = req.header(
reqwest::header::ACCEPT,
reqwest::header::HeaderValue::from_static("application/json"),
);
req = req.header(
reqwest::header::CONTENT_TYPE,
reqwest::header::HeaderValue::from_static("application/json"),
);
if let Some(body) = body {
req = req.body(body);
}
Ok(RequestBuilder(req))
}
pub fn companies(&self) -> companies::Companies {
companies::Companies::new(self.clone())
}
pub fn employees(&self) -> employees::Employees {
employees::Employees::new(self.clone())
}
pub fn groups(&self) -> groups::Groups {
groups::Groups::new(self.clone())
}
pub fn saml(&self) -> saml::Saml {
saml::Saml::new(self.clone())
}
pub fn current_user(&self) -> current_user::CurrentUser {
current_user::CurrentUser::new(self.clone())
}
pub fn ats(&self) -> ats::Ats {
ats::Ats::new(self.clone())
}
pub fn application_management(&self) -> application_management::ApplicationManagement {
application_management::ApplicationManagement::new(self.clone())
}
pub fn leaves(&self) -> leaves::Leaves {
leaves::Leaves::new(self.clone())
}
}