use url::{ParseError, Url};
use crate::ApiKey;
use crate::directory_sync::DirectorySync;
use crate::events::Events;
use crate::mfa::Mfa;
use crate::organization_domains::OrganizationDomains;
use crate::organizations::Organizations;
use crate::portal::Portal;
use crate::roles::Roles;
use crate::sso::{ClientId, Sso};
use crate::user_management::UserManagement;
use crate::widgets::Widgets;
#[derive(Clone)]
pub struct WorkOs {
base_url: Url,
key: ApiKey,
client: reqwest::Client,
client_id: Option<ClientId>,
}
impl WorkOs {
pub fn new(key: &ApiKey) -> Self {
WorkOsBuilder::new(key).build()
}
pub fn builder(key: &ApiKey) -> WorkOsBuilder<'_> {
WorkOsBuilder::new(key)
}
pub(crate) fn base_url(&self) -> &Url {
&self.base_url
}
pub(crate) fn key(&self) -> &ApiKey {
&self.key
}
pub(crate) fn client(&self) -> &reqwest::Client {
&self.client
}
pub(crate) fn client_id(&self) -> Option<&ClientId> {
self.client_id.as_ref()
}
pub fn directory_sync(&self) -> DirectorySync<'_> {
DirectorySync::new(self)
}
pub fn events(&self) -> Events<'_> {
Events::new(self)
}
pub fn mfa(&self) -> Mfa<'_> {
Mfa::new(self)
}
pub fn organization_domains(&self) -> OrganizationDomains<'_> {
OrganizationDomains::new(self)
}
pub fn organizations(&self) -> Organizations<'_> {
Organizations::new(self)
}
pub fn portal(&self) -> Portal<'_> {
Portal::new(self)
}
pub fn roles(&self) -> Roles<'_> {
Roles::new(self)
}
pub fn sso(&self) -> Sso<'_> {
Sso::new(self)
}
pub fn user_management(&self) -> UserManagement<'_> {
UserManagement::new(self)
}
pub fn widgets(&self) -> Widgets<'_> {
Widgets::new(self)
}
}
pub struct WorkOsBuilder<'a> {
base_url: Url,
key: &'a ApiKey,
client_id: Option<&'a ClientId>,
client: Option<reqwest::Client>,
}
impl<'a> WorkOsBuilder<'a> {
pub fn new(key: &'a ApiKey) -> Self {
Self {
base_url: Url::parse("https://api.workos.com").unwrap(),
key,
client_id: None,
client: None,
}
}
pub fn base_url(mut self, base_url: &'a str) -> Result<Self, ParseError> {
self.base_url = Url::parse(base_url)?;
Ok(self)
}
pub fn key(mut self, key: &'a ApiKey) -> Self {
self.key = key;
self
}
pub fn client_id(mut self, client_id: &'a ClientId) -> Self {
self.client_id = Some(client_id);
self
}
pub fn client(mut self, client: reqwest::Client) -> Self {
self.client = Some(client);
self
}
pub fn build(self) -> WorkOs {
let client = self.client.unwrap_or_else(|| {
reqwest::Client::builder()
.user_agent(concat!("workos-rust/", env!("CARGO_PKG_VERSION")))
.build()
.unwrap()
});
WorkOs {
base_url: self.base_url,
key: self.key.to_owned(),
client,
client_id: self.client_id.cloned(),
}
}
}
#[cfg(test)]
mod test {
use reqwest::StatusCode;
use super::*;
#[test]
fn it_supports_setting_the_base_url_through_the_builder() {
let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.base_url("https://auth.your-app.com")
.unwrap()
.build();
assert_eq!(
workos.base_url(),
&Url::parse("https://auth.your-app.com").unwrap()
)
}
#[test]
fn it_supports_setting_the_api_key_through_the_builder() {
let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.key(&ApiKey::from("sk_another_api_key"))
.build();
assert_eq!(workos.key(), &ApiKey::from("sk_another_api_key"))
}
#[tokio::test]
async fn it_sets_the_user_agent_header_on_the_client() {
let mut server = mockito::Server::new_async().await;
let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.base_url(&server.url())
.unwrap()
.build();
server
.mock("GET", "/health")
.match_header(
"User-Agent",
concat!("workos-rust/", env!("CARGO_PKG_VERSION")),
)
.with_status(200)
.with_body("User-Agent correctly set")
.create_async()
.await;
let url = workos.base_url().join("/health").unwrap();
let response = workos.client().get(url).send().await.unwrap();
let response_body = response.text().await.unwrap();
assert_eq!(response_body, "User-Agent correctly set")
}
#[tokio::test]
async fn it_supports_setting_the_reqwest_client() {
let mut server = mockito::Server::new_async().await;
let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.base_url(&server.url())
.unwrap()
.client(
reqwest::Client::builder()
.user_agent("custom")
.build()
.unwrap(),
)
.build();
server
.mock("GET", "/health")
.match_header("User-Agent", "custom")
.with_status(204)
.create_async()
.await;
let url = workos.base_url().join("/health").unwrap();
let response = workos.client().get(url).send().await.unwrap();
assert_eq!(response.status(), StatusCode::NO_CONTENT);
}
}