From fe9b8b94e9610b571843119681500ce2376117b1 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 3 Apr 2024 13:06:32 -0400 Subject: [PATCH 01/33] An initial and somewhat naive implementation of list users --- Cargo.lock | 1 + wp_api/Cargo.toml | 1 + wp_api/src/lib.rs | 107 ++++++++++++++++++++++++++++++++++++++- wp_api/src/users.rs | 68 +++++++++++++++++++++++++ wp_cli/src/main.rs | 14 +++-- wp_networking/src/lib.rs | 24 +++++++-- 6 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 wp_api/src/users.rs diff --git a/Cargo.lock b/Cargo.lock index 690e83505..c4afbde41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1926,6 +1926,7 @@ dependencies = [ "thiserror", "uniffi", "url", + "wp_derive", ] [[package]] diff --git a/wp_api/Cargo.toml b/wp_api/Cargo.toml index 787e92fad..1e54a0e2e 100644 --- a/wp_api/Cargo.toml +++ b/wp_api/Cargo.toml @@ -15,6 +15,7 @@ serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" thiserror = { workspace = true } uniffi = { workspace = true } +wp_derive = { path = "../wp_derive" } [build-dependencies] uniffi = { workspace = true , features = [ "build", "cli" ] } diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 1d4829b9a..ecfbea2c9 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -1,18 +1,21 @@ #![allow(dead_code, unused_variables)] -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display}; pub use api_error::*; pub use login::*; pub use pages::*; pub use posts::*; +use serde::Deserialize; pub use url::*; +pub use users::*; pub mod api_error; pub mod login; pub mod pages; pub mod posts; pub mod url; +pub mod users; #[derive(uniffi::Object)] pub struct WPApiHelper { @@ -75,6 +78,62 @@ impl WPApiHelper { header_map: Some(header_map), } } + + pub fn user_list_request( + &self, + context: WPContext, + params: Option, + ) -> WPNetworkRequest { + let mut url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); + + let mut header_map = HashMap::new(); + + match &self.authentication { + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".into(), format!("Basic {}", token)); + } + WPAuthentication::None => (), + } + + url.query_pairs_mut() + .append_pair("context", &context.to_string()); + if let Some(params) = params { + url.query_pairs_mut().extend_pairs(params.query_pairs()); + } + + WPNetworkRequest { + method: RequestMethod::GET, + url: url.into(), + header_map: Some(header_map), + } + } +} + +#[derive(Debug, Clone, uniffi::Enum)] +pub enum WPContext { + Edit, + Embed, + View, +} + +impl Default for WPContext { + fn default() -> Self { + Self::View + } +} + +impl Display for WPContext { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Edit => "edit", + Self::Embed => "embed", + Self::View => "view", + } + ) + } } #[derive(Debug, Clone, uniffi::Enum)] @@ -171,6 +230,52 @@ pub fn parse_post_list_response( }) } +pub fn parse_user_list_response<'de, T: Deserialize<'de>>( + response: &'de WPNetworkResponse, +) -> Result, WPApiError> { + if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { + return Err(WPApiError::ClientError { + error_type: client_error_type, + status_code: response.status_code, + }); + } + let status = http::StatusCode::from_u16(response.status_code).unwrap(); + if status.is_server_error() { + return Err(WPApiError::ServerError { + status_code: response.status_code, + }); + } + + let user_list: Vec = + serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { + reason: err.to_string(), + response: std::str::from_utf8(&response.body).unwrap().to_string(), + })?; + + Ok(user_list) +} + +#[uniffi::export] +pub fn parse_user_list_response_with_edit_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_list_response(response) +} + +#[uniffi::export] +pub fn parse_user_list_response_with_embed_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_list_response(response) +} + +#[uniffi::export] +pub fn parse_user_list_response_with_view_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_list_response(response) +} + #[uniffi::export] pub fn parse_api_details_response(response: WPNetworkResponse) -> Result { let api_details = diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs new file mode 100644 index 000000000..d8fbc019d --- /dev/null +++ b/wp_api/src/users.rs @@ -0,0 +1,68 @@ +use serde::{Deserialize, Serialize}; +use wp_derive::WPContextual; + +#[derive(Default, uniffi::Record)] +pub struct UserListParams { + pub page: Option, + pub per_page: Option, +} + +impl UserListParams { + pub fn query_pairs(&self) -> impl IntoIterator { + [ + self.page.as_ref().map(|p| ("page", p.to_string())), + self.per_page.as_ref().map(|p| ("per_page", p.to_string())), + ] + .into_iter() + .flatten() + } +} + +#[derive(Debug, Serialize, Deserialize, uniffi::Record, WPContextual)] +pub struct SparseUser { + #[WPContext(edit, embed, view)] + pub id: Option, + #[WPContext(edit)] + pub username: Option, + #[WPContext(edit, embed, view)] + pub name: Option, + #[WPContext(edit)] + pub first_name: Option, + #[WPContext(edit)] + pub last_name: Option, + #[WPContext(edit)] + pub email: Option, + #[WPContext(edit, embed, view)] + pub url: Option, + #[WPContext(edit, embed, view)] + pub description: Option, + #[WPContext(edit, embed, view)] + pub link: Option, + #[WPContext(edit)] + pub locale: Option, + #[WPContext(edit)] + pub nickname: Option, + #[WPContext(edit, embed, view)] + pub slug: Option, + #[WPContext(edit)] + pub registered_date: Option, + #[WPContext(edit)] + pub roles: Option>, + #[WPContext(edit)] + pub capabilities: Option, + #[WPContext(edit)] + pub extra_capabilities: Option, + #[WPContext(edit, embed, view)] + pub avatar_urls: Option, + #[WPContext(edit, view)] + pub meta: Option, +} + +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +pub struct UserCapabilities {} +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +pub struct UserExtraCapabilities {} +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +pub struct UserAvatarUrls {} +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] +pub struct UserMeta {} diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 74cf76536..1724d42c2 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,6 +1,6 @@ use std::fs::read_to_string; -use wp_api::WPAuthentication; +use wp_api::{WPAuthentication, WPContext}; use wp_networking::WPNetworking; fn main() { @@ -16,6 +16,14 @@ fn main() { }; let wp_networking = WPNetworking::new(url.into(), authentication); - let post_list = wp_networking.list_posts(None).unwrap(); - println!("{:?}", post_list); + + let wp_request = wp_networking + .api_helper + .user_list_request(WPContext::View, None); + println!( + "{:?}", + wp_api::parse_user_list_response_with_view_context( + &wp_networking.request(wp_request).unwrap() + ) + ); } diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index fc78b2d4a..364e860d2 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -3,27 +3,43 @@ use http::HeaderMap; use reqwest::blocking::Client; use wp_api::{ - PostListParams, PostListResponse, WPApiError, WPApiHelper, WPAuthentication, WPNetworkResponse, + PostListParams, PostListResponse, WPApiError, WPApiHelper, WPAuthentication, WPNetworkRequest, + WPNetworkResponse, }; pub struct WPNetworking { client: Client, - helper: WPApiHelper, + pub api_helper: WPApiHelper, } impl WPNetworking { pub fn new(site_url: String, authentication: WPAuthentication) -> Self { Self { client: reqwest::blocking::Client::new(), - helper: WPApiHelper::new(site_url, authentication), + api_helper: WPApiHelper::new(site_url, authentication), } } + pub fn request( + &self, + wp_request: WPNetworkRequest, + ) -> Result { + let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); + let response = self + .client + .request(request_method(wp_request.method), wp_request.url) + .headers(request_headers) + .send()?; + Ok(wp_network_response(response)) + } + pub fn list_posts( &self, params: Option, ) -> Result { - let wp_request = self.helper.post_list_request(params.unwrap_or_default()); + let wp_request = self + .api_helper + .post_list_request(params.unwrap_or_default()); let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); let response = self .client From 98b30bcc998deba95efb2855281e97e9f73cfec8 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 3 Apr 2024 13:43:58 -0400 Subject: [PATCH 02/33] Add the remaining fields to UserListParams --- wp_api/src/users.rs | 116 +++++++++++++++++++++++++++++++++++++++++++- wp_cli/src/main.rs | 4 +- 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index d8fbc019d..f81fcd259 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,17 +1,129 @@ +use std::fmt::Display; + use serde::{Deserialize, Serialize}; use wp_derive::WPContextual; +// TODO: Should be in a centralized mod +// TODO: Need a better name +#[derive(uniffi::Enum)] +pub enum WPApiOrderParam { + Asc, + Desc, +} + +impl Default for WPApiOrderParam { + fn default() -> Self { + Self::Asc + } +} + +impl Display for WPApiOrderParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Asc => "asc", + Self::Desc => "desc", + } + ) + } +} + +// TODO: Need a better name? +#[derive(uniffi::Enum)] +pub enum UserListParamOrderBy { + Id, + Include, + Name, + RegisteredDate, + Slug, + IncludeSlugs, + Email, + Url, +} + +impl Default for UserListParamOrderBy { + fn default() -> Self { + Self::Name + } +} + +impl Display for UserListParamOrderBy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Id => "id", + Self::Include => "include", + Self::Name => "name", + Self::RegisteredDate => "registered_date", + Self::Slug => "slug", + Self::IncludeSlugs => "include_slugs", + Self::Email => "email", + Self::Url => "url", + } + ) + } +} + #[derive(Default, uniffi::Record)] pub struct UserListParams { + // TODO: Implement the `_filter` + /// Current page of the collection. + /// Default: `1` pub page: Option, + /// Maximum number of items to be returned in result set. + /// Default: `10` pub per_page: Option, + /// Limit results to those matching a string. + pub search: Option, + /// Ensure result set excludes specific IDs. + pub exclude: Option, + /// Limit result set to specific IDs. + pub include: Option, + /// Offset the result set by a specific number of items. + pub offset: Option, + /// Order sort attribute ascending or descending. + /// Default: `asc` + /// One of: `asc`, `desc` + pub order: Option, + /// Sort collection by user attribute. + /// Default: `name` + /// One of: `id`, `include`, `name`, `registered_date`, `slug`, `include_slugs`, `email`, `url` + pub order_by: Option, + /// Limit result set to users with one or more specific slugs. + pub slug: Option, + /// Limit result set to users matching at least one specific role provided. Accepts csv list or single role. + pub roles: Vec, + /// Limit result set to users matching at least one specific capability provided. Accepts csv list or single capability. + pub capabilities: Vec, + /// Limit result set to users who are considered authors. + /// One of: `authors` + pub who: Option, + /// Limit result set to users who have published posts. + pub has_published_posts: Option, } impl UserListParams { pub fn query_pairs(&self) -> impl IntoIterator { [ - self.page.as_ref().map(|p| ("page", p.to_string())), - self.per_page.as_ref().map(|p| ("per_page", p.to_string())), + self.page.as_ref().map(|x| ("page", x.to_string())), + self.per_page.as_ref().map(|x| ("per_page", x.to_string())), + self.search.as_ref().map(|x| ("search", x.clone())), + self.exclude.as_ref().map(|x| ("exclude", x.clone())), + self.include.as_ref().map(|x| ("include", x.clone())), + self.offset.as_ref().map(|x| ("offset", x.to_string())), + self.order.as_ref().map(|x| ("order", x.to_string())), + self.order_by.as_ref().map(|x| ("order_by", x.to_string())), + self.slug.as_ref().map(|x| ("slug", x.clone())), + Some(("roles", self.roles.join(","))), + Some(("capabilities", self.capabilities.join(","))), + self.who.as_ref().map(|x| ("who", x.clone())), + self.has_published_posts + .as_ref() + .map(|x| ("has_published_posts", x.to_string())), ] .into_iter() .flatten() diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 1724d42c2..53247d721 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -19,10 +19,10 @@ fn main() { let wp_request = wp_networking .api_helper - .user_list_request(WPContext::View, None); + .user_list_request(WPContext::Edit, None); println!( "{:?}", - wp_api::parse_user_list_response_with_view_context( + wp_api::parse_user_list_response_with_edit_context( &wp_networking.request(wp_request).unwrap() ) ); From a2c49402e45085d764cb6b058f4aeb2272f5e32d Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 3 Apr 2024 14:53:13 -0400 Subject: [PATCH 03/33] Implements user_retrieve_request --- wp_api/src/lib.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++ wp_api/src/users.rs | 6 ++++ wp_cli/src/main.rs | 27 ++++++++++++----- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index ecfbea2c9..f45d38a2c 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -107,6 +107,35 @@ impl WPApiHelper { header_map: Some(header_map), } } + + pub fn user_retrieve_request( + &self, + context: WPContext, + params: UserRetrieveParams, + ) -> WPNetworkRequest { + let mut url = self + .site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap(); + + let mut header_map = HashMap::new(); + + match &self.authentication { + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".into(), format!("Basic {}", token)); + } + WPAuthentication::None => (), + } + + url.query_pairs_mut() + .append_pair("context", &context.to_string()); + + WPNetworkRequest { + method: RequestMethod::GET, + url: url.into(), + header_map: Some(header_map), + } + } } #[derive(Debug, Clone, uniffi::Enum)] @@ -276,6 +305,51 @@ pub fn parse_user_list_response_with_view_context( parse_user_list_response(response) } +pub fn parse_user_retrieve_response<'de, T: Deserialize<'de> + std::fmt::Debug>( + response: &'de WPNetworkResponse, +) -> Result { + if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { + return Err(WPApiError::ClientError { + error_type: client_error_type, + status_code: response.status_code, + }); + } + let status = http::StatusCode::from_u16(response.status_code).unwrap(); + if status.is_server_error() { + return Err(WPApiError::ServerError { + status_code: response.status_code, + }); + } + + let user: T = + serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { + reason: err.to_string(), + response: std::str::from_utf8(&response.body).unwrap().to_string(), + })?; + Ok(user) +} + +#[uniffi::export] +pub fn parse_user_retrieve_response_with_edit_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_retrieve_response(response) +} + +#[uniffi::export] +pub fn parse_user_retrieve_response_with_embed_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_retrieve_response(response) +} + +#[uniffi::export] +pub fn parse_user_retrieve_response_with_view_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_user_retrieve_response(response) +} + #[uniffi::export] pub fn parse_api_details_response(response: WPNetworkResponse) -> Result { let api_details = diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index f81fcd259..702bb50f7 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -130,6 +130,12 @@ impl UserListParams { } } +#[derive(Default, uniffi::Record)] +pub struct UserRetrieveParams { + /// Unique identifier for the user. + pub id: u32, +} + #[derive(Debug, Serialize, Deserialize, uniffi::Record, WPContextual)] pub struct SparseUser { #[WPContext(edit, embed, view)] diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 53247d721..d93b2ffb2 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,6 +1,6 @@ use std::fs::read_to_string; -use wp_api::{WPAuthentication, WPContext}; +use wp_api::{UserRetrieveParams, WPAuthentication, WPContext}; use wp_networking::WPNetworking; fn main() { @@ -17,13 +17,24 @@ fn main() { let wp_networking = WPNetworking::new(url.into(), authentication); - let wp_request = wp_networking + let user_list_request = wp_networking .api_helper .user_list_request(WPContext::Edit, None); - println!( - "{:?}", - wp_api::parse_user_list_response_with_edit_context( - &wp_networking.request(wp_request).unwrap() - ) - ); + let user_list = wp_api::parse_user_list_response_with_edit_context( + &wp_networking.request(user_list_request).unwrap(), + ) + .unwrap(); + println!("{:?}", user_list); + + if let Some(first_user) = user_list.first() { + let user_retrieve_request = wp_networking + .api_helper + .user_retrieve_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); + println!( + "{:?}", + wp_api::parse_user_retrieve_response_with_embed_context( + &wp_networking.request(user_retrieve_request).unwrap() + ) + ); + } } From 498fe328e7a3c2c57983ec10be817c36e0d3d5ff Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 12:00:12 -0400 Subject: [PATCH 04/33] Change UserListParams.slug to be Vec --- wp_api/src/users.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 702bb50f7..da937eb5e 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -94,7 +94,7 @@ pub struct UserListParams { /// One of: `id`, `include`, `name`, `registered_date`, `slug`, `include_slugs`, `email`, `url` pub order_by: Option, /// Limit result set to users with one or more specific slugs. - pub slug: Option, + pub slug: Vec, /// Limit result set to users matching at least one specific role provided. Accepts csv list or single role. pub roles: Vec, /// Limit result set to users matching at least one specific capability provided. Accepts csv list or single capability. @@ -117,7 +117,7 @@ impl UserListParams { self.offset.as_ref().map(|x| ("offset", x.to_string())), self.order.as_ref().map(|x| ("order", x.to_string())), self.order_by.as_ref().map(|x| ("order_by", x.to_string())), - self.slug.as_ref().map(|x| ("slug", x.clone())), + Some(("slug", self.slug.join(","))), Some(("roles", self.roles.join(","))), Some(("capabilities", self.capabilities.join(","))), self.who.as_ref().map(|x| ("who", x.clone())), From 5b73f8ef79e3ee9ea15a9935849add7eaa0c0fa8 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 12:12:52 -0400 Subject: [PATCH 05/33] Add UserCreateParams --- wp_api/src/users.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index da937eb5e..9e03a6159 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -130,6 +130,61 @@ impl UserListParams { } } +#[derive(Default, uniffi::Record)] +pub struct UserCreateParams { + /// Login name for the user. + pub username: String, + /// The email address for the user. + pub email: String, + /// Password for the user (never included). + pub password: String, + /// Display name for the user. + pub name: Option, + /// First name for the user. + pub first_name: Option, + /// Last name for the user. + pub last_name: Option, + /// URL of the user. + pub url: Option, + /// Description of the user. + pub description: Option, + /// Locale for the user. + /// One of: , `en_US` + pub locale: Option, + /// The nickname for the user. + pub nickname: Option, + /// An alphanumeric identifier for the user. + pub slug: Option, + /// Roles assigned to the user. + pub roles: Vec, + /// Meta fields. + pub meta: Option, +} + +impl UserCreateParams { + pub fn query_pairs(&self) -> impl IntoIterator { + [ + Some(("username", self.username.clone())), + Some(("email", self.email.clone())), + Some(("password", self.password.clone())), + self.name.as_ref().map(|x| ("name", x.clone())), + self.first_name.as_ref().map(|x| ("first_name", x.clone())), + self.last_name.as_ref().map(|x| ("last_name", x.clone())), + self.url.as_ref().map(|x| ("url", x.clone())), + self.description + .as_ref() + .map(|x| ("description", x.clone())), + self.locale.as_ref().map(|x| ("locale", x.clone())), + self.nickname.as_ref().map(|x| ("nickname", x.clone())), + self.slug.as_ref().map(|x| ("slug", x.clone())), + Some(("roles", self.roles.join(","))), + self.meta.as_ref().map(|x| ("meta", x.clone())), + ] + .into_iter() + .flatten() + } +} + #[derive(Default, uniffi::Record)] pub struct UserRetrieveParams { /// Unique identifier for the user. From f9bdd0bd8230883828f6923b816c13bad0eda2aa Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 13:04:22 -0400 Subject: [PATCH 06/33] Implement create user request --- Cargo.lock | 73 ++++++++++++++++++++++++++++++++++++++++ wp_api/Cargo.toml | 1 + wp_api/src/lib.rs | 25 ++++++++++++++ wp_api/src/users.rs | 41 ++++++++-------------- wp_cli/src/main.rs | 21 ++++++++++-- wp_networking/src/lib.rs | 15 ++++++--- 6 files changed, 142 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4afbde41..e0c932a6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,72 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "dissimilar" version = "1.0.7" @@ -592,6 +658,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1919,6 +1991,7 @@ dependencies = [ name = "wp_api" version = "0.1.0" dependencies = [ + "derive_builder", "http 1.1.0", "parse_link_header", "serde", diff --git a/wp_api/Cargo.toml b/wp_api/Cargo.toml index 1e54a0e2e..06ee836ea 100644 --- a/wp_api/Cargo.toml +++ b/wp_api/Cargo.toml @@ -8,6 +8,7 @@ crate-type = ["lib", "cdylib", "staticlib"] name = "wp_api" [dependencies] +derive_builder = "0.20" http = { workspace = true } url = "2.5" parse_link_header = "0.3" diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index f45d38a2c..ac6ff9a66 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -49,6 +49,7 @@ impl WPApiHelper { method: RequestMethod::GET, url: Url::parse(url.as_str()).unwrap().into(), header_map: Some(header_map), + body: None, } } @@ -76,6 +77,7 @@ impl WPApiHelper { method: RequestMethod::GET, url: url.into(), header_map: Some(header_map), + body: None, } } @@ -105,6 +107,7 @@ impl WPApiHelper { method: RequestMethod::GET, url: url.into(), header_map: Some(header_map), + body: None, } } @@ -134,6 +137,27 @@ impl WPApiHelper { method: RequestMethod::GET, url: url.into(), header_map: Some(header_map), + body: None, + } + } + + pub fn user_create_request(&self, params: UserCreateParams) -> WPNetworkRequest { + let url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); + + let mut header_map = HashMap::new(); + + match &self.authentication { + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".into(), format!("Basic {}", token)); + } + WPAuthentication::None => (), + } + + WPNetworkRequest { + method: RequestMethod::POST, + url: url.into(), + header_map: Some(header_map), + body: serde_json::to_vec(¶ms).ok(), } } } @@ -190,6 +214,7 @@ pub struct WPNetworkRequest { // It could be something similar to `reqwest`'s [`header`](https://docs.rs/reqwest/latest/reqwest/header/index.html) // module. pub header_map: Option>, + pub body: Option>, } #[derive(uniffi::Record)] diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 9e03a6159..2c10b3ea1 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,11 +1,12 @@ use std::fmt::Display; +use derive_builder::Builder; use serde::{Deserialize, Serialize}; use wp_derive::WPContextual; // TODO: Should be in a centralized mod // TODO: Need a better name -#[derive(uniffi::Enum)] +#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] pub enum WPApiOrderParam { Asc, Desc, @@ -31,7 +32,7 @@ impl Display for WPApiOrderParam { } // TODO: Need a better name? -#[derive(uniffi::Enum)] +#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] pub enum UserListParamOrderBy { Id, Include, @@ -130,7 +131,7 @@ impl UserListParams { } } -#[derive(Default, uniffi::Record)] +#[derive(Builder, Serialize, uniffi::Record)] pub struct UserCreateParams { /// Login name for the user. pub username: String, @@ -139,52 +140,38 @@ pub struct UserCreateParams { /// Password for the user (never included). pub password: String, /// Display name for the user. + #[builder(default)] pub name: Option, /// First name for the user. + #[builder(default)] pub first_name: Option, /// Last name for the user. + #[builder(default)] pub last_name: Option, /// URL of the user. + #[builder(default)] pub url: Option, /// Description of the user. + #[builder(default)] pub description: Option, /// Locale for the user. /// One of: , `en_US` + #[builder(default)] pub locale: Option, /// The nickname for the user. + #[builder(default)] pub nickname: Option, /// An alphanumeric identifier for the user. + #[builder(default)] pub slug: Option, /// Roles assigned to the user. + #[builder(default)] pub roles: Vec, /// Meta fields. + #[builder(default)] pub meta: Option, } -impl UserCreateParams { - pub fn query_pairs(&self) -> impl IntoIterator { - [ - Some(("username", self.username.clone())), - Some(("email", self.email.clone())), - Some(("password", self.password.clone())), - self.name.as_ref().map(|x| ("name", x.clone())), - self.first_name.as_ref().map(|x| ("first_name", x.clone())), - self.last_name.as_ref().map(|x| ("last_name", x.clone())), - self.url.as_ref().map(|x| ("url", x.clone())), - self.description - .as_ref() - .map(|x| ("description", x.clone())), - self.locale.as_ref().map(|x| ("locale", x.clone())), - self.nickname.as_ref().map(|x| ("nickname", x.clone())), - self.slug.as_ref().map(|x| ("slug", x.clone())), - Some(("roles", self.roles.join(","))), - self.meta.as_ref().map(|x| ("meta", x.clone())), - ] - .into_iter() - .flatten() - } -} - #[derive(Default, uniffi::Record)] pub struct UserRetrieveParams { /// Unique identifier for the user. diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index d93b2ffb2..16d8d7aa8 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,6 +1,6 @@ use std::fs::read_to_string; -use wp_api::{UserRetrieveParams, WPAuthentication, WPContext}; +use wp_api::{UserCreateParamsBuilder, UserRetrieveParams, WPAuthentication, WPContext}; use wp_networking::WPNetworking; fn main() { @@ -24,7 +24,7 @@ fn main() { &wp_networking.request(user_list_request).unwrap(), ) .unwrap(); - println!("{:?}", user_list); + println!("User List: {:?}", user_list); if let Some(first_user) = user_list.first() { let user_retrieve_request = wp_networking @@ -37,4 +37,21 @@ fn main() { ) ); } + + let user_create_params = UserCreateParamsBuilder::default() + .username("t_username".to_string()) + .email("t_email@foo.com".to_string()) + .password("t_password".to_string()) + .build() + .unwrap(); + + let user_create_request = wp_networking + .api_helper + .user_create_request(user_create_params); + let user_create_response = wp_networking.request(user_create_request).unwrap(); + + println!( + "Created User: {:?}", + wp_api::parse_user_retrieve_response_with_edit_context(&user_create_response) + ); } diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index 364e860d2..052793bf8 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code, unused_variables)] -use http::HeaderMap; +use http::{header::CONTENT_TYPE, HeaderMap, HeaderValue}; use reqwest::blocking::Client; use wp_api::{ PostListParams, PostListResponse, WPApiError, WPApiHelper, WPAuthentication, WPNetworkRequest, @@ -24,12 +24,17 @@ impl WPNetworking { &self, wp_request: WPNetworkRequest, ) -> Result { - let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); - let response = self + let mut request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); + request_headers.append(CONTENT_TYPE, HeaderValue::from_static("application/json")); + + let mut request = self .client .request(request_method(wp_request.method), wp_request.url) - .headers(request_headers) - .send()?; + .headers(request_headers); + if let Some(body) = wp_request.body { + request = request.body(body); + } + let response = request.send()?; Ok(wp_network_response(response)) } From 4c9046c1d8b30f1c8bba20e20be6afc33dad4a56 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 13:49:48 -0400 Subject: [PATCH 07/33] Implement user_update_request --- wp_api/src/lib.rs | 23 ++++++++++++++++ wp_api/src/users.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++ wp_cli/src/main.rs | 34 ++++++++++++++++++++---- 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index ac6ff9a66..2b64b6434 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -160,6 +160,29 @@ impl WPApiHelper { body: serde_json::to_vec(¶ms).ok(), } } + + pub fn user_update_request(&self, params: UserUpdateParams) -> WPNetworkRequest { + let url = self + .site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap(); + + let mut header_map = HashMap::new(); + + match &self.authentication { + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".into(), format!("Basic {}", token)); + } + WPAuthentication::None => (), + } + + WPNetworkRequest { + method: RequestMethod::POST, + url: url.into(), + header_map: Some(header_map), + body: serde_json::to_vec(¶ms).ok(), + } + } } #[derive(Debug, Clone, uniffi::Enum)] diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 2c10b3ea1..bfd8ea73b 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -141,34 +141,99 @@ pub struct UserCreateParams { pub password: String, /// Display name for the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, /// First name for the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub first_name: Option, /// Last name for the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub last_name: Option, /// URL of the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, /// Description of the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, /// Locale for the user. /// One of: , `en_US` #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub locale: Option, /// The nickname for the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub nickname: Option, /// An alphanumeric identifier for the user. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub slug: Option, /// Roles assigned to the user. #[builder(default)] + #[serde(skip_serializing_if = "Vec::is_empty")] pub roles: Vec, /// Meta fields. #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub meta: Option, +} + +#[derive(Builder, Serialize, uniffi::Record)] +pub struct UserUpdateParams { + /// Unique identifier for the user. + pub id: u32, + /// Display name for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// First name for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub first_name: Option, + /// Last name for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub last_name: Option, + /// The email address for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub email: Option, + /// URL of the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, + /// Description of the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Locale for the user. + /// One of: , `en_US` + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub locale: Option, + /// The nickname for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub nickname: Option, + /// An alphanumeric identifier for the user. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub slug: Option, + /// Roles assigned to the user. + #[builder(default)] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub roles: Vec, + /// Password for the user (never included). + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub password: Option, + /// Meta fields. + #[builder(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub meta: Option, } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 16d8d7aa8..7de7914b0 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,6 +1,9 @@ use std::fs::read_to_string; -use wp_api::{UserCreateParamsBuilder, UserRetrieveParams, WPAuthentication, WPContext}; +use wp_api::{ + UserCreateParamsBuilder, UserRetrieveParams, UserUpdateParamsBuilder, WPAuthentication, + WPContext, +}; use wp_networking::WPNetworking; fn main() { @@ -39,8 +42,8 @@ fn main() { } let user_create_params = UserCreateParamsBuilder::default() - .username("t_username".to_string()) - .email("t_email@foo.com".to_string()) + .username("t_username4".to_string()) + .email("t_email4@foo.com".to_string()) .password("t_password".to_string()) .build() .unwrap(); @@ -49,9 +52,30 @@ fn main() { .api_helper .user_create_request(user_create_params); let user_create_response = wp_networking.request(user_create_request).unwrap(); + let created_user = + wp_api::parse_user_retrieve_response_with_edit_context(&user_create_response); println!( - "Created User: {:?}", - wp_api::parse_user_retrieve_response_with_edit_context(&user_create_response) + "Create user response: {:?}", + std::str::from_utf8(&user_create_response.body) ); + println!("Created User: {:?}", created_user); + + let user_update_params = UserUpdateParamsBuilder::default() + .id(created_user.unwrap().unwrap().id) + .email(Some("t_email44@foo.com".to_string())) + .build() + .unwrap(); + let user_update_request = wp_networking + .api_helper + .user_update_request(user_update_params); + let user_update_response = wp_networking.request(user_update_request).unwrap(); + let updated_user = + wp_api::parse_user_retrieve_response_with_edit_context(&user_update_response); + + println!( + "Update user response: {:?}", + std::str::from_utf8(&user_update_response.body) + ); + println!("Updated User: {:?}", updated_user); } From 884faeab5fa5b1d73f616d4daa859c01ff7418c4 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 19:03:28 -0400 Subject: [PATCH 08/33] Implement user_delete_request --- wp_api/src/lib.rs | 25 ++++++++++++++++++++++++ wp_api/src/users.rs | 22 +++++++++++++++++++++ wp_cli/src/main.rs | 47 +++++++++++++++++++++++++++++---------------- 3 files changed, 77 insertions(+), 17 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 2b64b6434..fead28cf3 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -183,6 +183,31 @@ impl WPApiHelper { body: serde_json::to_vec(¶ms).ok(), } } + + pub fn user_delete_request(&self, params: UserDeleteParams) -> WPNetworkRequest { + let mut url = self + .site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap(); + + let mut header_map = HashMap::new(); + + match &self.authentication { + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".into(), format!("Basic {}", token)); + } + WPAuthentication::None => (), + } + + url.query_pairs_mut().extend_pairs(params.query_pairs()); + + WPNetworkRequest { + method: RequestMethod::DELETE, + url: url.into(), + header_map: Some(header_map), + body: None, + } + } } #[derive(Debug, Clone, uniffi::Enum)] diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index bfd8ea73b..1e558b8da 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -243,6 +243,28 @@ pub struct UserRetrieveParams { pub id: u32, } +#[derive(Default, uniffi::Record)] +pub struct UserDeleteParams { + /// Unique identifier for the user. + pub id: u32, + /// Reassign the deleted user's posts and links to this user ID. + pub reassign: u32, +} + +impl UserDeleteParams { + pub fn query_pairs(&self) -> impl IntoIterator { + [ + ("reassign", self.reassign.to_string()), + // From the [documentation](https://developer.wordpress.org/rest-api/reference/users/#delete-a-user): + // > Required to be true, as users do not support trashing. + // Since this argument always has to be `true`, we don't include it in the parameter + // fields + ("force", true.to_string()), + ] + .into_iter() + } +} + #[derive(Debug, Serialize, Deserialize, uniffi::Record, WPContextual)] pub struct SparseUser { #[WPContext(edit, embed, view)] diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 7de7914b0..044ae7332 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,8 +1,8 @@ use std::fs::read_to_string; use wp_api::{ - UserCreateParamsBuilder, UserRetrieveParams, UserUpdateParamsBuilder, WPAuthentication, - WPContext, + UserCreateParamsBuilder, UserDeleteParams, UserRetrieveParams, UserUpdateParamsBuilder, + WPAuthentication, WPContext, }; use wp_networking::WPNetworking; @@ -29,21 +29,20 @@ fn main() { .unwrap(); println!("User List: {:?}", user_list); - if let Some(first_user) = user_list.first() { - let user_retrieve_request = wp_networking - .api_helper - .user_retrieve_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); - println!( - "{:?}", - wp_api::parse_user_retrieve_response_with_embed_context( - &wp_networking.request(user_retrieve_request).unwrap() - ) - ); - } + let first_user = user_list.first().unwrap(); + let user_retrieve_request = wp_networking + .api_helper + .user_retrieve_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); + println!( + "{:?}", + wp_api::parse_user_retrieve_response_with_embed_context( + &wp_networking.request(user_retrieve_request).unwrap() + ) + ); let user_create_params = UserCreateParamsBuilder::default() - .username("t_username4".to_string()) - .email("t_email4@foo.com".to_string()) + .username("t_username".to_string()) + .email("t_email@foo.com".to_string()) .password("t_password".to_string()) .build() .unwrap(); @@ -61,9 +60,10 @@ fn main() { ); println!("Created User: {:?}", created_user); + let created_user = created_user.unwrap().unwrap(); let user_update_params = UserUpdateParamsBuilder::default() - .id(created_user.unwrap().unwrap().id) - .email(Some("t_email44@foo.com".to_string())) + .id(created_user.id) + .email(Some("t_email_updated@foo.com".to_string())) .build() .unwrap(); let user_update_request = wp_networking @@ -78,4 +78,17 @@ fn main() { std::str::from_utf8(&user_update_response.body) ); println!("Updated User: {:?}", updated_user); + + let user_delete_params = UserDeleteParams { + id: created_user.id, + reassign: first_user.id, + }; + let user_delete_request = wp_networking + .api_helper + .user_delete_request(user_delete_params); + let user_delete_response = wp_networking.request(user_delete_request).unwrap(); + println!( + "Delete user response: {:?}", + std::str::from_utf8(&user_delete_response.body) + ); } From 61f962cbc4f34369e456900f115216f9e7aebb74 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 19:21:43 -0400 Subject: [PATCH 09/33] Add a header_map helper to WPApiHelper --- wp_api/src/lib.rs | 87 +++++++++-------------------------------------- 1 file changed, 17 insertions(+), 70 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index fead28cf3..4a4fbd80e 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -36,19 +36,10 @@ impl WPApiHelper { } pub fn raw_request(&self, url: String) -> WPNetworkRequest { - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - WPNetworkRequest { method: RequestMethod::GET, url: Url::parse(url.as_str()).unwrap().into(), - header_map: Some(header_map), + header_map: self.header_map(), body: None, } } @@ -59,15 +50,6 @@ impl WPApiHelper { .join("/wp-json/wp/v2/posts?context=edit") .unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - url.query_pairs_mut() .append_pair("page", params.page.to_string().as_str()); url.query_pairs_mut() @@ -76,7 +58,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::GET, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: None, } } @@ -88,15 +70,6 @@ impl WPApiHelper { ) -> WPNetworkRequest { let mut url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - url.query_pairs_mut() .append_pair("context", &context.to_string()); if let Some(params) = params { @@ -106,7 +79,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::GET, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: None, } } @@ -121,22 +94,13 @@ impl WPApiHelper { .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) .unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - url.query_pairs_mut() .append_pair("context", &context.to_string()); WPNetworkRequest { method: RequestMethod::GET, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: None, } } @@ -144,19 +108,10 @@ impl WPApiHelper { pub fn user_create_request(&self, params: UserCreateParams) -> WPNetworkRequest { let url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - WPNetworkRequest { method: RequestMethod::POST, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: serde_json::to_vec(¶ms).ok(), } } @@ -167,19 +122,10 @@ impl WPApiHelper { .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) .unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - WPNetworkRequest { method: RequestMethod::POST, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: serde_json::to_vec(¶ms).ok(), } } @@ -190,24 +136,25 @@ impl WPApiHelper { .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) .unwrap(); - let mut header_map = HashMap::new(); - - match &self.authentication { - WPAuthentication::AuthorizationHeader { token } => { - header_map.insert("Authorization".into(), format!("Basic {}", token)); - } - WPAuthentication::None => (), - } - url.query_pairs_mut().extend_pairs(params.query_pairs()); WPNetworkRequest { method: RequestMethod::DELETE, url: url.into(), - header_map: Some(header_map), + header_map: self.header_map(), body: None, } } + + fn header_map(&self) -> Option> { + match &self.authentication { + WPAuthentication::None => None, + WPAuthentication::AuthorizationHeader { token } => Some(HashMap::from([( + "Authorization".into(), + format!("Basic {}", token), + )])), + } + } } #[derive(Debug, Clone, uniffi::Enum)] From 3e50d00ee3ed8bb4da9d45114a81b1319b301152 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Apr 2024 19:41:38 -0400 Subject: [PATCH 10/33] Implements UsersEndpoint --- wp_api/src/lib.rs | 42 ++++++------------------------------------ wp_api/src/users.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 4a4fbd80e..a7e71a74a 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -68,17 +68,9 @@ impl WPApiHelper { context: WPContext, params: Option, ) -> WPNetworkRequest { - let mut url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); - - url.query_pairs_mut() - .append_pair("context", &context.to_string()); - if let Some(params) = params { - url.query_pairs_mut().extend_pairs(params.query_pairs()); - } - WPNetworkRequest { method: RequestMethod::GET, - url: url.into(), + url: UsersEndpoint::list_users(&self.site_url, context, params.as_ref()).into(), header_map: self.header_map(), body: None, } @@ -89,58 +81,36 @@ impl WPApiHelper { context: WPContext, params: UserRetrieveParams, ) -> WPNetworkRequest { - let mut url = self - .site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) - .unwrap(); - - url.query_pairs_mut() - .append_pair("context", &context.to_string()); - WPNetworkRequest { method: RequestMethod::GET, - url: url.into(), + url: UsersEndpoint::retrieve_user(&self.site_url, context, ¶ms).into(), header_map: self.header_map(), body: None, } } pub fn user_create_request(&self, params: UserCreateParams) -> WPNetworkRequest { - let url = self.site_url.join("/wp-json/wp/v2/users").unwrap(); - WPNetworkRequest { method: RequestMethod::POST, - url: url.into(), + url: UsersEndpoint::create_user(&self.site_url).into(), header_map: self.header_map(), body: serde_json::to_vec(¶ms).ok(), } } pub fn user_update_request(&self, params: UserUpdateParams) -> WPNetworkRequest { - let url = self - .site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) - .unwrap(); - WPNetworkRequest { method: RequestMethod::POST, - url: url.into(), + url: UsersEndpoint::update_user(&self.site_url, ¶ms).into(), header_map: self.header_map(), body: serde_json::to_vec(¶ms).ok(), } } pub fn user_delete_request(&self, params: UserDeleteParams) -> WPNetworkRequest { - let mut url = self - .site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) - .unwrap(); - - url.query_pairs_mut().extend_pairs(params.query_pairs()); - WPNetworkRequest { method: RequestMethod::DELETE, - url: url.into(), + url: UsersEndpoint::delete_user(&self.site_url, ¶ms).into(), header_map: self.header_map(), body: None, } @@ -157,7 +127,7 @@ impl WPApiHelper { } } -#[derive(Debug, Clone, uniffi::Enum)] +#[derive(Debug, Clone, Copy, uniffi::Enum)] pub enum WPContext { Edit, Embed, diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 1e558b8da..cf58a0bfa 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -2,8 +2,52 @@ use std::fmt::Display; use derive_builder::Builder; use serde::{Deserialize, Serialize}; +use url::Url; use wp_derive::WPContextual; +use crate::WPContext; + +pub struct UsersEndpoint {} + +impl UsersEndpoint { + pub fn list_users(site_url: &Url, context: WPContext, params: Option<&UserListParams>) -> Url { + let mut url = site_url.join("/wp-json/wp/v2/users").unwrap(); + url.query_pairs_mut() + .append_pair("context", &context.to_string()); + if let Some(params) = params { + url.query_pairs_mut().extend_pairs(params.query_pairs()); + } + url + } + + pub fn retrieve_user(site_url: &Url, context: WPContext, params: &UserRetrieveParams) -> Url { + let mut url = site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap(); + url.query_pairs_mut() + .append_pair("context", &context.to_string()); + url + } + + pub fn create_user(site_url: &Url) -> Url { + site_url.join("/wp-json/wp/v2/users").unwrap() + } + + pub fn update_user(site_url: &Url, params: &UserUpdateParams) -> Url { + site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap() + } + + pub fn delete_user(site_url: &Url, params: &UserDeleteParams) -> Url { + let mut url = site_url + .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .unwrap(); + url.query_pairs_mut().extend_pairs(params.query_pairs()); + url + } +} + // TODO: Should be in a centralized mod // TODO: Need a better name #[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] From f3d2f80042e8072f2c2bcebe150b181726011d29 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 11:16:21 -0400 Subject: [PATCH 11/33] Rename user requests to start with verb --- wp_api/src/lib.rs | 10 +++++----- wp_cli/src/main.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index a7e71a74a..1a2c8e73b 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -63,7 +63,7 @@ impl WPApiHelper { } } - pub fn user_list_request( + pub fn list_users_request( &self, context: WPContext, params: Option, @@ -76,7 +76,7 @@ impl WPApiHelper { } } - pub fn user_retrieve_request( + pub fn retrieve_user_request( &self, context: WPContext, params: UserRetrieveParams, @@ -89,7 +89,7 @@ impl WPApiHelper { } } - pub fn user_create_request(&self, params: UserCreateParams) -> WPNetworkRequest { + pub fn create_user_request(&self, params: UserCreateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::create_user(&self.site_url).into(), @@ -98,7 +98,7 @@ impl WPApiHelper { } } - pub fn user_update_request(&self, params: UserUpdateParams) -> WPNetworkRequest { + pub fn update_user_request(&self, params: UserUpdateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_user(&self.site_url, ¶ms).into(), @@ -107,7 +107,7 @@ impl WPApiHelper { } } - pub fn user_delete_request(&self, params: UserDeleteParams) -> WPNetworkRequest { + pub fn delete_user_request(&self, params: UserDeleteParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::DELETE, url: UsersEndpoint::delete_user(&self.site_url, ¶ms).into(), diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 044ae7332..7619d09d5 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -22,7 +22,7 @@ fn main() { let user_list_request = wp_networking .api_helper - .user_list_request(WPContext::Edit, None); + .list_users_request(WPContext::Edit, None); let user_list = wp_api::parse_user_list_response_with_edit_context( &wp_networking.request(user_list_request).unwrap(), ) @@ -32,7 +32,7 @@ fn main() { let first_user = user_list.first().unwrap(); let user_retrieve_request = wp_networking .api_helper - .user_retrieve_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); + .retrieve_user_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); println!( "{:?}", wp_api::parse_user_retrieve_response_with_embed_context( @@ -49,7 +49,7 @@ fn main() { let user_create_request = wp_networking .api_helper - .user_create_request(user_create_params); + .create_user_request(user_create_params); let user_create_response = wp_networking.request(user_create_request).unwrap(); let created_user = wp_api::parse_user_retrieve_response_with_edit_context(&user_create_response); @@ -68,7 +68,7 @@ fn main() { .unwrap(); let user_update_request = wp_networking .api_helper - .user_update_request(user_update_params); + .update_user_request(user_update_params); let user_update_response = wp_networking.request(user_update_request).unwrap(); let updated_user = wp_api::parse_user_retrieve_response_with_edit_context(&user_update_response); @@ -85,7 +85,7 @@ fn main() { }; let user_delete_request = wp_networking .api_helper - .user_delete_request(user_delete_params); + .delete_user_request(user_delete_params); let user_delete_response = wp_networking.request(user_delete_request).unwrap(); println!( "Delete user response: {:?}", From 40559a73b989b5211d0b79f5c89b28faadee2fe7 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 11:23:12 -0400 Subject: [PATCH 12/33] Implements retrieve current user --- wp_api/src/lib.rs | 9 +++++++++ wp_api/src/users.rs | 7 +++++++ wp_cli/src/main.rs | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 1a2c8e73b..84db537dd 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -89,6 +89,15 @@ impl WPApiHelper { } } + pub fn retrieve_current_user(&self, context: WPContext) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::GET, + url: UsersEndpoint::retrieve_current_user(&self.site_url, context).into(), + header_map: self.header_map(), + body: None, + } + } + pub fn create_user_request(&self, params: UserCreateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index cf58a0bfa..d74617ef4 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -29,6 +29,13 @@ impl UsersEndpoint { url } + pub fn retrieve_current_user(site_url: &Url, context: WPContext) -> Url { + let mut url = site_url.join("/wp-json/wp/v2/users/me").unwrap(); + url.query_pairs_mut() + .append_pair("context", &context.to_string()); + url + } + pub fn create_user(site_url: &Url) -> Url { site_url.join("/wp-json/wp/v2/users").unwrap() } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 7619d09d5..db2e87517 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -91,4 +91,16 @@ fn main() { "Delete user response: {:?}", std::str::from_utf8(&user_delete_response.body) ); + println!( + "Retrieve current user: {:?}", + wp_api::parse_user_retrieve_response_with_edit_context( + &wp_networking + .request( + wp_networking + .api_helper + .retrieve_current_user(WPContext::Edit) + ) + .unwrap() + ) + ); } From 8061a5b0c27162ba6b41351b85bd3fef9f637db9 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 11:35:08 -0400 Subject: [PATCH 13/33] Adds UserId new type --- wp_api/src/users.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index d74617ef4..152adbb47 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -236,7 +236,7 @@ pub struct UserCreateParams { #[derive(Builder, Serialize, uniffi::Record)] pub struct UserUpdateParams { /// Unique identifier for the user. - pub id: u32, + pub id: UserId, /// Display name for the user. #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -288,18 +288,18 @@ pub struct UserUpdateParams { pub meta: Option, } -#[derive(Default, uniffi::Record)] +#[derive(uniffi::Record)] pub struct UserRetrieveParams { /// Unique identifier for the user. - pub id: u32, + pub id: UserId, } -#[derive(Default, uniffi::Record)] +#[derive(uniffi::Record)] pub struct UserDeleteParams { /// Unique identifier for the user. - pub id: u32, + pub id: UserId, /// Reassign the deleted user's posts and links to this user ID. - pub reassign: u32, + pub reassign: UserId, } impl UserDeleteParams { @@ -316,10 +316,20 @@ impl UserDeleteParams { } } +uniffi::custom_newtype!(UserId, i32); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct UserId(i32); + +impl std::fmt::Display for UserId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + #[derive(Debug, Serialize, Deserialize, uniffi::Record, WPContextual)] pub struct SparseUser { #[WPContext(edit, embed, view)] - pub id: Option, + pub id: Option, #[WPContext(edit)] pub username: Option, #[WPContext(edit, embed, view)] From 62cf189d2cf80b7f38ce3d57659a64c2249e0c7a Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 11:41:24 -0400 Subject: [PATCH 14/33] Use UserId for retrieve, update & delete user requests --- wp_api/src/lib.rs | 24 ++++++++++++++---------- wp_api/src/users.rs | 22 ++++++---------------- wp_cli/src/main.rs | 11 ++++------- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 84db537dd..6431f3010 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -76,14 +76,10 @@ impl WPApiHelper { } } - pub fn retrieve_user_request( - &self, - context: WPContext, - params: UserRetrieveParams, - ) -> WPNetworkRequest { + pub fn retrieve_user_request(&self, user_id: UserId, context: WPContext) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::GET, - url: UsersEndpoint::retrieve_user(&self.site_url, context, ¶ms).into(), + url: UsersEndpoint::retrieve_user(&self.site_url, user_id, context).into(), header_map: self.header_map(), body: None, } @@ -107,19 +103,27 @@ impl WPApiHelper { } } - pub fn update_user_request(&self, params: UserUpdateParams) -> WPNetworkRequest { + pub fn update_user_request( + &self, + user_id: UserId, + params: UserUpdateParams, + ) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, - url: UsersEndpoint::update_user(&self.site_url, ¶ms).into(), + url: UsersEndpoint::update_user(&self.site_url, user_id, ¶ms).into(), header_map: self.header_map(), body: serde_json::to_vec(¶ms).ok(), } } - pub fn delete_user_request(&self, params: UserDeleteParams) -> WPNetworkRequest { + pub fn delete_user_request( + &self, + user_id: UserId, + params: UserDeleteParams, + ) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::DELETE, - url: UsersEndpoint::delete_user(&self.site_url, ¶ms).into(), + url: UsersEndpoint::delete_user(&self.site_url, user_id, ¶ms).into(), header_map: self.header_map(), body: None, } diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 152adbb47..ce4f24391 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -20,9 +20,9 @@ impl UsersEndpoint { url } - pub fn retrieve_user(site_url: &Url, context: WPContext, params: &UserRetrieveParams) -> Url { + pub fn retrieve_user(site_url: &Url, user_id: UserId, context: WPContext) -> Url { let mut url = site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .join(format!("/wp-json/wp/v2/users/{}", user_id).as_str()) .unwrap(); url.query_pairs_mut() .append_pair("context", &context.to_string()); @@ -40,15 +40,15 @@ impl UsersEndpoint { site_url.join("/wp-json/wp/v2/users").unwrap() } - pub fn update_user(site_url: &Url, params: &UserUpdateParams) -> Url { + pub fn update_user(site_url: &Url, user_id: UserId, params: &UserUpdateParams) -> Url { site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .join(format!("/wp-json/wp/v2/users/{}", user_id).as_str()) .unwrap() } - pub fn delete_user(site_url: &Url, params: &UserDeleteParams) -> Url { + pub fn delete_user(site_url: &Url, user_id: UserId, params: &UserDeleteParams) -> Url { let mut url = site_url - .join(format!("/wp-json/wp/v2/users/{}", params.id).as_str()) + .join(format!("/wp-json/wp/v2/users/{}", user_id).as_str()) .unwrap(); url.query_pairs_mut().extend_pairs(params.query_pairs()); url @@ -235,8 +235,6 @@ pub struct UserCreateParams { #[derive(Builder, Serialize, uniffi::Record)] pub struct UserUpdateParams { - /// Unique identifier for the user. - pub id: UserId, /// Display name for the user. #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -288,16 +286,8 @@ pub struct UserUpdateParams { pub meta: Option, } -#[derive(uniffi::Record)] -pub struct UserRetrieveParams { - /// Unique identifier for the user. - pub id: UserId, -} - #[derive(uniffi::Record)] pub struct UserDeleteParams { - /// Unique identifier for the user. - pub id: UserId, /// Reassign the deleted user's posts and links to this user ID. pub reassign: UserId, } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index db2e87517..ce84e2c60 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -1,8 +1,7 @@ use std::fs::read_to_string; use wp_api::{ - UserCreateParamsBuilder, UserDeleteParams, UserRetrieveParams, UserUpdateParamsBuilder, - WPAuthentication, WPContext, + UserCreateParamsBuilder, UserDeleteParams, UserUpdateParamsBuilder, WPAuthentication, WPContext, }; use wp_networking::WPNetworking; @@ -32,7 +31,7 @@ fn main() { let first_user = user_list.first().unwrap(); let user_retrieve_request = wp_networking .api_helper - .retrieve_user_request(WPContext::Embed, UserRetrieveParams { id: first_user.id }); + .retrieve_user_request(first_user.id, WPContext::Embed); println!( "{:?}", wp_api::parse_user_retrieve_response_with_embed_context( @@ -62,13 +61,12 @@ fn main() { let created_user = created_user.unwrap().unwrap(); let user_update_params = UserUpdateParamsBuilder::default() - .id(created_user.id) .email(Some("t_email_updated@foo.com".to_string())) .build() .unwrap(); let user_update_request = wp_networking .api_helper - .update_user_request(user_update_params); + .update_user_request(created_user.id, user_update_params); let user_update_response = wp_networking.request(user_update_request).unwrap(); let updated_user = wp_api::parse_user_retrieve_response_with_edit_context(&user_update_response); @@ -80,12 +78,11 @@ fn main() { println!("Updated User: {:?}", updated_user); let user_delete_params = UserDeleteParams { - id: created_user.id, reassign: first_user.id, }; let user_delete_request = wp_networking .api_helper - .delete_user_request(user_delete_params); + .delete_user_request(created_user.id, user_delete_params); let user_delete_response = wp_networking.request(user_delete_request).unwrap(); println!( "Delete user response: {:?}", From c6048083c368f641504155c71746ac27506df410 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 11:59:31 -0400 Subject: [PATCH 15/33] Implements update & delete current user --- wp_api/src/lib.rs | 18 ++++++++++++++++++ wp_api/src/users.rs | 10 ++++++++++ wp_cli/src/main.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 6431f3010..312287325 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -116,6 +116,15 @@ impl WPApiHelper { } } + pub fn update_current_user_request(&self, params: UserUpdateParams) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::POST, + url: UsersEndpoint::update_current_user(&self.site_url).into(), + header_map: self.header_map(), + body: serde_json::to_vec(¶ms).ok(), + } + } + pub fn delete_user_request( &self, user_id: UserId, @@ -129,6 +138,15 @@ impl WPApiHelper { } } + pub fn delete_current_user_request(&self, params: UserDeleteParams) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::DELETE, + url: UsersEndpoint::delete_current_user(&self.site_url, ¶ms).into(), + header_map: self.header_map(), + body: None, + } + } + fn header_map(&self) -> Option> { match &self.authentication { WPAuthentication::None => None, diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index ce4f24391..e9a485733 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -46,6 +46,10 @@ impl UsersEndpoint { .unwrap() } + pub fn update_current_user(site_url: &Url) -> Url { + site_url.join("/wp-json/wp/v2/users/me").unwrap() + } + pub fn delete_user(site_url: &Url, user_id: UserId, params: &UserDeleteParams) -> Url { let mut url = site_url .join(format!("/wp-json/wp/v2/users/{}", user_id).as_str()) @@ -53,6 +57,12 @@ impl UsersEndpoint { url.query_pairs_mut().extend_pairs(params.query_pairs()); url } + + pub fn delete_current_user(site_url: &Url, params: &UserDeleteParams) -> Url { + let mut url = site_url.join("/wp-json/wp/v2/users/me").unwrap(); + url.query_pairs_mut().extend_pairs(params.query_pairs()); + url + } } // TODO: Should be in a centralized mod diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index ce84e2c60..8b569702b 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -100,4 +100,37 @@ fn main() { .unwrap() ) ); + + let update_current_user_params = UserUpdateParamsBuilder::default() + .description(Some("updated_description".to_string())) + .build() + .unwrap(); + let update_current_user_request = wp_networking + .api_helper + .update_current_user_request(update_current_user_params); + let update_current_user_response = wp_networking.request(update_current_user_request).unwrap(); + let updated_current_user = + wp_api::parse_user_retrieve_response_with_edit_context(&update_current_user_response); + println!( + "Update current user response: {:?}", + std::str::from_utf8(&update_current_user_response.body) + ); + println!("Updated Current User: {:?}", updated_current_user); + + // Remember to use a temporary user to test this + // println!( + // "Delete current user: {:?}", + // std::str::from_utf8( + // &wp_networking + // .request( + // wp_networking + // .api_helper + // .delete_current_user_request(UserDeleteParams { + // reassign: first_user.id + // }) + // ) + // .unwrap() + // .body + // ) + // ); } From 798770e3778cb6f8ec00a4648dbcc34ad68d3c34 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 12:43:16 -0400 Subject: [PATCH 16/33] Update capabilities & avatar_urls types for SparseUser --- wp_api/src/users.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index e9a485733..a606c077a 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{collections::HashMap, fmt::Display}; use derive_builder::Builder; use serde::{Deserialize, Serialize}; @@ -357,20 +357,10 @@ pub struct SparseUser { #[WPContext(edit)] pub roles: Option>, #[WPContext(edit)] - pub capabilities: Option, + pub capabilities: Option>, #[WPContext(edit)] - pub extra_capabilities: Option, + pub extra_capabilities: Option>, #[WPContext(edit, embed, view)] - pub avatar_urls: Option, - #[WPContext(edit, view)] - pub meta: Option, + pub avatar_urls: Option>, + // meta field is omitted for now: https://github.com/Automattic/wordpress-rs/issues/57 } - -#[derive(Debug, Serialize, Deserialize, uniffi::Record)] -pub struct UserCapabilities {} -#[derive(Debug, Serialize, Deserialize, uniffi::Record)] -pub struct UserExtraCapabilities {} -#[derive(Debug, Serialize, Deserialize, uniffi::Record)] -pub struct UserAvatarUrls {} -#[derive(Debug, Serialize, Deserialize, uniffi::Record)] -pub struct UserMeta {} From 9f6da9c3bb52be2b63948d297676b9e1da0df529 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 12:51:02 -0400 Subject: [PATCH 17/33] Move parsing code for users to users module --- wp_api/src/lib.rs | 92 -------------------------------------------- wp_api/src/users.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++- wp_cli/src/main.rs | 12 +++--- 3 files changed, 98 insertions(+), 99 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 312287325..bdc185bb7 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -6,7 +6,6 @@ pub use api_error::*; pub use login::*; pub use pages::*; pub use posts::*; -use serde::Deserialize; pub use url::*; pub use users::*; @@ -280,97 +279,6 @@ pub fn parse_post_list_response( }) } -pub fn parse_user_list_response<'de, T: Deserialize<'de>>( - response: &'de WPNetworkResponse, -) -> Result, WPApiError> { - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } - let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { - status_code: response.status_code, - }); - } - - let user_list: Vec = - serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { - reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), - })?; - - Ok(user_list) -} - -#[uniffi::export] -pub fn parse_user_list_response_with_edit_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_list_response(response) -} - -#[uniffi::export] -pub fn parse_user_list_response_with_embed_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_list_response(response) -} - -#[uniffi::export] -pub fn parse_user_list_response_with_view_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_list_response(response) -} - -pub fn parse_user_retrieve_response<'de, T: Deserialize<'de> + std::fmt::Debug>( - response: &'de WPNetworkResponse, -) -> Result { - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } - let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { - status_code: response.status_code, - }); - } - - let user: T = - serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { - reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), - })?; - Ok(user) -} - -#[uniffi::export] -pub fn parse_user_retrieve_response_with_edit_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_retrieve_response(response) -} - -#[uniffi::export] -pub fn parse_user_retrieve_response_with_embed_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_retrieve_response(response) -} - -#[uniffi::export] -pub fn parse_user_retrieve_response_with_view_context( - response: &WPNetworkResponse, -) -> Result, WPApiError> { - parse_user_retrieve_response(response) -} - #[uniffi::export] pub fn parse_api_details_response(response: WPNetworkResponse) -> Result { let api_details = diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index a606c077a..38e4b98c6 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -5,7 +5,98 @@ use serde::{Deserialize, Serialize}; use url::Url; use wp_derive::WPContextual; -use crate::WPContext; +use crate::{ClientErrorType, WPApiError, WPContext, WPNetworkResponse}; + +#[uniffi::export] +pub fn parse_list_users_response_with_edit_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_list_users_response(response) +} + +#[uniffi::export] +pub fn parse_list_users_response_with_embed_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_list_users_response(response) +} + +#[uniffi::export] +pub fn parse_list_users_response_with_view_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_list_users_response(response) +} + +#[uniffi::export] +pub fn parse_retrieve_user_response_with_edit_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_retrieve_user_response(response) +} + +#[uniffi::export] +pub fn parse_retrieve_user_response_with_embed_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_retrieve_user_response(response) +} + +#[uniffi::export] +pub fn parse_retrieve_user_response_with_view_context( + response: &WPNetworkResponse, +) -> Result, WPApiError> { + parse_retrieve_user_response(response) +} + +pub fn parse_list_users_response<'de, T: Deserialize<'de>>( + response: &'de WPNetworkResponse, +) -> Result, WPApiError> { + if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { + return Err(WPApiError::ClientError { + error_type: client_error_type, + status_code: response.status_code, + }); + } + let status = http::StatusCode::from_u16(response.status_code).unwrap(); + if status.is_server_error() { + return Err(WPApiError::ServerError { + status_code: response.status_code, + }); + } + + let user_list: Vec = + serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { + reason: err.to_string(), + response: std::str::from_utf8(&response.body).unwrap().to_string(), + })?; + + Ok(user_list) +} + +pub fn parse_retrieve_user_response<'de, T: Deserialize<'de> + std::fmt::Debug>( + response: &'de WPNetworkResponse, +) -> Result { + if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { + return Err(WPApiError::ClientError { + error_type: client_error_type, + status_code: response.status_code, + }); + } + let status = http::StatusCode::from_u16(response.status_code).unwrap(); + if status.is_server_error() { + return Err(WPApiError::ServerError { + status_code: response.status_code, + }); + } + + let user: T = + serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { + reason: err.to_string(), + response: std::str::from_utf8(&response.body).unwrap().to_string(), + })?; + Ok(user) +} pub struct UsersEndpoint {} diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 8b569702b..7b7e0f710 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -22,7 +22,7 @@ fn main() { let user_list_request = wp_networking .api_helper .list_users_request(WPContext::Edit, None); - let user_list = wp_api::parse_user_list_response_with_edit_context( + let user_list = wp_api::parse_list_users_response_with_edit_context( &wp_networking.request(user_list_request).unwrap(), ) .unwrap(); @@ -34,7 +34,7 @@ fn main() { .retrieve_user_request(first_user.id, WPContext::Embed); println!( "{:?}", - wp_api::parse_user_retrieve_response_with_embed_context( + wp_api::parse_retrieve_user_response_with_embed_context( &wp_networking.request(user_retrieve_request).unwrap() ) ); @@ -51,7 +51,7 @@ fn main() { .create_user_request(user_create_params); let user_create_response = wp_networking.request(user_create_request).unwrap(); let created_user = - wp_api::parse_user_retrieve_response_with_edit_context(&user_create_response); + wp_api::parse_retrieve_user_response_with_edit_context(&user_create_response); println!( "Create user response: {:?}", @@ -69,7 +69,7 @@ fn main() { .update_user_request(created_user.id, user_update_params); let user_update_response = wp_networking.request(user_update_request).unwrap(); let updated_user = - wp_api::parse_user_retrieve_response_with_edit_context(&user_update_response); + wp_api::parse_retrieve_user_response_with_edit_context(&user_update_response); println!( "Update user response: {:?}", @@ -90,7 +90,7 @@ fn main() { ); println!( "Retrieve current user: {:?}", - wp_api::parse_user_retrieve_response_with_edit_context( + wp_api::parse_retrieve_user_response_with_edit_context( &wp_networking .request( wp_networking @@ -110,7 +110,7 @@ fn main() { .update_current_user_request(update_current_user_params); let update_current_user_response = wp_networking.request(update_current_user_request).unwrap(); let updated_current_user = - wp_api::parse_user_retrieve_response_with_edit_context(&update_current_user_response); + wp_api::parse_retrieve_user_response_with_edit_context(&update_current_user_response); println!( "Update current user response: {:?}", std::str::from_utf8(&update_current_user_response.body) From f71b212a5c419599fe39655c4c7138387ca8e0a1 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:02:42 -0400 Subject: [PATCH 18/33] Extract generic error parsing to a helper --- wp_api/src/lib.rs | 33 +++++++++++++---------- wp_api/src/users.rs | 65 +++++++++------------------------------------ 2 files changed, 32 insertions(+), 66 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index bdc185bb7..5c6b658ab 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -247,20 +247,7 @@ impl WPNetworkResponse { pub fn parse_post_list_response( response: WPNetworkResponse, ) -> Result { - // TODO: Further parse the response body to include error message - // TODO: Lots of unwraps to get a basic setup working - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } - let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { - status_code: response.status_code, - }); - } + parse_response_for_generic_errors(&response)?; let post_list: Vec = serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { reason: err.to_string(), @@ -290,6 +277,24 @@ pub fn parse_api_details_response(response: WPNetworkResponse) -> Result Result<(), WPApiError> { + // TODO: Further parse the response body to include error message + // TODO: Lots of unwraps to get a basic setup working + if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { + return Err(WPApiError::ClientError { + error_type: client_error_type, + status_code: response.status_code, + }); + } + let status = http::StatusCode::from_u16(response.status_code).unwrap(); + if status.is_server_error() { + return Err(WPApiError::ServerError { + status_code: response.status_code, + }); + } + Ok(()) +} + // TODO: Figure out why we can't expose this method on `WPNetworkResponse` via UniFFI #[uniffi::export] pub fn get_link_header(response: &WPNetworkResponse, name: &str) -> Option { diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 38e4b98c6..d41974041 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -5,97 +5,58 @@ use serde::{Deserialize, Serialize}; use url::Url; use wp_derive::WPContextual; -use crate::{ClientErrorType, WPApiError, WPContext, WPNetworkResponse}; +use crate::{parse_response_for_generic_errors, WPApiError, WPContext, WPNetworkResponse}; #[uniffi::export] pub fn parse_list_users_response_with_edit_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_list_users_response(response) + parse_users_response(response) } #[uniffi::export] pub fn parse_list_users_response_with_embed_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_list_users_response(response) + parse_users_response(response) } #[uniffi::export] pub fn parse_list_users_response_with_view_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_list_users_response(response) + parse_users_response(response) } #[uniffi::export] pub fn parse_retrieve_user_response_with_edit_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_retrieve_user_response(response) + parse_users_response(response) } #[uniffi::export] pub fn parse_retrieve_user_response_with_embed_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_retrieve_user_response(response) + parse_users_response(response) } #[uniffi::export] pub fn parse_retrieve_user_response_with_view_context( response: &WPNetworkResponse, ) -> Result, WPApiError> { - parse_retrieve_user_response(response) + parse_users_response(response) } -pub fn parse_list_users_response<'de, T: Deserialize<'de>>( - response: &'de WPNetworkResponse, -) -> Result, WPApiError> { - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } - let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { - status_code: response.status_code, - }); - } - - let user_list: Vec = - serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { - reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), - })?; - - Ok(user_list) -} - -pub fn parse_retrieve_user_response<'de, T: Deserialize<'de> + std::fmt::Debug>( +pub fn parse_users_response<'de, T: Deserialize<'de>>( response: &'de WPNetworkResponse, ) -> Result { - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } - let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { - status_code: response.status_code, - }); - } - - let user: T = - serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { - reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), - })?; - Ok(user) + parse_response_for_generic_errors(response)?; + serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { + reason: err.to_string(), + response: std::str::from_utf8(&response.body).unwrap().to_string(), + }) } pub struct UsersEndpoint {} From a8aa1b75d833b63c1cde62e405d607f0ca9f77a7 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:06:51 -0400 Subject: [PATCH 19/33] Move WPApiParamOrder to wp_api lib.rs --- wp_api/src/lib.rs | 25 +++++++++++++++++++++++++ wp_api/src/users.rs | 42 ++++++++---------------------------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 5c6b658ab..d98e710a1 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -305,4 +305,29 @@ pub fn get_link_header(response: &WPNetworkResponse, name: &str) -> Option Self { + Self::Asc + } +} + +impl Display for WPApiParamOrder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Asc => "asc", + Self::Desc => "desc", + } + ) + } +} + uniffi::setup_scaffolding!(); diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index d41974041..fbfab9489 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -5,7 +5,9 @@ use serde::{Deserialize, Serialize}; use url::Url; use wp_derive::WPContextual; -use crate::{parse_response_for_generic_errors, WPApiError, WPContext, WPNetworkResponse}; +use crate::{ + parse_response_for_generic_errors, WPApiError, WPApiParamOrder, WPContext, WPNetworkResponse, +}; #[uniffi::export] pub fn parse_list_users_response_with_edit_context( @@ -117,36 +119,8 @@ impl UsersEndpoint { } } -// TODO: Should be in a centralized mod -// TODO: Need a better name #[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] -pub enum WPApiOrderParam { - Asc, - Desc, -} - -impl Default for WPApiOrderParam { - fn default() -> Self { - Self::Asc - } -} - -impl Display for WPApiOrderParam { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Self::Asc => "asc", - Self::Desc => "desc", - } - ) - } -} - -// TODO: Need a better name? -#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] -pub enum UserListParamOrderBy { +pub enum WPApiParamUsersOrderBy { Id, Include, Name, @@ -157,13 +131,13 @@ pub enum UserListParamOrderBy { Url, } -impl Default for UserListParamOrderBy { +impl Default for WPApiParamUsersOrderBy { fn default() -> Self { Self::Name } } -impl Display for UserListParamOrderBy { +impl Display for WPApiParamUsersOrderBy { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -202,11 +176,11 @@ pub struct UserListParams { /// Order sort attribute ascending or descending. /// Default: `asc` /// One of: `asc`, `desc` - pub order: Option, + pub order: Option, /// Sort collection by user attribute. /// Default: `name` /// One of: `id`, `include`, `name`, `registered_date`, `slug`, `include_slugs`, `email`, `url` - pub order_by: Option, + pub order_by: Option, /// Limit result set to users with one or more specific slugs. pub slug: Vec, /// Limit result set to users matching at least one specific role provided. Accepts csv list or single role. From d3fbcd10e13e4d7b20666a5a2e2d78b5e4bc401d Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:11:08 -0400 Subject: [PATCH 20/33] Replace Display trait with as_str for WPContext --- wp_api/src/lib.rs | 20 ++++++++------------ wp_api/src/users.rs | 6 +++--- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index d98e710a1..ad54db139 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -157,7 +157,7 @@ impl WPApiHelper { } } -#[derive(Debug, Clone, Copy, uniffi::Enum)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] pub enum WPContext { Edit, Embed, @@ -170,17 +170,13 @@ impl Default for WPContext { } } -impl Display for WPContext { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Self::Edit => "edit", - Self::Embed => "embed", - Self::View => "view", - } - ) +impl WPContext { + fn as_str(&self) -> &str { + match self { + Self::Edit => "edit", + Self::Embed => "embed", + Self::View => "view", + } } } diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index fbfab9489..010590f37 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -67,7 +67,7 @@ impl UsersEndpoint { pub fn list_users(site_url: &Url, context: WPContext, params: Option<&UserListParams>) -> Url { let mut url = site_url.join("/wp-json/wp/v2/users").unwrap(); url.query_pairs_mut() - .append_pair("context", &context.to_string()); + .append_pair("context", context.as_str()); if let Some(params) = params { url.query_pairs_mut().extend_pairs(params.query_pairs()); } @@ -79,14 +79,14 @@ impl UsersEndpoint { .join(format!("/wp-json/wp/v2/users/{}", user_id).as_str()) .unwrap(); url.query_pairs_mut() - .append_pair("context", &context.to_string()); + .append_pair("context", context.as_str()); url } pub fn retrieve_current_user(site_url: &Url, context: WPContext) -> Url { let mut url = site_url.join("/wp-json/wp/v2/users/me").unwrap(); url.query_pairs_mut() - .append_pair("context", &context.to_string()); + .append_pair("context", context.as_str()); url } From d9f5535ca518f98c46ee88e58a550f357e2eea5e Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:12:20 -0400 Subject: [PATCH 21/33] Rename retrieve_current_user as retrieve_current_user_request --- wp_api/src/lib.rs | 2 +- wp_cli/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index ad54db139..050e9ae03 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -84,7 +84,7 @@ impl WPApiHelper { } } - pub fn retrieve_current_user(&self, context: WPContext) -> WPNetworkRequest { + pub fn retrieve_current_user_request(&self, context: WPContext) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::GET, url: UsersEndpoint::retrieve_current_user(&self.site_url, context).into(), diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 7b7e0f710..2b3354872 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -95,7 +95,7 @@ fn main() { .request( wp_networking .api_helper - .retrieve_current_user(WPContext::Edit) + .retrieve_current_user_request(WPContext::Edit) ) .unwrap() ) From 301014e840b13f4cef4d3c462cf9de9e473480a9 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:15:22 -0400 Subject: [PATCH 22/33] Replace Display trait with as_str for WPApiParamOrder --- wp_api/src/lib.rs | 48 +++++++++++++++++++++------------------------ wp_api/src/users.rs | 4 +++- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 050e9ae03..b51cc2b61 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code, unused_variables)] -use std::{collections::HashMap, fmt::Display}; +use std::collections::HashMap; pub use api_error::*; pub use login::*; @@ -195,6 +195,27 @@ pub enum RequestMethod { HEAD, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] +pub enum WPApiParamOrder { + Asc, + Desc, +} + +impl Default for WPApiParamOrder { + fn default() -> Self { + Self::Asc + } +} + +impl WPApiParamOrder { + fn as_str(&self) -> &str { + match self { + Self::Asc => "asc", + Self::Desc => "desc", + } + } +} + #[derive(uniffi::Record)] pub struct WPNetworkRequest { pub method: RequestMethod, @@ -301,29 +322,4 @@ pub fn get_link_header(response: &WPNetworkResponse, name: &str) -> Option Self { - Self::Asc - } -} - -impl Display for WPApiParamOrder { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Self::Asc => "asc", - Self::Desc => "desc", - } - ) - } -} - uniffi::setup_scaffolding!(); diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 010590f37..5a4a927a2 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -203,7 +203,9 @@ impl UserListParams { self.exclude.as_ref().map(|x| ("exclude", x.clone())), self.include.as_ref().map(|x| ("include", x.clone())), self.offset.as_ref().map(|x| ("offset", x.to_string())), - self.order.as_ref().map(|x| ("order", x.to_string())), + self.order + .as_ref() + .map(|x| ("order", x.as_str().to_string())), self.order_by.as_ref().map(|x| ("order_by", x.to_string())), Some(("slug", self.slug.join(","))), Some(("roles", self.roles.join(","))), From 858e10fcfcbef51340a8c4918735c24c3c79c7d5 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:19:26 -0400 Subject: [PATCH 23/33] Remove unused list_posts from wp_networking --- wp_networking/src/lib.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index 052793bf8..b1d46d384 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -2,10 +2,7 @@ use http::{header::CONTENT_TYPE, HeaderMap, HeaderValue}; use reqwest::blocking::Client; -use wp_api::{ - PostListParams, PostListResponse, WPApiError, WPApiHelper, WPAuthentication, WPNetworkRequest, - WPNetworkResponse, -}; +use wp_api::{WPApiHelper, WPAuthentication, WPNetworkRequest, WPNetworkResponse}; pub struct WPNetworking { client: Client, @@ -37,23 +34,6 @@ impl WPNetworking { let response = request.send()?; Ok(wp_network_response(response)) } - - pub fn list_posts( - &self, - params: Option, - ) -> Result { - let wp_request = self - .api_helper - .post_list_request(params.unwrap_or_default()); - let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); - let response = self - .client - .request(request_method(wp_request.method), wp_request.url) - .headers(request_headers) - .send() - .unwrap(); - wp_api::parse_post_list_response(wp_network_response(response)) - } } fn request_method(method: wp_api::RequestMethod) -> http::Method { From 151ffecd5cc8e6872f49f12b88ec7559b8343c29 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 5 Apr 2024 13:56:53 -0400 Subject: [PATCH 24/33] Add body argument to WPNetworkRequest in WordPressAPI.swift --- native/swift/Sources/wordpress-api/WordPressAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/swift/Sources/wordpress-api/WordPressAPI.swift b/native/swift/Sources/wordpress-api/WordPressAPI.swift index 9b32323c8..b6042b923 100644 --- a/native/swift/Sources/wordpress-api/WordPressAPI.swift +++ b/native/swift/Sources/wordpress-api/WordPressAPI.swift @@ -160,7 +160,7 @@ extension RequestMethod { extension WpNetworkRequest { init(method: RequestMethod, url: URL, headerMap: [String: String]? = nil) { - self.init(method: method, url: url.absoluteString, headerMap: headerMap) + self.init(method: method, url: url.absoluteString, headerMap: headerMap, body: nil) } } From 49ffd28256f9f0b1a61f250a9b04f2709a1d40bf Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 9 Apr 2024 11:13:14 -0400 Subject: [PATCH 25/33] Add application/json header to WPNetworkRequest for post requests --- wp_api/src/lib.rs | 13 +++++++++++-- wp_networking/src/lib.rs | 5 ++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index b51cc2b61..5d24d98f4 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -97,7 +97,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::create_user(&self.site_url).into(), - header_map: self.header_map(), + header_map: Some(self.header_map_for_post_request()), body: serde_json::to_vec(¶ms).ok(), } } @@ -110,7 +110,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_user(&self.site_url, user_id, ¶ms).into(), - header_map: self.header_map(), + header_map: Some(self.header_map_for_post_request()), body: serde_json::to_vec(¶ms).ok(), } } @@ -155,6 +155,15 @@ impl WPApiHelper { )])), } } + + fn header_map_for_post_request(&self) -> HashMap { + let mut header_map = self.header_map().unwrap_or_default(); + header_map.insert( + http::header::CONTENT_TYPE.to_string(), + "application/json".to_string(), + ); + header_map + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index b1d46d384..6bcf51bf3 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code, unused_variables)] -use http::{header::CONTENT_TYPE, HeaderMap, HeaderValue}; +use http::HeaderMap; use reqwest::blocking::Client; use wp_api::{WPApiHelper, WPAuthentication, WPNetworkRequest, WPNetworkResponse}; @@ -21,8 +21,7 @@ impl WPNetworking { &self, wp_request: WPNetworkRequest, ) -> Result { - let mut request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); - request_headers.append(CONTENT_TYPE, HeaderValue::from_static("application/json")); + let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); let mut request = self .client From c46d3d8c874ab32a1cd3174920f49668e63592da Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 9 Apr 2024 11:41:18 -0400 Subject: [PATCH 26/33] Prefer from_utf8_lossy over from_utf8 --- wp_api/src/lib.rs | 4 ++-- wp_api/src/users.rs | 2 +- wp_cli/src/main.rs | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 5d24d98f4..fc71e2c5b 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -277,7 +277,7 @@ pub fn parse_post_list_response( let post_list: Vec = serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), + response: String::from_utf8_lossy(&response.body).to_string(), })?; let mut next_page: Option = None; @@ -297,7 +297,7 @@ pub fn parse_api_details_response(response: WPNetworkResponse) -> Result>( parse_response_for_generic_errors(response)?; serde_json::from_slice(&response.body).map_err(|err| WPApiError::ParsingError { reason: err.to_string(), - response: std::str::from_utf8(&response.body).unwrap().to_string(), + response: String::from_utf8_lossy(&response.body).to_string(), }) } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 2b3354872..1d8f3307e 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -55,7 +55,7 @@ fn main() { println!( "Create user response: {:?}", - std::str::from_utf8(&user_create_response.body) + String::from_utf8_lossy(&user_create_response.body) ); println!("Created User: {:?}", created_user); @@ -73,7 +73,7 @@ fn main() { println!( "Update user response: {:?}", - std::str::from_utf8(&user_update_response.body) + String::from_utf8_lossy(&user_update_response.body) ); println!("Updated User: {:?}", updated_user); @@ -86,7 +86,7 @@ fn main() { let user_delete_response = wp_networking.request(user_delete_request).unwrap(); println!( "Delete user response: {:?}", - std::str::from_utf8(&user_delete_response.body) + String::from_utf8_lossy(&user_delete_response.body) ); println!( "Retrieve current user: {:?}", @@ -113,14 +113,14 @@ fn main() { wp_api::parse_retrieve_user_response_with_edit_context(&update_current_user_response); println!( "Update current user response: {:?}", - std::str::from_utf8(&update_current_user_response.body) + String::from_utf8_lossy(&update_current_user_response.body) ); println!("Updated Current User: {:?}", updated_current_user); // Remember to use a temporary user to test this // println!( // "Delete current user: {:?}", - // std::str::from_utf8( + // String::from_utf8_lossy( // &wp_networking // .request( // wp_networking From 66508da55eb68664ffb57812e8ec51fa389247f1 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 9 Apr 2024 11:51:27 -0400 Subject: [PATCH 27/33] Replace Display trait with as_str for WPApiParamUsersOrderBy --- wp_api/src/users.rs | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 2c2a86e56..bc5285db8 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt::Display}; +use std::collections::HashMap; use derive_builder::Builder; use serde::{Deserialize, Serialize}; @@ -137,22 +137,18 @@ impl Default for WPApiParamUsersOrderBy { } } -impl Display for WPApiParamUsersOrderBy { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Self::Id => "id", - Self::Include => "include", - Self::Name => "name", - Self::RegisteredDate => "registered_date", - Self::Slug => "slug", - Self::IncludeSlugs => "include_slugs", - Self::Email => "email", - Self::Url => "url", - } - ) +impl WPApiParamUsersOrderBy { + fn as_str(&self) -> &str { + match self { + Self::Id => "id", + Self::Include => "include", + Self::Name => "name", + Self::RegisteredDate => "registered_date", + Self::Slug => "slug", + Self::IncludeSlugs => "include_slugs", + Self::Email => "email", + Self::Url => "url", + } } } @@ -206,7 +202,9 @@ impl UserListParams { self.order .as_ref() .map(|x| ("order", x.as_str().to_string())), - self.order_by.as_ref().map(|x| ("order_by", x.to_string())), + self.order_by + .as_ref() + .map(|x| ("order_by", x.as_str().to_string())), Some(("slug", self.slug.join(","))), Some(("roles", self.roles.join(","))), Some(("capabilities", self.capabilities.join(","))), From 9656d8ce6e9667efc5e54950bb38daeedf471323 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 10 Apr 2024 14:10:08 -0400 Subject: [PATCH 28/33] Use references for user request parameters --- wp_api/src/lib.rs | 18 +++++++++--------- wp_cli/src/main.rs | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index fc71e2c5b..cc26aba24 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -65,7 +65,7 @@ impl WPApiHelper { pub fn list_users_request( &self, context: WPContext, - params: Option, + params: &Option, // UniFFI doesn't support Option<&T> ) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::GET, @@ -93,7 +93,7 @@ impl WPApiHelper { } } - pub fn create_user_request(&self, params: UserCreateParams) -> WPNetworkRequest { + pub fn create_user_request(&self, params: &UserCreateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::create_user(&self.site_url).into(), @@ -105,17 +105,17 @@ impl WPApiHelper { pub fn update_user_request( &self, user_id: UserId, - params: UserUpdateParams, + params: &UserUpdateParams, ) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, - url: UsersEndpoint::update_user(&self.site_url, user_id, ¶ms).into(), + url: UsersEndpoint::update_user(&self.site_url, user_id, params).into(), header_map: Some(self.header_map_for_post_request()), body: serde_json::to_vec(¶ms).ok(), } } - pub fn update_current_user_request(&self, params: UserUpdateParams) -> WPNetworkRequest { + pub fn update_current_user_request(&self, params: &UserUpdateParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_current_user(&self.site_url).into(), @@ -127,20 +127,20 @@ impl WPApiHelper { pub fn delete_user_request( &self, user_id: UserId, - params: UserDeleteParams, + params: &UserDeleteParams, ) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::DELETE, - url: UsersEndpoint::delete_user(&self.site_url, user_id, ¶ms).into(), + url: UsersEndpoint::delete_user(&self.site_url, user_id, params).into(), header_map: self.header_map(), body: None, } } - pub fn delete_current_user_request(&self, params: UserDeleteParams) -> WPNetworkRequest { + pub fn delete_current_user_request(&self, params: &UserDeleteParams) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::DELETE, - url: UsersEndpoint::delete_current_user(&self.site_url, ¶ms).into(), + url: UsersEndpoint::delete_current_user(&self.site_url, params).into(), header_map: self.header_map(), body: None, } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index 1d8f3307e..edc0e8d93 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -21,7 +21,7 @@ fn main() { let user_list_request = wp_networking .api_helper - .list_users_request(WPContext::Edit, None); + .list_users_request(WPContext::Edit, &None); let user_list = wp_api::parse_list_users_response_with_edit_context( &wp_networking.request(user_list_request).unwrap(), ) @@ -48,7 +48,7 @@ fn main() { let user_create_request = wp_networking .api_helper - .create_user_request(user_create_params); + .create_user_request(&user_create_params); let user_create_response = wp_networking.request(user_create_request).unwrap(); let created_user = wp_api::parse_retrieve_user_response_with_edit_context(&user_create_response); @@ -66,7 +66,7 @@ fn main() { .unwrap(); let user_update_request = wp_networking .api_helper - .update_user_request(created_user.id, user_update_params); + .update_user_request(created_user.id, &user_update_params); let user_update_response = wp_networking.request(user_update_request).unwrap(); let updated_user = wp_api::parse_retrieve_user_response_with_edit_context(&user_update_response); @@ -82,7 +82,7 @@ fn main() { }; let user_delete_request = wp_networking .api_helper - .delete_user_request(created_user.id, user_delete_params); + .delete_user_request(created_user.id, &user_delete_params); let user_delete_response = wp_networking.request(user_delete_request).unwrap(); println!( "Delete user response: {:?}", @@ -107,7 +107,7 @@ fn main() { .unwrap(); let update_current_user_request = wp_networking .api_helper - .update_current_user_request(update_current_user_params); + .update_current_user_request(&update_current_user_params); let update_current_user_response = wp_networking.request(update_current_user_request).unwrap(); let updated_current_user = wp_api::parse_retrieve_user_response_with_edit_context(&update_current_user_response); @@ -125,7 +125,7 @@ fn main() { // .request( // wp_networking // .api_helper - // .delete_current_user_request(UserDeleteParams { + // .delete_current_user_request(&UserDeleteParams { // reassign: first_user.id // }) // ) From 6c9fe91fddc13faef8cb33632902a45e48b4dc76 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 11 Apr 2024 11:16:26 -0400 Subject: [PATCH 29/33] Refactor UserListParams.query_pairs() to be more readable --- wp_api/src/users.rs | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index bc5285db8..3117479f6 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -119,7 +119,7 @@ impl UsersEndpoint { } } -#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] pub enum WPApiParamUsersOrderBy { Id, Include, @@ -193,28 +193,26 @@ pub struct UserListParams { impl UserListParams { pub fn query_pairs(&self) -> impl IntoIterator { [ - self.page.as_ref().map(|x| ("page", x.to_string())), - self.per_page.as_ref().map(|x| ("per_page", x.to_string())), - self.search.as_ref().map(|x| ("search", x.clone())), - self.exclude.as_ref().map(|x| ("exclude", x.clone())), - self.include.as_ref().map(|x| ("include", x.clone())), - self.offset.as_ref().map(|x| ("offset", x.to_string())), - self.order - .as_ref() - .map(|x| ("order", x.as_str().to_string())), - self.order_by - .as_ref() - .map(|x| ("order_by", x.as_str().to_string())), - Some(("slug", self.slug.join(","))), - Some(("roles", self.roles.join(","))), - Some(("capabilities", self.capabilities.join(","))), - self.who.as_ref().map(|x| ("who", x.clone())), - self.has_published_posts - .as_ref() - .map(|x| ("has_published_posts", x.to_string())), + ("page", self.page.map(|x| x.to_string())), + ("per_page", self.per_page.map(|x| x.to_string())), + ("search", self.search.clone()), + ("exclude", self.exclude.clone()), + ("include", self.include.clone()), + ("offset", self.offset.map(|x| x.to_string())), + ("order", self.order.map(|x| x.as_str().to_string())), + ("order_by", self.order_by.map(|x| x.as_str().to_string())), + ("slug", Some(self.slug.join(","))), + ("roles", Some(self.roles.join(","))), + ("capabilities", Some(self.capabilities.join(","))), + ("who", self.who.clone()), + ( + "has_published_post", + self.has_published_posts.map(|x| x.to_string()), + ), ] .into_iter() - .flatten() + // Remove `None` values + .filter_map(|(k, opt_v)| opt_v.map(|v| (k, v))) } } From 24fcd6b08a05f3ae879c7bd57ba1c24abe261fdc Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 11 Apr 2024 11:20:35 -0400 Subject: [PATCH 30/33] Remove the Option from parse retrieve user results --- wp_api/src/users.rs | 6 +++--- wp_cli/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 3117479f6..432ae1227 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -33,21 +33,21 @@ pub fn parse_list_users_response_with_view_context( #[uniffi::export] pub fn parse_retrieve_user_response_with_edit_context( response: &WPNetworkResponse, -) -> Result, WPApiError> { +) -> Result { parse_users_response(response) } #[uniffi::export] pub fn parse_retrieve_user_response_with_embed_context( response: &WPNetworkResponse, -) -> Result, WPApiError> { +) -> Result { parse_users_response(response) } #[uniffi::export] pub fn parse_retrieve_user_response_with_view_context( response: &WPNetworkResponse, -) -> Result, WPApiError> { +) -> Result { parse_users_response(response) } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs index edc0e8d93..c33736ee0 100644 --- a/wp_cli/src/main.rs +++ b/wp_cli/src/main.rs @@ -59,7 +59,7 @@ fn main() { ); println!("Created User: {:?}", created_user); - let created_user = created_user.unwrap().unwrap(); + let created_user = created_user.unwrap(); let user_update_params = UserUpdateParamsBuilder::default() .email(Some("t_email_updated@foo.com".to_string())) .build() From 618e0994ef653eec2fc3cb2c4dd160d196443053 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 11 Apr 2024 11:24:32 -0400 Subject: [PATCH 31/33] update_current_user_request should use post request header map --- wp_api/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index cc26aba24..8684db737 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -119,7 +119,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_current_user(&self.site_url).into(), - header_map: self.header_map(), + header_map: Some(self.header_map_for_post_request()), body: serde_json::to_vec(¶ms).ok(), } } From b8f0b8d38558db8feb21ecaf4271d4bed3cf9e50 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 11 Apr 2024 11:40:57 -0400 Subject: [PATCH 32/33] Add 'Accept' header to all WPRequests --- wp_api/src/lib.rs | 31 +++++++++++++++++++------------ wp_networking/src/lib.rs | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 8684db737..b9fd9f987 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -16,6 +16,8 @@ pub mod posts; pub mod url; pub mod users; +const CONTENT_TYPE_JSON: &str = "application/json"; + #[derive(uniffi::Object)] pub struct WPApiHelper { site_url: Url, @@ -97,7 +99,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::create_user(&self.site_url).into(), - header_map: Some(self.header_map_for_post_request()), + header_map: self.header_map_for_post_request(), body: serde_json::to_vec(¶ms).ok(), } } @@ -110,7 +112,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_user(&self.site_url, user_id, params).into(), - header_map: Some(self.header_map_for_post_request()), + header_map: self.header_map_for_post_request(), body: serde_json::to_vec(¶ms).ok(), } } @@ -119,7 +121,7 @@ impl WPApiHelper { WPNetworkRequest { method: RequestMethod::POST, url: UsersEndpoint::update_current_user(&self.site_url).into(), - header_map: Some(self.header_map_for_post_request()), + header_map: self.header_map_for_post_request(), body: serde_json::to_vec(¶ms).ok(), } } @@ -146,21 +148,26 @@ impl WPApiHelper { } } - fn header_map(&self) -> Option> { + fn header_map(&self) -> HashMap { + let mut header_map = HashMap::new(); + header_map.insert( + http::header::ACCEPT.to_string(), + CONTENT_TYPE_JSON.to_string(), + ); match &self.authentication { WPAuthentication::None => None, - WPAuthentication::AuthorizationHeader { token } => Some(HashMap::from([( - "Authorization".into(), - format!("Basic {}", token), - )])), - } + WPAuthentication::AuthorizationHeader { token } => { + header_map.insert("Authorization".to_string(), format!("Basic {}", token)) + } + }; + header_map } fn header_map_for_post_request(&self) -> HashMap { - let mut header_map = self.header_map().unwrap_or_default(); + let mut header_map = self.header_map(); header_map.insert( http::header::CONTENT_TYPE.to_string(), - "application/json".to_string(), + CONTENT_TYPE_JSON.to_string(), ); header_map } @@ -234,7 +241,7 @@ pub struct WPNetworkRequest { // // It could be something similar to `reqwest`'s [`header`](https://docs.rs/reqwest/latest/reqwest/header/index.html) // module. - pub header_map: Option>, + pub header_map: HashMap, pub body: Option>, } diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index 6bcf51bf3..40ed0cd16 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -21,7 +21,7 @@ impl WPNetworking { &self, wp_request: WPNetworkRequest, ) -> Result { - let request_headers: HeaderMap = (&wp_request.header_map.unwrap()).try_into().unwrap(); + let request_headers: HeaderMap = (&wp_request.header_map).try_into().unwrap(); let mut request = self .client From 2023d8d80cd74d841ee3b373729b7e92e25bb837 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 11 Apr 2024 11:53:42 -0400 Subject: [PATCH 33/33] Update breaking changes in Swift for headerMap becoming non-optional --- native/swift/Sources/wordpress-api/Login/API+Login.swift | 4 ++-- native/swift/Sources/wordpress-api/WordPressAPI.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/swift/Sources/wordpress-api/Login/API+Login.swift b/native/swift/Sources/wordpress-api/Login/API+Login.swift index f134ffe8c..7424c3137 100644 --- a/native/swift/Sources/wordpress-api/Login/API+Login.swift +++ b/native/swift/Sources/wordpress-api/Login/API+Login.swift @@ -7,7 +7,7 @@ import FoundationNetworking public extension WordPressAPI { static func findRestApiEndpointRoot(forSiteUrl url: URL, using session: URLSession) async throws -> URL? { - let request = WpNetworkRequest(method: .head, url: url) + let request = WpNetworkRequest(method: .head, url: url, headerMap: [:]) let ephemeralClient = WordPressAPI(urlSession: session, baseUrl: url, authenticationStategy: .none) let response = try await ephemeralClient.perform(request: request) @@ -15,7 +15,7 @@ public extension WordPressAPI { } func getRestAPICapabilities(forApiRoot url: URL, using session: URLSession) async throws -> WpapiDetails { - let wpResponse = try await self.perform(request: WpNetworkRequest(method: .get, url: url, headerMap: nil)) + let wpResponse = try await self.perform(request: WpNetworkRequest(method: .get, url: url, headerMap: [:])) return try wordpress_api_wrapper.parseApiDetailsResponse(response: wpResponse) } } diff --git a/native/swift/Sources/wordpress-api/WordPressAPI.swift b/native/swift/Sources/wordpress-api/WordPressAPI.swift index b6042b923..06643d745 100644 --- a/native/swift/Sources/wordpress-api/WordPressAPI.swift +++ b/native/swift/Sources/wordpress-api/WordPressAPI.swift @@ -159,7 +159,7 @@ extension RequestMethod { } extension WpNetworkRequest { - init(method: RequestMethod, url: URL, headerMap: [String: String]? = nil) { + init(method: RequestMethod, url: URL, headerMap: [String: String]) { self.init(method: method, url: url.absoluteString, headerMap: headerMap, body: nil) } }