Dedup entries returned by LDAP

This commit is contained in:
orhtej2
2025-06-29 01:23:44 +02:00
committed by Jason Volk
parent 9496d05cd2
commit 2ead282bec

View File

@@ -1,6 +1,7 @@
#![cfg(feature = "ldap")] #![cfg(feature = "ldap")]
use itertools::Itertools; use std::collections::HashMap;
use ldap3::{LdapConnAsync, Scope, SearchEntry}; use ldap3::{LdapConnAsync, Scope, SearchEntry};
use ruma::UserId; use ruma::UserId;
use tuwunel_core::{Result, debug, err, error, implement, result::LogErr, trace}; use tuwunel_core::{Result, debug, err, error, implement, result::LogErr, trace};
@@ -56,7 +57,7 @@ pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, bool)>>
.inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Search")) .inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Search"))
.map_err(|e| err!(Ldap(error!(?attr, ?user_filter, "LDAP search error: {e}"))))?; .map_err(|e| err!(Ldap(error!(?attr, ?user_filter, "LDAP search error: {e}"))))?;
let mut dns = entries let mut dns: HashMap<String, bool> = entries
.into_iter() .into_iter()
.filter_map(|entry| { .filter_map(|entry| {
let search_entry = SearchEntry::construct(entry); let search_entry = SearchEntry::construct(entry);
@@ -69,7 +70,7 @@ pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, bool)>>
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart)) .any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
.then_some((search_entry.dn, false)) .then_some((search_entry.dn, false))
}) })
.collect_vec(); .collect();
if !config.admin_filter.is_empty() { if !config.admin_filter.is_empty() {
let admin_base_dn = if config.admin_base_dn.is_empty() { let admin_base_dn = if config.admin_base_dn.is_empty() {
@@ -91,22 +92,17 @@ pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, bool)>>
err!(Ldap(error!(?attr, ?admin_filter, "Ldap admin search error: {e}"))) err!(Ldap(error!(?attr, ?admin_filter, "Ldap admin search error: {e}")))
})?; })?;
let mut admin_dns = admin_entries dns.extend(admin_entries.into_iter().filter_map(|entry| {
.into_iter() let search_entry = SearchEntry::construct(entry);
.filter_map(|entry| { debug!(?search_entry, "LDAP search entry");
let search_entry = SearchEntry::construct(entry); search_entry
debug!(?search_entry, "LDAP search entry"); .attrs
search_entry .get(&config.uid_attribute)
.attrs .into_iter()
.get(&config.uid_attribute) .chain(search_entry.attrs.get(&config.name_attribute))
.into_iter() .any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
.chain(search_entry.attrs.get(&config.name_attribute)) .then_some((search_entry.dn, true))
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart)) }));
.then_some((search_entry.dn, true))
})
.collect_vec();
dns.append(&mut admin_dns);
} }
ldap.unbind() ldap.unbind()
@@ -115,7 +111,7 @@ pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, bool)>>
driver.await.log_err().ok(); driver.await.log_err().ok();
Ok(dns) Ok(dns.drain().collect())
} }
#[implement(super::Service)] #[implement(super::Service)]