refactor: Reuse typed LDAP attributes in search results

This commit is contained in:
selfhoster selfhoster 2026-09-21 15:39:49 +02:00
commit e32b4bfb82

View file

@ -148,31 +148,43 @@ pub async fn search_success(
fn search_entry_from_user(user: &User, req_attrs: &[String]) -> LdapSearchResultEntry { fn search_entry_from_user(user: &User, req_attrs: &[String]) -> LdapSearchResultEntry {
let mut res: Vec<LdapPartialAttribute> = vec![]; let mut res: Vec<LdapPartialAttribute> = vec![];
for attr in req_attrs { for attr_str in req_attrs {
if let Some(attr_values) = match attr.as_str() { // We keep a copy of the requested attribute so that we can answer as it was requested,
"uid" => Some(vec![user.username.clone()]), // eg. `CN` => `CN` (instead of normalizing to `cn`).
"cn" | "mail" => Some(vec![user.mail.clone()]), let Some(attr) = LdapAttribute::from_str(attr_str)
.inspect_err(|e| tracing::debug!("Unknown attribute in request: {e}"))
.ok()
else {
continue;
};
let str_values = match attr {
// TODO: should we normalize the value some more here?
LdapAttribute::Uid => vec![user.username.clone()],
// TODO: should CN be different than the mail?
// TODO: should we normalize values some more here?
LdapAttribute::CommonName | LdapAttribute::Mail | LdapAttribute::MailAlias => {
vec![user.mail.clone()]
}
// TODO: group membership // TODO: group membership
"memberof" => Some(vec![]), LdapAttribute::MemberOf => vec![],
// Copied from lldap output, not sure if we want to add/remove some classes depending on context // TODO: if we introduce mail permission, we need to remove mailaccount from here
"objectclass" => Some( LdapAttribute::ObjectClass => vec![
vec!["inetOrgPerson", "posixAccount", "mailAccount", "person"] "inetOrgPerson".to_string(),
.into_iter() "posixAccount".to_string(),
.map(String::from) "mailAccount".to_string(),
.collect(), "person".to_string(),
), ],
_ => { };
tracing::warn!("Ignoring unknown attr in search query: {attr}");
None
}
} {
res.push(LdapPartialAttribute { res.push(LdapPartialAttribute {
atype: attr.clone(), // Reuse the requested attribute name, not the normalized form
// we would otherwise produce.
atype: attr_str.clone(),
// LDAP response expects raw byte vec for each value // LDAP response expects raw byte vec for each value
vals: attr_values.into_iter().map(Vec::from).collect(), vals: str_values.into_iter().map(Vec::from).collect(),
}); });
} }
}
LdapSearchResultEntry { LdapSearchResultEntry {
dn: Dn::from_user(user).to_dn_string(), dn: Dn::from_user(user).to_dn_string(),