From 8602b1463072d1a1e42ce1d9bc6165d5013172ab Mon Sep 17 00:00:00 2001 From: Bill Fraser Date: Tue, 5 Nov 2024 16:10:31 -0800 Subject: [PATCH 1/3] simplify client tests; re-export client_trait_common types in {async_,}client_trait --- src/async_client_trait.rs | 2 +- src/client_trait.rs | 2 +- tests/async_client_test.rs | 18 ------------------ tests/sync_client_test.rs | 18 ------------------ 4 files changed, 2 insertions(+), 38 deletions(-) diff --git a/src/async_client_trait.rs b/src/async_client_trait.rs index 4443a2c..e9d8419 100644 --- a/src/async_client_trait.rs +++ b/src/async_client_trait.rs @@ -4,7 +4,7 @@ use std::future::{Future, ready}; use std::sync::Arc; use bytes::Bytes; use futures::AsyncRead; -use crate::client_trait_common::{HttpRequest, TeamSelect}; +pub use crate::client_trait_common::{HttpRequest, TeamSelect}; use crate::Error; /// The base HTTP asynchronous client trait. diff --git a/src/client_trait.rs b/src/client_trait.rs index 7c977e6..3485b62 100644 --- a/src/client_trait.rs +++ b/src/client_trait.rs @@ -4,7 +4,7 @@ use std::io::Read; use std::sync::Arc; -use crate::client_trait_common::{HttpRequest, TeamSelect}; +pub use crate::client_trait_common::{HttpRequest, TeamSelect}; use crate::Error; /// The base HTTP synchronous client trait. diff --git a/tests/async_client_test.rs b/tests/async_client_test.rs index 922c9fd..682681b 100644 --- a/tests/async_client_test.rs +++ b/tests/async_client_test.rs @@ -1,9 +1,7 @@ -use std::sync::Arc; use bytes::Bytes; use futures::io::Cursor; use dropbox_sdk::async_routes::check; use dropbox_sdk::async_client_trait::*; -use dropbox_sdk::client_trait_common::{HttpRequest, TeamSelect}; use dropbox_sdk::Error; struct TestAsyncClient; @@ -36,22 +34,6 @@ impl HttpClient for TestAsyncClient { fn new_request(&self, url: &str) -> Self::Request { TestRequest{ url: url.to_owned() } } - - async fn update_token(&self, _old_token: Arc) -> Result { - Ok(true) - } - - fn token(&self) -> Option> { - Some(Arc::new(String::new())) - } - - fn path_root(&self) -> Option<&str> { - None - } - - fn team_select(&self) -> Option<&TeamSelect> { - None - } } impl UserAuthClient for TestAsyncClient {} diff --git a/tests/sync_client_test.rs b/tests/sync_client_test.rs index 88f008d..476a236 100644 --- a/tests/sync_client_test.rs +++ b/tests/sync_client_test.rs @@ -1,8 +1,6 @@ use std::io::Cursor; -use std::sync::Arc; use dropbox_sdk::sync_routes::check; use dropbox_sdk::client_trait::*; -use dropbox_sdk::client_trait_common::{HttpRequest, TeamSelect}; use dropbox_sdk::Error; struct TestSyncClient; @@ -31,22 +29,6 @@ impl HttpClient for TestSyncClient { fn new_request(&self, url: &str) -> Self::Request { TestRequest{ url: url.to_owned() } } - - fn update_token(&self, _old_token: Arc) -> Result { - Ok(true) - } - - fn token(&self) -> Option> { - Some(Arc::new(String::new())) - } - - fn path_root(&self) -> Option<&str> { - None - } - - fn team_select(&self) -> Option<&TeamSelect> { - None - } } impl UserAuthClient for TestSyncClient {} From baa8bf26c7331cb38938733a5df445873efece78 Mon Sep 17 00:00:00 2001 From: Bill Fraser Date: Tue, 5 Nov 2024 16:50:06 -0800 Subject: [PATCH 2/3] implement AppAuthClient for default HTTP clients --- README.md | 5 ++--- RELEASE_NOTES.md | 4 ++++ src/default_async_client.rs | 40 ++++++++++++++++++++++++++++++++++++- src/default_client.rs | 40 ++++++++++++++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ebb98d8..8b0771d 100644 --- a/README.md +++ b/README.md @@ -69,9 +69,8 @@ The authentication type is designated by implementing a marker trait in addition to the base `HttpClient` trait: one of `NoauthClient`, `UserAuthClient`, `TeamAuthClient`, or `AppAuthClient`. -The default client has implementations of all of these (except for -`AppAuthClient` currently). They all share a common implementation and differ -only in which HTTP headers they add to the request. +The default client has implementations of all of these. They all share a common +implementation and differ only in which HTTP headers they add to the request. [authentication types]: https://www.dropbox.com/developers/reference/auth-types diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 726255b..29551a9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,7 @@ +# v0.19.0-beta3 +xxxx-yy-zz +* added implementations of AppAuthClient to default HTTP clients + # v0.19.0-beta2 2024-11-05 * renamed sync_routes_default feature to sync_routes_in_root diff --git a/src/default_async_client.rs b/src/default_async_client.rs index 10f069c..b8bcd75 100644 --- a/src/default_async_client.rs +++ b/src/default_async_client.rs @@ -15,7 +15,7 @@ use std::str::FromStr; use std::sync::Arc; use bytes::Bytes; use futures::{FutureExt, TryFutureExt, TryStreamExt}; -use crate::async_client_trait::{HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; +use crate::async_client_trait::{AppAuthClient, HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; use crate::client_trait_common::{HttpRequest, TeamSelect}; use crate::default_client_common::impl_set_path_root; use crate::Error; @@ -156,6 +156,44 @@ impl HttpClient for TeamAuthDefaultClient { impl TeamAuthClient for TeamAuthDefaultClient {} +/// Default HTTP client using App authorization. +#[derive(Debug)] +pub struct AppAuthDefaultClient { + inner: ReqwestClient, + path_root: Option, + auth: String, +} + +impl AppAuthDefaultClient { + /// Create a new App auth client using the given app key and secret, which can be found in the Dropbox app console. + pub fn new(app_key: &str, app_secret: &str) -> Self { + use base64::prelude::*; + let encoded = BASE64_STANDARD.encode(format!("{app_key}:{app_secret}")); + Self { + inner: ReqwestClient::default(), + path_root: None, + auth: format!("Basic {encoded}"), + } + } + + impl_set_path_root!(self); +} + +impl HttpClient for AppAuthDefaultClient { + type Request = ReqwestRequest; + + fn execute(&self, request: Self::Request, body: Bytes) -> impl Future> + Send { + self.inner.execute(request, body) + } + + fn new_request(&self, url: &str) -> Self::Request { + self.inner.new_request(url) + .set_header("Authorization", &self.auth) + } +} + +impl AppAuthClient for AppAuthDefaultClient {} + /// Default HTTP client for unauthenticated API calls. #[derive(Debug, Default)] pub struct NoauthDefaultClient { diff --git a/src/default_client.rs b/src/default_client.rs index 0a6c51c..b8769cf 100644 --- a/src/default_client.rs +++ b/src/default_client.rs @@ -18,7 +18,7 @@ use std::fmt::Write; use std::str::FromStr; use std::sync::Arc; use futures::FutureExt; -use crate::client_trait::{HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; +use crate::client_trait::{AppAuthClient, HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; use crate::client_trait_common::{HttpRequest, TeamSelect}; use crate::default_client_common::impl_set_path_root; @@ -145,6 +145,44 @@ impl HttpClient for TeamAuthDefaultClient { impl TeamAuthClient for TeamAuthDefaultClient {} +/// Default HTTP client using App authorization. +#[derive(Debug)] +pub struct AppAuthDefaultClient { + inner: UreqClient, + path_root: Option, + auth: String, +} + +impl AppAuthDefaultClient { + /// Create a new App auth client using the given app key and secret, which can be found in the Dropbox app console. + pub fn new(app_key: &str, app_secret: &str) -> Self { + use base64::prelude::*; + let encoded = BASE64_STANDARD.encode(format!("{app_key}:{app_secret}")); + Self { + inner: UreqClient::default(), + path_root: None, + auth: format!("Basic {encoded}"), + } + } + + impl_set_path_root!(self); +} + +impl HttpClient for AppAuthDefaultClient { + type Request = UreqRequest; + + fn execute(&self, request: Self::Request, body: &[u8]) -> Result { + self.inner.execute(request, body) + } + + fn new_request(&self, url: &str) -> Self::Request { + self.inner.new_request(url) + .set_header("Authorization", &self.auth) + } +} + +impl AppAuthClient for AppAuthDefaultClient {} + /// Default HTTP client for unauthenticated API calls. #[derive(Debug, Default)] pub struct NoauthDefaultClient { From bb20b88ed7fea5eee2b0ae9d4f278e31d99ba104 Mon Sep 17 00:00:00 2001 From: Bill Fraser Date: Wed, 13 Nov 2024 15:36:27 -0800 Subject: [PATCH 3/3] clean up re-exports a bit --- src/default_async_client.rs | 4 ++-- src/default_client.rs | 4 ++-- src/lib.rs | 13 ++++++------- tests/noop_client.rs | 1 - 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/default_async_client.rs b/src/default_async_client.rs index b8bcd75..2a0a0fa 100644 --- a/src/default_async_client.rs +++ b/src/default_async_client.rs @@ -15,8 +15,8 @@ use std::str::FromStr; use std::sync::Arc; use bytes::Bytes; use futures::{FutureExt, TryFutureExt, TryStreamExt}; -use crate::async_client_trait::{AppAuthClient, HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; -use crate::client_trait_common::{HttpRequest, TeamSelect}; +use crate::async_client_trait::{AppAuthClient, HttpClient, HttpRequest, HttpRequestResultRaw, + NoauthClient, TeamAuthClient, TeamSelect, UserAuthClient}; use crate::default_client_common::impl_set_path_root; use crate::Error; use crate::oauth2::{Authorization, TokenCache}; diff --git a/src/default_client.rs b/src/default_client.rs index b8769cf..8ecfc8e 100644 --- a/src/default_client.rs +++ b/src/default_client.rs @@ -18,8 +18,8 @@ use std::fmt::Write; use std::str::FromStr; use std::sync::Arc; use futures::FutureExt; -use crate::client_trait::{AppAuthClient, HttpClient, HttpRequestResultRaw, NoauthClient, TeamAuthClient, UserAuthClient}; -use crate::client_trait_common::{HttpRequest, TeamSelect}; +use crate::client_trait::{AppAuthClient, HttpClient, HttpRequest, HttpRequestResultRaw, + NoauthClient, TeamAuthClient, TeamSelect, UserAuthClient}; use crate::default_client_common::impl_set_path_root; macro_rules! impl_update_token { diff --git a/src/lib.rs b/src/lib.rs index 30ee32e..e99ab1e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,30 +44,29 @@ if_feature! { "default_client", if_feature! { "default_async_client", pub mod default_async_client; } #[cfg(any(feature = "default_client", feature = "default_async_client"))] -pub(crate) mod default_client_common; +mod default_client_common; -pub mod client_trait_common; +mod client_trait_common; pub mod client_trait; pub mod async_client_trait; -pub(crate) mod client_helpers; +mod client_helpers; pub mod oauth2; -mod generated; - // You need to run the Stone generator to create this module. +mod generated; pub use generated::*; #[cfg(feature = "async_routes")] #[cfg(not(feature = "sync_routes_in_root"))] -pub use generated::async_routes::*; +pub use async_routes::*; #[cfg(feature = "sync_routes")] #[cfg(feature = "sync_routes_in_root")] -pub use generated::sync_routes::*; +pub use sync_routes::*; mod error; pub use error::{BoxedError, Error, NoError}; diff --git a/tests/noop_client.rs b/tests/noop_client.rs index 46c24ee..df114a5 100644 --- a/tests/noop_client.rs +++ b/tests/noop_client.rs @@ -1,6 +1,5 @@ use std::fmt::{Debug, Display, Formatter}; use dropbox_sdk::client_trait::*; -use dropbox_sdk::client_trait_common::HttpRequest; macro_rules! noop_client { ($name:ident) => {