From 485c30d64fe86e17054bf76886c4c199e82a4916 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Mon, 4 Nov 2024 14:31:28 +0100 Subject: [PATCH] feat: read status attribute with TRUE or FALSE string value --- src/sources/ldap.rs | 48 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/sources/ldap.rs b/src/sources/ldap.rs index bd0561d..2751296 100644 --- a/src/sources/ldap.rs +++ b/src/sources/ldap.rs @@ -110,21 +110,25 @@ impl LdapSource { /// Construct a user from an LDAP SearchEntry pub(crate) fn parse_user(&self, entry: SearchEntry) -> Result { - let status_as_int = match read_search_entry(&entry, &self.ldap_config.attributes.status)? { - StringOrBytes::String(status) => status.parse::()?, + let disable_bitmask = { + use std::ops::BitOr; + self.ldap_config.attributes.disable_bitmasks.iter().fold(0, i32::bitor) + }; + + let enabled = match read_search_entry(&entry, &self.ldap_config.attributes.status)? { + StringOrBytes::String(status) => match &status[..] { + "TRUE" => true, + "FALSE" => false, + _ => status.parse::()? & disable_bitmask == 0, + }, StringOrBytes::Bytes(status) => { - i32::from_be_bytes(status.try_into().map_err(|err: Vec| { + let status = i32::from_be_bytes(status.try_into().map_err(|err: Vec| { let err_string = String::from_utf8_lossy(&err).to_string(); anyhow!(err_string).context("failed to convert to i32 flag") - })?) + })?); + status & disable_bitmask == 0 } }; - let enabled = !self - .ldap_config - .attributes - .disable_bitmasks - .iter() - .any(|flag| status_as_int & flag != 0); let first_name = read_search_entry(&entry, &self.ldap_config.attributes.first_name)?; let last_name = read_search_entry(&entry, &self.ldap_config.attributes.last_name)?; @@ -571,4 +575,28 @@ mod tests { assert_eq!(user.external_user_id, StringOrBytes::String("testuser".to_owned())); assert!(user.enabled); } + + #[tokio::test] + async fn test_text_enabled() { + let config = load_config(); + let ldap_source = + LdapSource { ldap_config: config.sources.ldap.unwrap(), is_dry_run: false }; + + for (attr, parsed) in [("TRUE", true), ("FALSE", false)] { + let entry = SearchEntry { + dn: "uid=testuser,ou=testorg,dc=example,dc=org".to_owned(), + attrs: { + let mut user = new_user(); + user.insert("shadowFlag".to_owned(), vec![attr.to_owned()]); + user + }, + bin_attrs: HashMap::new(), + }; + + let result = ldap_source.parse_user(entry); + assert!(result.is_ok(), "Failed to parse user: {:?}", result); + let user = result.unwrap(); + assert_eq!(user.enabled, parsed); + } + } }