From d1815f7757f552813fe843bba3824757b17e84c1 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 15:57:57 +0000 Subject: [PATCH 1/8] add lt param --- src/admin_portal.rs | 2 +- src/directory_sync.rs | 2 +- src/mfa.rs | 2 +- src/organizations.rs | 2 +- src/passwordless.rs | 2 +- src/sso.rs | 2 +- src/user_management.rs | 2 +- src/workos.rs | 10 +++++++--- 8 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/admin_portal.rs b/src/admin_portal.rs index cd8bab7..febd04a 100644 --- a/src/admin_portal.rs +++ b/src/admin_portal.rs @@ -12,7 +12,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: Admin Portal Guide](https://workos.com/docs/admin-portal/guide) pub struct AdminPortal<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> AdminPortal<'a> { diff --git a/src/directory_sync.rs b/src/directory_sync.rs index 12da4df..5dc3bae 100644 --- a/src/directory_sync.rs +++ b/src/directory_sync.rs @@ -14,7 +14,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: Directory Sync Guide](https://workos.com/docs/directory-sync/guide) pub struct DirectorySync<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> DirectorySync<'a> { diff --git a/src/mfa.rs b/src/mfa.rs index e0f125a..c34e119 100644 --- a/src/mfa.rs +++ b/src/mfa.rs @@ -14,7 +14,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: MFA Guide](https://workos.com/docs/mfa/guide) pub struct Mfa<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> Mfa<'a> { diff --git a/src/organizations.rs b/src/organizations.rs index 6318a65..2f63067 100644 --- a/src/organizations.rs +++ b/src/organizations.rs @@ -10,7 +10,7 @@ use crate::WorkOs; /// Organizations. pub struct Organizations<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> Organizations<'a> { diff --git a/src/passwordless.rs b/src/passwordless.rs index 7e7e837..8596004 100644 --- a/src/passwordless.rs +++ b/src/passwordless.rs @@ -14,7 +14,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: Magic Link Guide](https://workos.com/docs/magic-link/guide) pub struct Passwordless<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> Passwordless<'a> { diff --git a/src/sso.rs b/src/sso.rs index 5584b3d..e291c48 100644 --- a/src/sso.rs +++ b/src/sso.rs @@ -14,7 +14,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: SSO Guide](https://workos.com/docs/sso/guide) pub struct Sso<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> Sso<'a> { diff --git a/src/user_management.rs b/src/user_management.rs index 1975fee..5ff1479 100644 --- a/src/user_management.rs +++ b/src/user_management.rs @@ -14,7 +14,7 @@ use crate::WorkOs; /// /// [WorkOS Docs: User Management](https://workos.com/docs/user-management) pub struct UserManagement<'a> { - workos: &'a WorkOs, + workos: &'a WorkOs<'a>, } impl<'a> UserManagement<'a> { diff --git a/src/workos.rs b/src/workos.rs index 3d9ce2c..4a0a737 100644 --- a/src/workos.rs +++ b/src/workos.rs @@ -1,3 +1,5 @@ +use std::marker::PhantomData; + use url::{ParseError, Url}; use crate::ApiKey; @@ -11,13 +13,14 @@ use crate::user_management::UserManagement; /// The WorkOS client. #[derive(Clone)] -pub struct WorkOs { +pub struct WorkOs<'n> { base_url: Url, key: ApiKey, client: reqwest::Client, + phantom: PhantomData<&'n ()> } -impl WorkOs { +impl WorkOs<'_> { /// Returns a new instance of the WorkOS client using the provided API key. pub fn new(key: &ApiKey) -> Self { WorkOsBuilder::new(key).build() @@ -104,7 +107,7 @@ impl<'a> WorkOsBuilder<'a> { } /// Consumes the builder and returns the constructed client. - pub fn build(self) -> WorkOs { + pub fn build(self) -> WorkOs<'static> { let client = reqwest::Client::builder() .user_agent(concat!("workos-rust/", env!("CARGO_PKG_VERSION"))) .build() @@ -114,6 +117,7 @@ impl<'a> WorkOsBuilder<'a> { base_url: self.base_url, key: self.key.to_owned(), client, + phantom: PhantomData } } } From 16025d849246ac419babaa772f042e80742a4eb2 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 16:20:18 +0000 Subject: [PATCH 2/8] custom clients --- Cargo.lock | 17 +++++++++ Cargo.toml | 1 + src/core.rs | 2 + src/core/traits.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++ src/workos.rs | 13 ++++--- 5 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 src/core/traits.rs diff --git a/Cargo.lock b/Cargo.lock index c911c79..d40f215 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -230,6 +230,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "errno" version = "0.3.12" @@ -1690,6 +1700,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -2097,6 +2113,7 @@ dependencies = [ "async-trait", "chrono", "derive_more", + "erased-serde", "jsonwebtoken", "matches", "mockito", diff --git a/Cargo.toml b/Cargo.toml index b8b7425..b2ff184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ rustls-tls = ["reqwest/rustls-tls"] async-trait = "0.1.88" chrono = { version = "0.4.40", features = ["serde"] } derive_more = { version = "2.0.1", features = ["deref", "display", "from"] } +erased-serde = "0.4.6" jsonwebtoken = "9.3.1" querystring = "1.1.0" reqwest = { version = "0.12.0", features = ["json"] } diff --git a/src/core.rs b/src/core.rs index 9acfda6..2ed4d37 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,6 +1,8 @@ mod error; mod response; mod types; +pub mod traits; + pub use error::*; pub(crate) use response::*; diff --git a/src/core/traits.rs b/src/core/traits.rs new file mode 100644 index 0000000..035178c --- /dev/null +++ b/src/core/traits.rs @@ -0,0 +1,93 @@ +use std::fmt::Display; + +use async_trait::async_trait; +use reqwest::IntoUrl; +use url::Url; + +#[async_trait] +///An HTP client +pub trait Client { + fn get(&self, url: Url) -> Box; + fn post(&self, url: Url) -> Box; + fn put(&self, url: Url) -> Box; + fn delete(&self, url: Url) -> Box; +} +#[async_trait] +impl Client for reqwest::Client { + fn get(&self, url: Url) -> Box { + Box::new(self.get(url)) + } + fn post(&self, url: Url) -> Box { + Box::new(self.post(url)) + } + fn put(&self, url: Url) -> Box { + Box::new(self.put(url)) + } + fn delete(&self, url: Url) -> Box { + Box::new(self.delete(url)) + } +} +#[async_trait] +pub trait ClientRequest { + fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box + where + Self: 'a; + fn json<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a; + fn query<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a; + fn form<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a; + async fn send(self: Box) -> Result; +} +#[async_trait] +impl ClientRequest for reqwest::RequestBuilder { + async fn send(self: Box) -> Result { + reqwest::RequestBuilder::send(*self).await + } + fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box + where + Self: 'a, + { + Box::new((*self).bearer_auth(x)) + } + fn json<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).json(x)) + } + fn query<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).query(x)) + } + fn form<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).form(x)) + } +} diff --git a/src/workos.rs b/src/workos.rs index 4a0a737..251fe53 100644 --- a/src/workos.rs +++ b/src/workos.rs @@ -1,4 +1,5 @@ use std::marker::PhantomData; +use std::sync::Arc; use url::{ParseError, Url}; @@ -16,8 +17,8 @@ use crate::user_management::UserManagement; pub struct WorkOs<'n> { base_url: Url, key: ApiKey, - client: reqwest::Client, - phantom: PhantomData<&'n ()> + client: Arc, + phantom: PhantomData<&'n ()>, } impl WorkOs<'_> { @@ -39,8 +40,8 @@ impl WorkOs<'_> { &self.key } - pub(crate) fn client(&self) -> &reqwest::Client { - &self.client + pub(crate) fn client(&self) -> &(dyn crate::traits::Client + '_) { + &*self.client } /// Returns an [`AdminPortal`] instance. @@ -116,8 +117,8 @@ impl<'a> WorkOsBuilder<'a> { WorkOs { base_url: self.base_url, key: self.key.to_owned(), - client, - phantom: PhantomData + client: Arc::new(client), + phantom: PhantomData, } } } From df029b0eec8f78220e3e594391a001aeb8004d7f Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 16:47:43 +0000 Subject: [PATCH 3/8] dynamic dispatch --- .../operations/generate_portal_link.rs | 2 +- src/core/error.rs | 3 ++ src/core/response.rs | 31 +++++++---- src/core/traits.rs | 51 +++++++++++++++++-- .../operations/get_directory.rs | 2 +- .../operations/get_directory_group.rs | 2 +- .../operations/get_directory_user.rs | 2 +- .../operations/list_directories.rs | 2 +- .../operations/list_directory_groups.rs | 2 +- .../operations/list_directory_users.rs | 2 +- src/mfa/operations/challenge_factor.rs | 2 +- src/mfa/operations/enroll_factor.rs | 6 +-- src/mfa/operations/verify_challenge.rs | 2 +- .../operations/create_organization.rs | 2 +- .../operations/get_organization.rs | 2 +- .../operations/list_organizations.rs | 2 +- .../operations/update_organization.rs | 2 +- .../operations/create_passwordless_session.rs | 2 +- src/sso/operations/get_connection.rs | 2 +- src/sso/operations/get_profile.rs | 2 +- src/sso/operations/get_profile_and_token.rs | 9 ++-- src/sso/operations/list_connections.rs | 2 +- .../operations/authenticate_with_code.rs | 4 +- .../authenticate_with_email_verification.rs | 4 +- .../authenticate_with_magic_auth.rs | 4 +- .../operations/authenticate_with_password.rs | 4 +- .../authenticate_with_refresh_token.rs | 4 +- .../operations/authenticate_with_totp.rs | 4 +- .../operations/create_magic_auth.rs | 2 +- .../operations/create_password_reset.rs | 7 +-- src/user_management/operations/create_user.rs | 2 +- .../operations/enroll_auth_factor.rs | 7 +-- .../operations/get_email_verification.rs | 2 +- src/user_management/operations/get_jwks.rs | 2 +- .../operations/get_magic_auth.rs | 2 +- .../operations/get_password_reset.rs | 2 +- src/user_management/operations/get_user.rs | 2 +- .../operations/get_user_by_external_id.rs | 2 +- .../operations/get_user_identities.rs | 2 +- .../operations/list_auth_factors.rs | 2 +- src/user_management/operations/list_users.rs | 2 +- .../operations/reset_password.rs | 7 +-- src/user_management/operations/update_user.rs | 2 +- .../types/authenticate_error.rs | 9 ++-- 44 files changed, 137 insertions(+), 75 deletions(-) diff --git a/src/admin_portal/operations/generate_portal_link.rs b/src/admin_portal/operations/generate_portal_link.rs index 8532396..7513f4e 100644 --- a/src/admin_portal/operations/generate_portal_link.rs +++ b/src/admin_portal/operations/generate_portal_link.rs @@ -109,7 +109,7 @@ impl GeneratePortalLink for AdminPortal<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(generate_link_response) diff --git a/src/core/error.rs b/src/core/error.rs index 6051824..585d215 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -22,6 +22,9 @@ pub enum WorkOsError { /// An unhandled error occurred with the API request. #[error("request error")] RequestError(#[from] reqwest::Error), + + #[error("json error")] + Json(#[from] serde_json::Error), } /// A WorkOS SDK result. diff --git a/src/core/response.rs b/src/core/response.rs index 157b139..cfb08c3 100644 --- a/src/core/response.rs +++ b/src/core/response.rs @@ -1,25 +1,30 @@ use reqwest::{Response, StatusCode}; +use serde::de::DeserializeOwned; -use crate::{WorkOsError, WorkOsResult}; +use crate::{WorkOsError, WorkOsResult, traits::ClientResponse}; -pub trait ResponseExt +pub trait ResponseExt<'a> where Self: Sized, { /// Handles an unauthorized error from the WorkOS API by converting it into a /// [`WorkOsError::Unauthorized`] response. - fn handle_unauthorized_error(self) -> WorkOsResult; + fn handle_unauthorized_error(self) -> WorkOsResult, E>; /// Handles a generic error from the WorkOS API by converting it into a /// [`WorkOsError::RequestError`] response. - fn handle_generic_error(self) -> WorkOsResult; + fn handle_generic_error(self) -> WorkOsResult, E>; /// Handles an unauthorized or generic error from the WorkOS API. - fn handle_unauthorized_or_generic_error(self) -> WorkOsResult; + fn handle_unauthorized_or_generic_error( + self, + ) -> WorkOsResult, E>; + + async fn json(self) -> WorkOsResult; } -impl ResponseExt for Response { - fn handle_unauthorized_error(self) -> WorkOsResult { +impl<'a> ResponseExt<'a> for Box { + fn handle_unauthorized_error(self) -> WorkOsResult, E> { if self.status() == StatusCode::UNAUTHORIZED { Err(WorkOsError::Unauthorized) } else { @@ -27,14 +32,22 @@ impl ResponseExt for Response { } } - fn handle_generic_error(self) -> WorkOsResult { + fn handle_generic_error(self) -> WorkOsResult, E> { match self.error_for_status() { Ok(response) => Ok(response), Err(err) => Err(WorkOsError::RequestError(err)), } } - fn handle_unauthorized_or_generic_error(self) -> WorkOsResult { + fn handle_unauthorized_or_generic_error( + self, + ) -> WorkOsResult, E> { self.handle_unauthorized_error()?.handle_generic_error() } + + async fn json(self) -> WorkOsResult { + let t = self.text().await.map_err(WorkOsError::RequestError)?; + + Ok(serde_json::from_str(&t)?) + } } diff --git a/src/core/traits.rs b/src/core/traits.rs index 035178c..2bea132 100644 --- a/src/core/traits.rs +++ b/src/core/traits.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use async_trait::async_trait; -use reqwest::IntoUrl; +use reqwest::{IntoUrl, StatusCode}; use url::Url; #[async_trait] @@ -28,6 +28,41 @@ impl Client for reqwest::Client { } } #[async_trait] +pub trait ClientResponse: Send + Sync{ + fn status(&self) -> StatusCode; + fn error_for_status<'a>( + self: Box, + ) -> Result, reqwest::Error> + where + Self: 'a; + fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), reqwest::Error>; + async fn text(self: Box) -> Result; +} +#[async_trait] +impl ClientResponse for reqwest::Response { + fn status(&self) -> StatusCode { + self.status() + } + fn error_for_status<'a>(self: Box) -> Result, reqwest::Error> + where + Self: 'a, + { + match (*self).error_for_status() { + Err(e) => Err(e), + Ok(a) => Ok(Box::new(a)), + } + } + fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), reqwest::Error>{ + match self.error_for_status_ref(){ + Err(e) => Err(e), + Ok(v) => Ok(v) + } + } + async fn text(self: Box) -> Result { + (*self).text().await + } +} +#[async_trait] pub trait ClientRequest { fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box where @@ -50,12 +85,20 @@ pub trait ClientRequest { ) -> Box where Self: 'a; - async fn send(self: Box) -> Result; + async fn send<'a>(self: Box) -> Result, reqwest::Error> + where + Self: 'a; } #[async_trait] impl ClientRequest for reqwest::RequestBuilder { - async fn send(self: Box) -> Result { - reqwest::RequestBuilder::send(*self).await + async fn send<'a>(self: Box) -> Result, reqwest::Error> + where + Self: 'a, + { + match reqwest::RequestBuilder::send(*self).await { + Err(e) => Err(e), + Ok(a) => Ok(Box::new(a)), + } } fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box where diff --git a/src/directory_sync/operations/get_directory.rs b/src/directory_sync/operations/get_directory.rs index e70e1ea..3197528 100644 --- a/src/directory_sync/operations/get_directory.rs +++ b/src/directory_sync/operations/get_directory.rs @@ -53,7 +53,7 @@ impl GetDirectory for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory) diff --git a/src/directory_sync/operations/get_directory_group.rs b/src/directory_sync/operations/get_directory_group.rs index d351870..61cdbc9 100644 --- a/src/directory_sync/operations/get_directory_group.rs +++ b/src/directory_sync/operations/get_directory_group.rs @@ -64,7 +64,7 @@ impl GetDirectoryGroup for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory_group) diff --git a/src/directory_sync/operations/get_directory_user.rs b/src/directory_sync/operations/get_directory_user.rs index a456a94..07a0ee2 100644 --- a/src/directory_sync/operations/get_directory_user.rs +++ b/src/directory_sync/operations/get_directory_user.rs @@ -64,7 +64,7 @@ impl GetDirectoryUser for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory_user) diff --git a/src/directory_sync/operations/list_directories.rs b/src/directory_sync/operations/list_directories.rs index eda9bdd..f3575c3 100644 --- a/src/directory_sync/operations/list_directories.rs +++ b/src/directory_sync/operations/list_directories.rs @@ -74,7 +74,7 @@ impl ListDirectories for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(directories) diff --git a/src/directory_sync/operations/list_directory_groups.rs b/src/directory_sync/operations/list_directory_groups.rs index 31ef1e0..aed305b 100644 --- a/src/directory_sync/operations/list_directory_groups.rs +++ b/src/directory_sync/operations/list_directory_groups.rs @@ -82,7 +82,7 @@ impl ListDirectoryGroups for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(directory_groups) diff --git a/src/directory_sync/operations/list_directory_users.rs b/src/directory_sync/operations/list_directory_users.rs index 518ed3c..44dcb3d 100644 --- a/src/directory_sync/operations/list_directory_users.rs +++ b/src/directory_sync/operations/list_directory_users.rs @@ -82,7 +82,7 @@ impl ListDirectoryUsers for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(directory_users) diff --git a/src/mfa/operations/challenge_factor.rs b/src/mfa/operations/challenge_factor.rs index bb74c63..23a93e6 100644 --- a/src/mfa/operations/challenge_factor.rs +++ b/src/mfa/operations/challenge_factor.rs @@ -93,7 +93,7 @@ impl ChallengeFactor for Mfa<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(challenge) diff --git a/src/mfa/operations/enroll_factor.rs b/src/mfa/operations/enroll_factor.rs index aa6781f..8d9df2e 100644 --- a/src/mfa/operations/enroll_factor.rs +++ b/src/mfa/operations/enroll_factor.rs @@ -65,13 +65,13 @@ where } #[async_trait] -impl HandleEnrollFactorError for Response { +impl<'a> HandleEnrollFactorError for Box{ async fn handle_enroll_factor_error(self) -> WorkOsResult { match self.error_for_status_ref() { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::UNPROCESSABLE_ENTITY) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(match error.code.as_str() { "invalid_phone_number" => { @@ -139,7 +139,7 @@ impl EnrollFactor for Mfa<'_> { .handle_unauthorized_error()? .handle_enroll_factor_error() .await? - .json::() + .json::() .await?; Ok(factor) diff --git a/src/mfa/operations/verify_challenge.rs b/src/mfa/operations/verify_challenge.rs index 8de2dd2..70a40e2 100644 --- a/src/mfa/operations/verify_challenge.rs +++ b/src/mfa/operations/verify_challenge.rs @@ -85,7 +85,7 @@ impl VerifyChallenge for Mfa<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(verify_response) diff --git a/src/organizations/operations/create_organization.rs b/src/organizations/operations/create_organization.rs index e0abcab..5bba79c 100644 --- a/src/organizations/operations/create_organization.rs +++ b/src/organizations/operations/create_organization.rs @@ -89,7 +89,7 @@ impl CreateOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/organizations/operations/get_organization.rs b/src/organizations/operations/get_organization.rs index 814d14c..0646892 100644 --- a/src/organizations/operations/get_organization.rs +++ b/src/organizations/operations/get_organization.rs @@ -62,7 +62,7 @@ impl GetOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/organizations/operations/list_organizations.rs b/src/organizations/operations/list_organizations.rs index 9706cb3..1384c5d 100644 --- a/src/organizations/operations/list_organizations.rs +++ b/src/organizations/operations/list_organizations.rs @@ -88,7 +88,7 @@ impl ListOrganizations for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(organizations) diff --git a/src/organizations/operations/update_organization.rs b/src/organizations/operations/update_organization.rs index cc3997b..c6b54cd 100644 --- a/src/organizations/operations/update_organization.rs +++ b/src/organizations/operations/update_organization.rs @@ -97,7 +97,7 @@ impl UpdateOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/passwordless/operations/create_passwordless_session.rs b/src/passwordless/operations/create_passwordless_session.rs index fad5a2c..7c9ee16 100644 --- a/src/passwordless/operations/create_passwordless_session.rs +++ b/src/passwordless/operations/create_passwordless_session.rs @@ -90,7 +90,7 @@ impl CreatePasswordlessSession for Passwordless<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(passwordless_session) diff --git a/src/sso/operations/get_connection.rs b/src/sso/operations/get_connection.rs index e28445a..159dca7 100644 --- a/src/sso/operations/get_connection.rs +++ b/src/sso/operations/get_connection.rs @@ -59,7 +59,7 @@ impl GetConnection for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(connection) diff --git a/src/sso/operations/get_profile.rs b/src/sso/operations/get_profile.rs index 7192361..8c81da1 100644 --- a/src/sso/operations/get_profile.rs +++ b/src/sso/operations/get_profile.rs @@ -51,7 +51,7 @@ impl GetProfile for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(get_profile_response) diff --git a/src/sso/operations/get_profile_and_token.rs b/src/sso/operations/get_profile_and_token.rs index 1df1e66..f6ccb32 100644 --- a/src/sso/operations/get_profile_and_token.rs +++ b/src/sso/operations/get_profile_and_token.rs @@ -4,7 +4,8 @@ use serde::Deserialize; use thiserror::Error; use crate::sso::{AccessToken, AuthorizationCode, ClientId, Profile, Sso}; -use crate::{WorkOsError, WorkOsResult}; +use crate::traits::ClientResponse; +use crate::{ResponseExt, WorkOsError, WorkOsResult}; /// The parameters for [`GetProfileAndToken`]. #[derive(Debug)] @@ -49,7 +50,7 @@ where } #[async_trait] -impl HandleGetProfileAndTokenError for Response { +impl<'a> HandleGetProfileAndTokenError for Box { async fn handle_get_profile_and_token_error( self, ) -> WorkOsResult { @@ -57,7 +58,7 @@ impl HandleGetProfileAndTokenError for Response { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(match error.error.as_str() { "invalid_client" | "unauthorized_client" => WorkOsError::Unauthorized, @@ -125,7 +126,7 @@ impl GetProfileAndToken for Sso<'_> { .await? .handle_get_profile_and_token_error() .await? - .json::() + .json::() .await?; Ok(get_profile_and_token_response) diff --git a/src/sso/operations/list_connections.rs b/src/sso/operations/list_connections.rs index eddbdc9..5a6d530 100644 --- a/src/sso/operations/list_connections.rs +++ b/src/sso/operations/list_connections.rs @@ -68,7 +68,7 @@ impl ListConnections for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(connections) diff --git a/src/user_management/operations/authenticate_with_code.rs b/src/user_management/operations/authenticate_with_code.rs index d5986b9..280267c 100644 --- a/src/user_management/operations/authenticate_with_code.rs +++ b/src/user_management/operations/authenticate_with_code.rs @@ -7,7 +7,7 @@ use crate::sso::{AuthorizationCode, ClientId}; use crate::user_management::{ AuthenticateError, AuthenticationResponse, HandleAuthenticateError, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithCode`]. #[derive(Debug, Serialize)] @@ -109,7 +109,7 @@ impl AuthenticateWithCode for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_code_response) diff --git a/src/user_management/operations/authenticate_with_email_verification.rs b/src/user_management/operations/authenticate_with_email_verification.rs index 506670a..84ed3cf 100644 --- a/src/user_management/operations/authenticate_with_email_verification.rs +++ b/src/user_management/operations/authenticate_with_email_verification.rs @@ -8,7 +8,7 @@ use crate::user_management::{ AuthenticateError, AuthenticationResponse, EmailVerificationCode, HandleAuthenticateError, PendingAuthenticationToken, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithEmailVerification`]. #[derive(Debug, Serialize)] @@ -106,7 +106,7 @@ impl AuthenticateWithEmailVerification for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_email_verification_response) diff --git a/src/user_management/operations/authenticate_with_magic_auth.rs b/src/user_management/operations/authenticate_with_magic_auth.rs index bf32c65..38b354e 100644 --- a/src/user_management/operations/authenticate_with_magic_auth.rs +++ b/src/user_management/operations/authenticate_with_magic_auth.rs @@ -8,7 +8,7 @@ use crate::user_management::{ AuthenticateError, AuthenticationResponse, HandleAuthenticateError, MagicAuthCode, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithMagicAuth`]. #[derive(Debug, Serialize)] @@ -110,7 +110,7 @@ impl AuthenticateWithMagicAuth for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_magic_auth_response) diff --git a/src/user_management/operations/authenticate_with_password.rs b/src/user_management/operations/authenticate_with_password.rs index 224c933..e61eb9e 100644 --- a/src/user_management/operations/authenticate_with_password.rs +++ b/src/user_management/operations/authenticate_with_password.rs @@ -7,7 +7,7 @@ use crate::sso::ClientId; use crate::user_management::{ AuthenticateError, AuthenticationResponse, HandleAuthenticateError, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithPassword`]. #[derive(Debug, Serialize)] @@ -109,7 +109,7 @@ impl AuthenticateWithPassword for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_password_response) diff --git a/src/user_management/operations/authenticate_with_refresh_token.rs b/src/user_management/operations/authenticate_with_refresh_token.rs index 525e4d6..cc3df25 100644 --- a/src/user_management/operations/authenticate_with_refresh_token.rs +++ b/src/user_management/operations/authenticate_with_refresh_token.rs @@ -9,7 +9,7 @@ use crate::user_management::{ AuthenticateError, AuthenticationResponse, HandleAuthenticateError, RefreshToken, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithRefreshToken`]. #[derive(Debug, Serialize)] @@ -107,7 +107,7 @@ impl AuthenticateWithRefreshToken for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_refresh_token_response) diff --git a/src/user_management/operations/authenticate_with_totp.rs b/src/user_management/operations/authenticate_with_totp.rs index bca770b..145eb1e 100644 --- a/src/user_management/operations/authenticate_with_totp.rs +++ b/src/user_management/operations/authenticate_with_totp.rs @@ -9,7 +9,7 @@ use crate::user_management::{ AuthenticateError, AuthenticationResponse, HandleAuthenticateError, PendingAuthenticationToken, UserManagement, }; -use crate::{ApiKey, WorkOsResult}; +use crate::{ApiKey, ResponseExt, WorkOsResult}; /// The parameters for [`AuthenticateWithTotp`]. #[derive(Debug, Serialize)] @@ -112,7 +112,7 @@ impl AuthenticateWithTotp for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_totp_response) diff --git a/src/user_management/operations/create_magic_auth.rs b/src/user_management/operations/create_magic_auth.rs index 5cce238..6df04cc 100644 --- a/src/user_management/operations/create_magic_auth.rs +++ b/src/user_management/operations/create_magic_auth.rs @@ -76,7 +76,7 @@ impl CreateMagicAuth for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/create_password_reset.rs b/src/user_management/operations/create_password_reset.rs index 82c9990..da33467 100644 --- a/src/user_management/operations/create_password_reset.rs +++ b/src/user_management/operations/create_password_reset.rs @@ -3,6 +3,7 @@ use reqwest::{Response, StatusCode}; use serde::{Deserialize, Serialize}; use thiserror::Error; +use crate::traits::ClientResponse; use crate::user_management::{PasswordReset, UserManagement}; use crate::{ResponseExt, WorkOsError, WorkOsResult}; @@ -45,7 +46,7 @@ where } #[async_trait] -impl HandleCreatePasswordResetError for Response { +impl<'a> HandleCreatePasswordResetError for Box{ async fn handle_create_password_reset_error( self, ) -> WorkOsResult { @@ -53,7 +54,7 @@ impl HandleCreatePasswordResetError for Response { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::NOT_FOUND) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(WorkOsError::Operation(error)) } @@ -118,7 +119,7 @@ impl CreatePasswordReset for UserManagement<'_> { .handle_unauthorized_error()? .handle_create_password_reset_error() .await? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/create_user.rs b/src/user_management/operations/create_user.rs index c2195c1..834388f 100644 --- a/src/user_management/operations/create_user.rs +++ b/src/user_management/operations/create_user.rs @@ -99,7 +99,7 @@ impl CreateUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/enroll_auth_factor.rs b/src/user_management/operations/enroll_auth_factor.rs index 1c5e9bb..32765eb 100644 --- a/src/user_management/operations/enroll_auth_factor.rs +++ b/src/user_management/operations/enroll_auth_factor.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::mfa::{AuthenticationChallenge, AuthenticationFactor}; +use crate::traits::ClientResponse; use crate::user_management::{UserId, UserManagement}; use crate::{ResponseExt, WorkOsError, WorkOsResult}; @@ -77,14 +78,14 @@ where } #[async_trait] -impl HandleEnrollAuthFactorError for Response { +impl<'a> HandleEnrollAuthFactorError for Box { async fn handle_enroll_auth_factor_error(self) -> WorkOsResult { match self.error_for_status_ref() { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) | Some(StatusCode::UNPROCESSABLE_ENTITY) => { // let error = self.json::().await?; - let error = self.json::().await?; + let error = self.json::().await?; println!("{error:#?}"); @@ -158,7 +159,7 @@ impl EnrollAuthFactor for UserManagement<'_> { .handle_unauthorized_error()? .handle_enroll_auth_factor_error() .await? - .json::() + .json::() .await?; Ok(response) diff --git a/src/user_management/operations/get_email_verification.rs b/src/user_management/operations/get_email_verification.rs index c198197..1cc5d5a 100644 --- a/src/user_management/operations/get_email_verification.rs +++ b/src/user_management/operations/get_email_verification.rs @@ -62,7 +62,7 @@ impl GetEmailVerification for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_jwks.rs b/src/user_management/operations/get_jwks.rs index d4dcd71..6b8a7cb 100644 --- a/src/user_management/operations/get_jwks.rs +++ b/src/user_management/operations/get_jwks.rs @@ -52,7 +52,7 @@ impl GetJwks for UserManagement<'_> { .send() .await? .handle_generic_error()? - .json::() + .json::() .await?; Ok(jwks) diff --git a/src/user_management/operations/get_magic_auth.rs b/src/user_management/operations/get_magic_auth.rs index 1edca6c..5c24696 100644 --- a/src/user_management/operations/get_magic_auth.rs +++ b/src/user_management/operations/get_magic_auth.rs @@ -56,7 +56,7 @@ impl GetMagicAuth for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_password_reset.rs b/src/user_management/operations/get_password_reset.rs index 545de2f..6b343d3 100644 --- a/src/user_management/operations/get_password_reset.rs +++ b/src/user_management/operations/get_password_reset.rs @@ -62,7 +62,7 @@ impl GetPasswordReset for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_user.rs b/src/user_management/operations/get_user.rs index 0c818d5..aab0fbf 100644 --- a/src/user_management/operations/get_user.rs +++ b/src/user_management/operations/get_user.rs @@ -56,7 +56,7 @@ impl GetUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/get_user_by_external_id.rs b/src/user_management/operations/get_user_by_external_id.rs index d742451..187a6de 100644 --- a/src/user_management/operations/get_user_by_external_id.rs +++ b/src/user_management/operations/get_user_by_external_id.rs @@ -62,7 +62,7 @@ impl GetUserByExternalId for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/get_user_identities.rs b/src/user_management/operations/get_user_identities.rs index 621d058..8f37cea 100644 --- a/src/user_management/operations/get_user_identities.rs +++ b/src/user_management/operations/get_user_identities.rs @@ -63,7 +63,7 @@ impl GetUserIdentities for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(users) diff --git a/src/user_management/operations/list_auth_factors.rs b/src/user_management/operations/list_auth_factors.rs index 191ddf3..81e02f1 100644 --- a/src/user_management/operations/list_auth_factors.rs +++ b/src/user_management/operations/list_auth_factors.rs @@ -81,7 +81,7 @@ impl ListAuthFactors for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(organizations) diff --git a/src/user_management/operations/list_users.rs b/src/user_management/operations/list_users.rs index 2ecc745..30795a1 100644 --- a/src/user_management/operations/list_users.rs +++ b/src/user_management/operations/list_users.rs @@ -79,7 +79,7 @@ impl ListUsers for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::>() + .json::,_>() .await?; Ok(users) diff --git a/src/user_management/operations/reset_password.rs b/src/user_management/operations/reset_password.rs index c932510..fea5b21 100644 --- a/src/user_management/operations/reset_password.rs +++ b/src/user_management/operations/reset_password.rs @@ -3,6 +3,7 @@ use reqwest::{Response, StatusCode}; use serde::{Deserialize, Serialize}; use thiserror::Error; +use crate::traits::ClientResponse; use crate::user_management::{PasswordResetToken, User, UserManagement}; use crate::{ResponseExt, WorkOsError, WorkOsResult}; @@ -85,13 +86,13 @@ where } #[async_trait] -impl HandleResetPasswordError for Response { +impl<'a> HandleResetPasswordError for Box { async fn handle_reset_password_error(self) -> WorkOsResult { match self.error_for_status_ref() { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) | Some(StatusCode::NOT_FOUND) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(WorkOsError::Operation(error)) } @@ -158,7 +159,7 @@ impl ResetPassword for UserManagement<'_> { .handle_unauthorized_error()? .handle_reset_password_error() .await? - .json::() + .json::() .await?; Ok(response) diff --git a/src/user_management/operations/update_user.rs b/src/user_management/operations/update_user.rs index 5575252..3ba0c73 100644 --- a/src/user_management/operations/update_user.rs +++ b/src/user_management/operations/update_user.rs @@ -108,7 +108,7 @@ impl UpdateUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/types/authenticate_error.rs b/src/user_management/types/authenticate_error.rs index 3e2489c..d96a9df 100644 --- a/src/user_management/types/authenticate_error.rs +++ b/src/user_management/types/authenticate_error.rs @@ -4,8 +4,7 @@ use serde::Deserialize; use thiserror::Error; use crate::{ - WorkOsError, WorkOsResult, mfa::AuthenticationFactorIdAndType, - organizations::OrganizationIdAndName, sso::ConnectionId, + mfa::AuthenticationFactorIdAndType, organizations::OrganizationIdAndName, sso::ConnectionId, ResponseExt, WorkOsError, WorkOsResult }; use super::{AuthenticateMethods, EmailVerificationId, PendingAuthenticationToken, User}; @@ -270,13 +269,13 @@ where } #[async_trait] -impl HandleAuthenticateError for Response { +impl<'a> HandleAuthenticateError for Box { async fn handle_authenticate_error(self) -> WorkOsResult { match self.error_for_status_ref() { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) => { - let authenticate_error = self.json::().await?; + let authenticate_error = self.json::().await?; Err(match &authenticate_error { AuthenticateError::WithError(AuthenticateErrorWithError::Other { @@ -290,7 +289,7 @@ impl HandleAuthenticateError for Response { }) } Some(StatusCode::FORBIDDEN) => { - let authenticate_error = self.json::().await?; + let authenticate_error = self.json::().await?; Err(WorkOsError::Operation(authenticate_error)) } From c4a3fd36f1a05ac8b2f049a5d022fefdf26db2fb Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 16:57:08 +0000 Subject: [PATCH 4/8] better errors --- Cargo.lock | 1 + Cargo.toml | 1 + src/core/error.rs | 2 +- src/core/traits.rs | 82 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d40f215..c36356d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2114,6 +2114,7 @@ dependencies = [ "chrono", "derive_more", "erased-serde", + "http", "jsonwebtoken", "matches", "mockito", diff --git a/Cargo.toml b/Cargo.toml index b2ff184..863964d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ async-trait = "0.1.88" chrono = { version = "0.4.40", features = ["serde"] } derive_more = { version = "2.0.1", features = ["deref", "display", "from"] } erased-serde = "0.4.6" +http = "1.3.1" jsonwebtoken = "9.3.1" querystring = "1.1.0" reqwest = { version = "0.12.0", features = ["json"] } diff --git a/src/core/error.rs b/src/core/error.rs index 585d215..92bf65a 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -21,7 +21,7 @@ pub enum WorkOsError { /// An unhandled error occurred with the API request. #[error("request error")] - RequestError(#[from] reqwest::Error), + RequestError(#[from] crate::traits::RequestError), #[error("json error")] Json(#[from] serde_json::Error), diff --git a/src/core/traits.rs b/src/core/traits.rs index 2bea132..8c03145 100644 --- a/src/core/traits.rs +++ b/src/core/traits.rs @@ -1,9 +1,55 @@ use std::fmt::Display; use async_trait::async_trait; -use reqwest::{IntoUrl, StatusCode}; +use http::StatusCode; use url::Url; +pub trait StatusError: std::error::Error { + fn status(&self) -> Option; +} + +impl StatusError for reqwest::Error { + fn status(&self) -> Option { + self.status() + } +} + +#[derive(Debug)] +pub struct RequestError { + pub err: Box, +} + +impl StatusError for RequestError { + fn status(&self) -> Option { + self.err.status() + } +} + +impl RequestError { + pub fn status(&self) -> Option { + StatusError::status(self) + } +} + +impl Display for RequestError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", &self.err) + } +} +impl std::error::Error for RequestError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&*self.err) + } +} + +impl From for RequestError { + fn from(value: reqwest::Error) -> Self { + Self { + err: Box::new(value), + } + } +} + #[async_trait] ///An HTP client pub trait Client { @@ -28,38 +74,36 @@ impl Client for reqwest::Client { } } #[async_trait] -pub trait ClientResponse: Send + Sync{ +pub trait ClientResponse: Send + Sync { fn status(&self) -> StatusCode; - fn error_for_status<'a>( - self: Box, - ) -> Result, reqwest::Error> + fn error_for_status<'a>(self: Box) -> Result, RequestError> where Self: 'a; - fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), reqwest::Error>; - async fn text(self: Box) -> Result; + fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError>; + async fn text(self: Box) -> Result; } #[async_trait] impl ClientResponse for reqwest::Response { fn status(&self) -> StatusCode { self.status() } - fn error_for_status<'a>(self: Box) -> Result, reqwest::Error> + fn error_for_status<'a>(self: Box) -> Result, RequestError> where Self: 'a, { match (*self).error_for_status() { - Err(e) => Err(e), + Err(e) => Err(e.into()), Ok(a) => Ok(Box::new(a)), } } - fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), reqwest::Error>{ - match self.error_for_status_ref(){ - Err(e) => Err(e), - Ok(v) => Ok(v) - } + fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError> { + match self.error_for_status_ref() { + Err(e) => Err(e.into()), + Ok(v) => Ok(v), } - async fn text(self: Box) -> Result { - (*self).text().await + } + async fn text(self: Box) -> Result { + (*self).text().await.map_err(Into::into) } } #[async_trait] @@ -85,18 +129,18 @@ pub trait ClientRequest { ) -> Box where Self: 'a; - async fn send<'a>(self: Box) -> Result, reqwest::Error> + async fn send<'a>(self: Box) -> Result, RequestError> where Self: 'a; } #[async_trait] impl ClientRequest for reqwest::RequestBuilder { - async fn send<'a>(self: Box) -> Result, reqwest::Error> + async fn send<'a>(self: Box) -> Result, RequestError> where Self: 'a, { match reqwest::RequestBuilder::send(*self).await { - Err(e) => Err(e), + Err(e) => Err(e.into()), Ok(a) => Ok(Box::new(a)), } } From 4964163cc87e71f9dde0390d9a9d0d5c09372f55 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 17:03:51 +0000 Subject: [PATCH 5/8] support no reqwest --- Cargo.toml | 7 +- src/core/response.rs | 2 +- src/core/traits.rs | 191 +++++++++--------- src/mfa/operations/enroll_factor.rs | 2 +- src/sso/operations/get_profile_and_token.rs | 2 +- .../operations/create_password_reset.rs | 2 +- .../operations/enroll_auth_factor.rs | 2 +- .../operations/reset_password.rs | 2 +- .../types/authenticate_error.rs | 2 +- src/workos.rs | 14 +- 10 files changed, 123 insertions(+), 103 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 863964d..32a4d77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,9 @@ edition = "2024" [features] default = ["rustls-tls"] -native-tls = ["reqwest/native-tls"] -rustls-tls = ["reqwest/rustls-tls"] +reqwest=["dep:reqwest"] +native-tls = ["reqwest/native-tls","reqwest"] +rustls-tls = ["reqwest/rustls-tls","reqwest"] [dependencies] async-trait = "0.1.88" @@ -20,7 +21,7 @@ erased-serde = "0.4.6" http = "1.3.1" jsonwebtoken = "9.3.1" querystring = "1.1.0" -reqwest = { version = "0.12.0", features = ["json"] } +reqwest = { version = "0.12.0", features = ["json"], optional = true } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" thiserror = "2.0.0" diff --git a/src/core/response.rs b/src/core/response.rs index cfb08c3..55c563d 100644 --- a/src/core/response.rs +++ b/src/core/response.rs @@ -1,4 +1,4 @@ -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::de::DeserializeOwned; use crate::{WorkOsError, WorkOsResult, traits::ClientResponse}; diff --git a/src/core/traits.rs b/src/core/traits.rs index 8c03145..c81be35 100644 --- a/src/core/traits.rs +++ b/src/core/traits.rs @@ -8,12 +8,6 @@ pub trait StatusError: std::error::Error { fn status(&self) -> Option; } -impl StatusError for reqwest::Error { - fn status(&self) -> Option { - self.status() - } -} - #[derive(Debug)] pub struct RequestError { pub err: Box, @@ -42,14 +36,6 @@ impl std::error::Error for RequestError { } } -impl From for RequestError { - fn from(value: reqwest::Error) -> Self { - Self { - err: Box::new(value), - } - } -} - #[async_trait] ///An HTP client pub trait Client { @@ -58,21 +44,7 @@ pub trait Client { fn put(&self, url: Url) -> Box; fn delete(&self, url: Url) -> Box; } -#[async_trait] -impl Client for reqwest::Client { - fn get(&self, url: Url) -> Box { - Box::new(self.get(url)) - } - fn post(&self, url: Url) -> Box { - Box::new(self.post(url)) - } - fn put(&self, url: Url) -> Box { - Box::new(self.put(url)) - } - fn delete(&self, url: Url) -> Box { - Box::new(self.delete(url)) - } -} + #[async_trait] pub trait ClientResponse: Send + Sync { fn status(&self) -> StatusCode; @@ -82,30 +54,7 @@ pub trait ClientResponse: Send + Sync { fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError>; async fn text(self: Box) -> Result; } -#[async_trait] -impl ClientResponse for reqwest::Response { - fn status(&self) -> StatusCode { - self.status() - } - fn error_for_status<'a>(self: Box) -> Result, RequestError> - where - Self: 'a, - { - match (*self).error_for_status() { - Err(e) => Err(e.into()), - Ok(a) => Ok(Box::new(a)), - } - } - fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError> { - match self.error_for_status_ref() { - Err(e) => Err(e.into()), - Ok(v) => Ok(v), - } - } - async fn text(self: Box) -> Result { - (*self).text().await.map_err(Into::into) - } -} + #[async_trait] pub trait ClientRequest { fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box @@ -133,48 +82,106 @@ pub trait ClientRequest { where Self: 'a; } -#[async_trait] -impl ClientRequest for reqwest::RequestBuilder { - async fn send<'a>(self: Box) -> Result, RequestError> - where - Self: 'a, - { - match reqwest::RequestBuilder::send(*self).await { - Err(e) => Err(e.into()), - Ok(a) => Ok(Box::new(a)), +#[cfg(feature = "reqwest")] +const _: () = { + impl StatusError for reqwest::Error { + fn status(&self) -> Option { + self.status() } } - fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box - where - Self: 'a, - { - Box::new((*self).bearer_auth(x)) + + impl From for RequestError { + fn from(value: reqwest::Error) -> Self { + Self { + err: Box::new(value), + } + } } - fn json<'a>( - self: Box, - x: &(dyn erased_serde::Serialize + '_), - ) -> Box - where - Self: 'a, - { - Box::new((*self).json(x)) + + #[async_trait] + impl Client for reqwest::Client { + fn get(&self, url: Url) -> Box { + Box::new(self.get(url)) + } + fn post(&self, url: Url) -> Box { + Box::new(self.post(url)) + } + fn put(&self, url: Url) -> Box { + Box::new(self.put(url)) + } + fn delete(&self, url: Url) -> Box { + Box::new(self.delete(url)) + } } - fn query<'a>( - self: Box, - x: &(dyn erased_serde::Serialize + '_), - ) -> Box - where - Self: 'a, - { - Box::new((*self).query(x)) + #[async_trait] + impl ClientResponse for reqwest::Response { + fn status(&self) -> StatusCode { + self.status() + } + fn error_for_status<'a>( + self: Box, + ) -> Result, RequestError> + where + Self: 'a, + { + match (*self).error_for_status() { + Err(e) => Err(e.into()), + Ok(a) => Ok(Box::new(a)), + } + } + fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError> { + match self.error_for_status_ref() { + Err(e) => Err(e.into()), + Ok(v) => Ok(v), + } + } + async fn text(self: Box) -> Result { + (*self).text().await.map_err(Into::into) + } } - fn form<'a>( - self: Box, - x: &(dyn erased_serde::Serialize + '_), - ) -> Box - where - Self: 'a, - { - Box::new((*self).form(x)) + #[async_trait] + impl ClientRequest for reqwest::RequestBuilder { + async fn send<'a>(self: Box) -> Result, RequestError> + where + Self: 'a, + { + match reqwest::RequestBuilder::send(*self).await { + Err(e) => Err(e.into()), + Ok(a) => Ok(Box::new(a)), + } + } + fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box + where + Self: 'a, + { + Box::new((*self).bearer_auth(x)) + } + fn json<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).json(x)) + } + fn query<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).query(x)) + } + fn form<'a>( + self: Box, + x: &(dyn erased_serde::Serialize + '_), + ) -> Box + where + Self: 'a, + { + Box::new((*self).form(x)) + } } -} +}; diff --git a/src/mfa/operations/enroll_factor.rs b/src/mfa/operations/enroll_factor.rs index 8d9df2e..a611d15 100644 --- a/src/mfa/operations/enroll_factor.rs +++ b/src/mfa/operations/enroll_factor.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/src/sso/operations/get_profile_and_token.rs b/src/sso/operations/get_profile_and_token.rs index f6ccb32..8020515 100644 --- a/src/sso/operations/get_profile_and_token.rs +++ b/src/sso/operations/get_profile_and_token.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::Deserialize; use thiserror::Error; diff --git a/src/user_management/operations/create_password_reset.rs b/src/user_management/operations/create_password_reset.rs index da33467..b995e21 100644 --- a/src/user_management/operations/create_password_reset.rs +++ b/src/user_management/operations/create_password_reset.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/src/user_management/operations/enroll_auth_factor.rs b/src/user_management/operations/enroll_auth_factor.rs index 32765eb..ae9b541 100644 --- a/src/user_management/operations/enroll_auth_factor.rs +++ b/src/user_management/operations/enroll_auth_factor.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/src/user_management/operations/reset_password.rs b/src/user_management/operations/reset_password.rs index fea5b21..92123bb 100644 --- a/src/user_management/operations/reset_password.rs +++ b/src/user_management/operations/reset_password.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/src/user_management/types/authenticate_error.rs b/src/user_management/types/authenticate_error.rs index d96a9df..2560646 100644 --- a/src/user_management/types/authenticate_error.rs +++ b/src/user_management/types/authenticate_error.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{Response, StatusCode}; +use http::StatusCode; use serde::Deserialize; use thiserror::Error; diff --git a/src/workos.rs b/src/workos.rs index 251fe53..3822830 100644 --- a/src/workos.rs +++ b/src/workos.rs @@ -10,6 +10,7 @@ use crate::mfa::Mfa; use crate::organizations::Organizations; use crate::passwordless::Passwordless; use crate::sso::Sso; +use crate::traits::Client; use crate::user_management::UserManagement; /// The WorkOS client. @@ -107,6 +108,7 @@ impl<'a> WorkOsBuilder<'a> { self } + #[cfg(feature = "reqwest")] /// Consumes the builder and returns the constructed client. pub fn build(self) -> WorkOs<'static> { let client = reqwest::Client::builder() @@ -114,10 +116,20 @@ impl<'a> WorkOsBuilder<'a> { .build() .unwrap(); + self.build_with_client(Arc::new(client)) + } + + /// Consumes the builder and returns the constructed client. + pub fn build_with_client<'b>(self, client: Arc) -> WorkOs<'b> { + // let client = 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: Arc::new(client), + client, phantom: PhantomData, } } From 8636b1876bce0c359b6fffbd6eb0de0a9118f6bb Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 17:36:18 +0000 Subject: [PATCH 6/8] doc --- src/core/traits.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/traits.rs b/src/core/traits.rs index c81be35..8d012ea 100644 --- a/src/core/traits.rs +++ b/src/core/traits.rs @@ -3,13 +3,15 @@ use std::fmt::Display; use async_trait::async_trait; use http::StatusCode; use url::Url; - +///An error with a ststus code pub trait StatusError: std::error::Error { + ///The status code, if available, of this error fn status(&self) -> Option; } - +///A HTTP error #[derive(Debug)] pub struct RequestError { + ///The status code, if available, of this error pub err: Box, } @@ -20,6 +22,7 @@ impl StatusError for RequestError { } impl RequestError { + ///The status code, if available, of this error pub fn status(&self) -> Option { StatusError::status(self) } @@ -37,47 +40,62 @@ impl std::error::Error for RequestError { } #[async_trait] -///An HTP client +///An HTTP client pub trait Client { + ///Create a GET request fn get(&self, url: Url) -> Box; + ///Create a POST request fn post(&self, url: Url) -> Box; + ///Create a PUT request fn put(&self, url: Url) -> Box; + ///Create a DELETE request fn delete(&self, url: Url) -> Box; } #[async_trait] +///A response to a HTTP request pub trait ClientResponse: Send + Sync { + ///That response's status code fn status(&self) -> StatusCode; + ///Attept to catch error-signaling status codes and return them as errors fn error_for_status<'a>(self: Box) -> Result, RequestError> where Self: 'a; + ///Attept to catch error-signaling status codes and return them as errors fn error_for_status_ref(&self) -> Result<&(dyn ClientResponse + '_), RequestError>; + ///The text of the response async fn text(self: Box) -> Result; } #[async_trait] +///A HTTP request pub trait ClientRequest { + ///Its authenticaton fn bearer_auth<'a>(self: Box, x: &(dyn Display + '_)) -> Box where Self: 'a; + ///Adds ad JSON body fn json<'a>( self: Box, x: &(dyn erased_serde::Serialize + '_), ) -> Box where Self: 'a; + ///Adds a query string fn query<'a>( self: Box, x: &(dyn erased_serde::Serialize + '_), ) -> Box where Self: 'a; + ///Adds a form body fn form<'a>( self: Box, x: &(dyn erased_serde::Serialize + '_), ) -> Box where Self: 'a; + ///Sends the request async fn send<'a>(self: Box) -> Result, RequestError> where Self: 'a; From 83ee28b09392285d3ed94ba3f4e884aaf5e3e94d Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 17:45:50 +0000 Subject: [PATCH 7/8] doc 2 --- src/core.rs | 1 + src/core/error.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/core.rs b/src/core.rs index 2ed4d37..026afa0 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,6 +1,7 @@ mod error; mod response; mod types; +///Traits for requests and other core infrastructure pub mod traits; diff --git a/src/core/error.rs b/src/core/error.rs index 92bf65a..1338911 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -23,6 +23,7 @@ pub enum WorkOsError { #[error("request error")] RequestError(#[from] crate::traits::RequestError), + /// An error occurred when deserializing JSON #[error("json error")] Json(#[from] serde_json::Error), } From e5e4e6f1ecfb51022e6b24a10fdb07bd9473a796 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Thu, 24 Jul 2025 17:59:09 +0000 Subject: [PATCH 8/8] fmt --- src/admin_portal/operations/generate_portal_link.rs | 2 +- src/core.rs | 3 +-- src/directory_sync/operations/get_directory.rs | 2 +- src/directory_sync/operations/get_directory_group.rs | 2 +- src/directory_sync/operations/get_directory_user.rs | 2 +- src/directory_sync/operations/list_directories.rs | 2 +- src/directory_sync/operations/list_directory_groups.rs | 2 +- src/directory_sync/operations/list_directory_users.rs | 2 +- src/mfa/operations/challenge_factor.rs | 2 +- src/mfa/operations/enroll_factor.rs | 6 +++--- src/mfa/operations/verify_challenge.rs | 2 +- src/organizations/operations/create_organization.rs | 2 +- src/organizations/operations/get_organization.rs | 2 +- src/organizations/operations/list_organizations.rs | 2 +- src/organizations/operations/update_organization.rs | 2 +- src/passwordless/operations/create_passwordless_session.rs | 2 +- src/sso/operations/get_connection.rs | 2 +- src/sso/operations/get_profile.rs | 2 +- src/sso/operations/get_profile_and_token.rs | 4 ++-- src/sso/operations/list_connections.rs | 2 +- src/user_management/operations/authenticate_with_code.rs | 2 +- .../operations/authenticate_with_email_verification.rs | 2 +- .../operations/authenticate_with_magic_auth.rs | 2 +- .../operations/authenticate_with_password.rs | 2 +- .../operations/authenticate_with_refresh_token.rs | 2 +- src/user_management/operations/authenticate_with_totp.rs | 2 +- src/user_management/operations/create_magic_auth.rs | 2 +- src/user_management/operations/create_password_reset.rs | 6 +++--- src/user_management/operations/create_user.rs | 2 +- src/user_management/operations/enroll_auth_factor.rs | 4 ++-- src/user_management/operations/get_email_verification.rs | 2 +- src/user_management/operations/get_jwks.rs | 2 +- src/user_management/operations/get_magic_auth.rs | 2 +- src/user_management/operations/get_password_reset.rs | 2 +- src/user_management/operations/get_user.rs | 2 +- src/user_management/operations/get_user_by_external_id.rs | 2 +- src/user_management/operations/get_user_identities.rs | 2 +- src/user_management/operations/list_auth_factors.rs | 2 +- src/user_management/operations/list_users.rs | 2 +- src/user_management/operations/reset_password.rs | 4 ++-- src/user_management/operations/update_user.rs | 2 +- src/user_management/types/authenticate_error.rs | 7 ++++--- 42 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/admin_portal/operations/generate_portal_link.rs b/src/admin_portal/operations/generate_portal_link.rs index 7513f4e..80f3267 100644 --- a/src/admin_portal/operations/generate_portal_link.rs +++ b/src/admin_portal/operations/generate_portal_link.rs @@ -109,7 +109,7 @@ impl GeneratePortalLink for AdminPortal<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(generate_link_response) diff --git a/src/core.rs b/src/core.rs index 026afa0..547acad 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,9 +1,8 @@ mod error; mod response; -mod types; ///Traits for requests and other core infrastructure pub mod traits; - +mod types; pub use error::*; pub(crate) use response::*; diff --git a/src/directory_sync/operations/get_directory.rs b/src/directory_sync/operations/get_directory.rs index 3197528..fb2c194 100644 --- a/src/directory_sync/operations/get_directory.rs +++ b/src/directory_sync/operations/get_directory.rs @@ -53,7 +53,7 @@ impl GetDirectory for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory) diff --git a/src/directory_sync/operations/get_directory_group.rs b/src/directory_sync/operations/get_directory_group.rs index 61cdbc9..a4f6de9 100644 --- a/src/directory_sync/operations/get_directory_group.rs +++ b/src/directory_sync/operations/get_directory_group.rs @@ -64,7 +64,7 @@ impl GetDirectoryGroup for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory_group) diff --git a/src/directory_sync/operations/get_directory_user.rs b/src/directory_sync/operations/get_directory_user.rs index 07a0ee2..c44d4bc 100644 --- a/src/directory_sync/operations/get_directory_user.rs +++ b/src/directory_sync/operations/get_directory_user.rs @@ -64,7 +64,7 @@ impl GetDirectoryUser for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(directory_user) diff --git a/src/directory_sync/operations/list_directories.rs b/src/directory_sync/operations/list_directories.rs index f3575c3..24b8262 100644 --- a/src/directory_sync/operations/list_directories.rs +++ b/src/directory_sync/operations/list_directories.rs @@ -74,7 +74,7 @@ impl ListDirectories for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(directories) diff --git a/src/directory_sync/operations/list_directory_groups.rs b/src/directory_sync/operations/list_directory_groups.rs index aed305b..5e05dcb 100644 --- a/src/directory_sync/operations/list_directory_groups.rs +++ b/src/directory_sync/operations/list_directory_groups.rs @@ -82,7 +82,7 @@ impl ListDirectoryGroups for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(directory_groups) diff --git a/src/directory_sync/operations/list_directory_users.rs b/src/directory_sync/operations/list_directory_users.rs index 44dcb3d..c82a2c4 100644 --- a/src/directory_sync/operations/list_directory_users.rs +++ b/src/directory_sync/operations/list_directory_users.rs @@ -82,7 +82,7 @@ impl ListDirectoryUsers for DirectorySync<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(directory_users) diff --git a/src/mfa/operations/challenge_factor.rs b/src/mfa/operations/challenge_factor.rs index 23a93e6..49c65bd 100644 --- a/src/mfa/operations/challenge_factor.rs +++ b/src/mfa/operations/challenge_factor.rs @@ -93,7 +93,7 @@ impl ChallengeFactor for Mfa<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(challenge) diff --git a/src/mfa/operations/enroll_factor.rs b/src/mfa/operations/enroll_factor.rs index a611d15..8d94913 100644 --- a/src/mfa/operations/enroll_factor.rs +++ b/src/mfa/operations/enroll_factor.rs @@ -65,13 +65,13 @@ where } #[async_trait] -impl<'a> HandleEnrollFactorError for Box{ +impl<'a> HandleEnrollFactorError for Box { async fn handle_enroll_factor_error(self) -> WorkOsResult { match self.error_for_status_ref() { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::UNPROCESSABLE_ENTITY) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(match error.code.as_str() { "invalid_phone_number" => { @@ -139,7 +139,7 @@ impl EnrollFactor for Mfa<'_> { .handle_unauthorized_error()? .handle_enroll_factor_error() .await? - .json::() + .json::() .await?; Ok(factor) diff --git a/src/mfa/operations/verify_challenge.rs b/src/mfa/operations/verify_challenge.rs index 70a40e2..33d4bbd 100644 --- a/src/mfa/operations/verify_challenge.rs +++ b/src/mfa/operations/verify_challenge.rs @@ -85,7 +85,7 @@ impl VerifyChallenge for Mfa<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(verify_response) diff --git a/src/organizations/operations/create_organization.rs b/src/organizations/operations/create_organization.rs index 5bba79c..129879c 100644 --- a/src/organizations/operations/create_organization.rs +++ b/src/organizations/operations/create_organization.rs @@ -89,7 +89,7 @@ impl CreateOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/organizations/operations/get_organization.rs b/src/organizations/operations/get_organization.rs index 0646892..12cfce2 100644 --- a/src/organizations/operations/get_organization.rs +++ b/src/organizations/operations/get_organization.rs @@ -62,7 +62,7 @@ impl GetOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/organizations/operations/list_organizations.rs b/src/organizations/operations/list_organizations.rs index 1384c5d..7210d2b 100644 --- a/src/organizations/operations/list_organizations.rs +++ b/src/organizations/operations/list_organizations.rs @@ -88,7 +88,7 @@ impl ListOrganizations for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(organizations) diff --git a/src/organizations/operations/update_organization.rs b/src/organizations/operations/update_organization.rs index c6b54cd..835303b 100644 --- a/src/organizations/operations/update_organization.rs +++ b/src/organizations/operations/update_organization.rs @@ -97,7 +97,7 @@ impl UpdateOrganization for Organizations<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/passwordless/operations/create_passwordless_session.rs b/src/passwordless/operations/create_passwordless_session.rs index 7c9ee16..76f26d5 100644 --- a/src/passwordless/operations/create_passwordless_session.rs +++ b/src/passwordless/operations/create_passwordless_session.rs @@ -90,7 +90,7 @@ impl CreatePasswordlessSession for Passwordless<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(passwordless_session) diff --git a/src/sso/operations/get_connection.rs b/src/sso/operations/get_connection.rs index 159dca7..5867f6b 100644 --- a/src/sso/operations/get_connection.rs +++ b/src/sso/operations/get_connection.rs @@ -59,7 +59,7 @@ impl GetConnection for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(connection) diff --git a/src/sso/operations/get_profile.rs b/src/sso/operations/get_profile.rs index 8c81da1..1e6ec64 100644 --- a/src/sso/operations/get_profile.rs +++ b/src/sso/operations/get_profile.rs @@ -51,7 +51,7 @@ impl GetProfile for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(get_profile_response) diff --git a/src/sso/operations/get_profile_and_token.rs b/src/sso/operations/get_profile_and_token.rs index 8020515..f0265c6 100644 --- a/src/sso/operations/get_profile_and_token.rs +++ b/src/sso/operations/get_profile_and_token.rs @@ -58,7 +58,7 @@ impl<'a> HandleGetProfileAndTokenError for Box { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(match error.error.as_str() { "invalid_client" | "unauthorized_client" => WorkOsError::Unauthorized, @@ -126,7 +126,7 @@ impl GetProfileAndToken for Sso<'_> { .await? .handle_get_profile_and_token_error() .await? - .json::() + .json::() .await?; Ok(get_profile_and_token_response) diff --git a/src/sso/operations/list_connections.rs b/src/sso/operations/list_connections.rs index 5a6d530..5ed4692 100644 --- a/src/sso/operations/list_connections.rs +++ b/src/sso/operations/list_connections.rs @@ -68,7 +68,7 @@ impl ListConnections for Sso<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(connections) diff --git a/src/user_management/operations/authenticate_with_code.rs b/src/user_management/operations/authenticate_with_code.rs index 280267c..d4dc085 100644 --- a/src/user_management/operations/authenticate_with_code.rs +++ b/src/user_management/operations/authenticate_with_code.rs @@ -109,7 +109,7 @@ impl AuthenticateWithCode for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_code_response) diff --git a/src/user_management/operations/authenticate_with_email_verification.rs b/src/user_management/operations/authenticate_with_email_verification.rs index 84ed3cf..d40220c 100644 --- a/src/user_management/operations/authenticate_with_email_verification.rs +++ b/src/user_management/operations/authenticate_with_email_verification.rs @@ -106,7 +106,7 @@ impl AuthenticateWithEmailVerification for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_email_verification_response) diff --git a/src/user_management/operations/authenticate_with_magic_auth.rs b/src/user_management/operations/authenticate_with_magic_auth.rs index 38b354e..af9e5b6 100644 --- a/src/user_management/operations/authenticate_with_magic_auth.rs +++ b/src/user_management/operations/authenticate_with_magic_auth.rs @@ -110,7 +110,7 @@ impl AuthenticateWithMagicAuth for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_magic_auth_response) diff --git a/src/user_management/operations/authenticate_with_password.rs b/src/user_management/operations/authenticate_with_password.rs index e61eb9e..4648c7c 100644 --- a/src/user_management/operations/authenticate_with_password.rs +++ b/src/user_management/operations/authenticate_with_password.rs @@ -109,7 +109,7 @@ impl AuthenticateWithPassword for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_password_response) diff --git a/src/user_management/operations/authenticate_with_refresh_token.rs b/src/user_management/operations/authenticate_with_refresh_token.rs index cc3df25..b547f2d 100644 --- a/src/user_management/operations/authenticate_with_refresh_token.rs +++ b/src/user_management/operations/authenticate_with_refresh_token.rs @@ -107,7 +107,7 @@ impl AuthenticateWithRefreshToken for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_refresh_token_response) diff --git a/src/user_management/operations/authenticate_with_totp.rs b/src/user_management/operations/authenticate_with_totp.rs index 145eb1e..c7748d8 100644 --- a/src/user_management/operations/authenticate_with_totp.rs +++ b/src/user_management/operations/authenticate_with_totp.rs @@ -112,7 +112,7 @@ impl AuthenticateWithTotp for UserManagement<'_> { .await? .handle_authenticate_error() .await? - .json::() + .json::() .await?; Ok(authenticate_with_totp_response) diff --git a/src/user_management/operations/create_magic_auth.rs b/src/user_management/operations/create_magic_auth.rs index 6df04cc..71bf366 100644 --- a/src/user_management/operations/create_magic_auth.rs +++ b/src/user_management/operations/create_magic_auth.rs @@ -76,7 +76,7 @@ impl CreateMagicAuth for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/create_password_reset.rs b/src/user_management/operations/create_password_reset.rs index b995e21..661618b 100644 --- a/src/user_management/operations/create_password_reset.rs +++ b/src/user_management/operations/create_password_reset.rs @@ -46,7 +46,7 @@ where } #[async_trait] -impl<'a> HandleCreatePasswordResetError for Box{ +impl<'a> HandleCreatePasswordResetError for Box { async fn handle_create_password_reset_error( self, ) -> WorkOsResult { @@ -54,7 +54,7 @@ impl<'a> HandleCreatePasswordResetError for Box{ Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::NOT_FOUND) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(WorkOsError::Operation(error)) } @@ -119,7 +119,7 @@ impl CreatePasswordReset for UserManagement<'_> { .handle_unauthorized_error()? .handle_create_password_reset_error() .await? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/create_user.rs b/src/user_management/operations/create_user.rs index 834388f..38012e1 100644 --- a/src/user_management/operations/create_user.rs +++ b/src/user_management/operations/create_user.rs @@ -99,7 +99,7 @@ impl CreateUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/enroll_auth_factor.rs b/src/user_management/operations/enroll_auth_factor.rs index ae9b541..4490b2b 100644 --- a/src/user_management/operations/enroll_auth_factor.rs +++ b/src/user_management/operations/enroll_auth_factor.rs @@ -85,7 +85,7 @@ impl<'a> HandleEnrollAuthFactorError for Box { Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) | Some(StatusCode::UNPROCESSABLE_ENTITY) => { // let error = self.json::().await?; - let error = self.json::().await?; + let error = self.json::().await?; println!("{error:#?}"); @@ -159,7 +159,7 @@ impl EnrollAuthFactor for UserManagement<'_> { .handle_unauthorized_error()? .handle_enroll_auth_factor_error() .await? - .json::() + .json::() .await?; Ok(response) diff --git a/src/user_management/operations/get_email_verification.rs b/src/user_management/operations/get_email_verification.rs index 1cc5d5a..73e2c78 100644 --- a/src/user_management/operations/get_email_verification.rs +++ b/src/user_management/operations/get_email_verification.rs @@ -62,7 +62,7 @@ impl GetEmailVerification for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_jwks.rs b/src/user_management/operations/get_jwks.rs index 6b8a7cb..0414708 100644 --- a/src/user_management/operations/get_jwks.rs +++ b/src/user_management/operations/get_jwks.rs @@ -52,7 +52,7 @@ impl GetJwks for UserManagement<'_> { .send() .await? .handle_generic_error()? - .json::() + .json::() .await?; Ok(jwks) diff --git a/src/user_management/operations/get_magic_auth.rs b/src/user_management/operations/get_magic_auth.rs index 5c24696..f88c7b9 100644 --- a/src/user_management/operations/get_magic_auth.rs +++ b/src/user_management/operations/get_magic_auth.rs @@ -56,7 +56,7 @@ impl GetMagicAuth for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_password_reset.rs b/src/user_management/operations/get_password_reset.rs index 6b343d3..fa1842a 100644 --- a/src/user_management/operations/get_password_reset.rs +++ b/src/user_management/operations/get_password_reset.rs @@ -62,7 +62,7 @@ impl GetPasswordReset for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(organization) diff --git a/src/user_management/operations/get_user.rs b/src/user_management/operations/get_user.rs index aab0fbf..9547db8 100644 --- a/src/user_management/operations/get_user.rs +++ b/src/user_management/operations/get_user.rs @@ -56,7 +56,7 @@ impl GetUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/get_user_by_external_id.rs b/src/user_management/operations/get_user_by_external_id.rs index 187a6de..1739ae7 100644 --- a/src/user_management/operations/get_user_by_external_id.rs +++ b/src/user_management/operations/get_user_by_external_id.rs @@ -62,7 +62,7 @@ impl GetUserByExternalId for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/operations/get_user_identities.rs b/src/user_management/operations/get_user_identities.rs index 8f37cea..4e0c0e1 100644 --- a/src/user_management/operations/get_user_identities.rs +++ b/src/user_management/operations/get_user_identities.rs @@ -63,7 +63,7 @@ impl GetUserIdentities for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(users) diff --git a/src/user_management/operations/list_auth_factors.rs b/src/user_management/operations/list_auth_factors.rs index 81e02f1..febd595 100644 --- a/src/user_management/operations/list_auth_factors.rs +++ b/src/user_management/operations/list_auth_factors.rs @@ -81,7 +81,7 @@ impl ListAuthFactors for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(organizations) diff --git a/src/user_management/operations/list_users.rs b/src/user_management/operations/list_users.rs index 30795a1..1849830 100644 --- a/src/user_management/operations/list_users.rs +++ b/src/user_management/operations/list_users.rs @@ -79,7 +79,7 @@ impl ListUsers for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::,_>() + .json::, _>() .await?; Ok(users) diff --git a/src/user_management/operations/reset_password.rs b/src/user_management/operations/reset_password.rs index 92123bb..57d928c 100644 --- a/src/user_management/operations/reset_password.rs +++ b/src/user_management/operations/reset_password.rs @@ -92,7 +92,7 @@ impl<'a> HandleResetPasswordError for Box { Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) | Some(StatusCode::NOT_FOUND) => { - let error = self.json::().await?; + let error = self.json::().await?; Err(WorkOsError::Operation(error)) } @@ -159,7 +159,7 @@ impl ResetPassword for UserManagement<'_> { .handle_unauthorized_error()? .handle_reset_password_error() .await? - .json::() + .json::() .await?; Ok(response) diff --git a/src/user_management/operations/update_user.rs b/src/user_management/operations/update_user.rs index 3ba0c73..0cd9642 100644 --- a/src/user_management/operations/update_user.rs +++ b/src/user_management/operations/update_user.rs @@ -108,7 +108,7 @@ impl UpdateUser for UserManagement<'_> { .send() .await? .handle_unauthorized_or_generic_error()? - .json::() + .json::() .await?; Ok(user) diff --git a/src/user_management/types/authenticate_error.rs b/src/user_management/types/authenticate_error.rs index 2560646..6f5dd5f 100644 --- a/src/user_management/types/authenticate_error.rs +++ b/src/user_management/types/authenticate_error.rs @@ -4,7 +4,8 @@ use serde::Deserialize; use thiserror::Error; use crate::{ - mfa::AuthenticationFactorIdAndType, organizations::OrganizationIdAndName, sso::ConnectionId, ResponseExt, WorkOsError, WorkOsResult + ResponseExt, WorkOsError, WorkOsResult, mfa::AuthenticationFactorIdAndType, + organizations::OrganizationIdAndName, sso::ConnectionId, }; use super::{AuthenticateMethods, EmailVerificationId, PendingAuthenticationToken, User}; @@ -275,7 +276,7 @@ impl<'a> HandleAuthenticateError for Box Ok(_) => Ok(self), Err(err) => match err.status() { Some(StatusCode::BAD_REQUEST) => { - let authenticate_error = self.json::().await?; + let authenticate_error = self.json::().await?; Err(match &authenticate_error { AuthenticateError::WithError(AuthenticateErrorWithError::Other { @@ -289,7 +290,7 @@ impl<'a> HandleAuthenticateError for Box }) } Some(StatusCode::FORBIDDEN) => { - let authenticate_error = self.json::().await?; + let authenticate_error = self.json::().await?; Err(WorkOsError::Operation(authenticate_error)) }