diff --git a/CHANGELOG.md b/CHANGELOG.md index 04a93db..378397a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,18 @@ SPDX-License-Identifier: Apache-2.0 All notable changes to this project will be documented in this file. +## [0.12.0] - 2026-04-23 + +### Features + +- [**breaking**] Add org_id to list_user_metadata +- [**breaking**] Add org_id to list_users +- [**breaking**] Add org_id to user metadata functions + +### Refactor + +- [**breaking**] Change org_id param order + ## [0.11.1] - 2026-04-20 ### Bug Fixes diff --git a/Cargo.lock b/Cargo.lock index 20fef1c..7385da5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "famedly-zitadel-rust-client" -version = "0.11.1" +version = "0.12.0" dependencies = [ "anyhow", "anyhow_ext", diff --git a/Cargo.toml b/Cargo.toml index 85d2390..4a4753e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ [package] name = "famedly-zitadel-rust-client" description = "HTTP client for Zitadel IdP built by Famedly" -version = "0.11.1" +version = "0.12.0" authors = [] edition = "2024" resolver = "2" diff --git a/src/v2/users/mod.rs b/src/v2/users/mod.rs index 92fc8f1..d6478a2 100644 --- a/src/v2/users/mod.rs +++ b/src/v2/users/mod.rs @@ -137,13 +137,14 @@ impl Zitadel { pub fn list_idp_links( &self, user_id: &str, + org_id: Option, params: Option, ) -> Result> + Send> { Ok(PaginationHandler::new( self.clone(), params, self.make_url(&format!("v2/users/{user_id}/links/_search"))?, - None, // Endpoint does not support org_id + org_id, )) } /// List passkeys of an user @@ -167,6 +168,7 @@ impl Zitadel { /// [Docs](https://zitadel.com/docs/apis/resources/user_service_v2/user-service-list-users) pub fn list_users( &self, + org_id: Option, params: Option, sorting: Option, queries: Option>, @@ -175,7 +177,7 @@ impl Zitadel { self.clone(), (params, sorting, queries), self.make_url("v2/users")?, - None, + org_id, )) } @@ -574,10 +576,16 @@ impl Zitadel { Ok(self.send_request(request).await?) } /// Remove a metadata object from a user with a specific key - pub async fn delete_user_metadata(&self, user_id: &str, key: &str) -> Result
{ + pub async fn delete_user_metadata( + &self, + user_id: &str, + key: &str, + org_id: Option, + ) -> Result
{ let request = self .client .delete(self.make_url(&format!("/management/v1/users/{user_id}/metadata/{key}"))?) + .chain_opt(org_id, |req, org_id| req.header(HEADER_ZITADEL_ORGANIZATION_ID, org_id)) .build()?; Ok(self.send_request(request).await?) @@ -589,10 +597,12 @@ impl Zitadel { user_id: &str, key: &str, value: &str, + org_id: Option, ) -> Result { let request = self .client .post(self.make_url(&format!("/management/v1/users/{user_id}/metadata/{key}"))?) + .chain_opt(org_id, |req, org_id| req.header(HEADER_ZITADEL_ORGANIZATION_ID, org_id)) .json(&serde_json::json!({"value": BASE64_STANDARD.encode(value)})) .build()?; @@ -604,10 +614,12 @@ impl Zitadel { &self, user_id: &str, body: Vec, + org_id: Option, ) -> Result
{ let request = self .client .post(self.make_url(&format!("/management/v1/users/{user_id}/metadata/_bulk"))?) + .chain_opt(org_id, |req, org_id| req.header(HEADER_ZITADEL_ORGANIZATION_ID, org_id)) .json(&serde_json::json!({"metadata": body})) .build()?; @@ -618,10 +630,12 @@ impl Zitadel { &self, user_id: &str, body: Vec, + org_id: Option, ) -> Result
{ let request = self .client .delete(self.make_url(&format!("/management/v1/users/{user_id}/metadata/_bulk"))?) + .chain_opt(org_id, |req, org_id| req.header(HEADER_ZITADEL_ORGANIZATION_ID, org_id)) .json(&serde_json::json!({"keys": body})) .build()?; @@ -632,6 +646,7 @@ impl Zitadel { pub fn list_user_metadata( &self, user_id: &str, + org_id: Option, params: Option, queries: Option>, ) -> Result> + Send> { @@ -639,7 +654,7 @@ impl Zitadel { self.clone(), (params, queries), self.make_url(&format!("/management/v1/users/{user_id}/metadata/_search"))?, - None, // TODO: Breaking change -> possibility to add org_id to function args + org_id, )) } } diff --git a/tests/e2e.rs b/tests/e2e.rs index 03a9426..5b33845 100644 --- a/tests/e2e.rs +++ b/tests/e2e.rs @@ -73,7 +73,7 @@ async fn tear_down(zitadel: &Zitadel) { let queries = Some(vec![SearchQuery::new().with_type_query(TypeQuery::new(Userv2Type::Human))]); zitadel - .list_users(None, None, queries) + .list_users(None, None, None, queries) .expect("Error getting the list of users for tear down") .try_for_each(|user| async move { tracing::info!("user: {user:?}"); @@ -494,12 +494,13 @@ async fn test_e2e_create_organization() -> Result<()> { assert_eq!( zitadel .list_users( + None, None, None, Some(vec![ SearchQuery::new() .with_last_name_query(LastNameQuery::new("Adminmann".to_owned())) - ]) + ]), )? .count() .await, @@ -816,7 +817,7 @@ async fn test_e2e_list_human_users() -> Result<()> { Some(vec![SearchQuery::new().with_last_name_query(LastNameQuery::new("Doe".to_owned()))]); let pagination_params = Some(PaginationParams::DEFAULT.with_asc(true).with_page_size(5)); - let stream = zitadel.list_users(pagination_params, None, queries)?; + let stream = zitadel.list_users(None, pagination_params, None, queries)?; let res_user_emails: Vec<_> = stream .and_then(|user| { @@ -854,7 +855,7 @@ async fn test_e2e_list_idp_links() -> Result<()> { let id = ret.user_id().expect("Couldn't get the user id from response"); let pagination_params = Some(PaginationParams::DEFAULT.with_asc(true)); - let stream = zitadel.list_idp_links(id, pagination_params)?; + let stream = zitadel.list_idp_links(id, None, pagination_params)?; assert_eq!(stream.count().await, idp_links.len()); @@ -962,14 +963,14 @@ async fn test_e2e_delete_user() -> Result<()> { let pagination_params = Some(PaginationParams::DEFAULT.with_asc(true)); assert_eq!( - zitadel.list_users(pagination_params.clone(), None, queries.clone())?.count().await, + zitadel.list_users(None, pagination_params.clone(), None, queries.clone())?.count().await, 2 ); zitadel.delete_user(&id).await?; let user_count = zitadel - .list_users(pagination_params, None, queries)? + .list_users(None, pagination_params, None, queries)? .inspect_ok(|user| { let user_name = user .human() @@ -1010,7 +1011,7 @@ async fn test_e2e_user_metadata() -> Result<()> { .cloned() .expect("Couldn't get the user id from response"); - zitadel.set_user_metadata(&id, metadata[1].0, metadata[1].1).await?; + zitadel.set_user_metadata(&id, metadata[1].0, metadata[1].1, None).await?; for (query_key, expected_value) in &metadata { let ret = zitadel.get_user_metadata(&id, query_key, None).await?; @@ -1022,11 +1023,11 @@ async fn test_e2e_user_metadata() -> Result<()> { assert_eq!(*expected_value, value); } - zitadel.delete_user_metadata(&id, metadata[1].0).await?; + zitadel.delete_user_metadata(&id, metadata[1].0, None).await?; assert!(zitadel.get_user_metadata(&id, metadata[1].0, None).await.is_err()); let updated_value = "new_value"; - zitadel.set_user_metadata(&id, metadata[0].0, updated_value).await?; + zitadel.set_user_metadata(&id, metadata[0].0, updated_value, None).await?; let ret = zitadel.get_user_metadata(&id, metadata[0].0, None).await?; let value = ret @@ -1065,11 +1066,12 @@ async fn test_e2e_user_metadata_bulk() -> Result<()> { .cloned() .expect("Couldn't get the user id from response"); - zitadel.set_user_metadata_bulk(&id, metadata.clone()).await?; + zitadel.set_user_metadata_bulk(&id, metadata.clone(), None).await?; let stream = zitadel.list_user_metadata( &id, None, + None, Some(vec![KeyQuery::new("key".to_owned()).with_method(TextQueryMethod::Contains)]), )?; @@ -1098,6 +1100,7 @@ async fn test_e2e_user_metadata_bulk() -> Result<()> { .delete_user_metadata_bulk( &id, metadata.iter().map(|metadata| metadata.key().clone()).collect(), + None, ) .await?; @@ -1106,6 +1109,7 @@ async fn test_e2e_user_metadata_bulk() -> Result<()> { .list_user_metadata( &id, None, + None, Some(vec![KeyQuery::new("key".to_owned()).with_method(TextQueryMethod::Contains)]), )? .count()